summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
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) {