diff options
author | Jason Monk <jmonk@google.com> | 2014-05-16 17:30:30 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-05-16 17:30:31 +0000 |
commit | 8974f2490992b2921b636c0b65ebeb5b19dda89b (patch) | |
tree | 46f2a066f680a648dd1f0201a1fff25dc2b84ed3 /services | |
parent | 843adbba6ac29349f5ea7383af5208e1f2b8bf3c (diff) | |
parent | 62062996dd256df8b575b2ba1f0bf97109c4e0ba (diff) | |
download | frameworks_base-8974f2490992b2921b636c0b65ebeb5b19dda89b.zip frameworks_base-8974f2490992b2921b636c0b65ebeb5b19dda89b.tar.gz frameworks_base-8974f2490992b2921b636c0b65ebeb5b19dda89b.tar.bz2 |
Merge "Notify AppOpsService of UserRestrictions and Owners"
Diffstat (limited to 'services')
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, |