import android.app.IAppTask;
import android.app.ITaskStackListener;
import android.app.ProfilerInfo;
+import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.IDevicePolicyManager;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.usage.UsageEvents;
*/
SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
- /**
- * The package name of the DeviceOwner. This package is not permitted to have its data cleared.
- */
- String mDeviceOwnerName;
-
final UserController mUserController;
public class PendingAssistExtras extends Binder implements Runnable {
public boolean clearApplicationUserData(final String packageName,
final IPackageDataObserver observer, int userId) {
enforceNotIsolatedCaller("clearApplicationUserData");
- if (packageName != null && packageName.equals(mDeviceOwnerName)) {
- throw new SecurityException("Clearing DeviceOwner data is forbidden.");
+
+ final DevicePolicyManagerInternal dpmi =
+ LocalServices.getService(DevicePolicyManagerInternal.class);
+ if (dpmi != null && dpmi.isDeviceAdminPackage(userId, packageName)) {
+ throw new SecurityException(
+ "Clearing DeviceAdmin/DeviceOwner/ProfileOwner data is forbidden.");
}
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
}
@Override
- public void updateDeviceOwner(String packageName) {
- final int callingUid = Binder.getCallingUid();
- if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
- throw new SecurityException("updateDeviceOwner called from non-system process");
- }
- synchronized (this) {
- mDeviceOwnerName = packageName;
- }
- }
-
- @Override
public void updateLockTaskPackages(int userId, String[] packages) {
final int callingUid = Binder.getCallingUid();
if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
/**
* Implementation of the device policy APIs.
+ *
+ * Locking policies:
+ * - {@link DevicePolicyManagerService} must not call into {@link IActivityManager} within {@code
+ * this} lock to avoid lock inversion.
+ * - Methods that call into {@link IActivityManager} must have the "AM" suffix.
*/
public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
}
- IActivityManager getIActivityManager() {
+ IActivityManager getIActivityManagerInner() {
return ActivityManagerNative.getDefault();
}
}
/**
+ * Caller must not hold {@code this} lock. See also the class javadoc.
+ */
+ final IActivityManager getIActivityManager() {
+ if (Thread.holdsLock(this)) {
+ Slog.wtfStack(LOG_TAG, "Call to ActivityManager detected within DPMS lock");
+ }
+ return mInjector.getIActivityManagerInner();
+ }
+
+ /**
* Instantiates the service.
*/
public DevicePolicyManagerService(Context context) {
// TODO PO may not have a class name either due to b/17652534. Address that too.
- updateDeviceOwnerLocked();
-
// TODO Notify UM to update restrictions (?)
}
}
validatePasswordOwnerLocked(policy);
updateMaximumTimeToLockLocked(policy);
- updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
+ updateLockTaskPackages(policy.mLockTaskPackages, userHandle);
if (policy.mStatusBarDisabled) {
setStatusBarDisabledInternal(policy.mStatusBarDisabled, userHandle);
}
}
- private void updateLockTaskPackagesLocked(List<String> packages, int userId) {
- long ident = mInjector.binderClearCallingIdentity();
- try {
- mInjector.getIActivityManager()
- .updateLockTaskPackages(userId, packages.toArray(new String[packages.size()]));
- } catch (RemoteException e) {
- // Not gonna happen.
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
- }
-
- private void updateDeviceOwnerLocked() {
- long ident = mInjector.binderClearCallingIdentity();
- try {
- if (getDeviceOwner() != null) {
- mInjector.getIActivityManager()
- .updateDeviceOwner(getDeviceOwner().getPackageName());
+ private void updateLockTaskPackages(List<String> packages, final int userId) {
+ final String[] copy = packages.toArray(new String[packages.size()]);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ getIActivityManager().updateLockTaskPackages(userId, copy);
+ } catch (RemoteException willNotHappen) {
+ }
}
- } catch (RemoteException e) {
- // Not gonna happen.
- } finally {
- mInjector.binderRestoreCallingIdentity(ident);
- }
+ });
}
static void validateQualityConstant(int quality) {
}
private void ensureDeviceOwnerUserStarted() {
- if (mOwners.hasDeviceOwner()) {
- final int userId = mOwners.getDeviceOwnerUserId();
- if (VERBOSE_LOG) {
- Log.v(LOG_TAG, "Starting non-system DO user: " + userId);
- }
- if (userId != UserHandle.USER_SYSTEM) {
+ if (!mOwners.hasDeviceOwner()) {
+ return;
+ }
+ final int userId = mOwners.getDeviceOwnerUserId();
+ if (userId == UserHandle.USER_SYSTEM) {
+ return;
+ }
+ if (VERBOSE_LOG) {
+ Log.v(LOG_TAG, "Starting non-system DO user: " + userId);
+ }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
try {
- mInjector.getIActivityManager().startUserInBackground(userId);
+ getIActivityManager().startUserInBackground(userId);
// STOPSHIP Prevent the DO user from being killed.
Slog.w(LOG_TAG, "Exception starting user", e);
}
}
- }
+ });
}
private void cleanUpOldUsers() {
}
enforceCrossUserPermission(userHandle);
synchronized (this) {
- DevicePolicyData policy = getUserData(userHandle);
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- if (policy.mAdminList.get(i).info.getPackageName().equals(packageName)) {
- return true;
- }
+ return packageHasActiveAdminsLocked(packageName, userHandle);
+ }
+ }
+
+ boolean packageHasActiveAdminsLocked(String packageName, int userHandle) {
+ DevicePolicyData policy = getUserData(userHandle);
+ final int N = policy.mAdminList.size();
+ for (int i = 0; i < N; i++) {
+ if (policy.mAdminList.get(i).info.getPackageName().equals(packageName)) {
+ return true;
}
- return false;
}
+ return false;
}
@Override
@Override
public void run() {
try {
- IActivityManager am = mInjector.getIActivityManager();
+ IActivityManager am = getIActivityManager();
if (am.getCurrentUser().id == userHandle) {
am.switchUser(UserHandle.USER_SYSTEM);
}
mOwners.setDeviceOwner(admin, ownerName, userId);
mOwners.writeDeviceOwner();
- updateDeviceOwnerLocked();
Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED);
ident = mInjector.binderClearCallingIdentity();
mOwners.clearDeviceOwner();
mOwners.writeDeviceOwner();
- updateDeviceOwnerLocked();
// Reactivate backup service.
long ident = mInjector.binderClearCallingIdentity();
try {
}
}
- private boolean checkCallerIsCurrentUserOrProfile() {
+ private boolean checkCallerIsCurrentUserOrProfileAM() {
int callingUserId = UserHandle.getCallingUserId();
long token = mInjector.binderClearCallingIdentity();
try {
UserInfo currentUser;
UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
try {
- currentUser = mInjector.getIActivityManager().getCurrentUser();
+ currentUser = getIActivityManager().getCurrentUser();
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to talk to activity managed.", e);
return false;
// TODO When InputMethodManager supports per user calls remove
// this restriction.
- if (!checkCallerIsCurrentUserOrProfile()) {
+ if (!checkCallerIsCurrentUserOrProfileAM()) {
return false;
}
public List getPermittedInputMethodsForCurrentUser() {
UserInfo currentUser;
try {
- currentUser = mInjector.getIActivityManager().getCurrentUser();
+ currentUser = getIActivityManager().getCurrentUser();
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to make remote calls to get current user", e);
// Activity managed is dead, just allow all IMEs
}
// Start user in background.
- mInjector.getIActivityManager().startUserInBackground(userHandle);
+ getIActivityManager().startUserInBackground(userHandle);
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to make remote calls for configureUser", e);
}
Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+ }
- long id = mInjector.binderClearCallingIdentity();
- try {
- int userId = UserHandle.USER_SYSTEM;
- if (userHandle != null) {
- userId = userHandle.getIdentifier();
- }
- return mInjector.getIActivityManager().switchUser(userId);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Couldn't switch user", e);
- return false;
- } finally {
- mInjector.binderRestoreCallingIdentity(id);
+ long id = mInjector.binderClearCallingIdentity();
+ try {
+ int userId = UserHandle.USER_SYSTEM;
+ if (userHandle != null) {
+ userId = userHandle.getIdentifier();
}
+ return getIActivityManager().switchUser(userId);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Couldn't switch user", e);
+ return false;
+ } finally {
+ mInjector.binderRestoreCallingIdentity(id);
}
}
// Store the settings persistently.
saveSettingsLocked(userHandle);
- updateLockTaskPackagesLocked(packages, userHandle);
+ updateLockTaskPackages(packages, userHandle);
}
/**
}
}
+ @Override
+ public boolean isDeviceAdminPackage(int userId, String packageName) {
+ if (packageName == null) {
+ return false;
+ }
+ synchronized (DevicePolicyManagerService.this) {
+ return packageHasActiveAdminsLocked(packageName, userId);
+ }
+ }
+
private void notifyCrossProfileProvidersChanged(int userId, List<String> packages) {
final List<OnCrossProfileWidgetProvidersChangeListener> listeners;
synchronized (DevicePolicyManagerService.this) {