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);
}