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);
|
return new Recents(context, recentsImplementation, commandQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Binds
|
@SysUISingleton
|
||||||
abstract DeviceProvisionedController bindDeviceProvisionedController(
|
@Provides
|
||||||
DeviceProvisionedControllerImpl deviceProvisionedController);
|
static DeviceProvisionedController bindDeviceProvisionedController(
|
||||||
|
DeviceProvisionedControllerImpl deviceProvisionedController) {
|
||||||
|
deviceProvisionedController.init();
|
||||||
|
return deviceProvisionedController;
|
||||||
|
}
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract KeyguardViewController bindKeyguardViewController(
|
abstract KeyguardViewController bindKeyguardViewController(
|
||||||
|
|||||||
@@ -332,8 +332,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
|||||||
deviceProvisionedController.addCallback(new DeviceProvisionedListener() {
|
deviceProvisionedController.addCallback(new DeviceProvisionedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onUserSetupChanged() {
|
public void onUserSetupChanged() {
|
||||||
setUserSetupComplete(deviceProvisionedController.isUserSetup(
|
setUserSetupComplete(deviceProvisionedController.isCurrentUserSetup());
|
||||||
deviceProvisionedController.getCurrentUser()));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -604,8 +604,7 @@ public class PhoneStatusBarPolicy
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUserSetupChanged() {
|
public void onUserSetupChanged() {
|
||||||
boolean userSetup = mProvisionedController.isUserSetup(
|
boolean userSetup = mProvisionedController.isCurrentUserSetup();
|
||||||
mProvisionedController.getCurrentUser());
|
|
||||||
if (mCurrentUserSetup == userSetup) return;
|
if (mCurrentUserSetup == userSetup) return;
|
||||||
mCurrentUserSetup = userSetup;
|
mCurrentUserSetup = userSetup;
|
||||||
updateAlarm();
|
updateAlarm();
|
||||||
|
|||||||
@@ -4340,10 +4340,9 @@ public class StatusBar extends SystemUI implements
|
|||||||
private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() {
|
private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onUserSetupChanged() {
|
public void onUserSetupChanged() {
|
||||||
final boolean userSetup = mDeviceProvisionedController.isUserSetup(
|
final boolean userSetup = mDeviceProvisionedController.isCurrentUserSetup();
|
||||||
mDeviceProvisionedController.getCurrentUser());
|
Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for "
|
||||||
Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for user "
|
+ "current user");
|
||||||
+ mDeviceProvisionedController.getCurrentUser());
|
|
||||||
if (MULTIUSER_DEBUG) {
|
if (MULTIUSER_DEBUG) {
|
||||||
Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s",
|
Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s",
|
||||||
userSetup, mUserSetup));
|
userSetup, mUserSetup));
|
||||||
|
|||||||
@@ -14,23 +14,60 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.policy;
|
package com.android.systemui.statusbar.policy;
|
||||||
|
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
|
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> {
|
public interface DeviceProvisionedController extends CallbackController<DeviceProvisionedListener> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether the device is provisioned
|
||||||
|
* @see Settings.Global#DEVICE_PROVISIONED
|
||||||
|
*/
|
||||||
boolean isDeviceProvisioned();
|
boolean isDeviceProvisioned();
|
||||||
boolean isUserSetup(int currentUser);
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link com.android.systemui.settings.UserTracker}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
int getCurrentUser();
|
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 {
|
interface DeviceProvisionedListener {
|
||||||
|
/**
|
||||||
|
* Call when the device changes from not provisioned to provisioned
|
||||||
|
*/
|
||||||
default void onDeviceProvisionedChanged() { }
|
default void onDeviceProvisionedChanged() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call on user switched
|
||||||
|
*/
|
||||||
default void onUserSwitched() {
|
default void onUserSwitched() {
|
||||||
onUserSetupChanged();
|
onUserSetupChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call when some user changes from not provisioned to provisioned
|
||||||
|
*/
|
||||||
default void onUserSetupChanged() { }
|
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);
|
return new Recents(context, recentsImplementation, commandQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Binds
|
@SysUISingleton
|
||||||
abstract DeviceProvisionedController bindDeviceProvisionedController(
|
@Provides
|
||||||
DeviceProvisionedControllerImpl deviceProvisionedController);
|
static DeviceProvisionedController providesDeviceProvisionedController(
|
||||||
|
DeviceProvisionedControllerImpl deviceProvisionedController) {
|
||||||
|
deviceProvisionedController.init();
|
||||||
|
return deviceProvisionedController;
|
||||||
|
}
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract KeyguardViewController bindKeyguardViewController(
|
abstract KeyguardViewController bindKeyguardViewController(
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
|
|||||||
mCallbackHandler = mock(CallbackHandler.class);
|
mCallbackHandler = mock(CallbackHandler.class);
|
||||||
|
|
||||||
mMockProvisionController = mock(DeviceProvisionedController.class);
|
mMockProvisionController = mock(DeviceProvisionedController.class);
|
||||||
when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(true);
|
when(mMockProvisionController.isCurrentUserSetup()).thenReturn(true);
|
||||||
doAnswer(invocation -> {
|
doAnswer(invocation -> {
|
||||||
mUserCallback = (DeviceProvisionedListener) invocation.getArguments()[0];
|
mUserCallback = (DeviceProvisionedListener) invocation.getArguments()[0];
|
||||||
mUserCallback.onUserSetupChanged();
|
mUserCallback.onUserSetupChanged();
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
|
|||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Matchers.anyInt;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@@ -211,7 +210,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
|
|||||||
updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
|
updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
|
||||||
setConnectivityViaCallbackInNetworkController(
|
setConnectivityViaCallbackInNetworkController(
|
||||||
NetworkCapabilities.TRANSPORT_CELLULAR, false, false, null);
|
NetworkCapabilities.TRANSPORT_CELLULAR, false, false, null);
|
||||||
when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(false);
|
when(mMockProvisionController.isCurrentUserSetup()).thenReturn(false);
|
||||||
mUserCallback.onUserSetupChanged();
|
mUserCallback.onUserSetupChanged();
|
||||||
TestableLooper.get(this).processAllMessages();
|
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