Initialize UidStates in system ready

This is in preparation of moving the persistence of the persisted appops
states.

Bug: 266163878
Test: AppOps tests and inspect heapdump
Change-Id: I4f6b5b435fa9abfdab1da486b9c3f7cd337e4ed6
This commit is contained in:
Evan Severson
2023-01-26 15:19:12 -08:00
parent 51d58191e6
commit e96ddbca8f
6 changed files with 116 additions and 27 deletions

View File

@@ -105,6 +105,21 @@ public class AppOpsCheckingServiceImpl implements AppOpsCheckingServiceInterface
}
}
@Override
public SparseIntArray getNonDefaultPackageModes(String packageName, int userId) {
synchronized (mLock) {
ArrayMap<String, SparseIntArray> packageModes = mUserPackageModes.get(userId);
if (packageModes == null) {
return new SparseIntArray();
}
SparseIntArray opModes = packageModes.get(packageName);
if (opModes == null) {
return new SparseIntArray();
}
return opModes.clone();
}
}
@Override
public int getUidMode(int uid, int op) {
synchronized (mLock) {

View File

@@ -38,6 +38,15 @@ public interface AppOpsCheckingServiceInterface {
*/
SparseIntArray getNonDefaultUidModes(int uid);
/**
* Returns a copy of non-default app-ops with op as keys and their modes as values for a package
* and user.
* Returns an empty SparseIntArray if nothing is set.
* @param packageName for which we need the app-ops and their modes.
* @param userId for which the package is installed in.
*/
SparseIntArray getNonDefaultPackageModes(String packageName, int userId);
/**
* Returns the app-op mode for a particular app-op of a uid.
* Returns default op mode if the op mode for particular uid and op is not set.

View File

@@ -45,6 +45,13 @@ public class AppOpsCheckingServiceLoggingDecorator implements AppOpsCheckingServ
return mService.getNonDefaultUidModes(uid);
}
@Override
public SparseIntArray getNonDefaultPackageModes(String packageName, int userId) {
Log.i(LOG_TAG, "getNonDefaultPackageModes("
+ "packageName = " + packageName + ", userId = " + userId + ") ");
return mService.getNonDefaultPackageModes(packageName, userId);
}
@Override
public int getUidMode(int uid, int op) {
Log.i(LOG_TAG, "getUidMode(uid = " + uid + ", op = " + op + ")");

View File

@@ -98,6 +98,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION;
import android.net.Uri;
@@ -162,6 +163,7 @@ import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.component.ParsedAttribution;
import com.android.server.policy.AppOpsPolicy;
@@ -383,6 +385,9 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
/** Package Manager internal. Access via {@link #getPackageManagerInternal()} */
private @Nullable PackageManagerInternal mPackageManagerInternal;
/** User Manager internal. Access via {@link #getUserManagerInternal()} */
private @Nullable UserManagerInternal mUserManagerInternal;
/** Interface for app-op modes.*/
@VisibleForTesting
AppOpsCheckingServiceInterface mAppOpsCheckingService;
@@ -525,22 +530,6 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
pkgOps = null;
}
public boolean isDefault() {
boolean areAllPackageModesDefault = true;
if (pkgOps != null) {
for (String packageName : pkgOps.keySet()) {
if (!mAppOpsCheckingService.arePackageModesDefault(packageName,
UserHandle.getUserId(uid))) {
areAllPackageModesDefault = false;
break;
}
}
}
return (pkgOps == null || pkgOps.isEmpty())
&& mAppOpsCheckingService.areUidModesDefault(uid)
&& areAllPackageModesDefault;
}
// Functions for uid mode access and manipulation.
public SparseIntArray getNonDefaultUidModes() {
return mAppOpsCheckingService.getNonDefaultUidModes(uid);
@@ -1076,6 +1065,17 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
synchronized (this) {
upgradeLocked(mVersionAtBoot);
}
initializeUidStates();
getUserManagerInternal().addUserLifecycleListener(
new UserManagerInternal.UserLifecycleListener() {
@Override
public void onUserCreated(UserInfo user, Object token) {
initializeUserUidStates(user.id);
}
// onUserRemoved handled by #removeUser
});
mConstants.startMonitoring(mContext.getContentResolver());
mHistoricalRegistry.systemReady(mContext.getContentResolver());
@@ -1202,6 +1202,49 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
}
/**
* Initialize uid state objects for state contained in the checking service.
*/
private void initializeUidStates() {
UserManagerInternal umi = getUserManagerInternal();
int[] userIds = umi.getUserIds();
synchronized (this) {
for (int i = 0; i < userIds.length; i++) {
int userId = userIds[i];
initializeUserUidStatesLocked(userId);
}
}
}
private void initializeUserUidStates(int userId) {
synchronized (this) {
initializeUserUidStatesLocked(userId);
}
}
private void initializeUserUidStatesLocked(int userId) {
ArrayMap<String, ? extends PackageStateInternal> packageStates =
getPackageManagerInternal().getPackageStates();
for (int j = 0; j < packageStates.size(); j++) {
PackageStateInternal packageState = packageStates.valueAt(j);
int uid = UserHandle.getUid(userId, packageState.getAppId());
UidState uidState = getUidStateLocked(uid, true);
if (uidState.pkgOps == null) {
uidState.pkgOps = new ArrayMap<>();
}
String packageName = packageStates.keyAt(j);
Ops ops = new Ops(packageName, uidState);
uidState.pkgOps.put(packageName, ops);
SparseIntArray packageModes =
mAppOpsCheckingService.getNonDefaultPackageModes(packageName, userId);
for (int k = 0; k < packageModes.size(); k++) {
int code = packageModes.get(k);
ops.put(code, new Op(uidState, packageName, code, uid));
}
}
}
/**
* Sets a policy for handling app ops.
*
@@ -1687,13 +1730,6 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
pkgOps.remove(ops.packageName);
mAppOpsCheckingService.removePackage(ops.packageName,
UserHandle.getUserId(uidState.uid));
if (pkgOps.isEmpty()) {
uidState.pkgOps = null;
}
if (uidState.isDefault()) {
uidState.clear();
mUidStates.remove(uid);
}
}
}
}
@@ -2147,10 +2183,6 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
UserHandle.getUserId(uidState.uid));
}
}
if (uidState.isDefault()) {
uidState.clear();
mUidStates.remove(uidState.uid);
}
if (uidChanged) {
uidState.evalForegroundOps();
}
@@ -3587,6 +3619,20 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
return mPackageManagerInternal;
}
/**
* @return {@link UserManagerInternal}
*/
private @NonNull UserManagerInternal getUserManagerInternal() {
if (mUserManagerInternal == null) {
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
}
if (mUserManagerInternal == null) {
throw new IllegalStateException("UserManagerInternal not loaded");
}
return mUserManagerInternal;
}
/**
* Create a restriction description matching the properties of the package.
*

View File

@@ -71,6 +71,10 @@ class AppOpService(
return opNameMapToOpIntMap(getUidModes(uid))
}
override fun getNonDefaultPackageModes(packageName: String, userId: Int): SparseIntArray {
return opNameMapToOpIntMap(getPackageModes(packageName, userId))
}
override fun getUidMode(uid: Int, op: Int): Int {
val appId = UserHandle.getAppId(uid)
val userId = UserHandle.getUserId(uid)

View File

@@ -42,6 +42,7 @@ import android.content.pm.PackageManagerInternal;
import android.content.res.AssetManager;
import android.os.Handler;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -51,12 +52,14 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.util.ArrayUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.server.LocalServices;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.PackageStateInternal;
import org.junit.After;
import org.junit.Before;
@@ -188,6 +191,11 @@ public class AppOpsUpgradeTest {
// Stub out package calls to disable AppOpsService#updatePermissionRevokedCompat
doReturn(null).when(mPackageManager).getPackagesForUid(anyInt());
doReturn(new ArrayMap<String, PackageStateInternal>()).when(mPackageManagerInternal)
.getPackageStates();
doReturn(new int[] {0}).when(mUserManagerInternal).getUserIds();
}
@After