summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorJason Monk <jmonk@google.com>2014-05-16 17:30:30 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-05-16 17:30:31 +0000
commit8974f2490992b2921b636c0b65ebeb5b19dda89b (patch)
tree46f2a066f680a648dd1f0201a1fff25dc2b84ed3 /services
parent843adbba6ac29349f5ea7383af5208e1f2b8bf3c (diff)
parent62062996dd256df8b575b2ba1f0bf97109c4e0ba (diff)
downloadframeworks_base-8974f2490992b2921b636c0b65ebeb5b19dda89b.zip
frameworks_base-8974f2490992b2921b636c0b65ebeb5b19dda89b.tar.gz
frameworks_base-8974f2490992b2921b636c0b65ebeb5b19dda89b.tar.bz2
Merge "Notify AppOpsService of UserRestrictions and Owners"
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/AppOpsService.java96
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java26
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java5
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java35
4 files changed, 162 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index e26747c..be20616 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -36,12 +36,14 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.media.AudioService;
import android.os.AsyncTask;
import android.os.Binder;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -49,6 +51,7 @@ import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.Xml;
@@ -56,6 +59,7 @@ import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
+import com.google.android.util.AbstractMessageParser.MusicTrack;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -91,6 +95,10 @@ public class AppOpsService extends IAppOpsService.Stub {
final SparseArray<HashMap<String, Ops>> mUidOps
= new SparseArray<HashMap<String, Ops>>();
+ private int mDeviceOwnerUid;
+ private final SparseIntArray mProfileOwnerUids = new SparseIntArray();
+ private final SparseArray<boolean[]> mOpRestrictions = new SparseArray<boolean[]>();
+
public final static class Ops extends SparseArray<Op> {
public final String packageName;
public final int uid;
@@ -548,6 +556,9 @@ public class AppOpsService extends IAppOpsService.Stub {
verifyIncomingUid(uid);
verifyIncomingOp(code);
synchronized (this) {
+ if (isOpRestricted(uid, code)) {
+ return AppOpsManager.MODE_IGNORED;
+ }
Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
@@ -631,6 +642,9 @@ public class AppOpsService extends IAppOpsService.Stub {
return AppOpsManager.MODE_ERRORED;
}
Op op = getOpLocked(ops, code, true);
+ if (isOpRestricted(uid, code)) {
+ return AppOpsManager.MODE_IGNORED;
+ }
if (op.duration == -1) {
Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
+ " code " + code + " time=" + op.time + " duration=" + op.duration);
@@ -665,6 +679,9 @@ public class AppOpsService extends IAppOpsService.Stub {
return AppOpsManager.MODE_ERRORED;
}
Op op = getOpLocked(ops, code, true);
+ if (isOpRestricted(uid, code)) {
+ return AppOpsManager.MODE_IGNORED;
+ }
final int switchCode = AppOpsManager.opToSwitch(code);
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
@@ -830,6 +847,23 @@ public class AppOpsService extends IAppOpsService.Stub {
return op;
}
+ private boolean isOpRestricted(int uid, int code) {
+ int userHandle = UserHandle.getUserId(uid);
+ boolean[] opRestrictions = mOpRestrictions.get(userHandle);
+ if ((opRestrictions != null) && opRestrictions[code]) {
+ if (userHandle == UserHandle.USER_OWNER) {
+ if (uid != mDeviceOwnerUid) {
+ return true;
+ }
+ } else {
+ if (uid != mProfileOwnerUids.get(userHandle, -1)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
void readState() {
synchronized (mFile) {
synchronized (this) {
@@ -1167,4 +1201,66 @@ public class AppOpsService extends IAppOpsService.Stub {
int mode;
ArraySet<String> exceptionPackages = NO_EXCEPTIONS;
}
+
+ @Override
+ public void setDeviceOwner(String packageName) throws RemoteException {
+ checkSystemUid("setDeviceOwner");
+ try {
+ mDeviceOwnerUid = mContext.getPackageManager().getPackageUid(packageName,
+ UserHandle.USER_OWNER);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not find Device Owner UID");
+ mDeviceOwnerUid = -1;
+ throw new IllegalArgumentException("Could not find device owner package "
+ + packageName);
+ }
+ }
+
+ @Override
+ public void setProfileOwner(String packageName, int userHandle) throws RemoteException {
+ checkSystemUid("setProfileOwner");
+ try {
+ int uid = mContext.getPackageManager().getPackageUid(packageName,
+ userHandle);
+ mProfileOwnerUids.put(userHandle, uid);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not find Profile Owner UID");
+ mProfileOwnerUids.put(userHandle, -1);
+ throw new IllegalArgumentException("Could not find profile owner package "
+ + packageName);
+ }
+ }
+
+ @Override
+ public void setUserRestrictions(Bundle restrictions, int userHandle) throws RemoteException {
+ checkSystemUid("setUserRestrictions");
+ boolean[] opRestrictions = mOpRestrictions.get(userHandle);
+ if (opRestrictions == null) {
+ opRestrictions = new boolean[AppOpsManager._NUM_OP];
+ mOpRestrictions.put(userHandle, opRestrictions);
+ }
+ for (int i = 0; i < opRestrictions.length; ++i) {
+ String restriction = AppOpsManager.opToRestriction(i);
+ if (restriction != null) {
+ opRestrictions[i] = restrictions.getBoolean(restriction, false);
+ } else {
+ opRestrictions[i] = false;
+ }
+ }
+ }
+
+ @Override
+ public void removeUser(int userHandle) throws RemoteException {
+ checkSystemUid("removeUser");
+ mOpRestrictions.remove(userHandle);
+ mProfileOwnerUids.removeAt(mProfileOwnerUids.indexOfKey(userHandle));
+ }
+
+ private void checkSystemUid(String function) {
+ int uid = Binder.getCallingUid();
+ if (uid != Process.SYSTEM_UID) {
+ throw new SecurityException(function + " must by called by the system");
+ }
+ }
+
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a6cac5e..131d05b 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -40,6 +40,7 @@ import android.os.Handler;
import android.os.IUserManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.AtomicFile;
@@ -50,6 +51,7 @@ import android.util.SparseBooleanArray;
import android.util.TimeUtils;
import android.util.Xml;
+import com.android.internal.app.IAppOpsService;
import com.android.internal.content.PackageMonitor;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -162,6 +164,8 @@ public class UserManagerService extends IUserManager.Stub {
private int mNextSerialNumber;
private int mUserVersion = 0;
+ private IAppOpsService mAppOpsService;
+
private static UserManagerService sInstance;
public static UserManagerService getInstance() {
@@ -236,6 +240,15 @@ public class UserManagerService extends IUserManager.Stub {
void systemReady() {
mUserPackageMonitor.register(mContext, null, UserHandle.ALL, false);
userForeground(UserHandle.USER_OWNER);
+ mAppOpsService = IAppOpsService.Stub.asInterface(
+ ServiceManager.getService(Context.APP_OPS_SERVICE));
+ for (int i = 0; i < mUserIds.length; ++i) {
+ try {
+ mAppOpsService.setUserRestrictions(mUserRestrictions.get(mUserIds[i]), mUserIds[i]);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
+ }
+ }
}
@Override
@@ -482,6 +495,14 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mPackagesLock) {
mUserRestrictions.get(userId).clear();
mUserRestrictions.get(userId).putAll(restrictions);
+ long token = Binder.clearCallingIdentity();
+ try {
+ mAppOpsService.setUserRestrictions(mUserRestrictions.get(userId), userId);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
writeUserLocked(mUsers.get(userId));
}
}
@@ -1116,6 +1137,11 @@ public class UserManagerService extends IUserManager.Stub {
return false;
}
mRemovingUserIds.put(userHandle, true);
+ try {
+ mAppOpsService.removeUser(userHandle);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user", e);
+ }
// Set this to a partially created user, so that the user will be purged
// on next startup, in case the runtime stops now before stopping and
// removing the user completely.
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index 1647425..674c6f4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -39,6 +39,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
+import java.util.Set;
/**
* Stores and restores state for the Device and Profile owners. By definition there can be
@@ -137,6 +138,10 @@ public class DeviceOwner {
return profileOwner != null ? profileOwner.name : null;
}
+ Set<Integer> getProfileOwnerKeys() {
+ return mProfileOwners.keySet();
+ }
+
boolean hasDeviceOwner() {
return mDeviceOwner != null;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1980d1e..a0c59cc 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -19,6 +19,7 @@ package com.android.server.devicepolicy;
import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
import com.android.internal.R;
+import com.android.internal.app.IAppOpsService;
import com.android.internal.os.storage.ExternalStorageFormatter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
@@ -237,6 +238,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
};
+ private IAppOpsService mAppOpsService;
+
static class ActiveAdmin {
private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
private static final String TAG_DISABLE_CAMERA = "disable-camera";
@@ -1209,6 +1212,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
loadSettingsLocked(getUserData(UserHandle.USER_OWNER), UserHandle.USER_OWNER);
loadDeviceOwner();
}
+ mAppOpsService = IAppOpsService.Stub.asInterface(
+ ServiceManager.getService(Context.APP_OPS_SERVICE));
+ if (mDeviceOwner.hasDeviceOwner()) {
+ try {
+ mAppOpsService.setDeviceOwner(mDeviceOwner.getDeviceOwnerPackageName());
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to notify AppOpsService of DeviceOwner", e);
+ }
+ }
+ for (Integer i : mDeviceOwner.getProfileOwnerKeys()) {
+ try {
+ mAppOpsService.setProfileOwner(mDeviceOwner.getProfileOwnerName(i), i);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to notify AppOpsService of ProfileOwner", e);
+ }
+ }
}
private void handlePasswordExpirationNotification(int userHandle) {
@@ -2953,6 +2972,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"Trying to set device owner but device owner is already set.");
}
+ long token = Binder.clearCallingIdentity();
+ try {
+ mAppOpsService.setDeviceOwner(packageName);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to notify AppOpsService of DeviceOwner", e);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
if (mDeviceOwner == null) {
// Device owner is not set and does not exist, set it.
mDeviceOwner = DeviceOwner.createWithDeviceOwner(packageName, ownerName);
@@ -3029,6 +3056,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
throw new IllegalStateException(
"Trying to set profile owner but user is already set-up.");
}
+ long token = Binder.clearCallingIdentity();
+ try {
+ mAppOpsService.setProfileOwner(packageName, userHandle);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to notify AppOpsService of ProfileOwner", e);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
if (mDeviceOwner == null) {
// Device owner state does not exist, create it.
mDeviceOwner = DeviceOwner.createWithProfileOwner(packageName, ownerName,