Merge "Only add packageOps if they don't already exist in systemReady" into udc-dev

This commit is contained in:
Evan Severson
2023-03-23 21:10:46 +00:00
committed by Android (Google) Code Review
2 changed files with 109 additions and 22 deletions

View File

@@ -157,10 +157,10 @@ import com.android.server.LockGuard;
import com.android.server.SystemServerInitThreadPool; import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemServiceManager; import com.android.server.SystemServiceManager;
import com.android.server.pm.PackageList; import com.android.server.pm.PackageList;
import com.android.server.pm.PackageManagerLocal;
import com.android.server.pm.UserManagerInternal; import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState; 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.pm.pkg.component.ParsedAttribution;
import com.android.server.policy.AppOpsPolicy; import com.android.server.policy.AppOpsPolicy;
@@ -367,6 +367,9 @@ public class AppOpsService extends IAppOpsService.Stub {
/** Package Manager internal. Access via {@link #getPackageManagerInternal()} */ /** Package Manager internal. Access via {@link #getPackageManagerInternal()} */
private @Nullable PackageManagerInternal mPackageManagerInternal; private @Nullable PackageManagerInternal mPackageManagerInternal;
/** Package Manager local. Access via {@link #getPackageManagerLocal()} */
private @Nullable PackageManagerLocal mPackageManagerLocal;
/** User Manager internal. Access via {@link #getUserManagerInternal()} */ /** User Manager internal. Access via {@link #getUserManagerInternal()} */
private @Nullable UserManagerInternal mUserManagerInternal; private @Nullable UserManagerInternal mUserManagerInternal;
@@ -1189,42 +1192,64 @@ public class AppOpsService extends IAppOpsService.Stub {
/** /**
* Initialize uid state objects for state contained in the checking service. * Initialize uid state objects for state contained in the checking service.
*/ */
private void initializeUidStates() { @VisibleForTesting
void initializeUidStates() {
UserManagerInternal umi = getUserManagerInternal(); UserManagerInternal umi = getUserManagerInternal();
int[] userIds = umi.getUserIds();
synchronized (this) { synchronized (this) {
int[] userIds = umi.getUserIds();
try (PackageManagerLocal.UnfilteredSnapshot snapshot =
getPackageManagerLocal().withUnfilteredSnapshot()) {
Map<String, PackageState> packageStates = snapshot.getPackageStates();
for (int i = 0; i < userIds.length; i++) { for (int i = 0; i < userIds.length; i++) {
int userId = userIds[i]; int userId = userIds[i];
initializeUserUidStatesLocked(userId); initializeUserUidStatesLocked(userId, packageStates);
}
} }
} }
} }
private void initializeUserUidStates(int userId) { private void initializeUserUidStates(int userId) {
synchronized (this) { synchronized (this) {
initializeUserUidStatesLocked(userId); try (PackageManagerLocal.UnfilteredSnapshot snapshot =
getPackageManagerLocal().withUnfilteredSnapshot()) {
initializeUserUidStatesLocked(userId, snapshot.getPackageStates());
}
} }
} }
private void initializeUserUidStatesLocked(int userId) { private void initializeUserUidStatesLocked(int userId, Map<String,
ArrayMap<String, ? extends PackageStateInternal> packageStates = PackageState> packageStates) {
getPackageManagerInternal().getPackageStates(); for (Map.Entry<String, PackageState> entry : packageStates.entrySet()) {
for (int j = 0; j < packageStates.size(); j++) { int appId = entry.getValue().getAppId();
PackageStateInternal packageState = packageStates.valueAt(j); String packageName = entry.getKey();
int uid = UserHandle.getUid(userId, packageState.getAppId());
initializePackageUidStateLocked(userId, appId, packageName);
}
}
/*
Be careful not to clear any existing data; only want to add objects that don't already exist.
*/
private void initializePackageUidStateLocked(int userId, int appId, String packageName) {
int uid = UserHandle.getUid(userId, appId);
UidState uidState = getUidStateLocked(uid, true); UidState uidState = getUidStateLocked(uid, true);
String packageName = packageStates.keyAt(j); Ops ops = uidState.pkgOps.get(packageName);
Ops ops = new Ops(packageName, uidState); if (ops == null) {
ops = new Ops(packageName, uidState);
uidState.pkgOps.put(packageName, ops); uidState.pkgOps.put(packageName, ops);
}
SparseIntArray packageModes = SparseIntArray packageModes =
mAppOpsCheckingService.getNonDefaultPackageModes(packageName, userId); mAppOpsCheckingService.getNonDefaultPackageModes(packageName, userId);
for (int k = 0; k < packageModes.size(); k++) { for (int k = 0; k < packageModes.size(); k++) {
int code = packageModes.get(k); int code = packageModes.keyAt(k);
if (ops.indexOfKey(code) < 0) {
ops.put(code, new Op(uidState, packageName, code, uid)); ops.put(code, new Op(uidState, packageName, code, uid));
} }
uidState.evalForegroundOps();
} }
uidState.evalForegroundOps();
} }
/** /**
@@ -3648,6 +3673,20 @@ public class AppOpsService extends IAppOpsService.Stub {
return mPackageManagerInternal; return mPackageManagerInternal;
} }
/**
* @return {@link PackageManagerLocal}
*/
private @NonNull PackageManagerLocal getPackageManagerLocal() {
if (mPackageManagerLocal == null) {
mPackageManagerLocal = LocalManagerRegistry.getManager(PackageManagerLocal.class);
}
if (mPackageManagerLocal == null) {
throw new IllegalStateException("PackageManagerLocal not loaded");
}
return mPackageManagerLocal;
}
/** /**
* @return {@link UserManagerInternal} * @return {@link UserManagerInternal}
*/ */

View File

@@ -19,9 +19,11 @@ import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED; import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.OP_COARSE_LOCATION; import static android.app.AppOpsManager.OP_COARSE_LOCATION;
import static android.app.AppOpsManager.OP_FLAGS_ALL; import static android.app.AppOpsManager.OP_FLAGS_ALL;
import static android.app.AppOpsManager.OP_FLAG_SELF;
import static android.app.AppOpsManager.OP_READ_SMS; import static android.app.AppOpsManager.OP_READ_SMS;
import static android.app.AppOpsManager.OP_WIFI_SCAN; import static android.app.AppOpsManager.OP_WIFI_SCAN;
import static android.app.AppOpsManager.OP_WRITE_SMS; import static android.app.AppOpsManager.OP_WRITE_SMS;
import static android.os.UserHandle.getUserId;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -33,12 +35,15 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage; import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.nullable;
import android.app.AppOpsManager;
import android.app.AppOpsManager.OpEntry; import android.app.AppOpsManager.OpEntry;
import android.app.AppOpsManager.PackageOps; import android.app.AppOpsManager.PackageOps;
import android.content.ContentResolver; import android.content.ContentResolver;
@@ -48,14 +53,19 @@ import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.Process; import android.os.Process;
import android.provider.Settings; import android.provider.Settings;
import android.util.ArrayMap;
import androidx.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.server.LocalManagerRegistry;
import com.android.server.LocalServices; import com.android.server.LocalServices;
import com.android.server.pm.PackageManagerLocal;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.pkg.AndroidPackage; 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.PackageStateInternal;
import org.junit.After; import org.junit.After;
@@ -67,6 +77,7 @@ import org.mockito.quality.Strictness;
import java.io.File; import java.io.File;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Unit tests for AppOpsService. Covers functionality that is difficult to test using CTS tests * Unit tests for AppOpsService. Covers functionality that is difficult to test using CTS tests
@@ -133,6 +144,7 @@ public class AppOpsServiceTest {
mMockingSession = mockitoSession() mMockingSession = mockitoSession()
.strictness(Strictness.LENIENT) .strictness(Strictness.LENIENT)
.spyStatic(LocalServices.class) .spyStatic(LocalServices.class)
.spyStatic(LocalManagerRegistry.class)
.spyStatic(Settings.Global.class) .spyStatic(Settings.Global.class)
.startMocking(); .startMocking();
@@ -152,6 +164,23 @@ public class AppOpsServiceTest {
doReturn(mockPackageManagerInternal).when( doReturn(mockPackageManagerInternal).when(
() -> LocalServices.getService(PackageManagerInternal.class)); () -> LocalServices.getService(PackageManagerInternal.class));
PackageManagerLocal mockPackageManagerLocal = mock(PackageManagerLocal.class);
PackageManagerLocal.UnfilteredSnapshot mockUnfilteredSnapshot =
mock(PackageManagerLocal.UnfilteredSnapshot.class);
PackageState mockMyPS = mock(PackageState.class);
ArrayMap<String, PackageState> packageStates = new ArrayMap<>();
packageStates.put(sMyPackageName, mockMyPS);
when(mockMyPS.getAppId()).thenReturn(mMyUid);
when(mockUnfilteredSnapshot.getPackageStates()).thenReturn(packageStates);
when(mockPackageManagerLocal.withUnfilteredSnapshot()).thenReturn(mockUnfilteredSnapshot);
doReturn(mockPackageManagerLocal).when(
() -> LocalManagerRegistry.getManager(PackageManagerLocal.class));
UserManagerInternal mockUserManagerInternal = mock(UserManagerInternal.class);
when(mockUserManagerInternal.getUserIds()).thenReturn(new int[] {getUserId(mMyUid)});
doReturn(mockUserManagerInternal).when(
() -> LocalServices.getService(UserManagerInternal.class));
// Mock behavior to use specific Settings.Global.APPOP_HISTORY_PARAMETERS // Mock behavior to use specific Settings.Global.APPOP_HISTORY_PARAMETERS
doReturn(null).when(() -> Settings.Global.getString(any(ContentResolver.class), doReturn(null).when(() -> Settings.Global.getString(any(ContentResolver.class),
eq(Settings.Global.APPOP_HISTORY_PARAMETERS))); eq(Settings.Global.APPOP_HISTORY_PARAMETERS)));
@@ -337,6 +366,25 @@ public class AppOpsServiceTest {
assertThat(getLoggedOps()).isNull(); assertThat(getLoggedOps()).isNull();
} }
@Test
public void testUidStateInitializationDoesntClearState() throws InterruptedException {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null, false);
mAppOpsService.initializeUidStates();
List<PackageOps> ops = mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName,
new int[]{OP_READ_SMS});
assertNotNull(ops);
for (int i = 0; i < ops.size(); i++) {
List<OpEntry> opEntries = ops.get(i).getOps();
for (int j = 0; j < opEntries.size(); j++) {
Map<String, AppOpsManager.AttributedOpEntry> attributedOpEntries = opEntries.get(
j).getAttributedOpEntries();
assertNotEquals(-1, attributedOpEntries.get(null)
.getLastAccessTime(OP_FLAG_SELF));
}
}
}
private List<PackageOps> getLoggedOps() { private List<PackageOps> getLoggedOps() {
return mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName, null /* all ops */); return mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName, null /* all ops */);
} }