Loading core/java/android/app/AppOpsManagerInternal.java 0 → 100644 +33 −0 Original line number Diff line number Diff line /* * 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); } services/core/java/com/android/server/AppOpsService.java +53 −18 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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 Loading Loading @@ -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() { Loading Loading @@ -921,12 +928,27 @@ public class AppOpsService extends IAppOpsService.Stub { } } @Override public void setUidMode(int code, int uid, int mode) { if (Binder.getCallingPid() != Process.myPid()) { 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) { enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); verifyIncomingOp(code); code = AppOpsManager.opToSwitch(code); Loading Loading @@ -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); Loading Loading @@ -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); Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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(); Loading Loading @@ -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++) { Loading Loading @@ -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; } } } } services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -3352,6 +3352,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. Loading services/devicepolicy/java/com/android/server/devicepolicy/Owners.java +56 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -179,6 +186,7 @@ class Owners { getDeviceOwnerUserId())); } pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading Loading @@ -262,6 +270,7 @@ class Owners { mUserManagerInternal.setDeviceManaged(true); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading @@ -272,6 +281,7 @@ class Owners { mUserManagerInternal.setDeviceManaged(false); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading @@ -283,6 +293,7 @@ class Owners { /* remoteBugreportHash =*/ null)); mUserManagerInternal.setUserManaged(userId, true); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading @@ -291,6 +302,7 @@ class Owners { mProfileOwners.remove(userId); mUserManagerInternal.setUserManaged(userId, false); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading @@ -302,6 +314,7 @@ class Owners { ownerInfo.remoteBugreportHash); mProfileOwners.put(userId, newOwnerInfo); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading @@ -313,6 +326,7 @@ class Owners { mDeviceOwner.userRestrictionsMigrated, mDeviceOwner.remoteBugreportUri, mDeviceOwner.remoteBugreportHash); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading Loading @@ -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; Loading Loading
core/java/android/app/AppOpsManagerInternal.java 0 → 100644 +33 −0 Original line number Diff line number Diff line /* * 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); }
services/core/java/com/android/server/AppOpsService.java +53 −18 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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 Loading Loading @@ -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() { Loading Loading @@ -921,12 +928,27 @@ public class AppOpsService extends IAppOpsService.Stub { } } @Override public void setUidMode(int code, int uid, int mode) { if (Binder.getCallingPid() != Process.myPid()) { 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) { enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid); verifyIncomingOp(code); code = AppOpsManager.opToSwitch(code); Loading Loading @@ -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); Loading Loading @@ -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); Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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) { Loading @@ -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(); Loading Loading @@ -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++) { Loading Loading @@ -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; } } } }
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +1 −0 Original line number Diff line number Diff line Loading @@ -3352,6 +3352,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. Loading
services/devicepolicy/java/com/android/server/devicepolicy/Owners.java +56 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -179,6 +186,7 @@ class Owners { getDeviceOwnerUserId())); } pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading Loading @@ -262,6 +270,7 @@ class Owners { mUserManagerInternal.setDeviceManaged(true); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading @@ -272,6 +281,7 @@ class Owners { mUserManagerInternal.setDeviceManaged(false); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading @@ -283,6 +293,7 @@ class Owners { /* remoteBugreportHash =*/ null)); mUserManagerInternal.setUserManaged(userId, true); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading @@ -291,6 +302,7 @@ class Owners { mProfileOwners.remove(userId); mUserManagerInternal.setUserManaged(userId, false); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading @@ -302,6 +314,7 @@ class Owners { ownerInfo.remoteBugreportHash); mProfileOwners.put(userId, newOwnerInfo); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading @@ -313,6 +326,7 @@ class Owners { mDeviceOwner.userRestrictionsMigrated, mDeviceOwner.remoteBugreportUri, mDeviceOwner.remoteBugreportHash); pushToPackageManagerLocked(); pushToAppOpsLocked(); } } Loading Loading @@ -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; Loading