Merge "Rewrite DeviceProvisionedController" into sc-v2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
546aaad7e4
@@ -187,9 +187,13 @@ public abstract class SystemUIDefaultModule {
|
||||
return new Recents(context, recentsImplementation, commandQueue);
|
||||
}
|
||||
|
||||
@Binds
|
||||
abstract DeviceProvisionedController bindDeviceProvisionedController(
|
||||
DeviceProvisionedControllerImpl deviceProvisionedController);
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static DeviceProvisionedController bindDeviceProvisionedController(
|
||||
DeviceProvisionedControllerImpl deviceProvisionedController) {
|
||||
deviceProvisionedController.init();
|
||||
return deviceProvisionedController;
|
||||
}
|
||||
|
||||
@Binds
|
||||
abstract KeyguardViewController bindKeyguardViewController(
|
||||
|
||||
@@ -332,8 +332,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
deviceProvisionedController.addCallback(new DeviceProvisionedListener() {
|
||||
@Override
|
||||
public void onUserSetupChanged() {
|
||||
setUserSetupComplete(deviceProvisionedController.isUserSetup(
|
||||
deviceProvisionedController.getCurrentUser()));
|
||||
setUserSetupComplete(deviceProvisionedController.isCurrentUserSetup());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -604,8 +604,7 @@ public class PhoneStatusBarPolicy
|
||||
|
||||
@Override
|
||||
public void onUserSetupChanged() {
|
||||
boolean userSetup = mProvisionedController.isUserSetup(
|
||||
mProvisionedController.getCurrentUser());
|
||||
boolean userSetup = mProvisionedController.isCurrentUserSetup();
|
||||
if (mCurrentUserSetup == userSetup) return;
|
||||
mCurrentUserSetup = userSetup;
|
||||
updateAlarm();
|
||||
|
||||
@@ -4340,10 +4340,9 @@ public class StatusBar extends SystemUI implements
|
||||
private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() {
|
||||
@Override
|
||||
public void onUserSetupChanged() {
|
||||
final boolean userSetup = mDeviceProvisionedController.isUserSetup(
|
||||
mDeviceProvisionedController.getCurrentUser());
|
||||
Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for user "
|
||||
+ mDeviceProvisionedController.getCurrentUser());
|
||||
final boolean userSetup = mDeviceProvisionedController.isCurrentUserSetup();
|
||||
Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for "
|
||||
+ "current user");
|
||||
if (MULTIUSER_DEBUG) {
|
||||
Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s",
|
||||
userSetup, mUserSetup));
|
||||
|
||||
@@ -14,23 +14,60 @@
|
||||
|
||||
package com.android.systemui.statusbar.policy;
|
||||
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
|
||||
|
||||
/**
|
||||
* Controller to cache in process the state of the device provisioning.
|
||||
* <p>
|
||||
* This controller keeps track of the values of device provisioning and user setup complete
|
||||
*/
|
||||
public interface DeviceProvisionedController extends CallbackController<DeviceProvisionedListener> {
|
||||
|
||||
/**
|
||||
* @return whether the device is provisioned
|
||||
* @see Settings.Global#DEVICE_PROVISIONED
|
||||
*/
|
||||
boolean isDeviceProvisioned();
|
||||
boolean isUserSetup(int currentUser);
|
||||
|
||||
/**
|
||||
* @deprecated use {@link com.android.systemui.settings.UserTracker}
|
||||
*/
|
||||
@Deprecated
|
||||
int getCurrentUser();
|
||||
|
||||
default boolean isCurrentUserSetup() {
|
||||
return isUserSetup(getCurrentUser());
|
||||
}
|
||||
/**
|
||||
* @param user the user to query
|
||||
* @return whether that user has completed the user setup
|
||||
* @see Settings.Secure#USER_SETUP_COMPLETE
|
||||
*/
|
||||
boolean isUserSetup(int user);
|
||||
|
||||
/**
|
||||
* @see DeviceProvisionedController#isUserSetup
|
||||
*/
|
||||
boolean isCurrentUserSetup();
|
||||
|
||||
/**
|
||||
* Interface to provide calls when the values tracked change
|
||||
*/
|
||||
interface DeviceProvisionedListener {
|
||||
/**
|
||||
* Call when the device changes from not provisioned to provisioned
|
||||
*/
|
||||
default void onDeviceProvisionedChanged() { }
|
||||
|
||||
/**
|
||||
* Call on user switched
|
||||
*/
|
||||
default void onUserSwitched() {
|
||||
onUserSetupChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call when some user changes from not provisioned to provisioned
|
||||
*/
|
||||
default void onUserSetupChanged() { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the
|
||||
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.policy;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings.Global;
|
||||
import android.provider.Settings.Secure;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.settings.CurrentUserTracker;
|
||||
import com.android.systemui.util.settings.GlobalSettings;
|
||||
import com.android.systemui.util.settings.SecureSettings;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
*/
|
||||
@SysUISingleton
|
||||
public class DeviceProvisionedControllerImpl extends CurrentUserTracker implements
|
||||
DeviceProvisionedController {
|
||||
|
||||
protected static final String TAG = DeviceProvisionedControllerImpl.class.getSimpleName();
|
||||
protected final ArrayList<DeviceProvisionedListener> mListeners = new ArrayList<>();
|
||||
private final GlobalSettings mGlobalSettings;
|
||||
private final SecureSettings mSecureSettings;
|
||||
private final Uri mDeviceProvisionedUri;
|
||||
private final Uri mUserSetupUri;
|
||||
protected final ContentObserver mSettingsObserver;
|
||||
|
||||
/**
|
||||
*/
|
||||
@Inject
|
||||
public DeviceProvisionedControllerImpl(@Main Handler mainHandler,
|
||||
BroadcastDispatcher broadcastDispatcher, GlobalSettings globalSettings,
|
||||
SecureSettings secureSettings) {
|
||||
super(broadcastDispatcher);
|
||||
mGlobalSettings = globalSettings;
|
||||
mSecureSettings = secureSettings;
|
||||
mDeviceProvisionedUri = mGlobalSettings.getUriFor(Global.DEVICE_PROVISIONED);
|
||||
mUserSetupUri = mSecureSettings.getUriFor(Secure.USER_SETUP_COMPLETE);
|
||||
mSettingsObserver = new ContentObserver(mainHandler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri, int flags) {
|
||||
Log.d(TAG, "Setting change: " + uri);
|
||||
if (mUserSetupUri.equals(uri)) {
|
||||
notifySetupChanged();
|
||||
} else {
|
||||
notifyProvisionedChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeviceProvisioned() {
|
||||
return mGlobalSettings.getInt(Global.DEVICE_PROVISIONED, 0) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserSetup(int currentUser) {
|
||||
return mSecureSettings.getIntForUser(Secure.USER_SETUP_COMPLETE, 0, currentUser) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentUser() {
|
||||
return ActivityManager.getCurrentUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCallback(@NonNull DeviceProvisionedListener listener) {
|
||||
mListeners.add(listener);
|
||||
if (mListeners.size() == 1) {
|
||||
startListening(getCurrentUser());
|
||||
}
|
||||
listener.onUserSetupChanged();
|
||||
listener.onDeviceProvisionedChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCallback(@NonNull DeviceProvisionedListener listener) {
|
||||
mListeners.remove(listener);
|
||||
if (mListeners.size() == 0) {
|
||||
stopListening();
|
||||
}
|
||||
}
|
||||
|
||||
protected void startListening(int user) {
|
||||
mGlobalSettings.registerContentObserverForUser(mDeviceProvisionedUri, true,
|
||||
mSettingsObserver, 0);
|
||||
mSecureSettings.registerContentObserverForUser(mUserSetupUri, true,
|
||||
mSettingsObserver, user);
|
||||
startTracking();
|
||||
}
|
||||
|
||||
protected void stopListening() {
|
||||
stopTracking();
|
||||
mGlobalSettings.unregisterContentObserver(mSettingsObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserSwitched(int newUserId) {
|
||||
mGlobalSettings.unregisterContentObserver(mSettingsObserver);
|
||||
mGlobalSettings.registerContentObserverForUser(mDeviceProvisionedUri, true,
|
||||
mSettingsObserver, 0);
|
||||
mSecureSettings.registerContentObserverForUser(mUserSetupUri, true,
|
||||
mSettingsObserver, newUserId);
|
||||
notifyUserChanged();
|
||||
}
|
||||
|
||||
private void notifyUserChanged() {
|
||||
for (int i = mListeners.size() - 1; i >= 0; --i) {
|
||||
mListeners.get(i).onUserSwitched();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifySetupChanged() {
|
||||
for (int i = mListeners.size() - 1; i >= 0; --i) {
|
||||
mListeners.get(i).onUserSetupChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyProvisionedChanged() {
|
||||
for (int i = mListeners.size() - 1; i >= 0; --i) {
|
||||
mListeners.get(i).onDeviceProvisionedChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.policy
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.UserInfo
|
||||
import android.database.ContentObserver
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.HandlerExecutor
|
||||
import android.os.UserHandle
|
||||
import android.provider.Settings
|
||||
import android.util.ArraySet
|
||||
import android.util.SparseBooleanArray
|
||||
import androidx.annotation.GuardedBy
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.android.systemui.Dumpable
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.util.settings.GlobalSettings
|
||||
import com.android.systemui.util.settings.SecureSettings
|
||||
import java.io.FileDescriptor
|
||||
import java.io.PrintWriter
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import javax.inject.Inject
|
||||
|
||||
@SysUISingleton
|
||||
open class DeviceProvisionedControllerImpl @Inject constructor(
|
||||
private val secureSettings: SecureSettings,
|
||||
private val globalSettings: GlobalSettings,
|
||||
private val userTracker: UserTracker,
|
||||
private val dumpManager: DumpManager,
|
||||
@Background private val backgroundHandler: Handler,
|
||||
@Main private val mainExecutor: Executor
|
||||
) : DeviceProvisionedController,
|
||||
DeviceProvisionedController.DeviceProvisionedListener,
|
||||
Dumpable {
|
||||
|
||||
companion object {
|
||||
private const val ALL_USERS = -1
|
||||
private const val NO_USERS = -2
|
||||
protected const val TAG = "DeviceProvisionedControllerImpl"
|
||||
}
|
||||
|
||||
private val deviceProvisionedUri = globalSettings.getUriFor(Settings.Global.DEVICE_PROVISIONED)
|
||||
private val userSetupUri = secureSettings.getUriFor(Settings.Secure.USER_SETUP_COMPLETE)
|
||||
|
||||
private val deviceProvisioned = AtomicBoolean(false)
|
||||
@GuardedBy("lock")
|
||||
private val userSetupComplete = SparseBooleanArray()
|
||||
@GuardedBy("lock")
|
||||
private val listeners = ArraySet<DeviceProvisionedController.DeviceProvisionedListener>()
|
||||
|
||||
private val lock = Any()
|
||||
|
||||
private val backgroundExecutor = HandlerExecutor(backgroundHandler)
|
||||
|
||||
private val initted = AtomicBoolean(false)
|
||||
|
||||
private val _currentUser: Int
|
||||
get() = userTracker.userId
|
||||
|
||||
override fun getCurrentUser(): Int {
|
||||
return _currentUser
|
||||
}
|
||||
|
||||
private val observer = object : ContentObserver(backgroundHandler) {
|
||||
override fun onChange(
|
||||
selfChange: Boolean,
|
||||
uris: MutableCollection<Uri>,
|
||||
flags: Int,
|
||||
userId: Int
|
||||
) {
|
||||
val updateDeviceProvisioned = deviceProvisionedUri in uris
|
||||
val updateUser = if (userSetupUri in uris) userId else NO_USERS
|
||||
updateValues(updateDeviceProvisioned, updateUser)
|
||||
if (updateDeviceProvisioned) {
|
||||
onDeviceProvisionedChanged()
|
||||
}
|
||||
if (updateUser != NO_USERS) {
|
||||
onUserSetupChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val userChangedCallback = object : UserTracker.Callback {
|
||||
@WorkerThread
|
||||
override fun onUserChanged(newUser: Int, userContext: Context) {
|
||||
updateValues(updateDeviceProvisioned = false, updateUser = newUser)
|
||||
onUserSwitched()
|
||||
}
|
||||
|
||||
override fun onProfilesChanged(profiles: List<UserInfo>) {}
|
||||
}
|
||||
|
||||
init {
|
||||
userSetupComplete.put(currentUser, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Call to initialize values and register observers
|
||||
*/
|
||||
open fun init() {
|
||||
if (!initted.compareAndSet(false, true)) {
|
||||
return
|
||||
}
|
||||
dumpManager.registerDumpable(this)
|
||||
updateValues()
|
||||
userTracker.addCallback(userChangedCallback, backgroundExecutor)
|
||||
globalSettings.registerContentObserver(deviceProvisionedUri, observer)
|
||||
secureSettings.registerContentObserverForUser(userSetupUri, observer, UserHandle.USER_ALL)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun updateValues(updateDeviceProvisioned: Boolean = true, updateUser: Int = ALL_USERS) {
|
||||
if (updateDeviceProvisioned) {
|
||||
deviceProvisioned
|
||||
.set(globalSettings.getInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0)
|
||||
}
|
||||
synchronized(lock) {
|
||||
if (updateUser == ALL_USERS) {
|
||||
val N = userSetupComplete.size()
|
||||
for (i in 0 until N) {
|
||||
val user = userSetupComplete.keyAt(i)
|
||||
val value = secureSettings
|
||||
.getIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0, user) != 0
|
||||
userSetupComplete.put(user, value)
|
||||
}
|
||||
} else if (updateUser != NO_USERS) {
|
||||
val value = secureSettings
|
||||
.getIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0, updateUser) != 0
|
||||
userSetupComplete.put(updateUser, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener.
|
||||
*
|
||||
* The listener will not be called when this happens.
|
||||
*/
|
||||
override fun addCallback(listener: DeviceProvisionedController.DeviceProvisionedListener) {
|
||||
synchronized(lock) {
|
||||
listeners.add(listener)
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeCallback(listener: DeviceProvisionedController.DeviceProvisionedListener) {
|
||||
synchronized(lock) {
|
||||
listeners.remove(listener)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isDeviceProvisioned(): Boolean {
|
||||
return deviceProvisioned.get()
|
||||
}
|
||||
|
||||
override fun isUserSetup(user: Int): Boolean {
|
||||
val index = synchronized(lock) {
|
||||
userSetupComplete.indexOfKey(user)
|
||||
}
|
||||
return if (index < 0) {
|
||||
val value = secureSettings
|
||||
.getIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0, user) != 0
|
||||
synchronized(lock) {
|
||||
userSetupComplete.put(user, value)
|
||||
}
|
||||
value
|
||||
} else {
|
||||
synchronized(lock) {
|
||||
userSetupComplete.get(user, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun isCurrentUserSetup(): Boolean {
|
||||
return isUserSetup(currentUser)
|
||||
}
|
||||
|
||||
override fun onDeviceProvisionedChanged() {
|
||||
dispatchChange(
|
||||
DeviceProvisionedController.DeviceProvisionedListener::onDeviceProvisionedChanged
|
||||
)
|
||||
}
|
||||
|
||||
override fun onUserSetupChanged() {
|
||||
dispatchChange(DeviceProvisionedController.DeviceProvisionedListener::onUserSetupChanged)
|
||||
}
|
||||
|
||||
override fun onUserSwitched() {
|
||||
dispatchChange(DeviceProvisionedController.DeviceProvisionedListener::onUserSwitched)
|
||||
}
|
||||
|
||||
protected fun dispatchChange(
|
||||
callback: DeviceProvisionedController.DeviceProvisionedListener.() -> Unit
|
||||
) {
|
||||
val listenersCopy = synchronized(lock) {
|
||||
ArrayList(listeners)
|
||||
}
|
||||
mainExecutor.execute {
|
||||
listenersCopy.forEach(callback)
|
||||
}
|
||||
}
|
||||
|
||||
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
|
||||
pw.println("Device provisioned: ${deviceProvisioned.get()}")
|
||||
synchronized(lock) {
|
||||
pw.println("User setup complete: $userSetupComplete")
|
||||
pw.println("Listeners: $listeners")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,9 +180,13 @@ public abstract class TvSystemUIModule {
|
||||
return new Recents(context, recentsImplementation, commandQueue);
|
||||
}
|
||||
|
||||
@Binds
|
||||
abstract DeviceProvisionedController bindDeviceProvisionedController(
|
||||
DeviceProvisionedControllerImpl deviceProvisionedController);
|
||||
@SysUISingleton
|
||||
@Provides
|
||||
static DeviceProvisionedController providesDeviceProvisionedController(
|
||||
DeviceProvisionedControllerImpl deviceProvisionedController) {
|
||||
deviceProvisionedController.init();
|
||||
return deviceProvisionedController;
|
||||
}
|
||||
|
||||
@Binds
|
||||
abstract KeyguardViewController bindKeyguardViewController(
|
||||
|
||||
@@ -216,7 +216,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
|
||||
mCallbackHandler = mock(CallbackHandler.class);
|
||||
|
||||
mMockProvisionController = mock(DeviceProvisionedController.class);
|
||||
when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(true);
|
||||
when(mMockProvisionController.isCurrentUserSetup()).thenReturn(true);
|
||||
doAnswer(invocation -> {
|
||||
mUserCallback = (DeviceProvisionedListener) invocation.getArguments()[0];
|
||||
mUserCallback.onUserSetupChanged();
|
||||
|
||||
@@ -21,7 +21,6 @@ import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -211,7 +210,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
|
||||
updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
|
||||
setConnectivityViaCallbackInNetworkController(
|
||||
NetworkCapabilities.TRANSPORT_CELLULAR, false, false, null);
|
||||
when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(false);
|
||||
when(mMockProvisionController.isCurrentUserSetup()).thenReturn(false);
|
||||
mUserCallback.onUserSetupChanged();
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.policy
|
||||
|
||||
import android.os.Handler
|
||||
import android.provider.Settings
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.capture
|
||||
import com.android.systemui.util.settings.FakeSettings
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Captor
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@TestableLooper.RunWithLooper
|
||||
class DeviceProvisionedControllerImplTest : SysuiTestCase() {
|
||||
|
||||
companion object {
|
||||
private const val START_USER = 0
|
||||
}
|
||||
|
||||
private lateinit var controller: DeviceProvisionedControllerImpl
|
||||
|
||||
@Mock
|
||||
private lateinit var userTracker: UserTracker
|
||||
@Mock
|
||||
private lateinit var dumpManager: DumpManager
|
||||
@Mock
|
||||
private lateinit var listener: DeviceProvisionedController.DeviceProvisionedListener
|
||||
@Captor
|
||||
private lateinit var userTrackerCallbackCaptor: ArgumentCaptor<UserTracker.Callback>
|
||||
|
||||
private lateinit var mainExecutor: FakeExecutor
|
||||
private lateinit var testableLooper: TestableLooper
|
||||
private lateinit var settings: FakeSettings
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
testableLooper = TestableLooper.get(this)
|
||||
mainExecutor = FakeExecutor(FakeSystemClock())
|
||||
settings = FakeSettings()
|
||||
`when`(userTracker.userId).thenReturn(START_USER)
|
||||
|
||||
controller = DeviceProvisionedControllerImpl(
|
||||
settings,
|
||||
settings,
|
||||
userTracker,
|
||||
dumpManager,
|
||||
Handler(testableLooper.looper),
|
||||
mainExecutor
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNotProvisionedByDefault() {
|
||||
init()
|
||||
assertThat(controller.isDeviceProvisioned).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNotUserSetupByDefault() {
|
||||
init()
|
||||
assertThat(controller.isUserSetup(START_USER)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testProvisionedWhenCreated() {
|
||||
settings.putInt(Settings.Global.DEVICE_PROVISIONED, 1)
|
||||
init()
|
||||
|
||||
assertThat(controller.isDeviceProvisioned).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUserSetupWhenCreated() {
|
||||
settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
|
||||
init()
|
||||
|
||||
assertThat(controller.isUserSetup(START_USER))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDeviceProvisionedChange() {
|
||||
init()
|
||||
|
||||
settings.putInt(Settings.Global.DEVICE_PROVISIONED, 1)
|
||||
testableLooper.processAllMessages() // background observer
|
||||
|
||||
assertThat(controller.isDeviceProvisioned).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUserSetupChange() {
|
||||
init()
|
||||
|
||||
settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
|
||||
testableLooper.processAllMessages() // background observer
|
||||
|
||||
assertThat(controller.isUserSetup(START_USER)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUserSetupChange_otherUser() {
|
||||
init()
|
||||
val otherUser = 10
|
||||
|
||||
settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, otherUser)
|
||||
testableLooper.processAllMessages() // background observer
|
||||
|
||||
assertThat(controller.isUserSetup(START_USER)).isFalse()
|
||||
assertThat(controller.isUserSetup(otherUser)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCurrentUserSetup() {
|
||||
val otherUser = 10
|
||||
settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, otherUser)
|
||||
init()
|
||||
|
||||
assertThat(controller.isCurrentUserSetup).isFalse()
|
||||
switchUser(otherUser)
|
||||
testableLooper.processAllMessages()
|
||||
|
||||
assertThat(controller.isCurrentUserSetup).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testListenerNotCalledOnAdd() {
|
||||
init()
|
||||
controller.addCallback(listener)
|
||||
|
||||
mainExecutor.runAllReady()
|
||||
|
||||
verify(listener, never()).onDeviceProvisionedChanged()
|
||||
verify(listener, never()).onUserSetupChanged()
|
||||
verify(listener, never()).onUserSwitched()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testListenerCalledOnUserSwitched() {
|
||||
init()
|
||||
controller.addCallback(listener)
|
||||
|
||||
switchUser(10)
|
||||
|
||||
testableLooper.processAllMessages()
|
||||
mainExecutor.runAllReady()
|
||||
|
||||
verify(listener).onUserSwitched()
|
||||
verify(listener, never()).onUserSetupChanged()
|
||||
verify(listener, never()).onDeviceProvisionedChanged()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testListenerCalledOnUserSetupChanged() {
|
||||
init()
|
||||
controller.addCallback(listener)
|
||||
|
||||
settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
|
||||
testableLooper.processAllMessages()
|
||||
mainExecutor.runAllReady()
|
||||
|
||||
verify(listener, never()).onUserSwitched()
|
||||
verify(listener).onUserSetupChanged()
|
||||
verify(listener, never()).onDeviceProvisionedChanged()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testListenerCalledOnDeviceProvisionedChanged() {
|
||||
init()
|
||||
controller.addCallback(listener)
|
||||
|
||||
settings.putInt(Settings.Global.DEVICE_PROVISIONED, 1)
|
||||
testableLooper.processAllMessages()
|
||||
mainExecutor.runAllReady()
|
||||
|
||||
verify(listener, never()).onUserSwitched()
|
||||
verify(listener, never()).onUserSetupChanged()
|
||||
verify(listener).onDeviceProvisionedChanged()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRemoveListener() {
|
||||
init()
|
||||
controller.addCallback(listener)
|
||||
controller.removeCallback(listener)
|
||||
|
||||
switchUser(10)
|
||||
settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
|
||||
settings.putInt(Settings.Global.DEVICE_PROVISIONED, 1)
|
||||
|
||||
testableLooper.processAllMessages()
|
||||
mainExecutor.runAllReady()
|
||||
|
||||
verify(listener, never()).onDeviceProvisionedChanged()
|
||||
verify(listener, never()).onUserSetupChanged()
|
||||
verify(listener, never()).onUserSwitched()
|
||||
}
|
||||
|
||||
private fun init() {
|
||||
controller.init()
|
||||
verify(userTracker).addCallback(capture(userTrackerCallbackCaptor), any())
|
||||
}
|
||||
|
||||
private fun switchUser(toUser: Int) {
|
||||
`when`(userTracker.userId).thenReturn(toUser)
|
||||
userTrackerCallbackCaptor.value.onUserChanged(toUser, mContext)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user