summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2012-09-14 23:20:08 -0700
committerAmith Yamasani <yamasani@google.com>2012-09-18 14:28:33 -0700
commit599dd7ce9adf8ca067cefb0b191a5ac20ec35a79 (patch)
tree37665dd877c99b5c0fd921123adec8d4ea3d737a /services
parent24ed2769130a8f9df44e7fc22be52b6282e724c3 (diff)
downloadframeworks_base-599dd7ce9adf8ca067cefb0b191a5ac20ec35a79.zip
frameworks_base-599dd7ce9adf8ca067cefb0b191a5ac20ec35a79.tar.gz
frameworks_base-599dd7ce9adf8ca067cefb0b191a5ac20ec35a79.tar.bz2
DevicePolicyManager per user
Bug: 7136483 Store device policy information for each user and apply them when user switches. Global proxy can only be controlled by owner. Camera restriction applies to all users, if any one has an admin that disables it. Storage encryption can only be controlled by owner, although other users can query the state. Wipe data will only remove the user if non-zero, wipe the device, if zero. Change-Id: I359be46c1bc3828fd13d4be3228f11495081c8f2
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/DevicePolicyManagerService.java970
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java4
-rw-r--r--services/java/com/android/server/wm/KeyguardDisableHandler.java14
3 files changed, 604 insertions, 384 deletions
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 28a4310..aec5d6e 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -16,7 +16,6 @@
package com.android.server;
-import com.android.internal.content.PackageMonitor;
import com.android.internal.os.storage.ExternalStorageFormatter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
@@ -28,7 +27,9 @@ import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import android.app.Activity;
+import android.app.ActivityManagerNative;
import android.app.AlarmManager;
+import android.app.AppGlobals;
import android.app.PendingIntent;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DeviceAdminReceiver;
@@ -40,6 +41,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
@@ -49,6 +51,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IPowerManager;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RecoverySystem;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -56,10 +59,12 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.Xml;
import android.view.IWindowManager;
import android.view.WindowManagerPolicy;
@@ -82,56 +87,86 @@ import java.util.Set;
* Implementation of the device policy APIs.
*/
public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+ private static final String DEVICE_POLICIES_XML = "device_policies.xml";
+
private static final String TAG = "DevicePolicyManagerService";
private static final int REQUEST_EXPIRE_PASSWORD = 5571;
- private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * 86400 * 1000; // 5 days, in ms
+ private static final long MS_PER_DAY = 86400 * 1000;
+
+ private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * MS_PER_DAY; // 5 days, in ms
protected static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION
= "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
- private static final long MS_PER_DAY = 86400 * 1000;
+ private static final boolean DBG = false;
final Context mContext;
- final MyPackageMonitor mMonitor;
final PowerManager.WakeLock mWakeLock;
IPowerManager mIPowerManager;
IWindowManager mIWindowManager;
- int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
- int mActivePasswordLength = 0;
- int mActivePasswordUpperCase = 0;
- int mActivePasswordLowerCase = 0;
- int mActivePasswordLetters = 0;
- int mActivePasswordNumeric = 0;
- int mActivePasswordSymbols = 0;
- int mActivePasswordNonLetter = 0;
- int mFailedPasswordAttempts = 0;
-
- int mPasswordOwner = -1;
- Handler mHandler = new Handler();
+ public static class DevicePolicyData {
+ int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ int mActivePasswordLength = 0;
+ int mActivePasswordUpperCase = 0;
+ int mActivePasswordLowerCase = 0;
+ int mActivePasswordLetters = 0;
+ int mActivePasswordNumeric = 0;
+ int mActivePasswordSymbols = 0;
+ int mActivePasswordNonLetter = 0;
+ int mFailedPasswordAttempts = 0;
+
+ int mUserHandle;;
+ int mPasswordOwner = -1;
+ long mLastMaximumTimeToLock = -1;
+
+ final HashMap<ComponentName, ActiveAdmin> mAdminMap
+ = new HashMap<ComponentName, ActiveAdmin>();
+ final ArrayList<ActiveAdmin> mAdminList
+ = new ArrayList<ActiveAdmin>();
+
+ public DevicePolicyData(int userHandle) {
+ mUserHandle = userHandle;
+ }
+ }
- long mLastMaximumTimeToLock = -1;
+ final SparseArray<DevicePolicyData> mUserData = new SparseArray<DevicePolicyData>();
- final HashMap<ComponentName, ActiveAdmin> mAdminMap
- = new HashMap<ComponentName, ActiveAdmin>();
- final ArrayList<ActiveAdmin> mAdminList
- = new ArrayList<ActiveAdmin>();
+ Handler mHandler = new Handler();
BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
+ final String action = intent.getAction();
+ final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ getSendingUserId());
if (Intent.ACTION_BOOT_COMPLETED.equals(action)
|| ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
- Slog.v(TAG, "Sending password expiration notifications for action " + action);
+ Slog.v(TAG, "Sending password expiration notifications for action " + action
+ + " for user " + userHandle);
mHandler.post(new Runnable() {
public void run() {
- handlePasswordExpirationNotification();
+ handlePasswordExpirationNotification(getUserData(userHandle));
}
});
+ } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+ removeUserData(userHandle);
+ } else if (Intent.ACTION_USER_STARTED.equals(action)
+ || Intent.ACTION_PACKAGE_CHANGED.equals(action)
+ || Intent.ACTION_PACKAGE_REMOVED.equals(action)
+ || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
+
+ if (Intent.ACTION_USER_STARTED.equals(action)) {
+ // Reset the policy data
+ synchronized (DevicePolicyManagerService.this) {
+ mUserData.remove(userHandle);
+ }
+ }
+
+ handlePackagesChanged(userHandle);
}
}
};
@@ -194,6 +229,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int getUid() { return info.getActivityInfo().applicationInfo.uid; }
+ public UserHandle getUserHandle() {
+ return new UserHandle(UserHandle.getUserId(info.getActivityInfo().applicationInfo.uid));
+ }
+
void writeToXml(XmlSerializer out)
throws IllegalArgumentException, IllegalStateException, IOException {
out.startTag(null, "policies");
@@ -421,39 +460,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- class MyPackageMonitor extends PackageMonitor {
- @Override
- public void onSomePackagesChanged() {
- synchronized (DevicePolicyManagerService.this) {
- boolean removed = false;
- for (int i=mAdminList.size()-1; i>=0; i--) {
- ActiveAdmin aa = mAdminList.get(i);
- int change = isPackageDisappearing(aa.info.getPackageName());
- if (change == PACKAGE_PERMANENT_CHANGE
- || change == PACKAGE_TEMPORARY_CHANGE) {
- Slog.w(TAG, "Admin unexpectedly uninstalled: "
- + aa.info.getComponent());
- removed = true;
- mAdminList.remove(i);
- } else if (isPackageModified(aa.info.getPackageName())) {
- try {
- mContext.getPackageManager().getReceiverInfo(
- aa.info.getComponent(), 0);
- } catch (NameNotFoundException e) {
- Slog.w(TAG, "Admin package change removed component: "
- + aa.info.getComponent());
- removed = true;
- mAdminList.remove(i);
- }
- }
- }
- if (removed) {
- validatePasswordOwnerLocked();
- syncDeviceCapabilitiesLocked();
- saveSettingsLocked();
+ private void handlePackagesChanged(int userHandle) {
+ boolean removed = false;
+ Slog.d(TAG, "Handling package changes for user " + userHandle);
+ DevicePolicyData policy = getUserData(userHandle);
+ IPackageManager pm = AppGlobals.getPackageManager();
+ for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
+ ActiveAdmin aa = policy.mAdminList.get(i);
+ try {
+ if (pm.getPackageInfo(aa.info.getPackageName(), 0, userHandle) == null
+ || pm.getReceiverInfo(aa.info.getComponent(), 0, userHandle) == null) {
+ removed = true;
+ policy.mAdminList.remove(i);
}
+ } catch (RemoteException re) {
+ // Shouldn't happen
}
}
+ if (removed) {
+ validatePasswordOwnerLocked(policy);
+ syncDeviceCapabilitiesLocked(policy);
+ saveSettingsLocked(policy.mUserHandle);
+ }
}
/**
@@ -461,22 +489,62 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
*/
public DevicePolicyManagerService(Context context) {
mContext = context;
- mMonitor = new MyPackageMonitor();
- mMonitor.register(context, null, true);
mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE))
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION);
- context.registerReceiver(mReceiver, filter);
+ filter.addAction(Intent.ACTION_USER_REMOVED);
+ filter.addAction(Intent.ACTION_USER_STARTED);
+ context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
+ filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+ filter.addDataScheme("package");
+ context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
+ }
+
+ /**
+ * Creates and loads the policy data from xml.
+ * @param userHandle the user for whom to load the policy data
+ * @return
+ */
+ DevicePolicyData getUserData(int userHandle) {
+ synchronized (this) {
+ DevicePolicyData policy = mUserData.get(userHandle);
+ if (policy == null) {
+ policy = new DevicePolicyData(userHandle);
+ mUserData.append(userHandle, policy);
+ loadSettingsLocked(policy, userHandle);
+ }
+ return policy;
+ }
+ }
+
+ void removeUserData(int userHandle) {
+ synchronized (this) {
+ if (userHandle == UserHandle.USER_OWNER) {
+ Slog.w(TAG, "Tried to remove device policy file for user 0! Ignoring.");
+ return;
+ }
+ DevicePolicyData policy = mUserData.get(userHandle);
+ if (policy != null) {
+ mUserData.remove(userHandle);
+ }
+ File policyFile = new File(Environment.getUserSystemDirectory(userHandle),
+ DEVICE_POLICIES_XML);
+ policyFile.delete();
+ Slog.i(TAG, "Removed device policy file " + policyFile.getAbsolutePath());
+ }
}
/**
* Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration
* reminders. Clears alarm if no expirations are configured.
*/
- protected void setExpirationAlarmCheckLocked(Context context) {
- final long expiration = getPasswordExpirationLocked(null);
+ protected void setExpirationAlarmCheckLocked(Context context, DevicePolicyData policy) {
+ final long expiration = getPasswordExpirationLocked(null, policy.mUserHandle);
final long now = System.currentTimeMillis();
final long timeToExpire = expiration - now;
final long alarmTime;
@@ -499,9 +567,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
long token = Binder.clearCallingIdentity();
try {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- PendingIntent pi = PendingIntent.getBroadcast(context, REQUEST_EXPIRE_PASSWORD,
+ PendingIntent pi = PendingIntent.getBroadcastAsUser(context, REQUEST_EXPIRE_PASSWORD,
new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
- PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT,
+ new UserHandle(policy.mUserHandle));
am.cancel(pi);
if (alarmTime != 0) {
am.set(AlarmManager.RTC, alarmTime, pi);
@@ -527,8 +596,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return mIWindowManager;
}
- ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) {
- ActiveAdmin admin = mAdminMap.get(who);
+ ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) {
+ ActiveAdmin admin = getUserData(userHandle).mAdminMap.get(who);
if (admin != null
&& who.getPackageName().equals(admin.info.getActivityInfo().packageName)
&& who.getClassName().equals(admin.info.getActivityInfo().name)) {
@@ -540,8 +609,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
throws SecurityException {
final int callingUid = Binder.getCallingUid();
+ final int userHandle = UserHandle.getUserId(callingUid);
+ final DevicePolicyData policy = getUserData(userHandle);
if (who != null) {
- ActiveAdmin admin = mAdminMap.get(who);
+ ActiveAdmin admin = policy.mAdminMap.get(who);
if (admin == null) {
throw new SecurityException("No active admin " + who);
}
@@ -556,9 +627,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
return admin;
} else {
- final int N = mAdminList.size();
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
return admin;
}
@@ -579,18 +650,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
intent.putExtra("expiration", admin.passwordExpirationDate);
}
if (result != null) {
- mContext.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER,
+ mContext.sendOrderedBroadcastAsUser(intent, admin.getUserHandle(),
null, result, mHandler, Activity.RESULT_OK, null, null);
} else {
mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
}
}
- void sendAdminCommandLocked(String action, int reqPolicy) {
- final int N = mAdminList.size();
- if (N > 0) {
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ 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);
if (admin.info.usesPolicy(reqPolicy)) {
sendAdminCommandLocked(admin, action);
}
@@ -598,8 +670,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- void removeActiveAdminLocked(final ComponentName adminReceiver) {
- final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
+ void removeActiveAdminLocked(final ComponentName adminReceiver, int userHandle) {
+ final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (admin != null) {
sendAdminCommandLocked(admin,
DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED,
@@ -607,28 +679,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (DevicePolicyManagerService.this) {
+ int userHandle = admin.getUserHandle().getIdentifier();
+ DevicePolicyData policy = getUserData(userHandle);
boolean doProxyCleanup = admin.info.usesPolicy(
DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
- mAdminList.remove(admin);
- mAdminMap.remove(adminReceiver);
- validatePasswordOwnerLocked();
- syncDeviceCapabilitiesLocked();
+ policy.mAdminList.remove(admin);
+ policy.mAdminMap.remove(adminReceiver);
+ validatePasswordOwnerLocked(policy);
+ syncDeviceCapabilitiesLocked(policy);
if (doProxyCleanup) {
- resetGlobalProxyLocked();
+ resetGlobalProxyLocked(getUserData(userHandle));
}
- saveSettingsLocked();
- updateMaximumTimeToLockLocked();
+ saveSettingsLocked(userHandle);
+ updateMaximumTimeToLockLocked(policy);
}
}
});
}
}
- public DeviceAdminInfo findAdmin(ComponentName adminName) {
+ public DeviceAdminInfo findAdmin(ComponentName adminName, int userHandle) {
+ enforceCrossUserPermission(userHandle);
Intent resolveIntent = new Intent();
resolveIntent.setComponent(adminName);
List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
- resolveIntent, PackageManager.GET_META_DATA);
+ resolveIntent, PackageManager.GET_META_DATA, userHandle);
if (infos == null || infos.size() <= 0) {
throw new IllegalArgumentException("Unknown admin: " + adminName);
}
@@ -636,21 +711,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
try {
return new DeviceAdminInfo(mContext, infos.get(0));
} catch (XmlPullParserException e) {
- Slog.w(TAG, "Bad device admin requested: " + adminName, e);
+ Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e);
return null;
} catch (IOException e) {
- Slog.w(TAG, "Bad device admin requested: " + adminName, e);
+ Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e);
return null;
}
}
- private static JournaledFile makeJournaledFile() {
- final String base = "/data/system/device_policies.xml";
+ private static JournaledFile makeJournaledFile(int userHandle) {
+ final String base = userHandle == 0
+ ? "/data/system/" + DEVICE_POLICIES_XML
+ : new File(Environment.getUserSystemDirectory(userHandle), DEVICE_POLICIES_XML)
+ .getAbsolutePath();
return new JournaledFile(new File(base), new File(base + ".tmp"));
}
- private void saveSettingsLocked() {
- JournaledFile journal = makeJournaledFile();
+ private void saveSettingsLocked(int userHandle) {
+ DevicePolicyData policy = getUserData(userHandle);
+ JournaledFile journal = makeJournaledFile(userHandle);
FileOutputStream stream = null;
try {
stream = new FileOutputStream(journal.chooseForWrite(), false);
@@ -660,9 +739,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.startTag(null, "policies");
- final int N = mAdminList.size();
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- ActiveAdmin ap = mAdminList.get(i);
+ ActiveAdmin ap = policy.mAdminList.get(i);
if (ap != null) {
out.startTag(null, "admin");
out.attribute(null, "name", ap.info.getComponent().flattenToString());
@@ -671,32 +750,32 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- if (mPasswordOwner >= 0) {
+ if (policy.mPasswordOwner >= 0) {
out.startTag(null, "password-owner");
- out.attribute(null, "value", Integer.toString(mPasswordOwner));
+ out.attribute(null, "value", Integer.toString(policy.mPasswordOwner));
out.endTag(null, "password-owner");
}
- if (mFailedPasswordAttempts != 0) {
+ if (policy.mFailedPasswordAttempts != 0) {
out.startTag(null, "failed-password-attempts");
- out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts));
+ out.attribute(null, "value", Integer.toString(policy.mFailedPasswordAttempts));
out.endTag(null, "failed-password-attempts");
}
- if (mActivePasswordQuality != 0 || mActivePasswordLength != 0
- || mActivePasswordUpperCase != 0 || mActivePasswordLowerCase != 0
- || mActivePasswordLetters != 0 || mActivePasswordNumeric != 0
- || mActivePasswordSymbols != 0 || mActivePasswordNonLetter != 0) {
+ if (policy.mActivePasswordQuality != 0 || policy.mActivePasswordLength != 0
+ || policy.mActivePasswordUpperCase != 0 || policy.mActivePasswordLowerCase != 0
+ || policy.mActivePasswordLetters != 0 || policy.mActivePasswordNumeric != 0
+ || policy.mActivePasswordSymbols != 0 || policy.mActivePasswordNonLetter != 0) {
out.startTag(null, "active-password");
- out.attribute(null, "quality", Integer.toString(mActivePasswordQuality));
- out.attribute(null, "length", Integer.toString(mActivePasswordLength));
- out.attribute(null, "uppercase", Integer.toString(mActivePasswordUpperCase));
- out.attribute(null, "lowercase", Integer.toString(mActivePasswordLowerCase));
- out.attribute(null, "letters", Integer.toString(mActivePasswordLetters));
+ out.attribute(null, "quality", Integer.toString(policy.mActivePasswordQuality));
+ out.attribute(null, "length", Integer.toString(policy.mActivePasswordLength));
+ out.attribute(null, "uppercase", Integer.toString(policy.mActivePasswordUpperCase));
+ out.attribute(null, "lowercase", Integer.toString(policy.mActivePasswordLowerCase));
+ out.attribute(null, "letters", Integer.toString(policy.mActivePasswordLetters));
out.attribute(null, "numeric", Integer
- .toString(mActivePasswordNumeric));
- out.attribute(null, "symbols", Integer.toString(mActivePasswordSymbols));
- out.attribute(null, "nonletter", Integer.toString(mActivePasswordNonLetter));
+ .toString(policy.mActivePasswordNumeric));
+ out.attribute(null, "symbols", Integer.toString(policy.mActivePasswordSymbols));
+ out.attribute(null, "nonletter", Integer.toString(policy.mActivePasswordNonLetter));
out.endTag(null, "active-password");
}
@@ -705,7 +784,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.endDocument();
stream.close();
journal.commit();
- sendChangedNotification();
+ sendChangedNotification(userHandle);
} catch (IOException e) {
try {
if (stream != null) {
@@ -718,20 +797,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- private void sendChangedNotification() {
+ private void sendChangedNotification(int userHandle) {
Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
long ident = Binder.clearCallingIdentity();
try {
- // TODO: This shouldn't be sent to all users, if DPM is per user.
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle));
} finally {
Binder.restoreCallingIdentity(ident);
}
}
- private void loadSettingsLocked() {
- JournaledFile journal = makeJournaledFile();
+ private void loadSettingsLocked(DevicePolicyData policy, int userHandle) {
+ JournaledFile journal = makeJournaledFile(userHandle);
FileInputStream stream = null;
File file = journal.chooseForRead();
try {
@@ -760,40 +838,46 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
String name = parser.getAttributeValue(null, "name");
try {
DeviceAdminInfo dai = findAdmin(
- ComponentName.unflattenFromString(name));
+ ComponentName.unflattenFromString(name), userHandle);
+ if (DBG && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid)
+ != userHandle)) {
+ Slog.w(TAG, "findAdmin returned an incorrect uid "
+ + dai.getActivityInfo().applicationInfo.uid + " for user "
+ + userHandle);
+ }
if (dai != null) {
ActiveAdmin ap = new ActiveAdmin(dai);
ap.readFromXml(parser);
- mAdminMap.put(ap.info.getComponent(), ap);
- mAdminList.add(ap);
+ policy.mAdminMap.put(ap.info.getComponent(), ap);
+ policy.mAdminList.add(ap);
}
} catch (RuntimeException e) {
Slog.w(TAG, "Failed loading admin " + name, e);
}
} else if ("failed-password-attempts".equals(tag)) {
- mFailedPasswordAttempts = Integer.parseInt(
+ policy.mFailedPasswordAttempts = Integer.parseInt(
parser.getAttributeValue(null, "value"));
XmlUtils.skipCurrentTag(parser);
} else if ("password-owner".equals(tag)) {
- mPasswordOwner = Integer.parseInt(
+ policy.mPasswordOwner = Integer.parseInt(
parser.getAttributeValue(null, "value"));
XmlUtils.skipCurrentTag(parser);
} else if ("active-password".equals(tag)) {
- mActivePasswordQuality = Integer.parseInt(
+ policy.mActivePasswordQuality = Integer.parseInt(
parser.getAttributeValue(null, "quality"));
- mActivePasswordLength = Integer.parseInt(
+ policy.mActivePasswordLength = Integer.parseInt(
parser.getAttributeValue(null, "length"));
- mActivePasswordUpperCase = Integer.parseInt(
+ policy.mActivePasswordUpperCase = Integer.parseInt(
parser.getAttributeValue(null, "uppercase"));
- mActivePasswordLowerCase = Integer.parseInt(
+ policy.mActivePasswordLowerCase = Integer.parseInt(
parser.getAttributeValue(null, "lowercase"));
- mActivePasswordLetters = Integer.parseInt(
+ policy.mActivePasswordLetters = Integer.parseInt(
parser.getAttributeValue(null, "letters"));
- mActivePasswordNumeric = Integer.parseInt(
+ policy.mActivePasswordNumeric = Integer.parseInt(
parser.getAttributeValue(null, "numeric"));
- mActivePasswordSymbols = Integer.parseInt(
+ policy.mActivePasswordSymbols = Integer.parseInt(
parser.getAttributeValue(null, "symbols"));
- mActivePasswordNonLetter = Integer.parseInt(
+ policy.mActivePasswordNonLetter = Integer.parseInt(
parser.getAttributeValue(null, "nonletter"));
XmlUtils.skipCurrentTag(parser);
} else {
@@ -827,24 +911,24 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// a sanity check in case the two get out of sync; this should
// never normally happen.
LockPatternUtils utils = new LockPatternUtils(mContext);
- if (utils.getActivePasswordQuality() < mActivePasswordQuality) {
+ if (utils.getActivePasswordQuality() < policy.mActivePasswordQuality) {
Slog.w(TAG, "Active password quality 0x"
- + Integer.toHexString(mActivePasswordQuality)
+ + Integer.toHexString(policy.mActivePasswordQuality)
+ " does not match actual quality 0x"
+ Integer.toHexString(utils.getActivePasswordQuality()));
- mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
- mActivePasswordLength = 0;
- mActivePasswordUpperCase = 0;
- mActivePasswordLowerCase = 0;
- mActivePasswordLetters = 0;
- mActivePasswordNumeric = 0;
- mActivePasswordSymbols = 0;
- mActivePasswordNonLetter = 0;
+ policy.mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ policy.mActivePasswordLength = 0;
+ policy.mActivePasswordUpperCase = 0;
+ policy.mActivePasswordLowerCase = 0;
+ policy.mActivePasswordLetters = 0;
+ policy.mActivePasswordNumeric = 0;
+ policy.mActivePasswordSymbols = 0;
+ policy.mActivePasswordNonLetter = 0;
}
- validatePasswordOwnerLocked();
- syncDeviceCapabilitiesLocked();
- updateMaximumTimeToLockLocked();
+ validatePasswordOwnerLocked(policy);
+ syncDeviceCapabilitiesLocked(policy);
+ updateMaximumTimeToLockLocked(policy);
}
static void validateQualityConstant(int quality) {
@@ -862,19 +946,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+ Integer.toHexString(quality));
}
- void validatePasswordOwnerLocked() {
- if (mPasswordOwner >= 0) {
+ void validatePasswordOwnerLocked(DevicePolicyData policy) {
+ if (policy.mPasswordOwner >= 0) {
boolean haveOwner = false;
- for (int i=mAdminList.size()-1; i>=0; i--) {
- if (mAdminList.get(i).getUid() == mPasswordOwner) {
+ for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
+ if (policy.mAdminList.get(i).getUid() == policy.mPasswordOwner) {
haveOwner = true;
break;
}
}
if (!haveOwner) {
- Slog.w(TAG, "Previous password owner " + mPasswordOwner
+ Slog.w(TAG, "Previous password owner " + policy.mPasswordOwner
+ " no longer active; disabling");
- mPasswordOwner = -1;
+ policy.mPasswordOwner = -1;
}
}
}
@@ -883,11 +967,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* Pushes down policy information to the system for any policies related to general device
* capabilities that need to be enforced by lower level services (e.g. Camera services).
*/
- void syncDeviceCapabilitiesLocked() {
+ void syncDeviceCapabilitiesLocked(DevicePolicyData policy) {
// Ensure the status of the camera is synced down to the system. Interested native services
// should monitor this value and act accordingly.
boolean systemState = SystemProperties.getBoolean(SYSTEM_PROP_DISABLE_CAMERA, false);
- boolean cameraDisabled = getCameraDisabled(null);
+ boolean cameraDisabled = getCameraDisabled(null, policy.mUserHandle);
if (cameraDisabled != systemState) {
long token = Binder.clearCallingIdentity();
try {
@@ -903,19 +987,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public void systemReady() {
synchronized (this) {
- loadSettingsLocked();
+ loadSettingsLocked(getUserData(UserHandle.USER_OWNER), UserHandle.USER_OWNER);
}
}
- private void handlePasswordExpirationNotification() {
+ private void handlePasswordExpirationNotification(DevicePolicyData policy) {
synchronized (this) {
final long now = System.currentTimeMillis();
- final int N = mAdminList.size();
+ final int N = policy.mAdminList.size();
if (N <= 0) {
return;
}
for (int i=0; i < N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
&& admin.passwordExpirationTimeout > 0L
&& admin.passwordExpirationDate > 0L
@@ -923,7 +1007,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
}
}
- setExpirationAlarmCheckLocked(mContext);
+ setExpirationAlarmCheckLocked(mContext, policy);
}
}
@@ -931,27 +1015,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* @param adminReceiver The admin to add
* @param refreshing true = update an active admin, no error
*/
- public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing) {
+ public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+ enforceCrossUserPermission(userHandle);
- DeviceAdminInfo info = findAdmin(adminReceiver);
+ DevicePolicyData policy = getUserData(userHandle);
+ DeviceAdminInfo info = findAdmin(adminReceiver, userHandle);
if (info == null) {
throw new IllegalArgumentException("Bad admin: " + adminReceiver);
}
synchronized (this) {
long ident = Binder.clearCallingIdentity();
try {
- if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver) != null) {
+ if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) {
throw new IllegalArgumentException("Admin is already added");
}
ActiveAdmin newAdmin = new ActiveAdmin(info);
- mAdminMap.put(adminReceiver, newAdmin);
+ policy.mAdminMap.put(adminReceiver, newAdmin);
int replaceIndex = -1;
if (refreshing) {
- final int N = mAdminList.size();
+ final int N = policy.mAdminList.size();
for (int i=0; i < N; i++) {
- ActiveAdmin oldAdmin = mAdminList.get(i);
+ ActiveAdmin oldAdmin = policy.mAdminList.get(i);
if (oldAdmin.info.getComponent().equals(adminReceiver)) {
replaceIndex = i;
break;
@@ -959,11 +1045,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
if (replaceIndex == -1) {
- mAdminList.add(newAdmin);
+ policy.mAdminList.add(newAdmin);
} else {
- mAdminList.set(replaceIndex, newAdmin);
+ policy.mAdminList.set(replaceIndex, newAdmin);
}
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -971,15 +1057,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public boolean isAdminActive(ComponentName adminReceiver) {
+ public boolean isAdminActive(ComponentName adminReceiver, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
- return getActiveAdminUncheckedLocked(adminReceiver) != null;
+ return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;
}
}
- public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId) {
+ public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
- ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver);
+ ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (administrator == null) {
throw new SecurityException("No active admin " + adminReceiver);
}
@@ -987,25 +1075,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public List<ComponentName> getActiveAdmins() {
+ public List<ComponentName> getActiveAdmins(int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
if (N <= 0) {
return null;
}
ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
for (int i=0; i<N; i++) {
- res.add(mAdminList.get(i).info.getComponent());
+ res.add(policy.mAdminList.get(i).info.getComponent());
}
return res;
}
}
- public boolean packageHasActiveAdmins(String packageName) {
+ public boolean packageHasActiveAdmins(String packageName, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- if (mAdminList.get(i).info.getPackageName().equals(packageName)) {
+ if (policy.mAdminList.get(i).info.getPackageName().equals(packageName)) {
return true;
}
}
@@ -1013,9 +1105,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void removeActiveAdmin(ComponentName adminReceiver) {
+ public void removeActiveAdmin(ComponentName adminReceiver, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (admin == null) {
return;
}
@@ -1025,15 +1118,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
long ident = Binder.clearCallingIdentity();
try {
- removeActiveAdminLocked(adminReceiver);
+ removeActiveAdminLocked(adminReceiver, userHandle);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
- public void setPasswordQuality(ComponentName who, int quality) {
+ public void setPasswordQuality(ComponentName who, int quality, int userHandle) {
validateQualityConstant(quality);
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
@@ -1043,23 +1137,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.passwordQuality != quality) {
ap.passwordQuality = quality;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
}
}
- public int getPasswordQuality(ComponentName who) {
+ public int getPasswordQuality(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ DevicePolicyData policy = getUserData(userHandle);
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.passwordQuality : mode;
}
- final int N = mAdminList.size();
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (mode < admin.passwordQuality) {
mode = admin.passwordQuality;
}
@@ -1068,7 +1164,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setPasswordMinimumLength(ComponentName who, int length) {
+ public void setPasswordMinimumLength(ComponentName who, int length, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -1077,23 +1174,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordLength != length) {
ap.minimumPasswordLength = length;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
}
}
- public int getPasswordMinimumLength(ComponentName who) {
+ public int getPasswordMinimumLength(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
+ DevicePolicyData policy = getUserData(userHandle);
int length = 0;
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.minimumPasswordLength : length;
}
- final int N = mAdminList.size();
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (length < admin.minimumPasswordLength) {
length = admin.minimumPasswordLength;
}
@@ -1102,7 +1201,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setPasswordHistoryLength(ComponentName who, int length) {
+ public void setPasswordHistoryLength(ComponentName who, int length, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -1111,23 +1211,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.passwordHistoryLength != length) {
ap.passwordHistoryLength = length;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
}
}
- public int getPasswordHistoryLength(ComponentName who) {
+ public int getPasswordHistoryLength(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
+ DevicePolicyData policy = getUserData(userHandle);
int length = 0;
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.passwordHistoryLength : length;
}
- final int N = mAdminList.size();
+ final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (length < admin.passwordHistoryLength) {
length = admin.passwordHistoryLength;
}
@@ -1136,7 +1238,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setPasswordExpirationTimeout(ComponentName who, long timeout) {
+ public void setPasswordExpirationTimeout(ComponentName who, long timeout, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -1155,8 +1258,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+ DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)
.format(new Date(expiration)));
}
- saveSettingsLocked();
- setExpirationAlarmCheckLocked(mContext); // in case this is the first one
+ saveSettingsLocked(userHandle);
+ // in case this is the first one
+ setExpirationAlarmCheckLocked(mContext, getUserData(userHandle));
}
}
@@ -1164,17 +1268,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* Return a single admin's expiration cycle time, or the min of all cycle times.
* Returns 0 if not configured.
*/
- public long getPasswordExpirationTimeout(ComponentName who) {
+ public long getPasswordExpirationTimeout(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.passwordExpirationTimeout : 0L;
}
long timeout = 0L;
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (timeout == 0L || (admin.passwordExpirationTimeout != 0L
&& timeout > admin.passwordExpirationTimeout)) {
timeout = admin.passwordExpirationTimeout;
@@ -1188,16 +1294,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* Return a single admin's expiration date/time, or the min (soonest) for all admins.
* Returns 0 if not configured.
*/
- private long getPasswordExpirationLocked(ComponentName who) {
+ private long getPasswordExpirationLocked(ComponentName who, int userHandle) {
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.passwordExpirationDate : 0L;
}
long timeout = 0L;
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (timeout == 0L || (admin.passwordExpirationDate != 0
&& timeout > admin.passwordExpirationDate)) {
timeout = admin.passwordExpirationDate;
@@ -1206,13 +1313,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return timeout;
}
- public long getPasswordExpiration(ComponentName who) {
+ public long getPasswordExpiration(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
- return getPasswordExpirationLocked(who);
+ return getPasswordExpirationLocked(who, userHandle);
}
}
- public void setPasswordMinimumUpperCase(ComponentName who, int length) {
+ public void setPasswordMinimumUpperCase(ComponentName who, int length, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -1221,23 +1330,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordUpperCase != length) {
ap.minimumPasswordUpperCase = length;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
}
}
- public int getPasswordMinimumUpperCase(ComponentName who) {
+ public int getPasswordMinimumUpperCase(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
int length = 0;
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.minimumPasswordUpperCase : length;
}
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (length < admin.minimumPasswordUpperCase) {
length = admin.minimumPasswordUpperCase;
}
@@ -1246,7 +1357,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setPasswordMinimumLowerCase(ComponentName who, int length) {
+ public void setPasswordMinimumLowerCase(ComponentName who, int length, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -1255,23 +1367,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordLowerCase != length) {
ap.minimumPasswordLowerCase = length;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
}
}
- public int getPasswordMinimumLowerCase(ComponentName who) {
+ public int getPasswordMinimumLowerCase(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
int length = 0;
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.minimumPasswordLowerCase : length;
}
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (length < admin.minimumPasswordLowerCase) {
length = admin.minimumPasswordLowerCase;
}
@@ -1280,7 +1394,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setPasswordMinimumLetters(ComponentName who, int length) {
+ public void setPasswordMinimumLetters(ComponentName who, int length, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -1289,23 +1404,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordLetters != length) {
ap.minimumPasswordLetters = length;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
}
}
- public int getPasswordMinimumLetters(ComponentName who) {
+ public int getPasswordMinimumLetters(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
int length = 0;
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.minimumPasswordLetters : length;
}
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (length < admin.minimumPasswordLetters) {
length = admin.minimumPasswordLetters;
}
@@ -1314,7 +1431,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setPasswordMinimumNumeric(ComponentName who, int length) {
+ public void setPasswordMinimumNumeric(ComponentName who, int length, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -1323,23 +1441,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordNumeric != length) {
ap.minimumPasswordNumeric = length;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
}
}
- public int getPasswordMinimumNumeric(ComponentName who) {
+ public int getPasswordMinimumNumeric(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
int length = 0;
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.minimumPasswordNumeric : length;
}
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (length < admin.minimumPasswordNumeric) {
length = admin.minimumPasswordNumeric;
}
@@ -1348,7 +1468,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setPasswordMinimumSymbols(ComponentName who, int length) {
+ public void setPasswordMinimumSymbols(ComponentName who, int length, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -1357,23 +1478,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordSymbols != length) {
ap.minimumPasswordSymbols = length;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
}
}
- public int getPasswordMinimumSymbols(ComponentName who) {
+ public int getPasswordMinimumSymbols(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
int length = 0;
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.minimumPasswordSymbols : length;
}
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (length < admin.minimumPasswordSymbols) {
length = admin.minimumPasswordSymbols;
}
@@ -1382,7 +1505,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setPasswordMinimumNonLetter(ComponentName who, int length) {
+ public void setPasswordMinimumNonLetter(ComponentName who, int length, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -1391,23 +1515,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordNonLetter != length) {
ap.minimumPasswordNonLetter = length;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
}
}
- public int getPasswordMinimumNonLetter(ComponentName who) {
+ public int getPasswordMinimumNonLetter(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
int length = 0;
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.minimumPasswordNonLetter : length;
}
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (length < admin.minimumPasswordNonLetter) {
length = admin.minimumPasswordNonLetter;
}
@@ -1416,39 +1542,43 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public boolean isActivePasswordSufficient() {
+ public boolean isActivePasswordSufficient(int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
+ DevicePolicyData policy = getUserData(userHandle);
// 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_LIMIT_PASSWORD);
- if (mActivePasswordQuality < getPasswordQuality(null)
- || mActivePasswordLength < getPasswordMinimumLength(null)) {
+ if (policy.mActivePasswordQuality < getPasswordQuality(null, userHandle)
+ || policy.mActivePasswordLength < getPasswordMinimumLength(null, userHandle)) {
return false;
}
- if(mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
+ if (policy.mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
return true;
}
- return mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null)
- && mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null)
- && mActivePasswordLetters >= getPasswordMinimumLetters(null)
- && mActivePasswordNumeric >= getPasswordMinimumNumeric(null)
- && mActivePasswordSymbols >= getPasswordMinimumSymbols(null)
- && mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null);
+ return policy.mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null, userHandle)
+ && policy.mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null, userHandle)
+ && policy.mActivePasswordLetters >= getPasswordMinimumLetters(null, userHandle)
+ && policy.mActivePasswordNumeric >= getPasswordMinimumNumeric(null, userHandle)
+ && policy.mActivePasswordSymbols >= getPasswordMinimumSymbols(null, userHandle)
+ && policy.mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null, userHandle);
}
}
- public int getCurrentFailedPasswordAttempts() {
+ public int getCurrentFailedPasswordAttempts(int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
- return mFailedPasswordAttempts;
+ return getUserData(userHandle).mFailedPasswordAttempts;
}
}
- public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
+ public void setMaximumFailedPasswordsForWipe(ComponentName who, int num, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
@@ -1458,23 +1588,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
if (ap.maximumFailedPasswordsForWipe != num) {
ap.maximumFailedPasswordsForWipe = num;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
}
}
- public int getMaximumFailedPasswordsForWipe(ComponentName who) {
+ public int getMaximumFailedPasswordsForWipe(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
+ DevicePolicyData policy = getUserData(userHandle);
int count = 0;
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.maximumFailedPasswordsForWipe : count;
}
- final int N = mAdminList.size();
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (count == 0) {
count = admin.maximumFailedPasswordsForWipe;
} else if (admin.maximumFailedPasswordsForWipe != 0
@@ -1486,14 +1618,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public boolean resetPassword(String password, int flags) {
+ public boolean resetPassword(String password, int flags, int userHandle) {
+ enforceCrossUserPermission(userHandle);
int quality;
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_RESET_PASSWORD);
- quality = getPasswordQuality(null);
+ quality = getPasswordQuality(null, userHandle);
if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
int realQuality = LockPatternUtils.computePasswordQuality(password);
if (realQuality < quality
@@ -1506,7 +1639,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
quality = Math.max(realQuality, quality);
}
- int length = getPasswordMinimumLength(null);
+ int length = getPasswordMinimumLength(null, userHandle);
if (password.length() < length) {
Slog.w(TAG, "resetPassword: password length " + password.length()
+ " does not meet required length " + length);
@@ -1535,13 +1668,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
nonletter++;
}
}
- int neededLetters = getPasswordMinimumLetters(null);
+ int neededLetters = getPasswordMinimumLetters(null, userHandle);
if(letters < neededLetters) {
Slog.w(TAG, "resetPassword: number of letters " + letters
+ " does not meet required number of letters " + neededLetters);
return false;
}
- int neededNumbers = getPasswordMinimumNumeric(null);
+ int neededNumbers = getPasswordMinimumNumeric(null, userHandle);
if (numbers < neededNumbers) {
Slog
.w(TAG, "resetPassword: number of numerical digits " + numbers
@@ -1549,27 +1682,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+ neededNumbers);
return false;
}
- int neededLowerCase = getPasswordMinimumLowerCase(null);
+ int neededLowerCase = getPasswordMinimumLowerCase(null, userHandle);
if (lowercase < neededLowerCase) {
Slog.w(TAG, "resetPassword: number of lowercase letters " + lowercase
+ " does not meet required number of lowercase letters "
+ neededLowerCase);
return false;
}
- int neededUpperCase = getPasswordMinimumUpperCase(null);
+ int neededUpperCase = getPasswordMinimumUpperCase(null, userHandle);
if (uppercase < neededUpperCase) {
Slog.w(TAG, "resetPassword: number of uppercase letters " + uppercase
+ " does not meet required number of uppercase letters "
+ neededUpperCase);
return false;
}
- int neededSymbols = getPasswordMinimumSymbols(null);
+ int neededSymbols = getPasswordMinimumSymbols(null, userHandle);
if (symbols < neededSymbols) {
Slog.w(TAG, "resetPassword: number of special symbols " + symbols
+ " does not meet required number of special symbols " + neededSymbols);
return false;
}
- int neededNonLetter = getPasswordMinimumNonLetter(null);
+ int neededNonLetter = getPasswordMinimumNonLetter(null, userHandle);
if (nonletter < neededNonLetter) {
Slog.w(TAG, "resetPassword: number of non-letter characters " + nonletter
+ " does not meet required number of non-letter characters "
@@ -1580,7 +1713,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
int callingUid = Binder.getCallingUid();
- if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) {
+ DevicePolicyData policy = getUserData(userHandle);
+ if (policy.mPasswordOwner >= 0 && policy.mPasswordOwner != callingUid) {
Slog.w(TAG, "resetPassword: already set by another uid and not entered by user");
return false;
}
@@ -1590,13 +1724,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
LockPatternUtils utils = new LockPatternUtils(mContext);
- utils.saveLockPassword(password, quality);
+ utils.saveLockPassword(password, quality, false, userHandle);
synchronized (this) {
int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
!= 0 ? callingUid : -1;
- if (mPasswordOwner != newOwner) {
- mPasswordOwner = newOwner;
- saveSettingsLocked();
+ if (policy.mPasswordOwner != newOwner) {
+ policy.mPasswordOwner = newOwner;
+ saveSettingsLocked(userHandle);
}
}
} finally {
@@ -1606,7 +1740,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return true;
}
- public void setMaximumTimeToLock(ComponentName who, long timeMs) {
+ public void setMaximumTimeToLock(ComponentName who, long timeMs, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -1615,15 +1750,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
if (ap.maximumTimeToUnlock != timeMs) {
ap.maximumTimeToUnlock = timeMs;
- saveSettingsLocked();
- updateMaximumTimeToLockLocked();
+ saveSettingsLocked(userHandle);
+ updateMaximumTimeToLockLocked(getUserData(userHandle));
}
}
}
- void updateMaximumTimeToLockLocked() {
- long timeMs = getMaximumTimeToLock(null);
- if (mLastMaximumTimeToLock == timeMs) {
+ void updateMaximumTimeToLockLocked(DevicePolicyData policy) {
+ long timeMs = getMaximumTimeToLock(null, policy.mUserHandle);
+ if (policy.mLastMaximumTimeToLock == timeMs) {
return;
}
@@ -1638,7 +1773,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
}
- mLastMaximumTimeToLock = timeMs;
+ policy.mLastMaximumTimeToLock = timeMs;
try {
getIPowerManager().setMaximumScreenOffTimeoutFromDeviceAdmin((int)timeMs);
@@ -1650,18 +1785,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public long getMaximumTimeToLock(ComponentName who) {
+ public long getMaximumTimeToLock(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
long time = 0;
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return admin != null ? admin.maximumTimeToUnlock : time;
}
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (time == 0) {
time = admin.maximumTimeToUnlock;
} else if (admin.maximumTimeToUnlock != 0
@@ -1679,17 +1816,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
- long ident = Binder.clearCallingIdentity();
- try {
- // Power off the display
- getIPowerManager().goToSleep(SystemClock.uptimeMillis(),
- PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN);
- // Ensure the device is locked
- getWindowManager().lockNow();
- } catch (RemoteException e) {
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ lockNowUnchecked();
+ }
+ }
+
+ private void lockNowUnchecked() {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ // Power off the display
+ getIPowerManager().goToSleep(SystemClock.uptimeMillis(),
+ PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN);
+ // Ensure the device is locked
+ getWindowManager().lockNow();
+ } catch (RemoteException e) {
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
@@ -1719,7 +1860,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void wipeData(int flags) {
+ public void wipeData(int flags, final 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.
@@ -1727,19 +1869,35 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_WIPE_DATA);
long ident = Binder.clearCallingIdentity();
try {
- wipeDataLocked(flags);
+ if (userHandle == UserHandle.USER_OWNER) {
+ wipeDataLocked(flags);
+ } else {
+ lockNowUnchecked();
+ mHandler.post(new Runnable() {
+ public void run() {
+ try {
+ ActivityManagerNative.getDefault().switchUser(0);
+ ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
+ .removeUser(userHandle);
+ } catch (RemoteException re) {
+ // Shouldn't happen
+ }
+ }
+ });
+ }
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
- public void getRemoveWarning(ComponentName comp, final RemoteCallback result) {
+ public void getRemoveWarning(ComponentName comp, final RemoteCallback result, int userHandle) {
+ enforceCrossUserPermission(userHandle);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
synchronized (this) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(comp);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(comp, userHandle);
if (admin == null) {
try {
result.sendResult(null);
@@ -1749,7 +1907,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
intent.setComponent(admin.info.getComponent());
- mContext.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER,
+ mContext.sendOrderedBroadcastAsUser(intent, new UserHandle(userHandle),
null, new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -1763,34 +1921,36 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
public void setActivePasswordState(int quality, int length, int letters, int uppercase,
- int lowercase, int numbers, int symbols, int nonletter) {
+ int lowercase, int numbers, int symbols, int nonletter, int userHandle) {
+ enforceCrossUserPermission(userHandle);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+ DevicePolicyData p = getUserData(userHandle);
validateQualityConstant(quality);
synchronized (this) {
- if (mActivePasswordQuality != quality || mActivePasswordLength != length
- || mFailedPasswordAttempts != 0 || mActivePasswordLetters != letters
- || mActivePasswordUpperCase != uppercase
- || mActivePasswordLowerCase != lowercase || mActivePasswordNumeric != numbers
- || mActivePasswordSymbols != symbols || mActivePasswordNonLetter != nonletter) {
+ if (p.mActivePasswordQuality != quality || p.mActivePasswordLength != length
+ || p.mFailedPasswordAttempts != 0 || p.mActivePasswordLetters != letters
+ || p.mActivePasswordUpperCase != uppercase
+ || p.mActivePasswordLowerCase != lowercase || p.mActivePasswordNumeric != numbers
+ || p.mActivePasswordSymbols != symbols || p.mActivePasswordNonLetter != nonletter) {
long ident = Binder.clearCallingIdentity();
try {
- mActivePasswordQuality = quality;
- mActivePasswordLength = length;
- mActivePasswordLetters = letters;
- mActivePasswordLowerCase = lowercase;
- mActivePasswordUpperCase = uppercase;
- mActivePasswordNumeric = numbers;
- mActivePasswordSymbols = symbols;
- mActivePasswordNonLetter = nonletter;
- mFailedPasswordAttempts = 0;
- saveSettingsLocked();
- updatePasswordExpirationsLocked();
- setExpirationAlarmCheckLocked(mContext);
+ p.mActivePasswordQuality = quality;
+ p.mActivePasswordLength = length;
+ p.mActivePasswordLetters = letters;
+ p.mActivePasswordLowerCase = lowercase;
+ p.mActivePasswordUpperCase = uppercase;
+ p.mActivePasswordNumeric = numbers;
+ p.mActivePasswordSymbols = symbols;
+ p.mActivePasswordNonLetter = nonletter;
+ p.mFailedPasswordAttempts = 0;
+ saveSettingsLocked(userHandle);
+ updatePasswordExpirationsLocked(userHandle);
+ setExpirationAlarmCheckLocked(mContext, p);
sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
- DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+ DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1801,55 +1961,60 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
/**
* Called any time the device password is updated. Resets all password expiration clocks.
*/
- private void updatePasswordExpirationsLocked() {
- final int N = mAdminList.size();
+ 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 = mAdminList.get(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();
+ saveSettingsLocked(userHandle);
}
}
- public void reportFailedPasswordAttempt() {
+ public void reportFailedPasswordAttempt(int userHandle) {
+ enforceCrossUserPermission(userHandle);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
synchronized (this) {
+ DevicePolicyData policy = getUserData(userHandle);
long ident = Binder.clearCallingIdentity();
try {
- mFailedPasswordAttempts++;
- saveSettingsLocked();
- int max = getMaximumFailedPasswordsForWipe(null);
- if (max > 0 && mFailedPasswordAttempts >= max) {
+ policy.mFailedPasswordAttempts++;
+ saveSettingsLocked(userHandle);
+ int max = getMaximumFailedPasswordsForWipe(null, userHandle);
+ if (max > 0 && policy.mFailedPasswordAttempts >= max) {
wipeDataLocked(0);
}
sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
- DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
+ DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
- public void reportSuccessfulPasswordAttempt() {
+ public void reportSuccessfulPasswordAttempt(int userHandle) {
+ enforceCrossUserPermission(userHandle);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
synchronized (this) {
- if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) {
+ DevicePolicyData policy = getUserData(userHandle);
+ if (policy.mFailedPasswordAttempts != 0 || policy.mPasswordOwner >= 0) {
long ident = Binder.clearCallingIdentity();
try {
- mFailedPasswordAttempts = 0;
- mPasswordOwner = -1;
- saveSettingsLocked();
+ policy.mFailedPasswordAttempts = 0;
+ policy.mPasswordOwner = -1;
+ saveSettingsLocked(userHandle);
sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
- DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
+ DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1858,26 +2023,36 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
public ComponentName setGlobalProxy(ComponentName who, String proxySpec,
- String exclusionList) {
+ String exclusionList, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized(this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
+ // Only check if owner has set global proxy. We don't allow other users to set it.
+ DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
// Scan through active admins and find if anyone has already
// set the global proxy.
- Set<ComponentName> compSet = mAdminMap.keySet();
+ Set<ComponentName> compSet = policy.mAdminMap.keySet();
for (ComponentName component : compSet) {
- ActiveAdmin ap = mAdminMap.get(component);
+ ActiveAdmin ap = policy.mAdminMap.get(component);
if ((ap.specifiesGlobalProxy) && (!component.equals(who))) {
// Another admin already sets the global proxy
// Return it to the caller.
return component;
}
}
+
+ // If the user is not the owner, don't set the global proxy. Fail silently.
+ if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
+ Slog.w(TAG, "Only the owner is allowed to set the global proxy. User "
+ + userHandle + " is not permitted.");
+ return null;
+ }
if (proxySpec == null) {
admin.specifiesGlobalProxy = false;
admin.globalProxySpec = null;
@@ -1892,19 +2067,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Reset the global proxy accordingly
// Do this using system permissions, as apps cannot write to secure settings
long origId = Binder.clearCallingIdentity();
- resetGlobalProxyLocked();
+ resetGlobalProxyLocked(policy);
Binder.restoreCallingIdentity(origId);
return null;
}
}
- public ComponentName getGlobalProxyAdmin() {
+ public ComponentName getGlobalProxyAdmin(int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized(this) {
+ DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
// Scan through active admins and find if anyone has already
// set the global proxy.
- final int N = mAdminList.size();
+ final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
- ActiveAdmin ap = mAdminList.get(i);
+ ActiveAdmin ap = policy.mAdminList.get(i);
if (ap.specifiesGlobalProxy) {
// Device admin sets the global proxy
// Return it to the caller.
@@ -1916,10 +2093,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return null;
}
- private void resetGlobalProxyLocked() {
- final int N = mAdminList.size();
+ private void resetGlobalProxyLocked(DevicePolicyData policy) {
+ final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
- ActiveAdmin ap = mAdminList.get(i);
+ ActiveAdmin ap = policy.mAdminList.get(i);
if (ap.specifiesGlobalProxy) {
saveGlobalProxyLocked(ap.globalProxySpec, ap.globalProxyExclusionList);
return;
@@ -1957,12 +2134,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* Set the storage encryption request for a single admin. Returns the new total request
* status (for all admins).
*/
- public int setStorageEncryption(ComponentName who, boolean encrypt) {
+ public int setStorageEncryption(ComponentName who, boolean encrypt, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
// Check for permissions
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
+ // Only owner can set storage encryption
+ if (userHandle != UserHandle.USER_OWNER
+ || UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
+ Slog.w(TAG, "Only owner is allowed to set storage encryption. User "
+ + UserHandle.getCallingUserId() + " is not permitted.");
+ return 0;
+ }
+
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_ENCRYPTED_STORAGE);
@@ -1974,14 +2160,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// (1) Record the value for the admin so it's sticky
if (ap.encryptionRequested != encrypt) {
ap.encryptionRequested = encrypt;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
+ DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
// (2) Compute "max" for all admins
boolean newRequested = false;
- final int N = mAdminList.size();
+ final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
- newRequested |= mAdminList.get(i).encryptionRequested;
+ newRequested |= policy.mAdminList.get(i).encryptionRequested;
}
// Notify OS of new request
@@ -1998,20 +2185,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* Get the current storage encryption request status for a given admin, or aggregate of all
* active admins.
*/
- public boolean getStorageEncryption(ComponentName who) {
+ public boolean getStorageEncryption(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
// Check for permissions if a particular caller is specified
if (who != null) {
// When checking for a single caller, status is based on caller's request
- ActiveAdmin ap = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin ap = getActiveAdminUncheckedLocked(who, userHandle);
return ap != null ? ap.encryptionRequested : false;
}
// If no particular caller is specified, return the aggregate set of requests.
// This is short circuited by returning true on the first hit.
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
- if (mAdminList.get(i).encryptionRequested) {
+ if (policy.mAdminList.get(i).encryptionRequested) {
return true;
}
}
@@ -2022,7 +2211,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
/**
* Get the current encryption status of the device.
*/
- public int getStorageEncryptionStatus() {
+ public int getStorageEncryptionStatus(int userHandle) {
+ enforceCrossUserPermission(userHandle);
return getEncryptionStatus();
}
@@ -2069,7 +2259,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
/**
* Disables all device cameras according to the specified admin.
*/
- public void setCameraDisabled(ComponentName who, boolean disabled) {
+ public void setCameraDisabled(ComponentName who, boolean disabled, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -2078,9 +2269,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
if (ap.disableCamera != disabled) {
ap.disableCamera = disabled;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
- syncDeviceCapabilitiesLocked();
+ syncDeviceCapabilitiesLocked(getUserData(userHandle));
}
}
@@ -2088,17 +2279,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* Gets whether or not all device cameras are disabled for a given admin, or disabled for any
* active admins.
*/
- public boolean getCameraDisabled(ComponentName who) {
+ public boolean getCameraDisabled(ComponentName who, int userHandle) {
synchronized (this) {
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return (admin != null) ? admin.disableCamera : false;
}
+ DevicePolicyData policy = getUserData(userHandle);
// Determine whether or not the device camera is disabled for any active admins.
- final int N = mAdminList.size();
+ final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
if (admin.disableCamera) {
return true;
}
@@ -2110,7 +2302,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
/**
* Selectively disable keyguard widgets.
*/
- public void setKeyguardWidgetsDisabled(ComponentName who, int which) {
+ public void setKeyguardWidgetsDisabled(ComponentName who, int which, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
@@ -2119,9 +2312,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_WIDGETS);
if ((ap.disableKeyguardWidgets & which) != which) {
ap.disableKeyguardWidgets |= which;
- saveSettingsLocked();
+ saveSettingsLocked(userHandle);
}
- syncDeviceCapabilitiesLocked();
+ syncDeviceCapabilitiesLocked(getUserData(userHandle));
}
}
@@ -2129,24 +2322,39 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* Gets the disabled state for widgets in keyguard for the given admin,
* or the aggregate of all active admins if who is null.
*/
- public int getKeyguardWidgetsDisabled(ComponentName who) {
+ public int getKeyguardWidgetsDisabled(ComponentName who, int userHandle) {
+ enforceCrossUserPermission(userHandle);
synchronized (this) {
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return (admin != null) ? admin.disableKeyguardWidgets : 0;
}
// Determine whether or not keyguard widgets are disabled for any active admins.
- final int N = mAdminList.size();
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
int which = 0;
for (int i = 0; i < N; i++) {
- ActiveAdmin admin = mAdminList.get(i);
+ ActiveAdmin admin = policy.mAdminList.get(i);
which |= admin.disableKeyguardWidgets;
}
return which;
}
}
+ private void enforceCrossUserPermission(int userHandle) {
+ if (userHandle < 0) {
+ throw new IllegalArgumentException("Invalid userId " + userHandle);
+ }
+ final int callingUid = Binder.getCallingUid();
+ if (userHandle == UserHandle.getUserId(callingUid)) return;
+ if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "Must be system or have"
+ + " INTERACT_ACROSS_USERS_FULL permission");
+ }
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -2163,19 +2371,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
p.println("Current Device Policy Manager state:");
- p.println(" Enabled Device Admins:");
- final int N = mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin ap = mAdminList.get(i);
- if (ap != null) {
- pw.print(" "); pw.print(ap.info.getComponent().flattenToShortString());
- pw.println(":");
- ap.dump(" ", pw);
+ int userCount = mUserData.size();
+ for (int u = 0; u < userCount; u++) {
+ DevicePolicyData policy = getUserData(mUserData.keyAt(u));
+ p.println(" Enabled Device Admins (User " + policy.mUserHandle + "):");
+ final int N = policy.mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin ap = policy.mAdminList.get(i);
+ if (ap != null) {
+ pw.print(" "); pw.print(ap.info.getComponent().flattenToShortString());
+ pw.println(":");
+ ap.dump(" ", pw);
+ }
}
- }
- pw.println(" ");
- pw.print(" mPasswordOwner="); pw.println(mPasswordOwner);
+ pw.println(" ");
+ pw.print(" mPasswordOwner="); pw.println(policy.mPasswordOwner);
+ }
}
}
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 536c612..f0cc083 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -8044,13 +8044,13 @@ public class PackageManagerService extends IPackageManager.Stub {
IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
try {
- if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
+ if (dpm != null && dpm.packageHasActiveAdmins(packageName, UserHandle.getUserId(uid))) {
Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
}
} catch (RemoteException e) {
}
-
+
synchronized (mInstallLock) {
res = deletePackageLI(packageName,
(flags & PackageManager.DELETE_ALL_USERS) != 0
diff --git a/services/java/com/android/server/wm/KeyguardDisableHandler.java b/services/java/com/android/server/wm/KeyguardDisableHandler.java
index d935b8b..859df51 100644
--- a/services/java/com/android/server/wm/KeyguardDisableHandler.java
+++ b/services/java/com/android/server/wm/KeyguardDisableHandler.java
@@ -16,12 +16,15 @@
package com.android.server.wm;
+import android.app.ActivityManagerNative;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.RemoteException;
import android.os.TokenWatcher;
+import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
import android.view.WindowManagerPolicy;
@@ -87,9 +90,14 @@ public class KeyguardDisableHandler extends Handler {
DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
Context.DEVICE_POLICY_SERVICE);
if (dpm != null) {
- mAllowDisableKeyguard = dpm.getPasswordQuality(null)
- == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
- ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
+ try {
+ mAllowDisableKeyguard = dpm.getPasswordQuality(null,
+ ActivityManagerNative.getDefault().getCurrentUser().id)
+ == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
+ ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
+ } catch (RemoteException re) {
+ // Nothing much we can do
+ }
}
}
if (mAllowDisableKeyguard == ALLOW_DISABLE_YES) {