Merge "Allow device/profile owners to change app ops modes." into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
adaca2146d
33
core/java/android/app/AppOpsManagerInternal.java
Normal file
33
core/java/android/app/AppOpsManagerInternal.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app;
|
||||
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
/**
|
||||
* App ops service local interface.
|
||||
*
|
||||
* @hide Only for use within the system server.
|
||||
*/
|
||||
public abstract class AppOpsManagerInternal {
|
||||
/**
|
||||
* Set the currently configured device and profile owners. Specifies the package uid (value)
|
||||
* that has been configured for each user (key) that has one. These will be allowed privileged
|
||||
* access to app ops for their user.
|
||||
*/
|
||||
public abstract void setDeviceAndProfileOwners(SparseIntArray owners);
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.app.ActivityManager;
|
||||
import android.app.ActivityThread;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.AppOpsManagerInternal;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@@ -172,6 +173,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
final AtomicFile mFile;
|
||||
final Handler mHandler;
|
||||
|
||||
private final AppOpsManagerInternalImpl mAppOpsManagerInternal
|
||||
= new AppOpsManagerInternalImpl();
|
||||
|
||||
boolean mWriteScheduled;
|
||||
boolean mFastWriteScheduled;
|
||||
final Runnable mWriteRunner = new Runnable() {
|
||||
@@ -200,6 +204,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
*/
|
||||
private final ArrayMap<IBinder, ClientRestrictionState> mOpUserRestrictions = new ArrayMap<>();
|
||||
|
||||
SparseIntArray mProfileOwners;
|
||||
|
||||
/**
|
||||
* All times are in milliseconds. These constants are kept synchronized with the system
|
||||
* global Settings. Any access to this class or its fields should be done while
|
||||
@@ -551,6 +557,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
public void publish(Context context) {
|
||||
mContext = context;
|
||||
ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
|
||||
LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal);
|
||||
}
|
||||
|
||||
public void systemReady() {
|
||||
@@ -921,12 +928,27 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
void enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid) {
|
||||
if (callingPid == Process.myPid()) {
|
||||
return;
|
||||
}
|
||||
final int callingUser = UserHandle.getUserId(callingUid);
|
||||
synchronized (this) {
|
||||
if (mProfileOwners != null && mProfileOwners.get(callingUser, -1) == callingUid) {
|
||||
if (targetUid >= 0 && callingUser == UserHandle.getUserId(targetUid)) {
|
||||
// Profile owners are allowed to change modes but only for apps
|
||||
// within their user.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
|
||||
Binder.getCallingPid(), Binder.getCallingUid(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUidMode(int code, int uid, int mode) {
|
||||
if (Binder.getCallingPid() != Process.myPid()) {
|
||||
mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
|
||||
Binder.getCallingPid(), Binder.getCallingUid(), null);
|
||||
}
|
||||
enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
|
||||
verifyIncomingOp(code);
|
||||
code = AppOpsManager.opToSwitch(code);
|
||||
|
||||
@@ -1029,10 +1051,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
|
||||
@Override
|
||||
public void setMode(int code, int uid, String packageName, int mode) {
|
||||
if (Binder.getCallingPid() != Process.myPid()) {
|
||||
mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
|
||||
Binder.getCallingPid(), Binder.getCallingUid(), null);
|
||||
}
|
||||
enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
|
||||
verifyIncomingOp(code);
|
||||
ArraySet<ModeCallback> repCbs = null;
|
||||
code = AppOpsManager.opToSwitch(code);
|
||||
@@ -1151,8 +1170,6 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
public void resetAllModes(int reqUserId, String reqPackageName) {
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
|
||||
callingPid, callingUid, null);
|
||||
reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId,
|
||||
true, true, "resetAllModes", null);
|
||||
|
||||
@@ -1166,6 +1183,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
enforceManageAppOpsModes(callingPid, callingUid, reqUid);
|
||||
|
||||
HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks = null;
|
||||
synchronized (this) {
|
||||
boolean changed = false;
|
||||
@@ -1428,10 +1447,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
@Override
|
||||
public void setAudioRestriction(int code, int usage, int uid, int mode,
|
||||
String[] exceptionPackages) {
|
||||
enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
|
||||
verifyIncomingUid(uid);
|
||||
verifyIncomingOp(code);
|
||||
mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
|
||||
Binder.getCallingPid(), Binder.getCallingUid(), null);
|
||||
synchronized (this) {
|
||||
SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
|
||||
if (usageRestrictions == null) {
|
||||
@@ -2809,9 +2827,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
return 0;
|
||||
}
|
||||
case "write-settings": {
|
||||
shell.mInternal.mContext.enforcePermission(
|
||||
android.Manifest.permission.MANAGE_APP_OPS_MODES,
|
||||
Binder.getCallingPid(), Binder.getCallingUid(), null);
|
||||
shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(),
|
||||
Binder.getCallingUid(), -1);
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (shell.mInternal) {
|
||||
@@ -2825,9 +2842,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
return 0;
|
||||
}
|
||||
case "read-settings": {
|
||||
shell.mInternal.mContext.enforcePermission(
|
||||
android.Manifest.permission.MANAGE_APP_OPS_MODES,
|
||||
Binder.getCallingPid(), Binder.getCallingUid(), null);
|
||||
shell.mInternal.enforceManageAppOpsModes(Binder.getCallingPid(),
|
||||
Binder.getCallingUid(), -1);
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
shell.mInternal.readState();
|
||||
@@ -2989,6 +3005,17 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
final Date date = new Date();
|
||||
boolean needSep = false;
|
||||
if (dumpOp < 0 && dumpMode < 0 && dumpPackage == null && mProfileOwners != null) {
|
||||
pw.println(" Profile owners:");
|
||||
for (int poi = 0; poi < mProfileOwners.size(); poi++) {
|
||||
pw.print(" User #");
|
||||
pw.print(mProfileOwners.keyAt(poi));
|
||||
pw.print(": ");
|
||||
UserHandle.formatUid(pw, mProfileOwners.valueAt(poi));
|
||||
pw.println();
|
||||
}
|
||||
pw.println();
|
||||
}
|
||||
if (mOpModeWatchers.size() > 0) {
|
||||
boolean printedHeader = false;
|
||||
for (int i=0; i<mOpModeWatchers.size(); i++) {
|
||||
@@ -3702,4 +3729,12 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private final class AppOpsManagerInternalImpl extends AppOpsManagerInternal {
|
||||
@Override public void setDeviceAndProfileOwners(SparseIntArray owners) {
|
||||
synchronized (AppOpsService.this) {
|
||||
mProfileOwners = owners;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3351,6 +3351,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
case SystemService.PHASE_LOCK_SETTINGS_READY:
|
||||
onLockSettingsReady();
|
||||
loadAdminDataAsync();
|
||||
mOwners.systemReady();
|
||||
break;
|
||||
case SystemService.PHASE_BOOT_COMPLETED:
|
||||
ensureDeviceOwnerUserStarted(); // TODO Consider better place to do this.
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
package com.android.server.devicepolicy;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.AppOpsManagerInternal;
|
||||
import android.app.admin.SystemUpdateInfo;
|
||||
import android.app.admin.SystemUpdatePolicy;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Binder;
|
||||
import android.os.Environment;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
@@ -32,10 +35,12 @@ import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
@@ -99,6 +104,8 @@ class Owners {
|
||||
private final UserManagerInternal mUserManagerInternal;
|
||||
private final PackageManagerInternal mPackageManagerInternal;
|
||||
|
||||
private boolean mSystemReady;
|
||||
|
||||
// Internal state for the device owner package.
|
||||
private OwnerInfo mDeviceOwner;
|
||||
|
||||
@@ -179,6 +186,7 @@ class Owners {
|
||||
getDeviceOwnerUserId()));
|
||||
}
|
||||
pushToPackageManagerLocked();
|
||||
pushToAppOpsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,6 +270,7 @@ class Owners {
|
||||
|
||||
mUserManagerInternal.setDeviceManaged(true);
|
||||
pushToPackageManagerLocked();
|
||||
pushToAppOpsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,6 +281,7 @@ class Owners {
|
||||
|
||||
mUserManagerInternal.setDeviceManaged(false);
|
||||
pushToPackageManagerLocked();
|
||||
pushToAppOpsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,6 +293,7 @@ class Owners {
|
||||
/* remoteBugreportHash =*/ null));
|
||||
mUserManagerInternal.setUserManaged(userId, true);
|
||||
pushToPackageManagerLocked();
|
||||
pushToAppOpsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,6 +302,7 @@ class Owners {
|
||||
mProfileOwners.remove(userId);
|
||||
mUserManagerInternal.setUserManaged(userId, false);
|
||||
pushToPackageManagerLocked();
|
||||
pushToAppOpsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,6 +314,7 @@ class Owners {
|
||||
ownerInfo.remoteBugreportHash);
|
||||
mProfileOwners.put(userId, newOwnerInfo);
|
||||
pushToPackageManagerLocked();
|
||||
pushToAppOpsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +326,7 @@ class Owners {
|
||||
mDeviceOwner.userRestrictionsMigrated, mDeviceOwner.remoteBugreportUri,
|
||||
mDeviceOwner.remoteBugreportHash);
|
||||
pushToPackageManagerLocked();
|
||||
pushToAppOpsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -581,6 +595,48 @@ class Owners {
|
||||
}
|
||||
}
|
||||
|
||||
void pushToAppOpsLocked() {
|
||||
if (!mSystemReady) {
|
||||
return;
|
||||
}
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
final SparseIntArray owners = new SparseIntArray();
|
||||
if (mDeviceOwner != null) {
|
||||
final int uid = mPackageManagerInternal.getPackageUid(mDeviceOwner.packageName,
|
||||
PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES,
|
||||
mDeviceOwnerUserId);
|
||||
if (uid >= 0) {
|
||||
owners.put(mDeviceOwnerUserId, uid);
|
||||
}
|
||||
}
|
||||
if (mProfileOwners != null) {
|
||||
for (int poi = mProfileOwners.size() - 1; poi >= 0; poi--) {
|
||||
final int uid = mPackageManagerInternal.getPackageUid(
|
||||
mProfileOwners.valueAt(poi).packageName,
|
||||
PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES,
|
||||
mProfileOwners.keyAt(poi));
|
||||
if (uid >= 0) {
|
||||
owners.put(mProfileOwners.keyAt(poi), uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
AppOpsManagerInternal appops = LocalServices.getService(AppOpsManagerInternal.class);
|
||||
if (appops != null) {
|
||||
appops.setDeviceAndProfileOwners(owners.size() > 0 ? owners : null);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
|
||||
public void systemReady() {
|
||||
synchronized (mLock) {
|
||||
mSystemReady = true;
|
||||
pushToAppOpsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class FileReadWriter {
|
||||
private final File mFile;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user