Merge "Remove expansion and clear button."
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 @@
     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 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 @@
     }
 
     /**
-     * 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 @@
     }
 
     /**
-     * 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 @@
 
     /**
      * 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 @@
 
     /**
      * 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 @@
 
     /**
      * 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 @@
 
     /**
      * 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 @@
 
     /**
      * 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 @@
     }
 
     /**
-     * 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 @@
     /**
      * 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 @@
 
     /**
      * 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 @@
      * {@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 @@
     }
 
     /**
-     * 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 @@
             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 @@
 # 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 @@
 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.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 @@
 
     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 @@
         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 @@
         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 @@
                 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 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 @@
                     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 @@
     @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 @@
     @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 @@
     @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 @@
             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 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 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 @@
     @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 @@
                 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 @@
             }
 
             // 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 @@
         @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 @@
         @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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 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 @@
                     & 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 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 @@
                 }
             } 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 @@
                 }
             } 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 @@
                 }
             } 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 @@
                 }
             } 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 @@
                 }
             } 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 @@
                     || 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 @@
                 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 static final class NotificationRecord
     {
         final StatusBarNotification sbn;
-        final SingleNotificationStats stats = new SingleNotificationStats();
+        SingleNotificationStats stats;
         IBinder statusBarKey;
 
         NotificationRecord(StatusBarNotification sbn)
@@ -1639,7 +1639,7 @@
                     } 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 @@
      * 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 @@
     /**
      * 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 @@
     private static final boolean DBG = false;
 
     final Context mContext;
+    final UserManager mUserManager;
     final PowerManager.WakeLock mWakeLock;
 
     IPowerManager mIPowerManager;
@@ -209,7 +210,7 @@
                         + action + " for user " + userHandle);
                 mHandler.post(new Runnable() {
                     public void run() {
-                        handlePasswordExpirationNotification(getUserData(userHandle));
+                        handlePasswordExpirationNotification(userHandle);
                     }
                 });
             }
@@ -611,6 +612,7 @@
      */
     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 @@
         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 @@
         }
     }
 
+    /**
+     * 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 @@
         }
     }
 
+    /**
+     * 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 @@
         }
     }
 
-    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 @@
         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 @@
         // 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 @@
         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 @@
         }
         enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            DevicePolicyData policy = getUserData(userHandle);
             int length = 0;
 
             if (who != null) {
@@ -1484,11 +1512,16 @@
                 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 @@
         }
         enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            DevicePolicyData policy = getUserData(userHandle);
             int length = 0;
 
             if (who != null) {
@@ -1527,11 +1559,16 @@
                 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 @@
         }
         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 @@
      * 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 @@
                 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 @@
                 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 @@
                 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 @@
                 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 @@
                 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 @@
                 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 @@
             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 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 @@
         }
         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 @@
         }
         enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            DevicePolicyData policy = getUserData(userHandle);
             int count = 0;
 
             if (who != null) {
@@ -1955,14 +2037,19 @@
                 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 @@
             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 @@
                 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 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 @@
             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 @@
                     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 @@
     }
 
     /**
-     * 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 @@
                     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 @@
                     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 @@
             // 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 @@
             // 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 @@
         }
         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 @@
             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 @@
         }
     }
 
+    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 @@
             }
             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 @@
             }
             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 @@
             }
             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);
             }