diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index e7cea570ae5de..8fb6948e332e7 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -413,6 +413,13 @@ public final class PendingIntent implements Parcelable { */ public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags) { + return getBroadcastAsUser(context, requestCode, intent, flags, + new UserHandle(UserHandle.myUserId())); + } + + /** @hide */ + public static PendingIntent getBroadcastAsUser(Context context, int requestCode, + Intent intent, int flags, UserHandle userHandle) { String packageName = context.getPackageName(); String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null; @@ -423,7 +430,7 @@ public final class PendingIntent implements Parcelable { ActivityManager.INTENT_SENDER_BROADCAST, packageName, null, null, requestCode, new Intent[] { intent }, resolvedType != null ? new String[] { resolvedType } : null, - flags, null, UserHandle.myUserId()); + flags, null, userHandle.getIdentifier()); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 4c55bb3be9498..600d02a174b72 100755 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -29,6 +29,7 @@ import android.os.Handler; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.util.Log; import java.io.IOException; @@ -131,7 +132,7 @@ public class DevicePolicyManager { public boolean isAdminActive(ComponentName who) { if (mService != null) { try { - return mService.isAdminActive(who); + return mService.isAdminActive(who, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -147,7 +148,7 @@ public class DevicePolicyManager { public List getActiveAdmins() { if (mService != null) { try { - return mService.getActiveAdmins(); + return mService.getActiveAdmins(UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -156,12 +157,14 @@ public class DevicePolicyManager { } /** + * Used by package administration code to determine if a package can be stopped + * or uninstalled. * @hide */ public boolean packageHasActiveAdmins(String packageName) { if (mService != null) { try { - return mService.packageHasActiveAdmins(packageName); + return mService.packageHasActiveAdmins(packageName, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -178,7 +181,7 @@ public class DevicePolicyManager { public void removeActiveAdmin(ComponentName who) { if (mService != null) { try { - mService.removeActiveAdmin(who); + mService.removeActiveAdmin(who, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -197,7 +200,7 @@ public class DevicePolicyManager { public boolean hasGrantedPolicy(ComponentName admin, int usesPolicy) { if (mService != null) { try { - return mService.hasGrantedPolicy(admin, usesPolicy); + return mService.hasGrantedPolicy(admin, usesPolicy, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -289,7 +292,7 @@ public class DevicePolicyManager { public void setPasswordQuality(ComponentName admin, int quality) { if (mService != null) { try { - mService.setPasswordQuality(admin, quality); + mService.setPasswordQuality(admin, quality, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -303,9 +306,14 @@ public class DevicePolicyManager { * all admins. */ public int getPasswordQuality(ComponentName admin) { + return getPasswordQuality(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getPasswordQuality(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getPasswordQuality(admin); + return mService.getPasswordQuality(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -337,7 +345,7 @@ public class DevicePolicyManager { public void setPasswordMinimumLength(ComponentName admin, int length) { if (mService != null) { try { - mService.setPasswordMinimumLength(admin, length); + mService.setPasswordMinimumLength(admin, length, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -351,9 +359,14 @@ public class DevicePolicyManager { * all admins. */ public int getPasswordMinimumLength(ComponentName admin) { + return getPasswordMinimumLength(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getPasswordMinimumLength(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getPasswordMinimumLength(admin); + return mService.getPasswordMinimumLength(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -386,7 +399,7 @@ public class DevicePolicyManager { public void setPasswordMinimumUpperCase(ComponentName admin, int length) { if (mService != null) { try { - mService.setPasswordMinimumUpperCase(admin, length); + mService.setPasswordMinimumUpperCase(admin, length, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -406,9 +419,14 @@ public class DevicePolicyManager { * password. */ public int getPasswordMinimumUpperCase(ComponentName admin) { + return getPasswordMinimumUpperCase(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getPasswordMinimumUpperCase(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getPasswordMinimumUpperCase(admin); + return mService.getPasswordMinimumUpperCase(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -441,7 +459,7 @@ public class DevicePolicyManager { public void setPasswordMinimumLowerCase(ComponentName admin, int length) { if (mService != null) { try { - mService.setPasswordMinimumLowerCase(admin, length); + mService.setPasswordMinimumLowerCase(admin, length, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -461,9 +479,14 @@ public class DevicePolicyManager { * password. */ public int getPasswordMinimumLowerCase(ComponentName admin) { + return getPasswordMinimumLowerCase(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getPasswordMinimumLowerCase(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getPasswordMinimumLowerCase(admin); + return mService.getPasswordMinimumLowerCase(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -495,7 +518,7 @@ public class DevicePolicyManager { public void setPasswordMinimumLetters(ComponentName admin, int length) { if (mService != null) { try { - mService.setPasswordMinimumLetters(admin, length); + mService.setPasswordMinimumLetters(admin, length, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -514,9 +537,14 @@ public class DevicePolicyManager { * @return The minimum number of letters required in the password. */ public int getPasswordMinimumLetters(ComponentName admin) { + return getPasswordMinimumLetters(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getPasswordMinimumLetters(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getPasswordMinimumLetters(admin); + return mService.getPasswordMinimumLetters(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -548,7 +576,7 @@ public class DevicePolicyManager { public void setPasswordMinimumNumeric(ComponentName admin, int length) { if (mService != null) { try { - mService.setPasswordMinimumNumeric(admin, length); + mService.setPasswordMinimumNumeric(admin, length, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -567,9 +595,14 @@ public class DevicePolicyManager { * @return The minimum number of numerical digits required in the password. */ public int getPasswordMinimumNumeric(ComponentName admin) { + return getPasswordMinimumNumeric(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getPasswordMinimumNumeric(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getPasswordMinimumNumeric(admin); + return mService.getPasswordMinimumNumeric(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -601,7 +634,7 @@ public class DevicePolicyManager { public void setPasswordMinimumSymbols(ComponentName admin, int length) { if (mService != null) { try { - mService.setPasswordMinimumSymbols(admin, length); + mService.setPasswordMinimumSymbols(admin, length, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -620,9 +653,14 @@ public class DevicePolicyManager { * @return The minimum number of symbols required in the password. */ public int getPasswordMinimumSymbols(ComponentName admin) { + return getPasswordMinimumSymbols(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getPasswordMinimumSymbols(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getPasswordMinimumSymbols(admin); + return mService.getPasswordMinimumSymbols(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -654,7 +692,7 @@ public class DevicePolicyManager { public void setPasswordMinimumNonLetter(ComponentName admin, int length) { if (mService != null) { try { - mService.setPasswordMinimumNonLetter(admin, length); + mService.setPasswordMinimumNonLetter(admin, length, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -673,9 +711,14 @@ public class DevicePolicyManager { * @return The minimum number of letters required in the password. */ public int getPasswordMinimumNonLetter(ComponentName admin) { + return getPasswordMinimumNonLetter(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getPasswordMinimumNonLetter(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getPasswordMinimumNonLetter(admin); + return mService.getPasswordMinimumNonLetter(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -708,7 +751,7 @@ public class DevicePolicyManager { public void setPasswordHistoryLength(ComponentName admin, int length) { if (mService != null) { try { - mService.setPasswordHistoryLength(admin, length); + mService.setPasswordHistoryLength(admin, length, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -737,7 +780,7 @@ public class DevicePolicyManager { public void setPasswordExpirationTimeout(ComponentName admin, long timeout) { if (mService != null) { try { - mService.setPasswordExpirationTimeout(admin, timeout); + mService.setPasswordExpirationTimeout(admin, timeout, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -756,7 +799,7 @@ public class DevicePolicyManager { public long getPasswordExpirationTimeout(ComponentName admin) { if (mService != null) { try { - return mService.getPasswordExpirationTimeout(admin); + return mService.getPasswordExpirationTimeout(admin, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -776,7 +819,7 @@ public class DevicePolicyManager { public long getPasswordExpiration(ComponentName admin) { if (mService != null) { try { - return mService.getPasswordExpiration(admin); + return mService.getPasswordExpiration(admin, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -792,9 +835,14 @@ public class DevicePolicyManager { * @return The length of the password history */ public int getPasswordHistoryLength(ComponentName admin) { + return getPasswordHistoryLength(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getPasswordHistoryLength(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getPasswordHistoryLength(admin); + return mService.getPasswordHistoryLength(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -828,7 +876,7 @@ public class DevicePolicyManager { public boolean isActivePasswordSufficient() { if (mService != null) { try { - return mService.isActivePasswordSufficient(); + return mService.isActivePasswordSufficient(UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -847,7 +895,7 @@ public class DevicePolicyManager { public int getCurrentFailedPasswordAttempts() { if (mService != null) { try { - return mService.getCurrentFailedPasswordAttempts(); + return mService.getCurrentFailedPasswordAttempts(UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -877,7 +925,7 @@ public class DevicePolicyManager { public void setMaximumFailedPasswordsForWipe(ComponentName admin, int num) { if (mService != null) { try { - mService.setMaximumFailedPasswordsForWipe(admin, num); + mService.setMaximumFailedPasswordsForWipe(admin, num, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -892,9 +940,14 @@ public class DevicePolicyManager { * all admins. */ public int getMaximumFailedPasswordsForWipe(ComponentName admin) { + return getMaximumFailedPasswordsForWipe(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getMaximumFailedPasswordsForWipe(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getMaximumFailedPasswordsForWipe(admin); + return mService.getMaximumFailedPasswordsForWipe(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -933,7 +986,7 @@ public class DevicePolicyManager { public boolean resetPassword(String password, int flags) { if (mService != null) { try { - return mService.resetPassword(password, flags); + return mService.resetPassword(password, flags, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -957,7 +1010,7 @@ public class DevicePolicyManager { public void setMaximumTimeToLock(ComponentName admin, long timeMs) { if (mService != null) { try { - mService.setMaximumTimeToLock(admin, timeMs); + mService.setMaximumTimeToLock(admin, timeMs, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -971,9 +1024,14 @@ public class DevicePolicyManager { * all admins. */ public long getMaximumTimeToLock(ComponentName admin) { + return getMaximumTimeToLock(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public long getMaximumTimeToLock(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getMaximumTimeToLock(admin); + return mService.getMaximumTimeToLock(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1021,7 +1079,7 @@ public class DevicePolicyManager { public void wipeData(int flags) { if (mService != null) { try { - mService.wipeData(flags); + mService.wipeData(flags, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1090,7 +1148,7 @@ public class DevicePolicyManager { } android.net.Proxy.validate(hostName, Integer.toString(port), exclSpec); } - return mService.setGlobalProxy(admin, hostSpec, exclSpec); + return mService.setGlobalProxy(admin, hostSpec, exclSpec, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1107,7 +1165,7 @@ public class DevicePolicyManager { public ComponentName getGlobalProxyAdmin() { if (mService != null) { try { - return mService.getGlobalProxyAdmin(); + return mService.getGlobalProxyAdmin(UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1199,7 +1257,7 @@ public class DevicePolicyManager { public int setStorageEncryption(ComponentName admin, boolean encrypt) { if (mService != null) { try { - return mService.setStorageEncryption(admin, encrypt); + return mService.setStorageEncryption(admin, encrypt, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1219,7 +1277,7 @@ public class DevicePolicyManager { public boolean getStorageEncryption(ComponentName admin) { if (mService != null) { try { - return mService.getStorageEncryption(admin); + return mService.getStorageEncryption(admin, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1244,9 +1302,14 @@ public class DevicePolicyManager { * {@link #ENCRYPTION_STATUS_ACTIVATING}, or{@link #ENCRYPTION_STATUS_ACTIVE}. */ public int getStorageEncryptionStatus() { + return getStorageEncryptionStatus(UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getStorageEncryptionStatus(int userHandle) { if (mService != null) { try { - return mService.getStorageEncryptionStatus(); + return mService.getStorageEncryptionStatus(userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1269,7 +1332,7 @@ public class DevicePolicyManager { public void setCameraDisabled(ComponentName admin, boolean disabled) { if (mService != null) { try { - mService.setCameraDisabled(admin, disabled); + mService.setCameraDisabled(admin, disabled, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1283,9 +1346,14 @@ public class DevicePolicyManager { * have disabled the camera */ public boolean getCameraDisabled(ComponentName admin) { + return getCameraDisabled(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public boolean getCameraDisabled(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getCameraDisabled(admin); + return mService.getCameraDisabled(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1309,7 +1377,7 @@ public class DevicePolicyManager { public void setKeyguardWidgetsDisabled(ComponentName admin, int which) { if (mService != null) { try { - mService.setKeyguardWidgetsDisabled(admin, which); + mService.setKeyguardWidgetsDisabled(admin, which, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1323,9 +1391,14 @@ public class DevicePolicyManager { * have disabled widgets in keyguard. */ public int getKeyguardWidgetsDisabled(ComponentName admin) { + return getKeyguardWidgetsDisabled(admin, UserHandle.myUserId()); + } + + /** @hide per-user version */ + public int getKeyguardWidgetsDisabled(ComponentName admin, int userHandle) { if (mService != null) { try { - return mService.getKeyguardWidgetsDisabled(admin); + return mService.getKeyguardWidgetsDisabled(admin, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1339,7 +1412,7 @@ public class DevicePolicyManager { public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) { if (mService != null) { try { - mService.setActiveAdmin(policyReceiver, refreshing); + mService.setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1380,7 +1453,7 @@ public class DevicePolicyManager { public void getRemoveWarning(ComponentName admin, RemoteCallback result) { if (mService != null) { try { - mService.getRemoveWarning(admin, result); + mService.getRemoveWarning(admin, result, UserHandle.myUserId()); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1391,11 +1464,11 @@ public class DevicePolicyManager { * @hide */ public void setActivePasswordState(int quality, int length, int letters, int uppercase, - int lowercase, int numbers, int symbols, int nonletter) { + int lowercase, int numbers, int symbols, int nonletter, int userHandle) { if (mService != null) { try { mService.setActivePasswordState(quality, length, letters, uppercase, lowercase, - numbers, symbols, nonletter); + numbers, symbols, nonletter, userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1405,10 +1478,10 @@ public class DevicePolicyManager { /** * @hide */ - public void reportFailedPasswordAttempt() { + public void reportFailedPasswordAttempt(int userHandle) { if (mService != null) { try { - mService.reportFailedPasswordAttempt(); + mService.reportFailedPasswordAttempt(userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1418,14 +1491,13 @@ public class DevicePolicyManager { /** * @hide */ - public void reportSuccessfulPasswordAttempt() { + public void reportSuccessfulPasswordAttempt(int userHandle) { if (mService != null) { try { - mService.reportSuccessfulPasswordAttempt(); + mService.reportSuccessfulPasswordAttempt(userHandle); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } } } - } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 0b7ec1229e187..bdfb177acb533 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -25,76 +25,76 @@ import android.os.RemoteCallback; * {@hide} */ interface IDevicePolicyManager { - void setPasswordQuality(in ComponentName who, int quality); - int getPasswordQuality(in ComponentName who); + void setPasswordQuality(in ComponentName who, int quality, int userHandle); + int getPasswordQuality(in ComponentName who, int userHandle); - void setPasswordMinimumLength(in ComponentName who, int length); - int getPasswordMinimumLength(in ComponentName who); + void setPasswordMinimumLength(in ComponentName who, int length, int userHandle); + int getPasswordMinimumLength(in ComponentName who, int userHandle); - void setPasswordMinimumUpperCase(in ComponentName who, int length); - int getPasswordMinimumUpperCase(in ComponentName who); + void setPasswordMinimumUpperCase(in ComponentName who, int length, int userHandle); + int getPasswordMinimumUpperCase(in ComponentName who, int userHandle); - void setPasswordMinimumLowerCase(in ComponentName who, int length); - int getPasswordMinimumLowerCase(in ComponentName who); + void setPasswordMinimumLowerCase(in ComponentName who, int length, int userHandle); + int getPasswordMinimumLowerCase(in ComponentName who, int userHandle); - void setPasswordMinimumLetters(in ComponentName who, int length); - int getPasswordMinimumLetters(in ComponentName who); + void setPasswordMinimumLetters(in ComponentName who, int length, int userHandle); + int getPasswordMinimumLetters(in ComponentName who, int userHandle); - void setPasswordMinimumNumeric(in ComponentName who, int length); - int getPasswordMinimumNumeric(in ComponentName who); + void setPasswordMinimumNumeric(in ComponentName who, int length, int userHandle); + int getPasswordMinimumNumeric(in ComponentName who, int userHandle); - void setPasswordMinimumSymbols(in ComponentName who, int length); - int getPasswordMinimumSymbols(in ComponentName who); + void setPasswordMinimumSymbols(in ComponentName who, int length, int userHandle); + int getPasswordMinimumSymbols(in ComponentName who, int userHandle); - void setPasswordMinimumNonLetter(in ComponentName who, int length); - int getPasswordMinimumNonLetter(in ComponentName who); + void setPasswordMinimumNonLetter(in ComponentName who, int length, int userHandle); + int getPasswordMinimumNonLetter(in ComponentName who, int userHandle); - void setPasswordHistoryLength(in ComponentName who, int length); - int getPasswordHistoryLength(in ComponentName who); + void setPasswordHistoryLength(in ComponentName who, int length, int userHandle); + int getPasswordHistoryLength(in ComponentName who, int userHandle); - void setPasswordExpirationTimeout(in ComponentName who, long expiration); - long getPasswordExpirationTimeout(in ComponentName who); + void setPasswordExpirationTimeout(in ComponentName who, long expiration, int userHandle); + long getPasswordExpirationTimeout(in ComponentName who, int userHandle); - long getPasswordExpiration(in ComponentName who); + long getPasswordExpiration(in ComponentName who, int userHandle); - boolean isActivePasswordSufficient(); - int getCurrentFailedPasswordAttempts(); + boolean isActivePasswordSufficient(int userHandle); + int getCurrentFailedPasswordAttempts(int userHandle); - void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num); - int getMaximumFailedPasswordsForWipe(in ComponentName admin); + void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num, int userHandle); + int getMaximumFailedPasswordsForWipe(in ComponentName admin, int userHandle); - boolean resetPassword(String password, int flags); + boolean resetPassword(String password, int flags, int userHandle); - void setMaximumTimeToLock(in ComponentName who, long timeMs); - long getMaximumTimeToLock(in ComponentName who); + void setMaximumTimeToLock(in ComponentName who, long timeMs, int userHandle); + long getMaximumTimeToLock(in ComponentName who, int userHandle); void lockNow(); - void wipeData(int flags); + void wipeData(int flags, int userHandle); - ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList); - ComponentName getGlobalProxyAdmin(); + ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList, int userHandle); + ComponentName getGlobalProxyAdmin(int userHandle); - int setStorageEncryption(in ComponentName who, boolean encrypt); - boolean getStorageEncryption(in ComponentName who); - int getStorageEncryptionStatus(); + int setStorageEncryption(in ComponentName who, boolean encrypt, int userHandle); + boolean getStorageEncryption(in ComponentName who, int userHandle); + int getStorageEncryptionStatus(int userHandle); - void setCameraDisabled(in ComponentName who, boolean disabled); - boolean getCameraDisabled(in ComponentName who); + void setCameraDisabled(in ComponentName who, boolean disabled, int userHandle); + boolean getCameraDisabled(in ComponentName who, int userHandle); - void setKeyguardWidgetsDisabled(in ComponentName who, int which); - int getKeyguardWidgetsDisabled(in ComponentName who); + void setKeyguardWidgetsDisabled(in ComponentName who, int which, int userHandle); + int getKeyguardWidgetsDisabled(in ComponentName who, int userHandle); - void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing); - boolean isAdminActive(in ComponentName policyReceiver); - List getActiveAdmins(); - boolean packageHasActiveAdmins(String packageName); - void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result); - void removeActiveAdmin(in ComponentName policyReceiver); - boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy); + void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing, int userHandle); + boolean isAdminActive(in ComponentName policyReceiver, int userHandle); + List getActiveAdmins(int userHandle); + boolean packageHasActiveAdmins(String packageName, int userHandle); + void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result, int userHandle); + void removeActiveAdmin(in ComponentName policyReceiver, int userHandle); + boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy, int userHandle); void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, - int numbers, int symbols, int nonletter); - void reportFailedPasswordAttempt(); - void reportSuccessfulPasswordAttempt(); + int numbers, int symbols, int nonletter, int userHandle); + void reportFailedPasswordAttempt(int userHandle); + void reportSuccessfulPasswordAttempt(int userHandle); } diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 0710d96ff2535..3207435d8bf9b 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -165,7 +165,7 @@ public class LockPatternUtils { } public int getRequestedMinimumPasswordLength() { - return getDevicePolicyManager().getPasswordMinimumLength(null); + return getDevicePolicyManager().getPasswordMinimumLength(null, getCurrentOrCallingUserId()); } /** @@ -173,47 +173,54 @@ public class LockPatternUtils { * MODE_PATTERN which allows the user to choose anything. */ public int getRequestedPasswordQuality() { - return getDevicePolicyManager().getPasswordQuality(null); + return getDevicePolicyManager().getPasswordQuality(null, getCurrentOrCallingUserId()); } public int getRequestedPasswordHistoryLength() { - return getDevicePolicyManager().getPasswordHistoryLength(null); + return getDevicePolicyManager().getPasswordHistoryLength(null, getCurrentOrCallingUserId()); } public int getRequestedPasswordMinimumLetters() { - return getDevicePolicyManager().getPasswordMinimumLetters(null); + return getDevicePolicyManager().getPasswordMinimumLetters(null, + getCurrentOrCallingUserId()); } public int getRequestedPasswordMinimumUpperCase() { - return getDevicePolicyManager().getPasswordMinimumUpperCase(null); + return getDevicePolicyManager().getPasswordMinimumUpperCase(null, + getCurrentOrCallingUserId()); } public int getRequestedPasswordMinimumLowerCase() { - return getDevicePolicyManager().getPasswordMinimumLowerCase(null); + return getDevicePolicyManager().getPasswordMinimumLowerCase(null, + getCurrentOrCallingUserId()); } public int getRequestedPasswordMinimumNumeric() { - return getDevicePolicyManager().getPasswordMinimumNumeric(null); + return getDevicePolicyManager().getPasswordMinimumNumeric(null, + getCurrentOrCallingUserId()); } public int getRequestedPasswordMinimumSymbols() { - return getDevicePolicyManager().getPasswordMinimumSymbols(null); + return getDevicePolicyManager().getPasswordMinimumSymbols(null, + getCurrentOrCallingUserId()); } public int getRequestedPasswordMinimumNonLetter() { - return getDevicePolicyManager().getPasswordMinimumNonLetter(null); + return getDevicePolicyManager().getPasswordMinimumNonLetter(null, + getCurrentOrCallingUserId()); } + /** * Returns the actual password mode, as set by keyguard after updating the password. * * @return */ public void reportFailedPasswordAttempt() { - getDevicePolicyManager().reportFailedPasswordAttempt(); + getDevicePolicyManager().reportFailedPasswordAttempt(getCurrentOrCallingUserId()); } public void reportSuccessfulPasswordAttempt() { - getDevicePolicyManager().reportSuccessfulPasswordAttempt(); + getDevicePolicyManager().reportSuccessfulPasswordAttempt(getCurrentOrCallingUserId()); } public void setCurrentUser(int userId) { @@ -249,7 +256,9 @@ public class LockPatternUtils { private int getCurrentOrCallingUserId() { int callingUid = Binder.getCallingUid(); if (callingUid == android.os.Process.SYSTEM_UID) { - return mCurrentUserId; + // TODO: This is a little inefficient. See if all users of this are able to + // handle USER_CURRENT and pass that instead. + return getCurrentUser(); } else { return UserHandle.getUserId(callingUid); } @@ -481,21 +490,21 @@ public class LockPatternUtils { deleteGallery(); setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, - pattern.size(), 0, 0, 0, 0, 0, 0); + pattern.size(), 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId()); } else { setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK); setLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); finishBiometricWeak(); dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, - 0, 0, 0, 0, 0, 0, 0); + 0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId()); } } else { if (keyStore.isEmpty()) { keyStore.reset(); } dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, - 0, 0, 0, 0, 0); + 0, 0, 0, 0, 0, getCurrentOrCallingUserId()); } } catch (RemoteException re) { Log.e(TAG, "Couldn't save lock pattern " + re); @@ -532,7 +541,8 @@ public class LockPatternUtils { /** Update the encryption password if it is enabled **/ private void updateEncryptionPassword(String password) { DevicePolicyManager dpm = getDevicePolicyManager(); - if (dpm.getStorageEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE) { + if (dpm.getStorageEncryptionStatus(getCurrentOrCallingUserId()) + != DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE) { return; } @@ -558,7 +568,7 @@ public class LockPatternUtils { * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} */ public void saveLockPassword(String password, int quality) { - this.saveLockPassword(password, quality, false); + this.saveLockPassword(password, quality, false, getCurrentOrCallingUserId()); } /** @@ -570,23 +580,42 @@ public class LockPatternUtils { * @param isFallback Specifies if this is a fallback to biometric weak */ public void saveLockPassword(String password, int quality, boolean isFallback) { + saveLockPassword(password, quality, isFallback, getCurrentOrCallingUserId()); + } + + /** + * Save a lock password. Does not ensure that the password is as good + * as the requested mode, but will adjust the mode to be as good as the + * pattern. + * @param password The password to save + * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} + * @param isFallback Specifies if this is a fallback to biometric weak + * @param userHandle The userId of the user to change the password for + */ + public void saveLockPassword(String password, int quality, boolean isFallback, int userHandle) { // Compute the hash final byte[] hash = passwordToHash(password); try { - getLockSettings().setLockPassword(hash, getCurrentOrCallingUserId()); + if (Process.myUid() != Process.SYSTEM_UID && userHandle != UserHandle.myUserId()) { + throw new SecurityException( + "Only the system process can save lock password for another user"); + } + getLockSettings().setLockPassword(hash, userHandle); DevicePolicyManager dpm = getDevicePolicyManager(); KeyStore keyStore = KeyStore.getInstance(); if (password != null) { - // Update the encryption password. - updateEncryptionPassword(password); + if (userHandle == UserHandle.USER_OWNER) { + // Update the encryption password. + updateEncryptionPassword(password); - // Update the keystore password - keyStore.password(password); + // Update the keystore password + keyStore.password(password); + } int computedQuality = computePasswordQuality(password); if (!isFallback) { deleteGallery(); - setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality)); + setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality), userHandle); if (computedQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { int letters = 0; int uppercase = 0; @@ -612,25 +641,27 @@ public class LockPatternUtils { } dpm.setActivePasswordState(Math.max(quality, computedQuality), password.length(), letters, uppercase, lowercase, - numbers, symbols, nonletter); + numbers, symbols, nonletter, userHandle); } else { // The password is not anything. dpm.setActivePasswordState( DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, - 0, 0, 0, 0, 0, 0, 0); + 0, 0, 0, 0, 0, 0, 0, userHandle); } } else { // Case where it's a fallback for biometric weak - setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK); - setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality)); + setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, + userHandle); + setLong(PASSWORD_TYPE_ALTERNATE_KEY, Math.max(quality, computedQuality), + userHandle); finishBiometricWeak(); dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK, - 0, 0, 0, 0, 0, 0, 0); + 0, 0, 0, 0, 0, 0, 0, userHandle); } // Add the password to the password history. We assume all // password // hashes have the same length for simplicity of implementation. - String passwordHistory = getString(PASSWORD_HISTORY_KEY); + String passwordHistory = getString(PASSWORD_HISTORY_KEY, userHandle); if (passwordHistory == null) { passwordHistory = new String(); } @@ -645,7 +676,7 @@ public class LockPatternUtils { * passwordHistoryLength + passwordHistoryLength - 1, passwordHistory .length())); } - setString(PASSWORD_HISTORY_KEY, passwordHistory); + setString(PASSWORD_HISTORY_KEY, passwordHistory, userHandle); } else { // Conditionally reset the keystore if empty. If // non-empty, we are just switching key guard type @@ -653,7 +684,8 @@ public class LockPatternUtils { keyStore.reset(); } dpm.setActivePasswordState( - DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0); + DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, + userHandle); } } catch (RemoteException re) { // Cant do much @@ -849,7 +881,7 @@ public class LockPatternUtils { if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) { return false; } - if (getDevicePolicyManager().getCameraDisabled(null)) { + if (getDevicePolicyManager().getCameraDisabled(null, getCurrentOrCallingUserId())) { return false; } @@ -1027,6 +1059,10 @@ public class LockPatternUtils { } private void setLong(String secureSettingKey, long value) { + setLong(secureSettingKey, value, getCurrentOrCallingUserId()); + } + + private void setLong(String secureSettingKey, long value, int userHandle) { try { getLockSettings().setLong(secureSettingKey, value, getCurrentOrCallingUserId()); } catch (RemoteException re) { @@ -1036,17 +1072,20 @@ public class LockPatternUtils { } private String getString(String secureSettingKey) { + return getString(secureSettingKey, getCurrentOrCallingUserId()); + } + + private String getString(String secureSettingKey, int userHandle) { try { - return getLockSettings().getString(secureSettingKey, null, - getCurrentOrCallingUserId()); + return getLockSettings().getString(secureSettingKey, null, userHandle); } catch (RemoteException re) { return null; } } - private void setString(String secureSettingKey, String value) { + private void setString(String secureSettingKey, String value, int userHandle) { try { - getLockSettings().setString(secureSettingKey, value, getCurrentOrCallingUserId()); + getLockSettings().setString(secureSettingKey, value, userHandle); } catch (RemoteException re) { // What can we do? Log.e(TAG, "Couldn't write string " + secureSettingKey + re); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index 991f90b015046..47760b57080d7 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -33,6 +33,7 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Rect; import android.os.Looper; +import android.os.UserHandle; import android.os.UserManager; import android.util.AttributeSet; import android.util.Log; @@ -345,7 +346,7 @@ public class KeyguardHostView extends KeyguardViewBase { final boolean usingPattern = mode == KeyguardSecurityModel.SecurityMode.Pattern; final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager() - .getMaximumFailedPasswordsForWipe(null); + .getMaximumFailedPasswordsForWipe(null, mLockPatternUtils.getCurrentUser()); final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT; @@ -683,7 +684,7 @@ public class KeyguardHostView extends KeyguardViewBase { private void maybePopulateWidgets() { DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); - if (dpm != null && dpm.getKeyguardWidgetsDisabled(null) + if (dpm != null && dpm.getKeyguardWidgetsDisabled(null, mLockPatternUtils.getCurrentUser()) != DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_NONE) { Log.v(TAG, "Keyguard widgets disabled because of device policy admin"); return; diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java index 75542361ed4f0..dc20e746e97e4 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java @@ -191,8 +191,9 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri } private void updateTargets() { + int currentUserHandle = mLockPatternUtils.getCurrentUser(); boolean disabledByAdmin = mLockPatternUtils.getDevicePolicyManager() - .getCameraDisabled(null); + .getCameraDisabled(null, currentUserHandle); final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(getContext()); boolean disabledBySimState = monitor.isSimLocked(); boolean cameraTargetPresent = diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java index 7f5a00e3cb28a..7f45a403039da 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java @@ -559,7 +559,7 @@ public class KeyguardViewMediator { // From DevicePolicyAdmin final long policyTimeout = mLockPatternUtils.getDevicePolicyManager() - .getMaximumTimeToLock(null); + .getMaximumTimeToLock(null, mLockPatternUtils.getCurrentUser()); long timeout; if (policyTimeout > 0) { diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index 28a4310734c51..aec5d6ed2555b 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -16,7 +16,6 @@ package com.android.server; -import com.android.internal.content.PackageMonitor; import com.android.internal.os.storage.ExternalStorageFormatter; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.JournaledFile; @@ -28,7 +27,9 @@ import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.app.Activity; +import android.app.ActivityManagerNative; import android.app.AlarmManager; +import android.app.AppGlobals; import android.app.PendingIntent; import android.app.admin.DeviceAdminInfo; import android.app.admin.DeviceAdminReceiver; @@ -40,6 +41,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; @@ -49,6 +51,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.IPowerManager; import android.os.PowerManager; +import android.os.Process; import android.os.RecoverySystem; import android.os.RemoteCallback; import android.os.RemoteException; @@ -56,10 +59,12 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.Slog; +import android.util.SparseArray; import android.util.Xml; import android.view.IWindowManager; import android.view.WindowManagerPolicy; @@ -82,56 +87,86 @@ import java.util.Set; * Implementation of the device policy APIs. */ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + private static final String DEVICE_POLICIES_XML = "device_policies.xml"; + private static final String TAG = "DevicePolicyManagerService"; private static final int REQUEST_EXPIRE_PASSWORD = 5571; - private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * 86400 * 1000; // 5 days, in ms + private static final long MS_PER_DAY = 86400 * 1000; + + private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * MS_PER_DAY; // 5 days, in ms protected static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION"; - private static final long MS_PER_DAY = 86400 * 1000; + private static final boolean DBG = false; final Context mContext; - final MyPackageMonitor mMonitor; final PowerManager.WakeLock mWakeLock; IPowerManager mIPowerManager; IWindowManager mIWindowManager; - int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; - int mActivePasswordLength = 0; - int mActivePasswordUpperCase = 0; - int mActivePasswordLowerCase = 0; - int mActivePasswordLetters = 0; - int mActivePasswordNumeric = 0; - int mActivePasswordSymbols = 0; - int mActivePasswordNonLetter = 0; - int mFailedPasswordAttempts = 0; + public static class DevicePolicyData { + int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; + int mActivePasswordLength = 0; + int mActivePasswordUpperCase = 0; + int mActivePasswordLowerCase = 0; + int mActivePasswordLetters = 0; + int mActivePasswordNumeric = 0; + int mActivePasswordSymbols = 0; + int mActivePasswordNonLetter = 0; + int mFailedPasswordAttempts = 0; + + int mUserHandle;; + int mPasswordOwner = -1; + long mLastMaximumTimeToLock = -1; + + final HashMap mAdminMap + = new HashMap(); + final ArrayList mAdminList + = new ArrayList(); + + public DevicePolicyData(int userHandle) { + mUserHandle = userHandle; + } + } + + final SparseArray mUserData = new SparseArray(); - int mPasswordOwner = -1; Handler mHandler = new Handler(); - long mLastMaximumTimeToLock = -1; - - final HashMap mAdminMap - = new HashMap(); - final ArrayList mAdminList - = new ArrayList(); - BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); + final String action = intent.getAction(); + final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, + getSendingUserId()); if (Intent.ACTION_BOOT_COMPLETED.equals(action) || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) { - Slog.v(TAG, "Sending password expiration notifications for action " + action); + Slog.v(TAG, "Sending password expiration notifications for action " + action + + " for user " + userHandle); mHandler.post(new Runnable() { public void run() { - handlePasswordExpirationNotification(); + handlePasswordExpirationNotification(getUserData(userHandle)); } }); + } else if (Intent.ACTION_USER_REMOVED.equals(action)) { + removeUserData(userHandle); + } else if (Intent.ACTION_USER_STARTED.equals(action) + || Intent.ACTION_PACKAGE_CHANGED.equals(action) + || Intent.ACTION_PACKAGE_REMOVED.equals(action) + || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { + + if (Intent.ACTION_USER_STARTED.equals(action)) { + // Reset the policy data + synchronized (DevicePolicyManagerService.this) { + mUserData.remove(userHandle); + } + } + + handlePackagesChanged(userHandle); } } }; @@ -194,6 +229,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int getUid() { return info.getActivityInfo().applicationInfo.uid; } + public UserHandle getUserHandle() { + return new UserHandle(UserHandle.getUserId(info.getActivityInfo().applicationInfo.uid)); + } + void writeToXml(XmlSerializer out) throws IllegalArgumentException, IllegalStateException, IOException { out.startTag(null, "policies"); @@ -421,39 +460,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - class MyPackageMonitor extends PackageMonitor { - @Override - public void onSomePackagesChanged() { - synchronized (DevicePolicyManagerService.this) { - boolean removed = false; - for (int i=mAdminList.size()-1; i>=0; i--) { - ActiveAdmin aa = mAdminList.get(i); - int change = isPackageDisappearing(aa.info.getPackageName()); - if (change == PACKAGE_PERMANENT_CHANGE - || change == PACKAGE_TEMPORARY_CHANGE) { - Slog.w(TAG, "Admin unexpectedly uninstalled: " - + aa.info.getComponent()); - removed = true; - mAdminList.remove(i); - } else if (isPackageModified(aa.info.getPackageName())) { - try { - mContext.getPackageManager().getReceiverInfo( - aa.info.getComponent(), 0); - } catch (NameNotFoundException e) { - Slog.w(TAG, "Admin package change removed component: " - + aa.info.getComponent()); - removed = true; - mAdminList.remove(i); - } - } - } - if (removed) { - validatePasswordOwnerLocked(); - syncDeviceCapabilitiesLocked(); - saveSettingsLocked(); + private void handlePackagesChanged(int userHandle) { + boolean removed = false; + Slog.d(TAG, "Handling package changes for user " + userHandle); + DevicePolicyData policy = getUserData(userHandle); + IPackageManager pm = AppGlobals.getPackageManager(); + for (int i = policy.mAdminList.size() - 1; i >= 0; i--) { + ActiveAdmin aa = policy.mAdminList.get(i); + try { + if (pm.getPackageInfo(aa.info.getPackageName(), 0, userHandle) == null + || pm.getReceiverInfo(aa.info.getComponent(), 0, userHandle) == null) { + removed = true; + policy.mAdminList.remove(i); } + } catch (RemoteException re) { + // Shouldn't happen } } + if (removed) { + validatePasswordOwnerLocked(policy); + syncDeviceCapabilitiesLocked(policy); + saveSettingsLocked(policy.mUserHandle); + } } /** @@ -461,22 +489,62 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { */ public DevicePolicyManagerService(Context context) { mContext = context; - mMonitor = new MyPackageMonitor(); - mMonitor.register(context, null, true); mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)) .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM"); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BOOT_COMPLETED); filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION); - context.registerReceiver(mReceiver, filter); + filter.addAction(Intent.ACTION_USER_REMOVED); + filter.addAction(Intent.ACTION_USER_STARTED); + context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); + filter = new IntentFilter(); + filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); + filter.addDataScheme("package"); + context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); + } + + /** + * Creates and loads the policy data from xml. + * @param userHandle the user for whom to load the policy data + * @return + */ + DevicePolicyData getUserData(int userHandle) { + synchronized (this) { + DevicePolicyData policy = mUserData.get(userHandle); + if (policy == null) { + policy = new DevicePolicyData(userHandle); + mUserData.append(userHandle, policy); + loadSettingsLocked(policy, userHandle); + } + return policy; + } + } + + void removeUserData(int userHandle) { + synchronized (this) { + if (userHandle == UserHandle.USER_OWNER) { + Slog.w(TAG, "Tried to remove device policy file for user 0! Ignoring."); + return; + } + DevicePolicyData policy = mUserData.get(userHandle); + if (policy != null) { + mUserData.remove(userHandle); + } + File policyFile = new File(Environment.getUserSystemDirectory(userHandle), + DEVICE_POLICIES_XML); + policyFile.delete(); + Slog.i(TAG, "Removed device policy file " + policyFile.getAbsolutePath()); + } } /** * Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration * reminders. Clears alarm if no expirations are configured. */ - protected void setExpirationAlarmCheckLocked(Context context) { - final long expiration = getPasswordExpirationLocked(null); + protected void setExpirationAlarmCheckLocked(Context context, DevicePolicyData policy) { + final long expiration = getPasswordExpirationLocked(null, policy.mUserHandle); final long now = System.currentTimeMillis(); final long timeToExpire = expiration - now; final long alarmTime; @@ -499,9 +567,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { long token = Binder.clearCallingIdentity(); try { AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - PendingIntent pi = PendingIntent.getBroadcast(context, REQUEST_EXPIRE_PASSWORD, + PendingIntent pi = PendingIntent.getBroadcastAsUser(context, REQUEST_EXPIRE_PASSWORD, new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION), - PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT, + new UserHandle(policy.mUserHandle)); am.cancel(pi); if (alarmTime != 0) { am.set(AlarmManager.RTC, alarmTime, pi); @@ -527,8 +596,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return mIWindowManager; } - ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) { - ActiveAdmin admin = mAdminMap.get(who); + ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) { + ActiveAdmin admin = getUserData(userHandle).mAdminMap.get(who); if (admin != null && who.getPackageName().equals(admin.info.getActivityInfo().packageName) && who.getClassName().equals(admin.info.getActivityInfo().name)) { @@ -540,8 +609,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy) throws SecurityException { final int callingUid = Binder.getCallingUid(); + final int userHandle = UserHandle.getUserId(callingUid); + final DevicePolicyData policy = getUserData(userHandle); if (who != null) { - ActiveAdmin admin = mAdminMap.get(who); + ActiveAdmin admin = policy.mAdminMap.get(who); if (admin == null) { throw new SecurityException("No active admin " + who); } @@ -556,9 +627,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } return admin; } else { - final int N = mAdminList.size(); + final int N = policy.mAdminList.size(); for (int i=0; i 0) { - for (int i=0; i 0) { + for (int i = 0; i < count; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); if (admin.info.usesPolicy(reqPolicy)) { sendAdminCommandLocked(admin, action); } @@ -598,8 +670,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - void removeActiveAdminLocked(final ComponentName adminReceiver) { - final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver); + void removeActiveAdminLocked(final ComponentName adminReceiver, int userHandle) { + final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle); if (admin != null) { sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED, @@ -607,28 +679,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public void onReceive(Context context, Intent intent) { synchronized (DevicePolicyManagerService.this) { + int userHandle = admin.getUserHandle().getIdentifier(); + DevicePolicyData policy = getUserData(userHandle); boolean doProxyCleanup = admin.info.usesPolicy( DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY); - mAdminList.remove(admin); - mAdminMap.remove(adminReceiver); - validatePasswordOwnerLocked(); - syncDeviceCapabilitiesLocked(); + policy.mAdminList.remove(admin); + policy.mAdminMap.remove(adminReceiver); + validatePasswordOwnerLocked(policy); + syncDeviceCapabilitiesLocked(policy); if (doProxyCleanup) { - resetGlobalProxyLocked(); + resetGlobalProxyLocked(getUserData(userHandle)); } - saveSettingsLocked(); - updateMaximumTimeToLockLocked(); + saveSettingsLocked(userHandle); + updateMaximumTimeToLockLocked(policy); } } }); } } - public DeviceAdminInfo findAdmin(ComponentName adminName) { + public DeviceAdminInfo findAdmin(ComponentName adminName, int userHandle) { + enforceCrossUserPermission(userHandle); Intent resolveIntent = new Intent(); resolveIntent.setComponent(adminName); List infos = mContext.getPackageManager().queryBroadcastReceivers( - resolveIntent, PackageManager.GET_META_DATA); + resolveIntent, PackageManager.GET_META_DATA, userHandle); if (infos == null || infos.size() <= 0) { throw new IllegalArgumentException("Unknown admin: " + adminName); } @@ -636,21 +711,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { try { return new DeviceAdminInfo(mContext, infos.get(0)); } catch (XmlPullParserException e) { - Slog.w(TAG, "Bad device admin requested: " + adminName, e); + Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e); return null; } catch (IOException e) { - Slog.w(TAG, "Bad device admin requested: " + adminName, e); + Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e); return null; } } - private static JournaledFile makeJournaledFile() { - final String base = "/data/system/device_policies.xml"; + private static JournaledFile makeJournaledFile(int userHandle) { + final String base = userHandle == 0 + ? "/data/system/" + DEVICE_POLICIES_XML + : new File(Environment.getUserSystemDirectory(userHandle), DEVICE_POLICIES_XML) + .getAbsolutePath(); return new JournaledFile(new File(base), new File(base + ".tmp")); } - private void saveSettingsLocked() { - JournaledFile journal = makeJournaledFile(); + private void saveSettingsLocked(int userHandle) { + DevicePolicyData policy = getUserData(userHandle); + JournaledFile journal = makeJournaledFile(userHandle); FileOutputStream stream = null; try { stream = new FileOutputStream(journal.chooseForWrite(), false); @@ -660,9 +739,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.startTag(null, "policies"); - final int N = mAdminList.size(); + final int N = policy.mAdminList.size(); for (int i=0; i= 0) { + if (policy.mPasswordOwner >= 0) { out.startTag(null, "password-owner"); - out.attribute(null, "value", Integer.toString(mPasswordOwner)); + out.attribute(null, "value", Integer.toString(policy.mPasswordOwner)); out.endTag(null, "password-owner"); } - if (mFailedPasswordAttempts != 0) { + if (policy.mFailedPasswordAttempts != 0) { out.startTag(null, "failed-password-attempts"); - out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts)); + out.attribute(null, "value", Integer.toString(policy.mFailedPasswordAttempts)); out.endTag(null, "failed-password-attempts"); } - if (mActivePasswordQuality != 0 || mActivePasswordLength != 0 - || mActivePasswordUpperCase != 0 || mActivePasswordLowerCase != 0 - || mActivePasswordLetters != 0 || mActivePasswordNumeric != 0 - || mActivePasswordSymbols != 0 || mActivePasswordNonLetter != 0) { + if (policy.mActivePasswordQuality != 0 || policy.mActivePasswordLength != 0 + || policy.mActivePasswordUpperCase != 0 || policy.mActivePasswordLowerCase != 0 + || policy.mActivePasswordLetters != 0 || policy.mActivePasswordNumeric != 0 + || policy.mActivePasswordSymbols != 0 || policy.mActivePasswordNonLetter != 0) { out.startTag(null, "active-password"); - out.attribute(null, "quality", Integer.toString(mActivePasswordQuality)); - out.attribute(null, "length", Integer.toString(mActivePasswordLength)); - out.attribute(null, "uppercase", Integer.toString(mActivePasswordUpperCase)); - out.attribute(null, "lowercase", Integer.toString(mActivePasswordLowerCase)); - out.attribute(null, "letters", Integer.toString(mActivePasswordLetters)); + out.attribute(null, "quality", Integer.toString(policy.mActivePasswordQuality)); + out.attribute(null, "length", Integer.toString(policy.mActivePasswordLength)); + out.attribute(null, "uppercase", Integer.toString(policy.mActivePasswordUpperCase)); + out.attribute(null, "lowercase", Integer.toString(policy.mActivePasswordLowerCase)); + out.attribute(null, "letters", Integer.toString(policy.mActivePasswordLetters)); out.attribute(null, "numeric", Integer - .toString(mActivePasswordNumeric)); - out.attribute(null, "symbols", Integer.toString(mActivePasswordSymbols)); - out.attribute(null, "nonletter", Integer.toString(mActivePasswordNonLetter)); + .toString(policy.mActivePasswordNumeric)); + out.attribute(null, "symbols", Integer.toString(policy.mActivePasswordSymbols)); + out.attribute(null, "nonletter", Integer.toString(policy.mActivePasswordNonLetter)); out.endTag(null, "active-password"); } @@ -705,7 +784,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.endDocument(); stream.close(); journal.commit(); - sendChangedNotification(); + sendChangedNotification(userHandle); } catch (IOException e) { try { if (stream != null) { @@ -718,20 +797,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - private void sendChangedNotification() { + private void sendChangedNotification(int userHandle) { Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); long ident = Binder.clearCallingIdentity(); try { - // TODO: This shouldn't be sent to all users, if DPM is per user. - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle)); } finally { Binder.restoreCallingIdentity(ident); } } - private void loadSettingsLocked() { - JournaledFile journal = makeJournaledFile(); + private void loadSettingsLocked(DevicePolicyData policy, int userHandle) { + JournaledFile journal = makeJournaledFile(userHandle); FileInputStream stream = null; File file = journal.chooseForRead(); try { @@ -760,40 +838,46 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { String name = parser.getAttributeValue(null, "name"); try { DeviceAdminInfo dai = findAdmin( - ComponentName.unflattenFromString(name)); + ComponentName.unflattenFromString(name), userHandle); + if (DBG && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid) + != userHandle)) { + Slog.w(TAG, "findAdmin returned an incorrect uid " + + dai.getActivityInfo().applicationInfo.uid + " for user " + + userHandle); + } if (dai != null) { ActiveAdmin ap = new ActiveAdmin(dai); ap.readFromXml(parser); - mAdminMap.put(ap.info.getComponent(), ap); - mAdminList.add(ap); + policy.mAdminMap.put(ap.info.getComponent(), ap); + policy.mAdminList.add(ap); } } catch (RuntimeException e) { Slog.w(TAG, "Failed loading admin " + name, e); } } else if ("failed-password-attempts".equals(tag)) { - mFailedPasswordAttempts = Integer.parseInt( + policy.mFailedPasswordAttempts = Integer.parseInt( parser.getAttributeValue(null, "value")); XmlUtils.skipCurrentTag(parser); } else if ("password-owner".equals(tag)) { - mPasswordOwner = Integer.parseInt( + policy.mPasswordOwner = Integer.parseInt( parser.getAttributeValue(null, "value")); XmlUtils.skipCurrentTag(parser); } else if ("active-password".equals(tag)) { - mActivePasswordQuality = Integer.parseInt( + policy.mActivePasswordQuality = Integer.parseInt( parser.getAttributeValue(null, "quality")); - mActivePasswordLength = Integer.parseInt( + policy.mActivePasswordLength = Integer.parseInt( parser.getAttributeValue(null, "length")); - mActivePasswordUpperCase = Integer.parseInt( + policy.mActivePasswordUpperCase = Integer.parseInt( parser.getAttributeValue(null, "uppercase")); - mActivePasswordLowerCase = Integer.parseInt( + policy.mActivePasswordLowerCase = Integer.parseInt( parser.getAttributeValue(null, "lowercase")); - mActivePasswordLetters = Integer.parseInt( + policy.mActivePasswordLetters = Integer.parseInt( parser.getAttributeValue(null, "letters")); - mActivePasswordNumeric = Integer.parseInt( + policy.mActivePasswordNumeric = Integer.parseInt( parser.getAttributeValue(null, "numeric")); - mActivePasswordSymbols = Integer.parseInt( + policy.mActivePasswordSymbols = Integer.parseInt( parser.getAttributeValue(null, "symbols")); - mActivePasswordNonLetter = Integer.parseInt( + policy.mActivePasswordNonLetter = Integer.parseInt( parser.getAttributeValue(null, "nonletter")); XmlUtils.skipCurrentTag(parser); } else { @@ -827,24 +911,24 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // a sanity check in case the two get out of sync; this should // never normally happen. LockPatternUtils utils = new LockPatternUtils(mContext); - if (utils.getActivePasswordQuality() < mActivePasswordQuality) { + if (utils.getActivePasswordQuality() < policy.mActivePasswordQuality) { Slog.w(TAG, "Active password quality 0x" - + Integer.toHexString(mActivePasswordQuality) + + Integer.toHexString(policy.mActivePasswordQuality) + " does not match actual quality 0x" + Integer.toHexString(utils.getActivePasswordQuality())); - mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; - mActivePasswordLength = 0; - mActivePasswordUpperCase = 0; - mActivePasswordLowerCase = 0; - mActivePasswordLetters = 0; - mActivePasswordNumeric = 0; - mActivePasswordSymbols = 0; - mActivePasswordNonLetter = 0; + policy.mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; + policy.mActivePasswordLength = 0; + policy.mActivePasswordUpperCase = 0; + policy.mActivePasswordLowerCase = 0; + policy.mActivePasswordLetters = 0; + policy.mActivePasswordNumeric = 0; + policy.mActivePasswordSymbols = 0; + policy.mActivePasswordNonLetter = 0; } - validatePasswordOwnerLocked(); - syncDeviceCapabilitiesLocked(); - updateMaximumTimeToLockLocked(); + validatePasswordOwnerLocked(policy); + syncDeviceCapabilitiesLocked(policy); + updateMaximumTimeToLockLocked(policy); } static void validateQualityConstant(int quality) { @@ -862,19 +946,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + Integer.toHexString(quality)); } - void validatePasswordOwnerLocked() { - if (mPasswordOwner >= 0) { + void validatePasswordOwnerLocked(DevicePolicyData policy) { + if (policy.mPasswordOwner >= 0) { boolean haveOwner = false; - for (int i=mAdminList.size()-1; i>=0; i--) { - if (mAdminList.get(i).getUid() == mPasswordOwner) { + for (int i = policy.mAdminList.size() - 1; i >= 0; i--) { + if (policy.mAdminList.get(i).getUid() == policy.mPasswordOwner) { haveOwner = true; break; } } if (!haveOwner) { - Slog.w(TAG, "Previous password owner " + mPasswordOwner + Slog.w(TAG, "Previous password owner " + policy.mPasswordOwner + " no longer active; disabling"); - mPasswordOwner = -1; + policy.mPasswordOwner = -1; } } } @@ -883,11 +967,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * Pushes down policy information to the system for any policies related to general device * capabilities that need to be enforced by lower level services (e.g. Camera services). */ - void syncDeviceCapabilitiesLocked() { + void syncDeviceCapabilitiesLocked(DevicePolicyData policy) { // Ensure the status of the camera is synced down to the system. Interested native services // should monitor this value and act accordingly. boolean systemState = SystemProperties.getBoolean(SYSTEM_PROP_DISABLE_CAMERA, false); - boolean cameraDisabled = getCameraDisabled(null); + boolean cameraDisabled = getCameraDisabled(null, policy.mUserHandle); if (cameraDisabled != systemState) { long token = Binder.clearCallingIdentity(); try { @@ -903,19 +987,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public void systemReady() { synchronized (this) { - loadSettingsLocked(); + loadSettingsLocked(getUserData(UserHandle.USER_OWNER), UserHandle.USER_OWNER); } } - private void handlePasswordExpirationNotification() { + private void handlePasswordExpirationNotification(DevicePolicyData policy) { synchronized (this) { final long now = System.currentTimeMillis(); - final int N = mAdminList.size(); + final int N = policy.mAdminList.size(); if (N <= 0) { return; } for (int i=0; i < N; i++) { - ActiveAdmin admin = mAdminList.get(i); + ActiveAdmin admin = policy.mAdminList.get(i); if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD) && admin.passwordExpirationTimeout > 0L && admin.passwordExpirationDate > 0L @@ -923,7 +1007,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING); } } - setExpirationAlarmCheckLocked(mContext); + setExpirationAlarmCheckLocked(mContext, policy); } } @@ -931,27 +1015,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * @param adminReceiver The admin to add * @param refreshing true = update an active admin, no error */ - public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing) { + public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); + enforceCrossUserPermission(userHandle); - DeviceAdminInfo info = findAdmin(adminReceiver); + DevicePolicyData policy = getUserData(userHandle); + DeviceAdminInfo info = findAdmin(adminReceiver, userHandle); if (info == null) { throw new IllegalArgumentException("Bad admin: " + adminReceiver); } synchronized (this) { long ident = Binder.clearCallingIdentity(); try { - if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver) != null) { + if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) { throw new IllegalArgumentException("Admin is already added"); } ActiveAdmin newAdmin = new ActiveAdmin(info); - mAdminMap.put(adminReceiver, newAdmin); + policy.mAdminMap.put(adminReceiver, newAdmin); int replaceIndex = -1; if (refreshing) { - final int N = mAdminList.size(); + final int N = policy.mAdminList.size(); for (int i=0; i < N; i++) { - ActiveAdmin oldAdmin = mAdminList.get(i); + ActiveAdmin oldAdmin = policy.mAdminList.get(i); if (oldAdmin.info.getComponent().equals(adminReceiver)) { replaceIndex = i; break; @@ -959,11 +1045,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } if (replaceIndex == -1) { - mAdminList.add(newAdmin); + policy.mAdminList.add(newAdmin); } else { - mAdminList.set(replaceIndex, newAdmin); + policy.mAdminList.set(replaceIndex, newAdmin); } - saveSettingsLocked(); + saveSettingsLocked(userHandle); sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED); } finally { Binder.restoreCallingIdentity(ident); @@ -971,15 +1057,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - public boolean isAdminActive(ComponentName adminReceiver) { + public boolean isAdminActive(ComponentName adminReceiver, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { - return getActiveAdminUncheckedLocked(adminReceiver) != null; + return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null; } } - public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId) { + public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { - ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver); + ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle); if (administrator == null) { throw new SecurityException("No active admin " + adminReceiver); } @@ -987,25 +1075,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - public List getActiveAdmins() { + public List getActiveAdmins(int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { - final int N = mAdminList.size(); + DevicePolicyData policy = getUserData(userHandle); + final int N = policy.mAdminList.size(); if (N <= 0) { return null; } ArrayList res = new ArrayList(N); for (int i=0; i admin.passwordExpirationTimeout)) { timeout = admin.passwordExpirationTimeout; @@ -1188,16 +1294,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * Return a single admin's expiration date/time, or the min (soonest) for all admins. * Returns 0 if not configured. */ - private long getPasswordExpirationLocked(ComponentName who) { + private long getPasswordExpirationLocked(ComponentName who, int userHandle) { if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); return admin != null ? admin.passwordExpirationDate : 0L; } long timeout = 0L; - final int N = mAdminList.size(); + DevicePolicyData policy = getUserData(userHandle); + final int N = policy.mAdminList.size(); for (int i = 0; i < N; i++) { - ActiveAdmin admin = mAdminList.get(i); + ActiveAdmin admin = policy.mAdminList.get(i); if (timeout == 0L || (admin.passwordExpirationDate != 0 && timeout > admin.passwordExpirationDate)) { timeout = admin.passwordExpirationDate; @@ -1206,13 +1313,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return timeout; } - public long getPasswordExpiration(ComponentName who) { + public long getPasswordExpiration(ComponentName who, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { - return getPasswordExpirationLocked(who); + return getPasswordExpirationLocked(who, userHandle); } } - public void setPasswordMinimumUpperCase(ComponentName who, int length) { + public void setPasswordMinimumUpperCase(ComponentName who, int length, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { if (who == null) { throw new NullPointerException("ComponentName is null"); @@ -1221,23 +1330,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); if (ap.minimumPasswordUpperCase != length) { ap.minimumPasswordUpperCase = length; - saveSettingsLocked(); + saveSettingsLocked(userHandle); } } } - public int getPasswordMinimumUpperCase(ComponentName who) { + public int getPasswordMinimumUpperCase(ComponentName who, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { int length = 0; if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); return admin != null ? admin.minimumPasswordUpperCase : length; } - final int N = mAdminList.size(); + DevicePolicyData policy = getUserData(userHandle); + final int N = policy.mAdminList.size(); for (int i=0; i= getPasswordMinimumUpperCase(null) - && mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null) - && mActivePasswordLetters >= getPasswordMinimumLetters(null) - && mActivePasswordNumeric >= getPasswordMinimumNumeric(null) - && mActivePasswordSymbols >= getPasswordMinimumSymbols(null) - && mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null); + return policy.mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null, userHandle) + && policy.mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null, userHandle) + && policy.mActivePasswordLetters >= getPasswordMinimumLetters(null, userHandle) + && policy.mActivePasswordNumeric >= getPasswordMinimumNumeric(null, userHandle) + && policy.mActivePasswordSymbols >= getPasswordMinimumSymbols(null, userHandle) + && policy.mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null, userHandle); } } - public int getCurrentFailedPasswordAttempts() { + public int getCurrentFailedPasswordAttempts(int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { // This API can only be called by an active device admin, // so try to retrieve it to check that the caller is one. getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); - return mFailedPasswordAttempts; + return getUserData(userHandle).mFailedPasswordAttempts; } } - public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) { + public void setMaximumFailedPasswordsForWipe(ComponentName who, int num, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { // This API can only be called by an active device admin, // so try to retrieve it to check that the caller is one. @@ -1458,23 +1588,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); if (ap.maximumFailedPasswordsForWipe != num) { ap.maximumFailedPasswordsForWipe = num; - saveSettingsLocked(); + saveSettingsLocked(userHandle); } } } - public int getMaximumFailedPasswordsForWipe(ComponentName who) { + public int getMaximumFailedPasswordsForWipe(ComponentName who, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { + DevicePolicyData policy = getUserData(userHandle); int count = 0; if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); return admin != null ? admin.maximumFailedPasswordsForWipe : count; } - final int N = mAdminList.size(); + final int N = policy.mAdminList.size(); for (int i=0; i= 0 && mPasswordOwner != callingUid) { + DevicePolicyData policy = getUserData(userHandle); + if (policy.mPasswordOwner >= 0 && policy.mPasswordOwner != callingUid) { Slog.w(TAG, "resetPassword: already set by another uid and not entered by user"); return false; } @@ -1590,13 +1724,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { long ident = Binder.clearCallingIdentity(); try { LockPatternUtils utils = new LockPatternUtils(mContext); - utils.saveLockPassword(password, quality); + utils.saveLockPassword(password, quality, false, userHandle); synchronized (this) { int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0 ? callingUid : -1; - if (mPasswordOwner != newOwner) { - mPasswordOwner = newOwner; - saveSettingsLocked(); + if (policy.mPasswordOwner != newOwner) { + policy.mPasswordOwner = newOwner; + saveSettingsLocked(userHandle); } } } finally { @@ -1606,7 +1740,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return true; } - public void setMaximumTimeToLock(ComponentName who, long timeMs) { + public void setMaximumTimeToLock(ComponentName who, long timeMs, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { if (who == null) { throw new NullPointerException("ComponentName is null"); @@ -1615,15 +1750,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DeviceAdminInfo.USES_POLICY_FORCE_LOCK); if (ap.maximumTimeToUnlock != timeMs) { ap.maximumTimeToUnlock = timeMs; - saveSettingsLocked(); - updateMaximumTimeToLockLocked(); + saveSettingsLocked(userHandle); + updateMaximumTimeToLockLocked(getUserData(userHandle)); } } } - void updateMaximumTimeToLockLocked() { - long timeMs = getMaximumTimeToLock(null); - if (mLastMaximumTimeToLock == timeMs) { + void updateMaximumTimeToLockLocked(DevicePolicyData policy) { + long timeMs = getMaximumTimeToLock(null, policy.mUserHandle); + if (policy.mLastMaximumTimeToLock == timeMs) { return; } @@ -1638,7 +1773,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0); } - mLastMaximumTimeToLock = timeMs; + policy.mLastMaximumTimeToLock = timeMs; try { getIPowerManager().setMaximumScreenOffTimeoutFromDeviceAdmin((int)timeMs); @@ -1650,18 +1785,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - public long getMaximumTimeToLock(ComponentName who) { + public long getMaximumTimeToLock(ComponentName who, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { long time = 0; if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); return admin != null ? admin.maximumTimeToUnlock : time; } - final int N = mAdminList.size(); + DevicePolicyData policy = getUserData(userHandle); + final int N = policy.mAdminList.size(); for (int i=0; i 0) { for (int i=0; i 0L ? (timeout + System.currentTimeMillis()) : 0L; admin.passwordExpirationDate = expiration; } } - saveSettingsLocked(); + saveSettingsLocked(userHandle); } } - public void reportFailedPasswordAttempt() { + public void reportFailedPasswordAttempt(int userHandle) { + enforceCrossUserPermission(userHandle); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); synchronized (this) { + DevicePolicyData policy = getUserData(userHandle); long ident = Binder.clearCallingIdentity(); try { - mFailedPasswordAttempts++; - saveSettingsLocked(); - int max = getMaximumFailedPasswordsForWipe(null); - if (max > 0 && mFailedPasswordAttempts >= max) { + policy.mFailedPasswordAttempts++; + saveSettingsLocked(userHandle); + int max = getMaximumFailedPasswordsForWipe(null, userHandle); + if (max > 0 && policy.mFailedPasswordAttempts >= max) { wipeDataLocked(0); } sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED, - DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); + DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle); } finally { Binder.restoreCallingIdentity(ident); } } } - public void reportSuccessfulPasswordAttempt() { + public void reportSuccessfulPasswordAttempt(int userHandle) { + enforceCrossUserPermission(userHandle); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); synchronized (this) { - if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) { + DevicePolicyData policy = getUserData(userHandle); + if (policy.mFailedPasswordAttempts != 0 || policy.mPasswordOwner >= 0) { long ident = Binder.clearCallingIdentity(); try { - mFailedPasswordAttempts = 0; - mPasswordOwner = -1; - saveSettingsLocked(); + policy.mFailedPasswordAttempts = 0; + policy.mPasswordOwner = -1; + saveSettingsLocked(userHandle); sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED, - DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); + DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle); } finally { Binder.restoreCallingIdentity(ident); } @@ -1858,26 +2023,36 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } public ComponentName setGlobalProxy(ComponentName who, String proxySpec, - String exclusionList) { + String exclusionList, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized(this) { if (who == null) { throw new NullPointerException("ComponentName is null"); } + // Only check if owner has set global proxy. We don't allow other users to set it. + DevicePolicyData policy = getUserData(UserHandle.USER_OWNER); ActiveAdmin admin = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY); // Scan through active admins and find if anyone has already // set the global proxy. - Set compSet = mAdminMap.keySet(); + Set compSet = policy.mAdminMap.keySet(); for (ComponentName component : compSet) { - ActiveAdmin ap = mAdminMap.get(component); + ActiveAdmin ap = policy.mAdminMap.get(component); if ((ap.specifiesGlobalProxy) && (!component.equals(who))) { // Another admin already sets the global proxy // Return it to the caller. return component; } } + + // If the user is not the owner, don't set the global proxy. Fail silently. + if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) { + Slog.w(TAG, "Only the owner is allowed to set the global proxy. User " + + userHandle + " is not permitted."); + return null; + } if (proxySpec == null) { admin.specifiesGlobalProxy = false; admin.globalProxySpec = null; @@ -1892,19 +2067,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // Reset the global proxy accordingly // Do this using system permissions, as apps cannot write to secure settings long origId = Binder.clearCallingIdentity(); - resetGlobalProxyLocked(); + resetGlobalProxyLocked(policy); Binder.restoreCallingIdentity(origId); return null; } } - public ComponentName getGlobalProxyAdmin() { + public ComponentName getGlobalProxyAdmin(int userHandle) { + enforceCrossUserPermission(userHandle); synchronized(this) { + DevicePolicyData policy = getUserData(UserHandle.USER_OWNER); // Scan through active admins and find if anyone has already // set the global proxy. - final int N = mAdminList.size(); + final int N = policy.mAdminList.size(); for (int i = 0; i < N; i++) { - ActiveAdmin ap = mAdminList.get(i); + ActiveAdmin ap = policy.mAdminList.get(i); if (ap.specifiesGlobalProxy) { // Device admin sets the global proxy // Return it to the caller. @@ -1916,10 +2093,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return null; } - private void resetGlobalProxyLocked() { - final int N = mAdminList.size(); + private void resetGlobalProxyLocked(DevicePolicyData policy) { + final int N = policy.mAdminList.size(); for (int i = 0; i < N; i++) { - ActiveAdmin ap = mAdminList.get(i); + ActiveAdmin ap = policy.mAdminList.get(i); if (ap.specifiesGlobalProxy) { saveGlobalProxyLocked(ap.globalProxySpec, ap.globalProxyExclusionList); return; @@ -1957,12 +2134,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * Set the storage encryption request for a single admin. Returns the new total request * status (for all admins). */ - public int setStorageEncryption(ComponentName who, boolean encrypt) { + public int setStorageEncryption(ComponentName who, boolean encrypt, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { // Check for permissions if (who == null) { throw new NullPointerException("ComponentName is null"); } + // Only owner can set storage encryption + if (userHandle != UserHandle.USER_OWNER + || UserHandle.getCallingUserId() != UserHandle.USER_OWNER) { + Slog.w(TAG, "Only owner is allowed to set storage encryption. User " + + UserHandle.getCallingUserId() + " is not permitted."); + return 0; + } + ActiveAdmin ap = getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_ENCRYPTED_STORAGE); @@ -1974,14 +2160,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // (1) Record the value for the admin so it's sticky if (ap.encryptionRequested != encrypt) { ap.encryptionRequested = encrypt; - saveSettingsLocked(); + saveSettingsLocked(userHandle); } + DevicePolicyData policy = getUserData(UserHandle.USER_OWNER); // (2) Compute "max" for all admins boolean newRequested = false; - final int N = mAdminList.size(); + final int N = policy.mAdminList.size(); for (int i = 0; i < N; i++) { - newRequested |= mAdminList.get(i).encryptionRequested; + newRequested |= policy.mAdminList.get(i).encryptionRequested; } // Notify OS of new request @@ -1998,20 +2185,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * Get the current storage encryption request status for a given admin, or aggregate of all * active admins. */ - public boolean getStorageEncryption(ComponentName who) { + public boolean getStorageEncryption(ComponentName who, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { // Check for permissions if a particular caller is specified if (who != null) { // When checking for a single caller, status is based on caller's request - ActiveAdmin ap = getActiveAdminUncheckedLocked(who); + ActiveAdmin ap = getActiveAdminUncheckedLocked(who, userHandle); return ap != null ? ap.encryptionRequested : false; } // If no particular caller is specified, return the aggregate set of requests. // This is short circuited by returning true on the first hit. - final int N = mAdminList.size(); + DevicePolicyData policy = getUserData(userHandle); + final int N = policy.mAdminList.size(); for (int i = 0; i < N; i++) { - if (mAdminList.get(i).encryptionRequested) { + if (policy.mAdminList.get(i).encryptionRequested) { return true; } } @@ -2022,7 +2211,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { /** * Get the current encryption status of the device. */ - public int getStorageEncryptionStatus() { + public int getStorageEncryptionStatus(int userHandle) { + enforceCrossUserPermission(userHandle); return getEncryptionStatus(); } @@ -2069,7 +2259,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { /** * Disables all device cameras according to the specified admin. */ - public void setCameraDisabled(ComponentName who, boolean disabled) { + public void setCameraDisabled(ComponentName who, boolean disabled, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { if (who == null) { throw new NullPointerException("ComponentName is null"); @@ -2078,9 +2269,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA); if (ap.disableCamera != disabled) { ap.disableCamera = disabled; - saveSettingsLocked(); + saveSettingsLocked(userHandle); } - syncDeviceCapabilitiesLocked(); + syncDeviceCapabilitiesLocked(getUserData(userHandle)); } } @@ -2088,17 +2279,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * Gets whether or not all device cameras are disabled for a given admin, or disabled for any * active admins. */ - public boolean getCameraDisabled(ComponentName who) { + public boolean getCameraDisabled(ComponentName who, int userHandle) { synchronized (this) { if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); return (admin != null) ? admin.disableCamera : false; } + DevicePolicyData policy = getUserData(userHandle); // Determine whether or not the device camera is disabled for any active admins. - final int N = mAdminList.size(); + final int N = policy.mAdminList.size(); for (int i = 0; i < N; i++) { - ActiveAdmin admin = mAdminList.get(i); + ActiveAdmin admin = policy.mAdminList.get(i); if (admin.disableCamera) { return true; } @@ -2110,7 +2302,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { /** * Selectively disable keyguard widgets. */ - public void setKeyguardWidgetsDisabled(ComponentName who, int which) { + public void setKeyguardWidgetsDisabled(ComponentName who, int which, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { if (who == null) { throw new NullPointerException("ComponentName is null"); @@ -2119,9 +2312,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_WIDGETS); if ((ap.disableKeyguardWidgets & which) != which) { ap.disableKeyguardWidgets |= which; - saveSettingsLocked(); + saveSettingsLocked(userHandle); } - syncDeviceCapabilitiesLocked(); + syncDeviceCapabilitiesLocked(getUserData(userHandle)); } } @@ -2129,24 +2322,39 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * Gets the disabled state for widgets in keyguard for the given admin, * or the aggregate of all active admins if who is null. */ - public int getKeyguardWidgetsDisabled(ComponentName who) { + public int getKeyguardWidgetsDisabled(ComponentName who, int userHandle) { + enforceCrossUserPermission(userHandle); synchronized (this) { if (who != null) { - ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); return (admin != null) ? admin.disableKeyguardWidgets : 0; } // Determine whether or not keyguard widgets are disabled for any active admins. - final int N = mAdminList.size(); + DevicePolicyData policy = getUserData(userHandle); + final int N = policy.mAdminList.size(); int which = 0; for (int i = 0; i < N; i++) { - ActiveAdmin admin = mAdminList.get(i); + ActiveAdmin admin = policy.mAdminList.get(i); which |= admin.disableKeyguardWidgets; } return which; } } + private void enforceCrossUserPermission(int userHandle) { + if (userHandle < 0) { + throw new IllegalArgumentException("Invalid userId " + userHandle); + } + final int callingUid = Binder.getCallingUid(); + if (userHandle == UserHandle.getUserId(callingUid)) return; + if (callingUid != Process.SYSTEM_UID && callingUid != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "Must be system or have" + + " INTERACT_ACROSS_USERS_FULL permission"); + } + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) @@ -2163,19 +2371,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (this) { p.println("Current Device Policy Manager state:"); - p.println(" Enabled Device Admins:"); - final int N = mAdminList.size(); - for (int i=0; i