diff options
10 files changed, 431 insertions, 199 deletions
diff --git a/api/current.txt b/api/current.txt index f2c88d7..9910fdf 100644 --- a/api/current.txt +++ b/api/current.txt @@ -33735,7 +33735,6 @@ package android.webkit { method public abstract long getResources(); method public abstract void grant(long); field public static final long RESOURCE_AUDIO_CAPTURE = 4L; // 0x4L - field public static final long RESOURCE_GEOLOCATION = 1L; // 0x1L field public static final long RESOURCE_VIDEO_CAPTURE = 2L; // 0x2L } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 24bb2cc..58049fd 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -16,8 +16,6 @@ package android.app.admin; -import org.xmlpull.v1.XmlPullParserException; - import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.ComponentName; @@ -39,6 +37,8 @@ import android.util.Log; import com.android.org.conscrypt.TrustedCertificateStore; +import org.xmlpull.v1.XmlPullParserException; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.InetSocketAddress; @@ -359,8 +359,8 @@ public class DevicePolicyManager { } /** - * Retrieve the current minimum password quality for all admins - * or a particular one. + * Retrieve the current minimum password quality for all admins of this user + * and its profiles or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. */ @@ -412,8 +412,8 @@ public class DevicePolicyManager { } /** - * Retrieve the current minimum password length for all admins - * or a particular one. + * Retrieve the current minimum password length for all admins of this + * user and its profiles or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. */ @@ -467,8 +467,9 @@ public class DevicePolicyManager { /** * Retrieve the current number of upper case letters required in the - * password for all admins or a particular one. This is the same value as - * set by {#link {@link #setPasswordMinimumUpperCase(ComponentName, int)} + * password for all admins of this user and its profiles or a particular one. + * This is the same value as set by + * {#link {@link #setPasswordMinimumUpperCase(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * @@ -527,8 +528,9 @@ public class DevicePolicyManager { /** * Retrieve the current number of lower case letters required in the - * password for all admins or a particular one. This is the same value as - * set by {#link {@link #setPasswordMinimumLowerCase(ComponentName, int)} + * password for all admins of this user and its profiles or a particular one. + * This is the same value as set by + * {#link {@link #setPasswordMinimumLowerCase(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * @@ -644,8 +646,9 @@ public class DevicePolicyManager { /** * Retrieve the current number of numerical digits required in the password - * for all admins or a particular one. This is the same value as - * set by {#link {@link #setPasswordMinimumNumeric(ComponentName, int)} + * for all admins of this user and its profiles or a particular one. + * This is the same value as set by + * {#link {@link #setPasswordMinimumNumeric(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * @@ -760,8 +763,9 @@ public class DevicePolicyManager { /** * Retrieve the current number of non-letter characters required in the - * password for all admins or a particular one. This is the same value as - * set by {#link {@link #setPasswordMinimumNonLetter(ComponentName, int)} + * password for all admins of this user and its profiles or a particular one. + * This is the same value as set by + * {#link {@link #setPasswordMinimumNonLetter(ComponentName, int)} * and only applies when the password quality is * {@link #PASSWORD_QUALITY_COMPLEX}. * @@ -868,9 +872,10 @@ public class DevicePolicyManager { /** * Get the current password expiration time for the given admin or an aggregate of - * all admins if admin is null. If the password is expired, this will return the time since - * the password expired as a negative number. If admin is null, then a composite of all - * expiration timeouts is returned - which will be the minimum of all timeouts. + * all admins of this user and its profiles if admin is null. If the password is + * expired, this will return the time since the password expired as a negative number. + * If admin is null, then a composite of all expiration timeouts is returned + * - which will be the minimum of all timeouts. * * @param admin The name of the admin component to check, or null to aggregate all admins. * @return The password expiration time, in ms. @@ -887,8 +892,8 @@ public class DevicePolicyManager { } /** - * Retrieve the current password history length for all admins - * or a particular one. + * Retrieve the current password history length for all admins of this + * user and its profiles or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. * @return The length of the password history @@ -923,14 +928,13 @@ public class DevicePolicyManager { /** * Determine whether the current password the user has set is sufficient * to meet the policy requirements (quality, minimum length) that have been - * requested. + * requested by the admins of this user and its profiles. * * <p>The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call * this method; if it has not, a security exception will be thrown. * - * @return Returns true if the password meets the current requirements, - * else false. + * @return Returns true if the password meets the current requirements, else false. */ public boolean isActivePasswordSufficient() { if (mService != null) { @@ -993,7 +997,7 @@ public class DevicePolicyManager { /** * Retrieve the current maximum number of login attempts that are allowed - * before the device wipes itself, for all admins + * before the device wipes itself, for all admins of this user and its profiles * or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. @@ -1037,6 +1041,8 @@ public class DevicePolicyManager { * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call * this method; if it has not, a security exception will be thrown. * + * Can not be called from a managed profile. + * * @param password The new password for the user. * @param flags May be 0 or {@link #RESET_PASSWORD_REQUIRE_ENTRY}. * @return Returns true if the password was applied, or false if it is @@ -1077,8 +1083,8 @@ public class DevicePolicyManager { } /** - * Retrieve the current maximum time to unlock for all admins - * or a particular one. + * Retrieve the current maximum time to unlock for all admins of this user + * and its profiles or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. */ diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java index 8f41e85..daf0065 100644 --- a/core/java/android/net/Proxy.java +++ b/core/java/android/net/Proxy.java @@ -278,7 +278,9 @@ public final class Proxy { host = p.getHost(); port = Integer.toString(p.getPort()); exclList = p.getExclusionListAsString(); - pacFileUrl = p.getPacFileUrl().toString(); + if (p.getPacFileUrl() != null) { + pacFileUrl = p.getPacFileUrl().toString(); + } } setHttpProxySystemProperty(host, port, exclList, pacFileUrl); } diff --git a/core/java/android/webkit/EventLogTags.logtags b/core/java/android/webkit/EventLogTags.logtags index b0b5493..a90aebd 100644 --- a/core/java/android/webkit/EventLogTags.logtags +++ b/core/java/android/webkit/EventLogTags.logtags @@ -8,3 +8,4 @@ option java_package android.webkit; # 70103- used by the browser app itself 70150 browser_snap_center +70151 exp_det_attempt_to_call_object_getclass (app_signature|3) diff --git a/core/java/android/webkit/PermissionRequest.java b/core/java/android/webkit/PermissionRequest.java index 3e33498..fa760b7 100644 --- a/core/java/android/webkit/PermissionRequest.java +++ b/core/java/android/webkit/PermissionRequest.java @@ -28,6 +28,7 @@ import android.net.Uri; public interface PermissionRequest { /** * Resource belongs to geolocation service. + * @hide - see b/14668406 */ public final static long RESOURCE_GEOLOCATION = 1 << 0; /** diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 3619112..4a59a8f 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -38,6 +38,7 @@ import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.UserInfo; import android.database.ContentObserver; import android.graphics.Point; import android.graphics.Rect; @@ -197,6 +198,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); + private final UserManager mUserManager; + private int mCurrentUserId = UserHandle.USER_OWNER; private final LongArray mTempLongArray = new LongArray(); @@ -210,15 +213,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return getUserStateLocked(mCurrentUserId); } - private UserState getUserStateLocked(int userId) { - UserState state = mUserStates.get(userId); - if (state == null) { - state = new UserState(userId); - mUserStates.put(userId, state); - } - return state; - } - /** * Creates a new instance. * @@ -228,6 +222,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { mContext = context; mPackageManager = mContext.getPackageManager(); mWindowManagerService = LocalServices.getService(WindowManagerInternal.class); + mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mSecurityPolicy = new SecurityPolicy(); mMainHandler = new MainHandler(mContext.getMainLooper()); registerBroadcastReceivers(); @@ -235,11 +230,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { context.getContentResolver()); } + private UserState getUserStateLocked(int userId) { + UserState state = mUserStates.get(userId); + if (state == null) { + state = new UserState(userId); + mUserStates.put(userId, state); + } + return state; + } + private void registerBroadcastReceivers() { PackageMonitor monitor = new PackageMonitor() { @Override public void onSomePackagesChanged() { synchronized (mLock) { + // Only the profile parent can install accessibility services. + // Therefore we ignore packages from linked profiles. if (getChangingUserId() != mCurrentUserId) { return; } @@ -262,6 +268,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public void onPackageRemoved(String packageName, int uid) { synchronized (mLock) { final int userId = getChangingUserId(); + // Only the profile parent can install accessibility services. + // Therefore we ignore packages from linked profiles. if (userId != mCurrentUserId) { return; } @@ -297,6 +305,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { int uid, boolean doit) { synchronized (mLock) { final int userId = getChangingUserId(); + // Only the profile parent can install accessibility services. + // Therefore we ignore packages from linked profiles. if (userId != mCurrentUserId) { return false; } @@ -359,6 +369,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public int addClient(IAccessibilityManagerClient client, int userId) { synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked(userId); // If the client is from a process that runs across users such as @@ -388,6 +401,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) { synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution.. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked(userId); // This method does nothing for a background user. @@ -414,6 +430,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) { synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked(userId); // The automation service is a fake one and should not be reported @@ -435,6 +454,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { int userId) { List<AccessibilityServiceInfo> result = null; synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked(userId); @@ -468,6 +490,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public void interrupt(int userId) { CopyOnWriteArrayList<Service> services; synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked(userId); // This method does nothing for a background user. @@ -491,6 +516,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public int addAccessibilityInteractionConnection(IWindow windowToken, IAccessibilityInteractionConnection connection, int userId) throws RemoteException { synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked(userId); final int windowId = sNextWindowId++; @@ -527,6 +555,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public void removeAccessibilityInteractionConnection(IWindow window) { synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked( UserHandle.getCallingUserId()); IBinder token = window.asBinder(); @@ -675,6 +706,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { Manifest.permission.RETRIEVE_WINDOW_TOKEN, GET_WINDOW_TOKEN); synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked( UserHandle.getCallingUserId()); @@ -770,7 +804,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } // Disconnect from services for the old user. - UserState oldUserState = getUserStateLocked(mCurrentUserId); + UserState oldUserState = getCurrentUserStateLocked(); oldUserState.onSwitchToAnotherUser(); // Disable the local managers for the old user. @@ -2034,6 +2068,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public List<AccessibilityWindowInfo> getWindows() { synchronized (mLock) { + // We treat calls from a profile as if made by its perent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked( UserHandle.getCallingUserId()); @@ -2062,6 +2099,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public AccessibilityWindowInfo getWindow(int windowId) { synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked( UserHandle.getCallingUserId()); @@ -2092,6 +2132,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final int resolvedWindowId; IAccessibilityInteractionConnection connection = null; synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked( UserHandle.getCallingUserId()); @@ -2136,9 +2179,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final int resolvedWindowId; IAccessibilityInteractionConnection connection = null; synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked( - UserHandle.getCallingUserId()); + UserHandle.getCallingUserId()); if (resolvedUserId != mCurrentUserId) { return false; } @@ -2180,9 +2226,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final int resolvedWindowId; IAccessibilityInteractionConnection connection = null; synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked( - UserHandle.getCallingUserId()); + UserHandle.getCallingUserId()); if (resolvedUserId != mCurrentUserId) { return false; } @@ -2224,9 +2273,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final int resolvedWindowId; IAccessibilityInteractionConnection connection = null; synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked( - UserHandle.getCallingUserId()); + UserHandle.getCallingUserId()); if (resolvedUserId != mCurrentUserId) { return false; } @@ -2268,9 +2320,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final int resolvedWindowId; IAccessibilityInteractionConnection connection = null; synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked( - UserHandle.getCallingUserId()); + UserHandle.getCallingUserId()); if (resolvedUserId != mCurrentUserId) { return false; } @@ -2311,9 +2366,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final int resolvedWindowId; IAccessibilityInteractionConnection connection = null; synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked( - UserHandle.getCallingUserId()); + UserHandle.getCallingUserId()); if (resolvedUserId != mCurrentUserId) { return false; } @@ -2346,9 +2404,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public boolean performGlobalAction(int action) { synchronized (mLock) { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked( - UserHandle.getCallingUserId()); + UserHandle.getCallingUserId()); if (resolvedUserId != mCurrentUserId) { return false; } @@ -3407,16 +3468,35 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0; } + private int resolveProfileParentLocked(int userId) { + if (userId != mCurrentUserId) { + final long identity = Binder.clearCallingIdentity(); + try { + UserInfo parent = mUserManager.getProfileParent(userId); + if (parent != null) { + return parent.getUserHandle().getIdentifier(); + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + return userId; + } + public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) { final int callingUid = Binder.getCallingUid(); if (callingUid == 0 || callingUid == Process.SYSTEM_UID || callingUid == Process.SHELL_UID) { - return mCurrentUserId; + if (userId == UserHandle.USER_CURRENT + || userId == UserHandle.USER_CURRENT_OR_SELF) { + return mCurrentUserId; + } + return resolveProfileParentLocked(userId); } final int callingUserId = UserHandle.getUserId(callingUid); if (callingUserId == userId) { - return userId; + return resolveProfileParentLocked(userId); } if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS) && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) { @@ -3673,8 +3753,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public void onChange(boolean selfChange, Uri uri) { if (mAccessibilityEnabledUri.equals(uri)) { synchronized (mLock) { - // We will update when the automation service dies. + // Profiles share the accessibility state of the parent. Therefore, + // we are checking for changes only the parent settings. UserState userState = getCurrentUserStateLocked(); + // We will update when the automation service dies. if (userState.mUiAutomationService == null) { if (readAccessibilityEnabledSettingLocked(userState)) { onUserStateChangedLocked(userState); @@ -3683,8 +3765,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } else if (mTouchExplorationEnabledUri.equals(uri)) { synchronized (mLock) { - // We will update when the automation service dies. + // Profiles share the accessibility state of the parent. Therefore, + // we are checking for changes only the parent settings. UserState userState = getCurrentUserStateLocked(); + // We will update when the automation service dies. if (userState.mUiAutomationService == null) { if (readTouchExplorationEnabledSettingLocked(userState)) { onUserStateChangedLocked(userState); @@ -3693,8 +3777,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } else if (mDisplayMagnificationEnabledUri.equals(uri)) { synchronized (mLock) { - // We will update when the automation service dies. + // Profiles share the accessibility state of the parent. Therefore, + // we are checking for changes only the parent settings. UserState userState = getCurrentUserStateLocked(); + // We will update when the automation service dies. if (userState.mUiAutomationService == null) { if (readDisplayMagnificationEnabledSettingLocked(userState)) { onUserStateChangedLocked(userState); @@ -3703,8 +3789,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } else if (mEnabledAccessibilityServicesUri.equals(uri)) { synchronized (mLock) { - // We will update when the automation service dies. + // Profiles share the accessibility state of the parent. Therefore, + // we are checking for changes only the parent settings. UserState userState = getCurrentUserStateLocked(); + // We will update when the automation service dies. if (userState.mUiAutomationService == null) { if (readEnabledAccessibilityServicesLocked(userState)) { onUserStateChangedLocked(userState); @@ -3713,8 +3801,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) { synchronized (mLock) { - // We will update when the automation service dies. + // Profiles share the accessibility state of the parent. Therefore, + // we are checking for changes only the parent settings. UserState userState = getCurrentUserStateLocked(); + // We will update when the automation service dies. if (userState.mUiAutomationService == null) { if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) { onUserStateChangedLocked(userState); @@ -3723,8 +3813,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } else if (mEnhancedWebAccessibilityUri.equals(uri)) { synchronized (mLock) { - // We will update when the automation service dies. + // Profiles share the accessibility state of the parent. Therefore, + // we are checking for changes only the parent settings. UserState userState = getCurrentUserStateLocked(); + // We will update when the automation service dies. if (userState.mUiAutomationService == null) { if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) { onUserStateChangedLocked(userState); @@ -3739,8 +3831,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { || mDisplayInversionUri.equals(uri) || mDisplayDaltonizerUri.equals(uri)) { synchronized (mLock) { - // We will update when the automation service dies. + // Profiles share the accessibility state of the parent. Therefore, + // we are checking for changes only the parent settings. UserState userState = getCurrentUserStateLocked(); + // We will update when the automation service dies. if (userState.mUiAutomationService == null) { if (readDisplayColorAdjustmentSettingsLocked(userState)) { updateDisplayColorAdjustmentSettingsLocked(userState); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 09e7e12..9f6dd0b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1327,12 +1327,14 @@ public final class ActivityManagerService extends ActivityManagerNative String host = ""; String port = ""; String exclList = ""; - String pacFileUrl = null; + String pacFileUrl = ""; if (proxy != null) { host = proxy.getHost(); port = Integer.toString(proxy.getPort()); exclList = proxy.getExclusionListAsString(); - pacFileUrl = proxy.getPacFileUrl().toString(); + if (proxy.getPacFileUrl() != null) { + pacFileUrl = proxy.getPacFileUrl().toString(); + } } synchronized (ActivityManagerService.this) { for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index fce86e8..4698587 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -444,7 +444,7 @@ public class NotificationManagerService extends SystemService { public static final class NotificationRecord { final StatusBarNotification sbn; - final SingleNotificationStats stats = new SingleNotificationStats(); + SingleNotificationStats stats; IBinder statusBarKey; NotificationRecord(StatusBarNotification sbn) @@ -1639,7 +1639,7 @@ public class NotificationManagerService extends SystemService { } else { old = mNotificationList.get(index); mNotificationList.set(index, r); - mUsageStats.registerUpdatedByApp(r); + mUsageStats.registerUpdatedByApp(r, old); // Make sure we don't lose the foreground service state. if (old != null) { notification.flags |= diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java index 45ab3d3..a60e95b 100644 --- a/services/core/java/com/android/server/notification/NotificationUsageStats.java +++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java @@ -58,6 +58,7 @@ public class NotificationUsageStats { * Called when a notification has been posted. */ public synchronized void registerPostedByApp(NotificationRecord notification) { + notification.stats = new SingleNotificationStats(); notification.stats.posttimeElapsedMs = SystemClock.elapsedRealtime(); for (AggregatedStats stats : getAggregatedStatsLocked(notification)) { stats.numPostedByApp++; @@ -68,7 +69,8 @@ public class NotificationUsageStats { /** * Called when a notification has been updated. */ - public void registerUpdatedByApp(NotificationRecord notification) { + public void registerUpdatedByApp(NotificationRecord notification, NotificationRecord old) { + notification.stats = old.stats; for (AggregatedStats stats : getAggregatedStatsLocked(notification)) { stats.numUpdatedByApp++; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 4e22b2a..1980d1e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -130,6 +130,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final boolean DBG = false; final Context mContext; + final UserManager mUserManager; final PowerManager.WakeLock mWakeLock; IPowerManager mIPowerManager; @@ -209,7 +210,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + action + " for user " + userHandle); mHandler.post(new Runnable() { public void run() { - handlePasswordExpirationNotification(getUserData(userHandle)); + handlePasswordExpirationNotification(userHandle); } }); } @@ -611,6 +612,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { */ public DevicePolicyManagerService(Context context) { mContext = context; + mUserManager = UserManager.get(mContext); mHasFeature = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_DEVICE_ADMIN); mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)) @@ -818,6 +820,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { sendAdminCommandLocked(admin, action, null); } + /** + * Send an update to one specific admin, get notified when that admin returns a result. + */ void sendAdminCommandLocked(ActiveAdmin admin, String action, BroadcastReceiver result) { Intent intent = new Intent(action); intent.setComponent(admin.info.getComponent()); @@ -832,12 +837,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + /** + * Send an update to all admins of a user that enforce a specified policy. + */ void sendAdminCommandLocked(String action, int reqPolicy, int userHandle) { final DevicePolicyData policy = getUserData(userHandle); final int count = policy.mAdminList.size(); if (count > 0) { for (int i = 0; i < count; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); + final ActiveAdmin admin = policy.mAdminList.get(i); if (admin.info.usesPolicy(reqPolicy)) { sendAdminCommandLocked(admin, action); } @@ -845,6 +853,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + /** + * Send an update intent to all admins of a user and its profiles. Only send to admins that + * enforce a specified policy. + */ + private void sendAdminCommandToSelfAndProfilesLocked(String action, int reqPolicy, + int userHandle) { + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo ui : profiles) { + int id = ui.getUserHandle().getIdentifier(); + sendAdminCommandLocked(action, reqPolicy, id); + } + } + void removeActiveAdminLocked(final ComponentName adminReceiver, int userHandle) { final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle); if (admin != null) { @@ -1190,23 +1211,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - private void handlePasswordExpirationNotification(DevicePolicyData policy) { + private void handlePasswordExpirationNotification(int userHandle) { synchronized (this) { final long now = System.currentTimeMillis(); - final int N = policy.mAdminList.size(); - if (N <= 0) { - return; - } - for (int i=0; i < N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD) - && admin.passwordExpirationTimeout > 0L - && admin.passwordExpirationDate > 0L - && now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS) { - sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING); + + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo ui : profiles) { + int profileUserHandle = ui.getUserHandle().getIdentifier(); + final DevicePolicyData policy = getUserData(profileUserHandle); + final int count = policy.mAdminList.size(); + if (count > 0) { + for (int i = 0; i < count; i++) { + final ActiveAdmin admin = policy.mAdminList.get(i); + if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD) + && admin.passwordExpirationTimeout > 0L + && now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS + && admin.passwordExpirationDate > 0L) { + sendAdminCommandLocked(admin, + DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING); + } + } } } - setExpirationAlarmCheckLocked(mContext, policy); + setExpirationAlarmCheckLocked(mContext, getUserData(userHandle)); } } @@ -1216,8 +1243,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled(); if (! hasCert) { if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) { - UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - for (UserInfo user : um.getUsers()) { + for (UserInfo user : mUserManager.getUsers()) { notificationManager.cancelAsUser( null, MONITORING_CERT_NOTIFICATION_ID, user.getUserHandle()); } @@ -1256,8 +1282,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // If this is a boot intent, this will fire for each user. But if this is a storage changed // intent, it will fire once, so we need to notify all users. if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) { - UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - for (UserInfo user : um.getUsers()) { + for (UserInfo user : mUserManager.getUsers()) { notificationManager.notifyAsUser( null, MONITORING_CERT_NOTIFICATION_ID, noti, user.getUserHandle()); } @@ -1434,18 +1459,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforceCrossUserPermission(userHandle); synchronized (this) { int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; - DevicePolicyData policy = getUserData(userHandle); if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); return admin != null ? admin.passwordQuality : mode; } - final int N = policy.mAdminList.size(); - for (int i=0; i<N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (mode < admin.passwordQuality) { - mode = admin.passwordQuality; + // Return strictest policy for this user and profiles that are visible from this user. + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (mode < admin.passwordQuality) { + mode = admin.passwordQuality; + } } } return mode; @@ -1476,7 +1505,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } enforceCrossUserPermission(userHandle); synchronized (this) { - DevicePolicyData policy = getUserData(userHandle); int length = 0; if (who != null) { @@ -1484,11 +1512,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admin != null ? admin.minimumPasswordLength : length; } - final int N = policy.mAdminList.size(); - for (int i=0; i<N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (length < admin.minimumPasswordLength) { - length = admin.minimumPasswordLength; + // Return strictest policy for this user and profiles that are visible from this user. + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (length < admin.minimumPasswordLength) { + length = admin.minimumPasswordLength; + } } } return length; @@ -1519,7 +1552,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } enforceCrossUserPermission(userHandle); synchronized (this) { - DevicePolicyData policy = getUserData(userHandle); int length = 0; if (who != null) { @@ -1527,11 +1559,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admin != null ? admin.passwordHistoryLength : length; } - final int N = policy.mAdminList.size(); - for (int i = 0; i < N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (length < admin.passwordHistoryLength) { - length = admin.passwordHistoryLength; + // Return strictest policy for this user and profiles that are visible from this user. + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i = 0; i < N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (length < admin.passwordHistoryLength) { + length = admin.passwordHistoryLength; + } } } return length; @@ -1577,19 +1614,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } enforceCrossUserPermission(userHandle); synchronized (this) { + long timeout = 0L; + if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); - return admin != null ? admin.passwordExpirationTimeout : 0L; + return admin != null ? admin.passwordExpirationTimeout : timeout; } - long timeout = 0L; - DevicePolicyData policy = getUserData(userHandle); - final int N = policy.mAdminList.size(); - for (int i = 0; i < N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (timeout == 0L || (admin.passwordExpirationTimeout != 0L - && timeout > admin.passwordExpirationTimeout)) { - timeout = admin.passwordExpirationTimeout; + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i = 0; i < N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (timeout == 0L || (admin.passwordExpirationTimeout != 0L + && timeout > admin.passwordExpirationTimeout)) { + timeout = admin.passwordExpirationTimeout; + } } } return timeout; @@ -1601,19 +1642,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * Returns 0 if not configured. */ private long getPasswordExpirationLocked(ComponentName who, int userHandle) { + long timeout = 0L; + if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); - return admin != null ? admin.passwordExpirationDate : 0L; + return admin != null ? admin.passwordExpirationDate : timeout; } - long timeout = 0L; - DevicePolicyData policy = getUserData(userHandle); - final int N = policy.mAdminList.size(); - for (int i = 0; i < N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (timeout == 0L || (admin.passwordExpirationDate != 0 - && timeout > admin.passwordExpirationDate)) { - timeout = admin.passwordExpirationDate; + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i = 0; i < N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (timeout == 0L || (admin.passwordExpirationDate != 0 + && timeout > admin.passwordExpirationDate)) { + timeout = admin.passwordExpirationDate; + } } } return timeout; @@ -1660,12 +1705,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admin != null ? admin.minimumPasswordUpperCase : length; } - DevicePolicyData policy = getUserData(userHandle); - final int N = policy.mAdminList.size(); - for (int i=0; i<N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (length < admin.minimumPasswordUpperCase) { - length = admin.minimumPasswordUpperCase; + // Return strictest policy for this user and profiles that are visible from this user. + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (length < admin.minimumPasswordUpperCase) { + length = admin.minimumPasswordUpperCase; + } } } return length; @@ -1700,12 +1749,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admin != null ? admin.minimumPasswordLowerCase : length; } - DevicePolicyData policy = getUserData(userHandle); - final int N = policy.mAdminList.size(); - for (int i=0; i<N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (length < admin.minimumPasswordLowerCase) { - length = admin.minimumPasswordLowerCase; + // Return strictest policy for this user and profiles that are visible from this user. + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (length < admin.minimumPasswordLowerCase) { + length = admin.minimumPasswordLowerCase; + } } } return length; @@ -1743,12 +1796,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admin != null ? admin.minimumPasswordLetters : length; } - DevicePolicyData policy = getUserData(userHandle); - final int N = policy.mAdminList.size(); - for (int i=0; i<N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (length < admin.minimumPasswordLetters) { - length = admin.minimumPasswordLetters; + // Return strictest policy for this user and profiles that are visible from this user. + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (length < admin.minimumPasswordLetters) { + length = admin.minimumPasswordLetters; + } } } return length; @@ -1786,12 +1843,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admin != null ? admin.minimumPasswordNumeric : length; } - DevicePolicyData policy = getUserData(userHandle); - final int N = policy.mAdminList.size(); - for (int i = 0; i < N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (length < admin.minimumPasswordNumeric) { - length = admin.minimumPasswordNumeric; + // Return strictest policy for this user and profiles that are visible from this user. + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i = 0; i < N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (length < admin.minimumPasswordNumeric) { + length = admin.minimumPasswordNumeric; + } } } return length; @@ -1829,12 +1890,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admin != null ? admin.minimumPasswordSymbols : length; } - DevicePolicyData policy = getUserData(userHandle); - final int N = policy.mAdminList.size(); - for (int i=0; i<N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (length < admin.minimumPasswordSymbols) { - length = admin.minimumPasswordSymbols; + // Return strictest policy for this user and profiles that are visible from this user. + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (length < admin.minimumPasswordSymbols) { + length = admin.minimumPasswordSymbols; + } } } return length; @@ -1872,12 +1937,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admin != null ? admin.minimumPasswordNonLetter : length; } - DevicePolicyData policy = getUserData(userHandle); - final int N = policy.mAdminList.size(); - for (int i=0; i<N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (length < admin.minimumPasswordNonLetter) { - length = admin.minimumPasswordNonLetter; + // Return strictest policy for this user and profiles that are visible from this user. + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (length < admin.minimumPasswordNonLetter) { + length = admin.minimumPasswordNonLetter; + } } } return length; @@ -1889,8 +1958,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return true; } enforceCrossUserPermission(userHandle); + synchronized (this) { - DevicePolicyData policy = getUserData(userHandle); + + // The active password is stored in the user that runs the launcher + // If the user this is called from is part of a profile group, that is the parent + // of the group. + UserInfo parent = getProfileParent(userHandle); + int id = parent == null ? userHandle : parent.id; + DevicePolicyData policy = getUserData(id); + // 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, @@ -1912,13 +1989,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } 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 getUserData(userHandle).mFailedPasswordAttempts; + + // The active password is stored in the parent. + DevicePolicyData policy = getUserData(getProfileParent(userHandle).id); + + return policy.mFailedPasswordAttempts; } } @@ -1928,6 +2008,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } enforceCrossUserPermission(userHandle); synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } // This API can only be called by an active device admin, // so try to retrieve it to check that the caller is one. getActiveAdminForCallerLocked(who, @@ -1947,7 +2030,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } enforceCrossUserPermission(userHandle); synchronized (this) { - DevicePolicyData policy = getUserData(userHandle); int count = 0; if (who != null) { @@ -1955,14 +2037,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admin != null ? admin.maximumFailedPasswordsForWipe : count; } - final int N = policy.mAdminList.size(); - for (int i=0; i<N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (count == 0) { - count = admin.maximumFailedPasswordsForWipe; - } else if (admin.maximumFailedPasswordsForWipe != 0 - && count > admin.maximumFailedPasswordsForWipe) { - count = admin.maximumFailedPasswordsForWipe; + // Return strictest policy for this user and profiles that are visible from this user. + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (count == 0) { + count = admin.maximumFailedPasswordsForWipe; + } else if (admin.maximumFailedPasswordsForWipe != 0 + && count > admin.maximumFailedPasswordsForWipe) { + count = admin.maximumFailedPasswordsForWipe; + } } } return count; @@ -1974,9 +2061,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return false; } enforceCrossUserPermission(userHandle); + enforceNotManagedProfile(userHandle, "reset the password"); + int quality; synchronized (this) { - // This API can only be called by an active device admin, + // 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_RESET_PASSWORD); @@ -2154,15 +2243,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return admin != null ? admin.maximumTimeToUnlock : time; } - DevicePolicyData policy = getUserData(userHandle); - final int N = policy.mAdminList.size(); - for (int i=0; i<N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (time == 0) { - time = admin.maximumTimeToUnlock; - } else if (admin.maximumTimeToUnlock != 0 - && time > admin.maximumTimeToUnlock) { - time = admin.maximumTimeToUnlock; + // Return strictest policy for this user and profiles that are visible from this user. + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier()); + final int N = policy.mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (time == 0) { + time = admin.maximumTimeToUnlock; + } else if (admin.maximumTimeToUnlock != 0 + && time > admin.maximumTimeToUnlock) { + time = admin.maximumTimeToUnlock; + } } } return time; @@ -2320,7 +2413,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public void run() { try { ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER); - ((UserManager) mContext.getSystemService(Context.USER_SERVICE)) + (mUserManager) .removeUser(userHandle); } catch (RemoteException re) { // Shouldn't happen @@ -2368,6 +2461,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } enforceCrossUserPermission(userHandle); + enforceNotManagedProfile(userHandle, "set the active password"); + mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); DevicePolicyData p = getUserData(userHandle); @@ -2396,7 +2491,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { saveSettingsLocked(userHandle); updatePasswordExpirationsLocked(userHandle); setExpirationAlarmCheckLocked(mContext, p); - sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED, + sendAdminCommandToSelfAndProfilesLocked( + DeviceAdminReceiver.ACTION_PASSWORD_CHANGED, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle); } finally { Binder.restoreCallingIdentity(ident); @@ -2406,26 +2502,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } /** - * Called any time the device password is updated. Resets all password expiration clocks. + * Called any time the device password is updated. Resets all password expiration clocks. */ private void updatePasswordExpirationsLocked(int userHandle) { - DevicePolicyData policy = getUserData(userHandle); - final int N = policy.mAdminList.size(); - if (N > 0) { - for (int i=0; i<N; i++) { - ActiveAdmin admin = policy.mAdminList.get(i); - if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) { - long timeout = admin.passwordExpirationTimeout; - long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L; - admin.passwordExpirationDate = expiration; + List<UserInfo> profiles = mUserManager.getProfiles(userHandle); + for (UserInfo userInfo : profiles) { + int profileId = userInfo.getUserHandle().getIdentifier(); + DevicePolicyData policy = getUserData(profileId); + final int N = policy.mAdminList.size(); + if (N > 0) { + for (int i=0; i<N; i++) { + ActiveAdmin admin = policy.mAdminList.get(i); + if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) { + long timeout = admin.passwordExpirationTimeout; + long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L; + admin.passwordExpirationDate = expiration; + } + } } + saveSettingsLocked(profileId); } - saveSettingsLocked(userHandle); - } } public void reportFailedPasswordAttempt(int userHandle) { enforceCrossUserPermission(userHandle); + enforceNotManagedProfile(userHandle, "report failed password attempt"); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); @@ -2440,7 +2541,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (max > 0 && policy.mFailedPasswordAttempts >= max) { wipeDeviceOrUserLocked(0, userHandle); } - sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED, + sendAdminCommandToSelfAndProfilesLocked( + DeviceAdminReceiver.ACTION_PASSWORD_FAILED, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle); } } finally { @@ -2463,7 +2565,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { policy.mPasswordOwner = -1; saveSettingsLocked(userHandle); if (mHasFeature) { - sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED, + sendAdminCommandToSelfAndProfilesLocked( + DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle); } } finally { @@ -2492,7 +2595,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // Scan through active admins and find if anyone has already // set the global proxy. Set<ComponentName> compSet = policy.mAdminMap.keySet(); - for (ComponentName component : compSet) { + for (ComponentName component : compSet) { ActiveAdmin ap = policy.mAdminMap.get(component); if ((ap.specifiesGlobalProxy) && (!component.equals(who))) { // Another admin already sets the global proxy @@ -2521,8 +2624,11 @@ 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(policy); - Binder.restoreCallingIdentity(origId); + try { + resetGlobalProxyLocked(policy); + } finally { + Binder.restoreCallingIdentity(origId); + } return null; } } @@ -2907,8 +3013,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null); - UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - if (um.getUserInfo(userHandle) == null) { + if (mUserManager.getUserInfo(userHandle) == null) { // User doesn't exist. throw new IllegalArgumentException( "Attempted to set profile owner for invalid userId: " + userHandle); @@ -2954,10 +3059,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int userId = UserHandle.getCallingUserId(); Slog.d(LOG_TAG, "Enabling the profile for: " + userId); - UserManager um = UserManager.get(mContext); long id = Binder.clearCallingIdentity(); try { - um.setUserEnabled(userId); + mUserManager.setUserEnabled(userId); Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED); intent.putExtra(Intent.EXTRA_USER, new UserHandle(UserHandle.getCallingUserId())); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | @@ -3021,6 +3125,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + private void enforceNotManagedProfile(int userHandle, String message) { + if(isManagedProfile(userHandle)) { + throw new SecurityException("You can not " + message + " from a managed profile. "); + } + } + + private UserInfo getProfileParent(int userHandle) { + long ident = Binder.clearCallingIdentity(); + try { + return mUserManager.getProfileParent(userHandle); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private boolean isManagedProfile(int userHandle) { + long ident = Binder.clearCallingIdentity(); + try { + return mUserManager.getUserInfo(userHandle).isManagedProfile(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + private void enableIfNecessary(String packageName, int userId) { try { IPackageManager ipm = AppGlobals.getPackageManager(); @@ -3124,10 +3252,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); - UserManager um = UserManager.get(mContext); long id = Binder.clearCallingIdentity(); try { - um.setApplicationRestrictions(packageName, settings, userHandle); + mUserManager.setApplicationRestrictions(packageName, settings, userHandle); } finally { restoreCallingIdentity(id); } @@ -3191,10 +3318,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); - UserManager um = UserManager.get(mContext); long id = Binder.clearCallingIdentity(); try { - return um.getApplicationRestrictions(packageName, userHandle); + return mUserManager.getApplicationRestrictions(packageName, userHandle); } finally { restoreCallingIdentity(id); } @@ -3211,10 +3337,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); - UserManager um = UserManager.get(mContext); long id = Binder.clearCallingIdentity(); try { - um.setUserRestriction(key, enabled, userHandle); + mUserManager.setUserRestriction(key, enabled, userHandle); } finally { restoreCallingIdentity(id); } |