From fc2ed91d5d912f51d2127d4d62ce40f56ea5dd0b Mon Sep 17 00:00:00 2001 From: Nate Myren Date: Thu, 23 Mar 2023 14:43:15 -0700 Subject: [PATCH] Add testing shims to allow switching of app ops/permission backend Add a shim layer in between the AppOpsService/PermissionManagerService and their respective implementations. In these shims, include both the old and new implementations. Select which implementation to use based on deviceConfig. Also support running both, and comparing the outputs. Bug: 252886104 Test: manual Change-Id: Ibe420a1985b041816cb2d6e675761cffa6462f24 --- .../appop/AppOpsServiceTestingShim.java | 291 +++++++++ .../permission/AccessTestingShimFactory.java | 75 +++ .../PermissionManagerServiceTestingShim.java | 565 ++++++++++++++++++ 3 files changed, 931 insertions(+) create mode 100644 services/core/java/com/android/server/appop/AppOpsServiceTestingShim.java create mode 100644 services/core/java/com/android/server/pm/permission/AccessTestingShimFactory.java create mode 100644 services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java diff --git a/services/core/java/com/android/server/appop/AppOpsServiceTestingShim.java b/services/core/java/com/android/server/appop/AppOpsServiceTestingShim.java new file mode 100644 index 0000000000000..6aaf19049f005 --- /dev/null +++ b/services/core/java/com/android/server/appop/AppOpsServiceTestingShim.java @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2022 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 com.android.server.appop; + +import android.util.ArraySet; +import android.util.SparseBooleanArray; +import android.util.SparseIntArray; + +import java.io.PrintWriter; +import java.util.Objects; + +/** + * A testing shim, which supports running two variants of an AppOpsServiceInterface at once, + * and checking the results of both. + */ +public class AppOpsServiceTestingShim implements AppOpsCheckingServiceInterface { + + private AppOpsCheckingServiceInterface mOldImplementation; + private AppOpsCheckingServiceInterface mNewImplementation; + + public AppOpsServiceTestingShim(AppOpsCheckingServiceInterface oldValImpl, + AppOpsCheckingServiceInterface newImpl) { + mOldImplementation = oldValImpl; + mNewImplementation = newImpl; + } + + private void signalImplDifference(String message) { + //TODO b/252886104 implement + } + + @Override + public void writeState() { + mOldImplementation.writeState(); + mNewImplementation.writeState(); + } + + @Override + public void readState() { + mOldImplementation.readState(); + mNewImplementation.readState(); + } + + @Override + public void shutdown() { + mOldImplementation.shutdown(); + mNewImplementation.shutdown(); + } + + @Override + public void systemReady() { + mOldImplementation.systemReady(); + mNewImplementation.systemReady(); + } + + @Override + public SparseIntArray getNonDefaultUidModes(int uid) { + SparseIntArray oldVal = mOldImplementation.getNonDefaultUidModes(uid); + SparseIntArray newVal = mNewImplementation.getNonDefaultUidModes(uid); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getNonDefaultUidModes"); + } + + return newVal; + } + + @Override + public SparseIntArray getNonDefaultPackageModes(String packageName, int userId) { + SparseIntArray oldVal = mOldImplementation.getNonDefaultPackageModes(packageName, userId); + SparseIntArray newVal = mNewImplementation.getNonDefaultPackageModes(packageName, userId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getNonDefaultPackageModes"); + } + + return newVal; + } + + @Override + public int getUidMode(int uid, int op) { + int oldVal = mOldImplementation.getUidMode(uid, op); + int newVal = mNewImplementation.getUidMode(uid, op); + + if (oldVal != newVal) { + signalImplDifference("getUidMode"); + } + + return newVal; + } + + @Override + public boolean setUidMode(int uid, int op, int mode) { + boolean oldVal = mOldImplementation.setUidMode(uid, op, mode); + boolean newVal = mNewImplementation.setUidMode(uid, op, mode); + + if (oldVal != newVal) { + signalImplDifference("setUidMode"); + } + + return newVal; + } + + @Override + public int getPackageMode(String packageName, int op, int userId) { + int oldVal = mOldImplementation.getPackageMode(packageName, op, userId); + int newVal = mNewImplementation.getPackageMode(packageName, op, userId); + + if (oldVal != newVal) { + signalImplDifference("getPackageMode"); + } + + return newVal; + } + + @Override + public void setPackageMode(String packageName, int op, int mode, int userId) { + mOldImplementation.setPackageMode(packageName, op, mode, userId); + mNewImplementation.setPackageMode(packageName, op, mode, userId); + } + + @Override + public boolean removePackage(String packageName, int userId) { + boolean oldVal = mOldImplementation.removePackage(packageName, userId); + boolean newVal = mNewImplementation.removePackage(packageName, userId); + + if (oldVal != newVal) { + signalImplDifference("removePackage"); + } + + return newVal; + } + + @Override + public void removeUid(int uid) { + mOldImplementation.removeUid(uid); + mNewImplementation.removeUid(uid); + } + + @Override + public boolean areUidModesDefault(int uid) { + boolean oldVal = mOldImplementation.areUidModesDefault(uid); + boolean newVal = mNewImplementation.areUidModesDefault(uid); + + if (oldVal != newVal) { + signalImplDifference("areUidModesDefault"); + } + + return newVal; + } + + @Override + public boolean arePackageModesDefault(String packageName, int userId) { + boolean oldVal = mOldImplementation.arePackageModesDefault(packageName, userId); + boolean newVal = mNewImplementation.arePackageModesDefault(packageName, userId); + + if (oldVal != newVal) { + signalImplDifference("arePackageModesDefault"); + } + + return newVal; + } + + @Override + public void clearAllModes() { + mOldImplementation.clearAllModes(); + mNewImplementation.clearAllModes(); + } + + @Override + public void startWatchingOpModeChanged(OnOpModeChangedListener changedListener, int op) { + mOldImplementation.startWatchingOpModeChanged(changedListener, op); + mNewImplementation.startWatchingOpModeChanged(changedListener, op); + } + + @Override + public void startWatchingPackageModeChanged(OnOpModeChangedListener changedListener, + String packageName) { + mOldImplementation.startWatchingPackageModeChanged(changedListener, packageName); + mNewImplementation.startWatchingPackageModeChanged(changedListener, packageName); + } + + @Override + public void removeListener(OnOpModeChangedListener changedListener) { + mOldImplementation.removeListener(changedListener); + mNewImplementation.removeListener(changedListener); + } + + @Override + public ArraySet getOpModeChangedListeners(int op) { + ArraySet oldVal = mOldImplementation.getOpModeChangedListeners(op); + ArraySet newVal = mNewImplementation.getOpModeChangedListeners(op); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getOpModeChangedListeners"); + } + + return newVal; + } + + @Override + public ArraySet getPackageModeChangedListeners(String packageName) { + ArraySet oldVal = mOldImplementation + .getPackageModeChangedListeners(packageName); + ArraySet newVal = mNewImplementation + .getPackageModeChangedListeners(packageName); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getPackageModeChangedListeners"); + } + + return newVal; + } + + @Override + public void notifyWatchersOfChange(int op, int uid) { + mOldImplementation.notifyWatchersOfChange(op, uid); + mNewImplementation.notifyWatchersOfChange(op, uid); + } + + @Override + public void notifyOpChanged(OnOpModeChangedListener changedListener, int op, int uid, + String packageName) { + mOldImplementation.notifyOpChanged(changedListener, op, uid, packageName); + mNewImplementation.notifyOpChanged(changedListener, op, uid, packageName); + } + + @Override + public void notifyOpChangedForAllPkgsInUid(int op, int uid, boolean onlyForeground, + OnOpModeChangedListener callbackToIgnore) { + mOldImplementation + .notifyOpChangedForAllPkgsInUid(op, uid, onlyForeground, callbackToIgnore); + mNewImplementation + .notifyOpChangedForAllPkgsInUid(op, uid, onlyForeground, callbackToIgnore); + } + + @Override + public SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps) { + SparseBooleanArray oldVal = mOldImplementation.evalForegroundUidOps(uid, foregroundOps); + SparseBooleanArray newVal = mNewImplementation.evalForegroundUidOps(uid, foregroundOps); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("evalForegroundUidOps"); + } + + return newVal; + } + + @Override + public SparseBooleanArray evalForegroundPackageOps(String packageName, + SparseBooleanArray foregroundOps, int userId) { + SparseBooleanArray oldVal = mOldImplementation + .evalForegroundPackageOps(packageName, foregroundOps, userId); + SparseBooleanArray newVal = mNewImplementation + .evalForegroundPackageOps(packageName, foregroundOps, userId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("evalForegroundPackageOps"); + } + + return newVal; + } + + @Override + public boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage, + PrintWriter printWriter) { + boolean oldVal = mOldImplementation + .dumpListeners(dumpOp, dumpUid, dumpPackage, printWriter); + boolean newVal = mNewImplementation + .dumpListeners(dumpOp, dumpUid, dumpPackage, printWriter); + + if (oldVal != newVal) { + signalImplDifference("dumpListeners"); + } + + return newVal; + } +} diff --git a/services/core/java/com/android/server/pm/permission/AccessTestingShimFactory.java b/services/core/java/com/android/server/pm/permission/AccessTestingShimFactory.java new file mode 100644 index 0000000000000..0682e92509939 --- /dev/null +++ b/services/core/java/com/android/server/pm/permission/AccessTestingShimFactory.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2022 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 com.android.server.pm.permission; + +import static android.provider.DeviceConfig.NAMESPACE_PRIVACY; + +import android.content.Context; +import android.provider.DeviceConfig; + +import com.android.server.appop.AppOpsCheckingServiceInterface; +import com.android.server.appop.AppOpsServiceTestingShim; + +import java.util.function.Supplier; + +/** + * A factory which will select one or both implementations of a PermissionManagerServiceInterface or + * AppOpsCheckingServiceInterface, based upon either a DeviceConfig value, or a hard coded config. + */ +public class AccessTestingShimFactory { + + private static final int RUN_OLD_SUBSYSTEM = 0; + private static final int RUN_NEW_SUBSYSTEM = 1; + private static final int RUN_BOTH_SUBSYSTEMS = 2; + public static final String DEVICE_CONFIG_SETTING = "selected_access_subsystem"; + + /** + * Get the PermissionManagerServiceInterface, based upon the current config state. + */ + public static PermissionManagerServiceInterface getPms(Context context, + Supplier oldImpl, + Supplier newImpl) { + int selectedSystem = DeviceConfig.getInt(NAMESPACE_PRIVACY, + DEVICE_CONFIG_SETTING, RUN_OLD_SUBSYSTEM); + switch (selectedSystem) { + case RUN_BOTH_SUBSYSTEMS: + return new PermissionManagerServiceTestingShim(oldImpl.get(), newImpl.get()); + case RUN_NEW_SUBSYSTEM: + return newImpl.get(); + default: + return oldImpl.get(); + } + } + + /** + * Get the AppOpsCheckingServiceInterface, based upon the current config state. + */ + public static AppOpsCheckingServiceInterface getAos(Context context, + Supplier oldImpl, + Supplier newImpl) { + int selectedSystem = DeviceConfig.getInt(NAMESPACE_PRIVACY, + DEVICE_CONFIG_SETTING, RUN_OLD_SUBSYSTEM); + switch (selectedSystem) { + case RUN_BOTH_SUBSYSTEMS: + return new AppOpsServiceTestingShim(oldImpl.get(), newImpl.get()); + case RUN_NEW_SUBSYSTEM: + return newImpl.get(); + default: + return oldImpl.get(); + } + } +} diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java new file mode 100644 index 0000000000000..3db08deab7b4d --- /dev/null +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceTestingShim.java @@ -0,0 +1,565 @@ +/* + * Copyright (C) 2022 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 com.android.server.pm.permission; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.UserIdInt; +import android.content.pm.PermissionGroupInfo; +import android.content.pm.PermissionInfo; +import android.content.pm.permission.SplitPermissionInfoParcelable; +import android.permission.IOnPermissionsChangeListener; + +import com.android.server.pm.pkg.AndroidPackage; +import com.android.server.pm.pkg.PackageState; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * A testing shim, which supports running two variants of a PermissionManagerServiceInterface at + * once, and checking the results of both. + */ +public class PermissionManagerServiceTestingShim implements PermissionManagerServiceInterface { + + private PermissionManagerServiceInterface mOldImplementation; + private PermissionManagerServiceInterface mNewImplementation; + + public PermissionManagerServiceTestingShim(PermissionManagerServiceInterface oldImpl, + PermissionManagerServiceInterface newImpl) { + mOldImplementation = oldImpl; + mNewImplementation = newImpl; + } + + private void signalImplDifference(String message) { + //TODO b/252886104 implement + } + + + @Nullable + @Override + public byte[] backupRuntimePermissions(int userId) { + byte[] oldVal = mOldImplementation.backupRuntimePermissions(userId); + byte[] newVal = mNewImplementation.backupRuntimePermissions(userId); + if (!Arrays.equals(oldVal, newVal)) { + signalImplDifference("backupRuntimePermissions"); + } + + return newVal; + } + + @Override + public void restoreRuntimePermissions(@NonNull byte[] backup, int userId) { + mOldImplementation.backupRuntimePermissions(userId); + mNewImplementation.backupRuntimePermissions(userId); + } + + @Override + public void restoreDelayedRuntimePermissions(@NonNull String packageName, int userId) { + mOldImplementation.restoreDelayedRuntimePermissions(packageName, userId); + mNewImplementation.restoreDelayedRuntimePermissions(packageName, userId); + + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + mOldImplementation.dump(fd, pw, args); + mNewImplementation.dump(fd, pw, args); + } + + @Override + public List getAllPermissionGroups(int flags) { + List oldVal = mOldImplementation.getAllPermissionGroups(flags); + List newVal = mNewImplementation.getAllPermissionGroups(flags); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getAllPermissionGroups"); + } + return newVal; + } + + @Override + public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags) { + PermissionGroupInfo oldVal = mOldImplementation.getPermissionGroupInfo(groupName, flags); + PermissionGroupInfo newVal = mNewImplementation.getPermissionGroupInfo(groupName, flags); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getPermissionGroupInfo"); + } + return newVal; + } + + @Override + public PermissionInfo getPermissionInfo(@NonNull String permName, int flags, + @NonNull String opPackageName) { + PermissionInfo oldVal = mOldImplementation.getPermissionInfo(permName, flags, + opPackageName); + PermissionInfo newVal = mNewImplementation.getPermissionInfo(permName, flags, + opPackageName); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getPermissionInfo"); + } + return newVal; + } + + @Override + public List queryPermissionsByGroup(String groupName, int flags) { + List oldVal = mOldImplementation.queryPermissionsByGroup(groupName, + flags); + List newVal = mNewImplementation.queryPermissionsByGroup(groupName, flags); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("queryPermissionsByGroup"); + } + return newVal; + } + + @Override + public boolean addPermission(PermissionInfo info, boolean async) { + boolean oldVal = mOldImplementation.addPermission(info, async); + boolean newVal = mNewImplementation.addPermission(info, async); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("addPermission"); + } + return newVal; + } + + @Override + public void removePermission(String permName) { + mOldImplementation.removePermission(permName); + mNewImplementation.removePermission(permName); + } + + @Override + public int getPermissionFlags(String packageName, String permName, int userId) { + int oldVal = mOldImplementation.getPermissionFlags(packageName, permName, userId); + int newVal = mNewImplementation.getPermissionFlags(packageName, permName, userId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getPermissionFlags"); + } + return newVal; + } + + @Override + public void updatePermissionFlags(String packageName, String permName, int flagMask, + int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) { + mOldImplementation.updatePermissionFlags(packageName, permName, flagMask, flagValues, + checkAdjustPolicyFlagPermission, userId); + mNewImplementation.updatePermissionFlags(packageName, permName, flagMask, flagValues, + checkAdjustPolicyFlagPermission, userId); + } + + @Override + public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId) { + mOldImplementation.updatePermissionFlagsForAllApps(flagMask, flagValues, userId); + mNewImplementation.updatePermissionFlagsForAllApps(flagMask, flagValues, userId); + } + + @Override + public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) { + mOldImplementation.addOnPermissionsChangeListener(listener); + mNewImplementation.addOnPermissionsChangeListener(listener); + } + + @Override + public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) { + mOldImplementation.removeOnPermissionsChangeListener(listener); + mNewImplementation.removeOnPermissionsChangeListener(listener); + } + + @Override + public boolean addAllowlistedRestrictedPermission(@NonNull String packageName, + @NonNull String permName, int flags, int userId) { + boolean oldVal = mOldImplementation.addAllowlistedRestrictedPermission(packageName, + permName, + flags, userId); + boolean newVal = mNewImplementation.addAllowlistedRestrictedPermission(packageName, + permName, flags, userId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("addAllowlistedRestrictedPermission"); + } + return newVal; + } + + @Override + public List getAllowlistedRestrictedPermissions(@NonNull String packageName, int flags, + int userId) { + List oldVal = mOldImplementation.getAllowlistedRestrictedPermissions(packageName, + flags, userId); + List newVal = mNewImplementation.getAllowlistedRestrictedPermissions(packageName, + flags, userId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getAllowlistedRestrictedPermissions"); + } + return newVal; + } + + @Override + public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName, + @NonNull String permName, int flags, int userId) { + boolean oldVal = mOldImplementation.removeAllowlistedRestrictedPermission(packageName, + permName, flags, userId); + boolean newVal = mNewImplementation.removeAllowlistedRestrictedPermission(packageName, + permName, flags, userId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("removeAllowlistedRestrictedPermission"); + } + return newVal; + } + + @Override + public void grantRuntimePermission(String packageName, String permName, int userId) { + mOldImplementation.grantRuntimePermission(packageName, permName, userId); + mNewImplementation.grantRuntimePermission(packageName, permName, userId); + } + + @Override + public void revokeRuntimePermission(String packageName, String permName, int userId, + String reason) { + mOldImplementation.grantRuntimePermission(packageName, permName, userId); + mNewImplementation.grantRuntimePermission(packageName, permName, userId); + } + + @Override + public void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId) { + mOldImplementation.revokePostNotificationPermissionWithoutKillForTest(packageName, + userId); + mNewImplementation.revokePostNotificationPermissionWithoutKillForTest(packageName, userId); + } + + @Override + public boolean shouldShowRequestPermissionRationale(String packageName, String permName, + int userId) { + boolean oldVal = mOldImplementation + .shouldShowRequestPermissionRationale(packageName, permName, userId); + boolean newVal = mNewImplementation + .shouldShowRequestPermissionRationale(packageName, permName, userId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("shouldShowRequestPermissionRationale"); + } + return newVal; + } + + @Override + public boolean isPermissionRevokedByPolicy(String packageName, String permName, int userId) { + boolean oldVal = mOldImplementation + .isPermissionRevokedByPolicy(packageName, permName, userId); + boolean newVal = mNewImplementation.isPermissionRevokedByPolicy(packageName, permName, + userId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("isPermissionRevokedByPolicy"); + } + return newVal; + } + + @Override + public List getSplitPermissions() { + List oldVal = mOldImplementation.getSplitPermissions(); + List newVal = mNewImplementation.getSplitPermissions(); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getSplitPermissions"); + } + return newVal; + } + + @Override + public int checkPermission(String pkgName, String permName, int userId) { + int oldVal = mOldImplementation.checkPermission(pkgName, permName, userId); + int newVal = mNewImplementation.checkPermission(pkgName, permName, userId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("checkPermission"); + } + return newVal; + } + + @Override + public int checkUidPermission(int uid, String permName) { + int oldVal = mOldImplementation.checkUidPermission(uid, permName); + int newVal = mNewImplementation.checkUidPermission(uid, permName); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("checkUidPermission"); + } + return newVal; + } + + @Override + public void addOnRuntimePermissionStateChangedListener(@NonNull + PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener listener) { + mOldImplementation.addOnRuntimePermissionStateChangedListener(listener); + mNewImplementation.addOnRuntimePermissionStateChangedListener(listener); + } + + @Override + public void removeOnRuntimePermissionStateChangedListener(@NonNull + PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener listener) { + mOldImplementation.removeOnRuntimePermissionStateChangedListener(listener); + mNewImplementation.removeOnRuntimePermissionStateChangedListener(listener); + } + + @Override + public Map> getAllAppOpPermissionPackages() { + Map> oldVal = mOldImplementation.getAllAppOpPermissionPackages(); + Map> newVal = mNewImplementation.getAllAppOpPermissionPackages(); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getAllAppOpPermissionPackages"); + } + return newVal; + } + + @Override + public boolean isPermissionsReviewRequired(@NonNull String packageName, int userId) { + boolean oldVal = mOldImplementation.isPermissionsReviewRequired(packageName, userId); + boolean newVal = mNewImplementation.isPermissionsReviewRequired(packageName, userId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("isPermissionsReviewRequired"); + } + return newVal; + } + + @Override + public void resetRuntimePermissions(@NonNull AndroidPackage pkg, @UserIdInt int userId) { + mOldImplementation.resetRuntimePermissions(pkg, userId); + mNewImplementation.resetRuntimePermissions(pkg, userId); + } + + @Override + public void resetRuntimePermissionsForUser(int userId) { + mOldImplementation.resetRuntimePermissionsForUser(userId); + mNewImplementation.resetRuntimePermissionsForUser(userId); + } + + @Override + public void readLegacyPermissionStateTEMP() { + mOldImplementation.readLegacyPermissionStateTEMP(); + mNewImplementation.readLegacyPermissionStateTEMP(); + } + + @Override + public void writeLegacyPermissionStateTEMP() { + mOldImplementation.writeLegacyPermissionStateTEMP(); + mNewImplementation.writeLegacyPermissionStateTEMP(); + } + + @Override + public Set getInstalledPermissions(String packageName) { + Set oldVal = mOldImplementation.getInstalledPermissions(packageName); + Set newVal = mNewImplementation.getInstalledPermissions(packageName); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getInstalledPermissions"); + } + return newVal; + } + + @NonNull + @Override + public Set getGrantedPermissions(@NonNull String packageName, int userId) { + Set oldVal = mOldImplementation.getGrantedPermissions(packageName, userId); + Set newVal = mNewImplementation.getGrantedPermissions(packageName, userId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getGrantedPermissions"); + } + return newVal; + } + + @NonNull + @Override + public int[] getPermissionGids(@NonNull String permissionName, int userId) { + int[] oldVal = mOldImplementation.getPermissionGids(permissionName, userId); + int[] newVal = mNewImplementation.getPermissionGids(permissionName, userId); + + if (!Arrays.equals(oldVal, newVal)) { + signalImplDifference("getPermissionGids"); + } + return newVal; + } + + @NonNull + @Override + public String[] getAppOpPermissionPackages(@NonNull String permissionName) { + String[] oldVal = mOldImplementation.getAppOpPermissionPackages(permissionName); + String[] newVal = mNewImplementation.getAppOpPermissionPackages(permissionName); + + if (!Arrays.equals(oldVal, newVal)) { + signalImplDifference("getAppOpPermissionPackages"); + } + return newVal; + } + + @Nullable + @Override + public Permission getPermissionTEMP(@NonNull String permName) { + Permission oldVal = mOldImplementation.getPermissionTEMP(permName); + Permission newVal = mNewImplementation.getPermissionTEMP(permName); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getPermissionTEMP"); + } + return newVal; + } + + @NonNull + @Override + public List getAllPermissionsWithProtection(int protection) { + List oldVal = mOldImplementation.getAllPermissionsWithProtection( + protection); + List newVal = mNewImplementation.getAllPermissionsWithProtection( + protection); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getAllPermissionsWithProtection"); + } + return newVal; + } + + @NonNull + @Override + public List getAllPermissionsWithProtectionFlags(int protectionFlags) { + List oldVal = mOldImplementation + .getAllPermissionsWithProtectionFlags(protectionFlags); + List newVal = mNewImplementation.getAllPermissionsWithProtectionFlags( + protectionFlags); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getAllPermissionsWithProtectionFlags"); + } + return newVal; + } + + @NonNull + @Override + public List getLegacyPermissions() { + List oldVal = mOldImplementation.getLegacyPermissions(); + List newVal = mNewImplementation.getLegacyPermissions(); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getLegacyPermissions"); + } + return newVal; + } + + @NonNull + @Override + public LegacyPermissionState getLegacyPermissionState(int appId) { + LegacyPermissionState oldVal = mOldImplementation.getLegacyPermissionState(appId); + LegacyPermissionState newVal = mNewImplementation.getLegacyPermissionState(appId); + + if (!Objects.equals(oldVal, newVal)) { + signalImplDifference("getLegacyPermissionState"); + } + return newVal; + } + + @Override + public void readLegacyPermissionsTEMP( + @NonNull LegacyPermissionSettings legacyPermissionSettings) { + mOldImplementation.readLegacyPermissionsTEMP(legacyPermissionSettings); + mNewImplementation.readLegacyPermissionsTEMP(legacyPermissionSettings); + } + + @Override + public void writeLegacyPermissionsTEMP( + @NonNull LegacyPermissionSettings legacyPermissionSettings) { + mOldImplementation.writeLegacyPermissionsTEMP(legacyPermissionSettings); + mNewImplementation.writeLegacyPermissionsTEMP(legacyPermissionSettings); + } + + @Override + public void onSystemReady() { + mOldImplementation.onSystemReady(); + mNewImplementation.onSystemReady(); + } + + @Override + public void onStorageVolumeMounted(@NonNull String volumeUuid, boolean fingerprintChanged) { + mOldImplementation.onStorageVolumeMounted(volumeUuid, fingerprintChanged); + mNewImplementation.onStorageVolumeMounted(volumeUuid, fingerprintChanged); + } + + @NonNull + @Override + public int[] getGidsForUid(int uid) { + int[] oldVal = mOldImplementation.getGidsForUid(uid); + int[] newVal = mNewImplementation.getGidsForUid(uid); + + if (!Arrays.equals(oldVal, newVal)) { + signalImplDifference("getGidsForUid"); + } + return newVal; + } + + @Override + public void onUserCreated(int userId) { + mOldImplementation.onUserCreated(userId); + mNewImplementation.onUserCreated(userId); + } + + @Override + public void onUserRemoved(int userId) { + mOldImplementation.onUserRemoved(userId); + mNewImplementation.onUserRemoved(userId); + } + + @Override + public void onPackageAdded(@NonNull PackageState pkg, boolean isInstantApp, + @Nullable AndroidPackage oldPkg) { + mOldImplementation.onPackageAdded(pkg, isInstantApp, oldPkg); + mNewImplementation.onPackageAdded(pkg, isInstantApp, oldPkg); + } + + @Override + public void onPackageInstalled(@NonNull AndroidPackage pkg, int previousAppId, + @NonNull PermissionManagerServiceInternal.PackageInstalledParams params, int userId) { + mOldImplementation.onPackageInstalled(pkg, previousAppId, params, userId); + mNewImplementation.onPackageInstalled(pkg, previousAppId, params, userId); + } + + @Override + public void onPackageRemoved(@NonNull AndroidPackage pkg) { + mOldImplementation.onPackageRemoved(pkg); + mNewImplementation.onPackageRemoved(pkg); + } + + @Override + public void onPackageUninstalled(@NonNull String packageName, int appId, + @NonNull PackageState packageState, @Nullable AndroidPackage pkg, + @NonNull List sharedUserPkgs, int userId) { + mOldImplementation.onPackageUninstalled(packageName, appId, packageState, pkg, + sharedUserPkgs, userId); + mNewImplementation.onPackageUninstalled(packageName, appId, packageState, pkg, + sharedUserPkgs, userId); + } +}