Loading core/java/android/app/admin/DevicePolicyManagerInternal.java +7 −0 Original line number Diff line number Diff line Loading @@ -153,4 +153,11 @@ public abstract class DevicePolicyManagerInternal { * Do not call it directly. Use {@link DevicePolicyCache#getInstance()} instead. */ protected abstract DevicePolicyCache getDevicePolicyCache(); /** * @return cached version of device state related to DPM that can be accessed without risking * deadlocks. * Do not call it directly. Use {@link DevicePolicyCache#getInstance()} instead. */ protected abstract DeviceStateCache getDeviceStateCache(); } core/java/android/app/admin/DeviceStateCache.java 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 android.app.admin; import com.android.server.LocalServices; /** * Stores a copy of the set of device state maintained by {@link DevicePolicyManager} which * is not directly related to admin policies. This lives in its own class so that the state * can be accessed from any place without risking dead locks. * * @hide */ public abstract class DeviceStateCache { protected DeviceStateCache() { } /** * @return the instance. */ public static DeviceStateCache getInstance() { final DevicePolicyManagerInternal dpmi = LocalServices.getService(DevicePolicyManagerInternal.class); return (dpmi != null) ? dpmi.getDeviceStateCache() : EmptyDeviceStateCache.INSTANCE; } /** * See {@link DevicePolicyManager#isDeviceProvisioned} */ public abstract boolean isDeviceProvisioned(); /** * Empty implementation. */ private static class EmptyDeviceStateCache extends DeviceStateCache { private static final EmptyDeviceStateCache INSTANCE = new EmptyDeviceStateCache(); @Override public boolean isDeviceProvisioned() { return false; } } } core/java/android/os/UserManagerInternal.java +10 −0 Original line number Diff line number Diff line Loading @@ -85,12 +85,22 @@ public abstract class UserManagerInternal { */ public abstract void setDeviceManaged(boolean isManaged); /** * Returns whether the device is managed by device owner. */ public abstract boolean isDeviceManaged(); /** * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to update * whether the user is managed by profile owner. */ public abstract void setUserManaged(int userId, boolean isManaged); /** * whether a profile owner manages this user. */ public abstract boolean isUserManaged(int userId); /** * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to omit * restriction check, because DevicePolicyManager must always be able to set user icon Loading services/core/java/com/android/server/locksettings/LockSettingsService.java +54 −42 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.DeviceStateCache; import android.app.admin.PasswordMetrics; import android.app.backup.BackupManager; import android.app.trust.IStrongAuthTracker; Loading Loading @@ -76,6 +77,7 @@ import android.os.StrictMode; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.os.storage.IStorageManager; import android.os.storage.StorageManager; import android.provider.Settings; Loading Loading @@ -429,6 +431,10 @@ public class LockSettingsService extends ILockSettings.Stub { return (UserManager) mContext.getSystemService(Context.USER_SERVICE); } public UserManagerInternal getUserManagerInternal() { return LocalServices.getService(UserManagerInternal.class); } /** * Return the {@link DevicePolicyManager} object. * Loading @@ -440,6 +446,10 @@ public class LockSettingsService extends ILockSettings.Stub { return (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); } public DeviceStateCache getDeviceStateCache() { return DeviceStateCache.getInstance(); } public KeyStore getKeyStore() { return KeyStore.getInstance(); } Loading Loading @@ -1023,11 +1033,16 @@ public class LockSettingsService extends ILockSettings.Stub { } private void notifySeparateProfileChallengeChanged(int userId) { // LSS cannot call into DPM directly, otherwise it will cause deadlock. // In this case, calling DPM on a handler thread is OK since DPM doesn't // expect reportSeparateProfileChallengeChanged() to happen synchronously. mHandler.post(() -> { final DevicePolicyManagerInternal dpmi = LocalServices.getService( DevicePolicyManagerInternal.class); if (dpmi != null) { dpmi.reportSeparateProfileChallengeChanged(userId); } }); } @Override Loading Loading @@ -2038,7 +2053,6 @@ public class LockSettingsService extends ILockSettings.Stub { * reporting the password changed. */ private void notifyPasswordChanged(@UserIdInt int userId) { // Same handler as notifyActivePasswordMetricsAvailable to ensure correct ordering mHandler.post(() -> { mInjector.getDevicePolicyManager().reportPasswordChanged(userId); LocalServices.getService(WindowManagerInternal.class).reportPasswordChanged(userId); Loading Loading @@ -3026,29 +3040,30 @@ public class LockSettingsService extends ILockSettings.Stub { pw.decreaseIndent(); } /** * Cryptographically disable escrow token support for the current user, if the user is not * managed (either user has a profile owner, or if device is managed). Do not disable * if we are running an automotive build. */ private void disableEscrowTokenOnNonManagedDevicesIfNeeded(int userId) { long ident = Binder.clearCallingIdentity(); try { final UserManagerInternal userManagerInternal = mInjector.getUserManagerInternal(); // Managed profile should have escrow enabled if (mUserManager.getUserInfo(userId).isManagedProfile()) { if (userManagerInternal.isUserManaged(userId)) { Slog.i(TAG, "Managed profile can have escrow token"); return; } DevicePolicyManager dpm = mInjector.getDevicePolicyManager(); // Devices with Device Owner should have escrow enabled on all users. if (dpm.getDeviceOwnerComponentOnAnyUser() != null) { if (userManagerInternal.isDeviceManaged()) { Slog.i(TAG, "Corp-owned device can have escrow token"); return; } // We could also have a profile owner on the given (non-managed) user for unicorn cases if (dpm.getProfileOwnerAsUser(userId) != null) { Slog.i(TAG, "User with profile owner can have escrow token"); return; } // If the device is yet to be provisioned (still in SUW), there is still // a chance that Device Owner will be set on the device later, so postpone // disabling escrow token for now. if (!dpm.isDeviceProvisioned()) { if (!mInjector.getDeviceStateCache().isDeviceProvisioned()) { Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned"); return; } Loading @@ -3063,9 +3078,6 @@ public class LockSettingsService extends ILockSettings.Stub { if (isSyntheticPasswordBasedCredentialLocked(userId)) { mSpManager.destroyEscrowData(userId); } } finally { Binder.restoreCallingIdentity(ident); } } private class DeviceProvisionedObserver extends ContentObserver { Loading services/core/java/com/android/server/pm/UserManagerService.java +15 −0 Original line number Diff line number Diff line Loading @@ -3978,6 +3978,13 @@ public class UserManagerService extends IUserManager.Stub { } } @Override public boolean isDeviceManaged() { synchronized (mUsersLock) { return mIsDeviceManaged; } } @Override public void setUserManaged(@UserIdInt int userId, boolean isManaged) { synchronized (mUsersLock) { Loading @@ -3985,6 +3992,13 @@ public class UserManagerService extends IUserManager.Stub { } } @Override public boolean isUserManaged(@UserIdInt int userId) { synchronized (mUsersLock) { return mIsUserManaged.get(userId); } } @Override public void setUserIcon(@UserIdInt int userId, Bitmap bitmap) { long ident = Binder.clearCallingIdentity(); Loading Loading @@ -4205,6 +4219,7 @@ public class UserManagerService extends IUserManager.Stub { return restrictions != null && restrictions.getBoolean(restrictionKey); } @Override public @Nullable UserInfo getUserInfo(@UserIdInt int userId) { UserData userData; synchronized (mUsersLock) { Loading Loading
core/java/android/app/admin/DevicePolicyManagerInternal.java +7 −0 Original line number Diff line number Diff line Loading @@ -153,4 +153,11 @@ public abstract class DevicePolicyManagerInternal { * Do not call it directly. Use {@link DevicePolicyCache#getInstance()} instead. */ protected abstract DevicePolicyCache getDevicePolicyCache(); /** * @return cached version of device state related to DPM that can be accessed without risking * deadlocks. * Do not call it directly. Use {@link DevicePolicyCache#getInstance()} instead. */ protected abstract DeviceStateCache getDeviceStateCache(); }
core/java/android/app/admin/DeviceStateCache.java 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 android.app.admin; import com.android.server.LocalServices; /** * Stores a copy of the set of device state maintained by {@link DevicePolicyManager} which * is not directly related to admin policies. This lives in its own class so that the state * can be accessed from any place without risking dead locks. * * @hide */ public abstract class DeviceStateCache { protected DeviceStateCache() { } /** * @return the instance. */ public static DeviceStateCache getInstance() { final DevicePolicyManagerInternal dpmi = LocalServices.getService(DevicePolicyManagerInternal.class); return (dpmi != null) ? dpmi.getDeviceStateCache() : EmptyDeviceStateCache.INSTANCE; } /** * See {@link DevicePolicyManager#isDeviceProvisioned} */ public abstract boolean isDeviceProvisioned(); /** * Empty implementation. */ private static class EmptyDeviceStateCache extends DeviceStateCache { private static final EmptyDeviceStateCache INSTANCE = new EmptyDeviceStateCache(); @Override public boolean isDeviceProvisioned() { return false; } } }
core/java/android/os/UserManagerInternal.java +10 −0 Original line number Diff line number Diff line Loading @@ -85,12 +85,22 @@ public abstract class UserManagerInternal { */ public abstract void setDeviceManaged(boolean isManaged); /** * Returns whether the device is managed by device owner. */ public abstract boolean isDeviceManaged(); /** * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to update * whether the user is managed by profile owner. */ public abstract void setUserManaged(int userId, boolean isManaged); /** * whether a profile owner manages this user. */ public abstract boolean isUserManaged(int userId); /** * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to omit * restriction check, because DevicePolicyManager must always be able to set user icon Loading
services/core/java/com/android/server/locksettings/LockSettingsService.java +54 −42 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.DeviceStateCache; import android.app.admin.PasswordMetrics; import android.app.backup.BackupManager; import android.app.trust.IStrongAuthTracker; Loading Loading @@ -76,6 +77,7 @@ import android.os.StrictMode; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.os.storage.IStorageManager; import android.os.storage.StorageManager; import android.provider.Settings; Loading Loading @@ -429,6 +431,10 @@ public class LockSettingsService extends ILockSettings.Stub { return (UserManager) mContext.getSystemService(Context.USER_SERVICE); } public UserManagerInternal getUserManagerInternal() { return LocalServices.getService(UserManagerInternal.class); } /** * Return the {@link DevicePolicyManager} object. * Loading @@ -440,6 +446,10 @@ public class LockSettingsService extends ILockSettings.Stub { return (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); } public DeviceStateCache getDeviceStateCache() { return DeviceStateCache.getInstance(); } public KeyStore getKeyStore() { return KeyStore.getInstance(); } Loading Loading @@ -1023,11 +1033,16 @@ public class LockSettingsService extends ILockSettings.Stub { } private void notifySeparateProfileChallengeChanged(int userId) { // LSS cannot call into DPM directly, otherwise it will cause deadlock. // In this case, calling DPM on a handler thread is OK since DPM doesn't // expect reportSeparateProfileChallengeChanged() to happen synchronously. mHandler.post(() -> { final DevicePolicyManagerInternal dpmi = LocalServices.getService( DevicePolicyManagerInternal.class); if (dpmi != null) { dpmi.reportSeparateProfileChallengeChanged(userId); } }); } @Override Loading Loading @@ -2038,7 +2053,6 @@ public class LockSettingsService extends ILockSettings.Stub { * reporting the password changed. */ private void notifyPasswordChanged(@UserIdInt int userId) { // Same handler as notifyActivePasswordMetricsAvailable to ensure correct ordering mHandler.post(() -> { mInjector.getDevicePolicyManager().reportPasswordChanged(userId); LocalServices.getService(WindowManagerInternal.class).reportPasswordChanged(userId); Loading Loading @@ -3026,29 +3040,30 @@ public class LockSettingsService extends ILockSettings.Stub { pw.decreaseIndent(); } /** * Cryptographically disable escrow token support for the current user, if the user is not * managed (either user has a profile owner, or if device is managed). Do not disable * if we are running an automotive build. */ private void disableEscrowTokenOnNonManagedDevicesIfNeeded(int userId) { long ident = Binder.clearCallingIdentity(); try { final UserManagerInternal userManagerInternal = mInjector.getUserManagerInternal(); // Managed profile should have escrow enabled if (mUserManager.getUserInfo(userId).isManagedProfile()) { if (userManagerInternal.isUserManaged(userId)) { Slog.i(TAG, "Managed profile can have escrow token"); return; } DevicePolicyManager dpm = mInjector.getDevicePolicyManager(); // Devices with Device Owner should have escrow enabled on all users. if (dpm.getDeviceOwnerComponentOnAnyUser() != null) { if (userManagerInternal.isDeviceManaged()) { Slog.i(TAG, "Corp-owned device can have escrow token"); return; } // We could also have a profile owner on the given (non-managed) user for unicorn cases if (dpm.getProfileOwnerAsUser(userId) != null) { Slog.i(TAG, "User with profile owner can have escrow token"); return; } // If the device is yet to be provisioned (still in SUW), there is still // a chance that Device Owner will be set on the device later, so postpone // disabling escrow token for now. if (!dpm.isDeviceProvisioned()) { if (!mInjector.getDeviceStateCache().isDeviceProvisioned()) { Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned"); return; } Loading @@ -3063,9 +3078,6 @@ public class LockSettingsService extends ILockSettings.Stub { if (isSyntheticPasswordBasedCredentialLocked(userId)) { mSpManager.destroyEscrowData(userId); } } finally { Binder.restoreCallingIdentity(ident); } } private class DeviceProvisionedObserver extends ContentObserver { Loading
services/core/java/com/android/server/pm/UserManagerService.java +15 −0 Original line number Diff line number Diff line Loading @@ -3978,6 +3978,13 @@ public class UserManagerService extends IUserManager.Stub { } } @Override public boolean isDeviceManaged() { synchronized (mUsersLock) { return mIsDeviceManaged; } } @Override public void setUserManaged(@UserIdInt int userId, boolean isManaged) { synchronized (mUsersLock) { Loading @@ -3985,6 +3992,13 @@ public class UserManagerService extends IUserManager.Stub { } } @Override public boolean isUserManaged(@UserIdInt int userId) { synchronized (mUsersLock) { return mIsUserManaged.get(userId); } } @Override public void setUserIcon(@UserIdInt int userId, Bitmap bitmap) { long ident = Binder.clearCallingIdentity(); Loading Loading @@ -4205,6 +4219,7 @@ public class UserManagerService extends IUserManager.Stub { return restrictions != null && restrictions.getBoolean(restrictionKey); } @Override public @Nullable UserInfo getUserInfo(@UserIdInt int userId) { UserData userData; synchronized (mUsersLock) { Loading