Loading services/core/java/com/android/server/appop/AppOpsService.java +133 −113 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/appop/AppOpsServiceInterface.java 0 → 100644 +98 −0 Original line number Diff line number Diff line /* * 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.annotation.NonNull; import android.app.AppOpsManager.Mode; import android.util.SparseIntArray; /** * Interface for accessing and modifying modes for app-ops i.e. package and uid modes. * In the future this interface will also include mode callbacks and op restrictions. */ public interface AppOpsServiceInterface { /** * Returns a copy of non-default app-ops with op as keys and their modes as values for a uid. * Returns an empty SparseIntArray if nothing is set. * @param uid for which we need the app-ops and their modes. */ SparseIntArray getNonDefaultUidModes(int uid); /** * 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. * @param uid user id for which we need the mode. * @param op app-op for which we need the mode. * @return mode of the app-op. */ int getUidMode(int uid, int op); /** * Set the app-op mode for a particular uid and op. * The mode is not set if the mode is the same as the default mode for the op. * @param uid user id for which we want to set the mode. * @param op app-op for which we want to set the mode. * @param mode mode for the app-op. * @return true if op mode is changed. */ boolean setUidMode(int uid, int op, @Mode int mode); /** * Gets the app-op mode for a particular package. * Returns default op mode if the op mode for the particular package is not set. * @param packageName package name for which we need the op mode. * @param op app-op for which we need the mode. * @return the mode of the app-op. */ int getPackageMode(@NonNull String packageName, int op); /** * Sets the app-op mode for a particular package. * @param packageName package name for which we need to set the op mode. * @param op app-op for which we need to set the mode. * @param mode the mode of the app-op. */ void setPackageMode(@NonNull String packageName, int op, @Mode int mode); /** * Stop tracking any app-op modes for a package. * @param packageName Name of the package for which we want to remove all mode tracking. */ boolean removePackage(@NonNull String packageName); /** * Stop tracking any app-op modes for this uid. * @param uid user id for which we want to remove all tracking. */ void removeUid(int uid); /** * Returns true if all uid modes for this uid are * in default state. * @param uid user id */ boolean areUidModesDefault(int uid); /** * Returns true if all package modes for this package name are * in default state. * @param packageName package name. */ boolean arePackageModesDefault(String packageName); /** * Stop tracking app-op modes for all uid and packages. */ void clearAllModes(); } services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java 0 → 100644 +198 −0 Original line number Diff line number Diff line /* * 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.annotation.NonNull; import android.app.AppOpsManager; import android.app.AppOpsManager.Mode; import android.util.ArrayMap; import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; /** * Legacy implementation for App-ops service's app-op mode (uid and package) storage and access. * In the future this class will also include mode callbacks and op restrictions. */ public class LegacyAppOpsServiceInterfaceImpl implements AppOpsServiceInterface { // Should be the same object that the AppOpsService is using for locking. final Object mLock; @GuardedBy("mLock") @VisibleForTesting final SparseArray<SparseIntArray> mUidModes = new SparseArray<>(); @GuardedBy("mLock") final ArrayMap<String, SparseIntArray> mPackageModes = new ArrayMap<>(); final PersistenceScheduler mPersistenceScheduler; LegacyAppOpsServiceInterfaceImpl(PersistenceScheduler persistenceScheduler, @NonNull Object lock) { this.mPersistenceScheduler = persistenceScheduler; this.mLock = lock; } @Override public SparseIntArray getNonDefaultUidModes(int uid) { synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid, null); if (opModes == null) { return new SparseIntArray(); } return opModes.clone(); } } @Override public int getUidMode(int uid, int op) { synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid, null); if (opModes == null) { return AppOpsManager.opToDefaultMode(op); } return opModes.get(op, AppOpsManager.opToDefaultMode(op)); } } @Override public boolean setUidMode(int uid, int op, int mode) { final int defaultMode = AppOpsManager.opToDefaultMode(op); synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid, null); if (opModes == null) { if (mode != defaultMode) { opModes = new SparseIntArray(); mUidModes.put(uid, opModes); opModes.put(op, mode); mPersistenceScheduler.scheduleWriteLocked(); } } else { if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) { return false; } if (mode == defaultMode) { opModes.delete(op); if (opModes.size() <= 0) { opModes = null; mUidModes.delete(uid); } } else { opModes.put(op, mode); } mPersistenceScheduler.scheduleWriteLocked(); } } return true; } @Override public int getPackageMode(String packageName, int op) { synchronized (mLock) { SparseIntArray opModes = mPackageModes.getOrDefault(packageName, null); if (opModes == null) { return AppOpsManager.opToDefaultMode(op); } return opModes.get(op, AppOpsManager.opToDefaultMode(op)); } } @Override public void setPackageMode(String packageName, int op, @Mode int mode) { final int defaultMode = AppOpsManager.opToDefaultMode(op); synchronized (mLock) { SparseIntArray opModes = mPackageModes.get(packageName); if (opModes == null) { if (mode != defaultMode) { opModes = new SparseIntArray(); mPackageModes.put(packageName, opModes); opModes.put(op, mode); mPersistenceScheduler.scheduleWriteLocked(); } } else { if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) { return; } if (mode == defaultMode) { opModes.delete(op); if (opModes.size() <= 0) { opModes = null; mPackageModes.remove(packageName); } } else { opModes.put(op, mode); } mPersistenceScheduler.scheduleWriteLocked(); } } } @Override public void removeUid(int uid) { synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid); if (opModes == null) { return; } mUidModes.remove(uid); mPersistenceScheduler.scheduleFastWriteLocked(); } } @Override public boolean areUidModesDefault(int uid) { synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid); return (opModes == null || opModes.size() <= 0); } } @Override public boolean arePackageModesDefault(String packageMode) { synchronized (mLock) { SparseIntArray opModes = mPackageModes.get(packageMode); return (opModes == null || opModes.size() <= 0); } } @Override public boolean removePackage(String packageName) { synchronized (mLock) { SparseIntArray ops = mPackageModes.remove(packageName); if (ops != null) { mPersistenceScheduler.scheduleFastWriteLocked(); return true; } return false; } } @Override public void clearAllModes() { synchronized (mLock) { mUidModes.clear(); mPackageModes.clear(); } } } services/core/java/com/android/server/appop/PersistenceScheduler.java 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * 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; /** * Interface that allows callers to persist AppOpsService's internal state * to disk. */ public interface PersistenceScheduler { /** * Schedules disk writes for appOpsService and it's internal states. */ void scheduleWriteLocked(); /** * Schedules fast disk writes for appOpsService and it's internal states. */ void scheduleFastWriteLocked(); } services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java +5 −3 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TypedXmlPullParser; import android.util.Xml; Loading Loading @@ -97,9 +98,10 @@ public class AppOpsUpgradeTest { final int defaultModeOp2 = AppOpsManager.opToDefaultMode(op2); for(int i = 0; i < uidStates.size(); i++) { final AppOpsService.UidState uidState = uidStates.valueAt(i); if (uidState.opModes != null) { final int uidMode1 = uidState.opModes.get(op1, defaultModeOp1); final int uidMode2 = uidState.opModes.get(op2, defaultModeOp2); SparseIntArray opModes = uidState.getNonDefaultUidModes(); if (opModes != null) { final int uidMode1 = opModes.get(op1, defaultModeOp1); final int uidMode2 = opModes.get(op2, defaultModeOp2); assertEquals(uidMode1, uidMode2); if (uidMode1 != defaultModeOp1) { numberOfNonDefaultOps++; Loading Loading
services/core/java/com/android/server/appop/AppOpsService.java +133 −113 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/appop/AppOpsServiceInterface.java 0 → 100644 +98 −0 Original line number Diff line number Diff line /* * 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.annotation.NonNull; import android.app.AppOpsManager.Mode; import android.util.SparseIntArray; /** * Interface for accessing and modifying modes for app-ops i.e. package and uid modes. * In the future this interface will also include mode callbacks and op restrictions. */ public interface AppOpsServiceInterface { /** * Returns a copy of non-default app-ops with op as keys and their modes as values for a uid. * Returns an empty SparseIntArray if nothing is set. * @param uid for which we need the app-ops and their modes. */ SparseIntArray getNonDefaultUidModes(int uid); /** * 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. * @param uid user id for which we need the mode. * @param op app-op for which we need the mode. * @return mode of the app-op. */ int getUidMode(int uid, int op); /** * Set the app-op mode for a particular uid and op. * The mode is not set if the mode is the same as the default mode for the op. * @param uid user id for which we want to set the mode. * @param op app-op for which we want to set the mode. * @param mode mode for the app-op. * @return true if op mode is changed. */ boolean setUidMode(int uid, int op, @Mode int mode); /** * Gets the app-op mode for a particular package. * Returns default op mode if the op mode for the particular package is not set. * @param packageName package name for which we need the op mode. * @param op app-op for which we need the mode. * @return the mode of the app-op. */ int getPackageMode(@NonNull String packageName, int op); /** * Sets the app-op mode for a particular package. * @param packageName package name for which we need to set the op mode. * @param op app-op for which we need to set the mode. * @param mode the mode of the app-op. */ void setPackageMode(@NonNull String packageName, int op, @Mode int mode); /** * Stop tracking any app-op modes for a package. * @param packageName Name of the package for which we want to remove all mode tracking. */ boolean removePackage(@NonNull String packageName); /** * Stop tracking any app-op modes for this uid. * @param uid user id for which we want to remove all tracking. */ void removeUid(int uid); /** * Returns true if all uid modes for this uid are * in default state. * @param uid user id */ boolean areUidModesDefault(int uid); /** * Returns true if all package modes for this package name are * in default state. * @param packageName package name. */ boolean arePackageModesDefault(String packageName); /** * Stop tracking app-op modes for all uid and packages. */ void clearAllModes(); }
services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java 0 → 100644 +198 −0 Original line number Diff line number Diff line /* * 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.annotation.NonNull; import android.app.AppOpsManager; import android.app.AppOpsManager.Mode; import android.util.ArrayMap; import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; /** * Legacy implementation for App-ops service's app-op mode (uid and package) storage and access. * In the future this class will also include mode callbacks and op restrictions. */ public class LegacyAppOpsServiceInterfaceImpl implements AppOpsServiceInterface { // Should be the same object that the AppOpsService is using for locking. final Object mLock; @GuardedBy("mLock") @VisibleForTesting final SparseArray<SparseIntArray> mUidModes = new SparseArray<>(); @GuardedBy("mLock") final ArrayMap<String, SparseIntArray> mPackageModes = new ArrayMap<>(); final PersistenceScheduler mPersistenceScheduler; LegacyAppOpsServiceInterfaceImpl(PersistenceScheduler persistenceScheduler, @NonNull Object lock) { this.mPersistenceScheduler = persistenceScheduler; this.mLock = lock; } @Override public SparseIntArray getNonDefaultUidModes(int uid) { synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid, null); if (opModes == null) { return new SparseIntArray(); } return opModes.clone(); } } @Override public int getUidMode(int uid, int op) { synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid, null); if (opModes == null) { return AppOpsManager.opToDefaultMode(op); } return opModes.get(op, AppOpsManager.opToDefaultMode(op)); } } @Override public boolean setUidMode(int uid, int op, int mode) { final int defaultMode = AppOpsManager.opToDefaultMode(op); synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid, null); if (opModes == null) { if (mode != defaultMode) { opModes = new SparseIntArray(); mUidModes.put(uid, opModes); opModes.put(op, mode); mPersistenceScheduler.scheduleWriteLocked(); } } else { if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) { return false; } if (mode == defaultMode) { opModes.delete(op); if (opModes.size() <= 0) { opModes = null; mUidModes.delete(uid); } } else { opModes.put(op, mode); } mPersistenceScheduler.scheduleWriteLocked(); } } return true; } @Override public int getPackageMode(String packageName, int op) { synchronized (mLock) { SparseIntArray opModes = mPackageModes.getOrDefault(packageName, null); if (opModes == null) { return AppOpsManager.opToDefaultMode(op); } return opModes.get(op, AppOpsManager.opToDefaultMode(op)); } } @Override public void setPackageMode(String packageName, int op, @Mode int mode) { final int defaultMode = AppOpsManager.opToDefaultMode(op); synchronized (mLock) { SparseIntArray opModes = mPackageModes.get(packageName); if (opModes == null) { if (mode != defaultMode) { opModes = new SparseIntArray(); mPackageModes.put(packageName, opModes); opModes.put(op, mode); mPersistenceScheduler.scheduleWriteLocked(); } } else { if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) { return; } if (mode == defaultMode) { opModes.delete(op); if (opModes.size() <= 0) { opModes = null; mPackageModes.remove(packageName); } } else { opModes.put(op, mode); } mPersistenceScheduler.scheduleWriteLocked(); } } } @Override public void removeUid(int uid) { synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid); if (opModes == null) { return; } mUidModes.remove(uid); mPersistenceScheduler.scheduleFastWriteLocked(); } } @Override public boolean areUidModesDefault(int uid) { synchronized (mLock) { SparseIntArray opModes = mUidModes.get(uid); return (opModes == null || opModes.size() <= 0); } } @Override public boolean arePackageModesDefault(String packageMode) { synchronized (mLock) { SparseIntArray opModes = mPackageModes.get(packageMode); return (opModes == null || opModes.size() <= 0); } } @Override public boolean removePackage(String packageName) { synchronized (mLock) { SparseIntArray ops = mPackageModes.remove(packageName); if (ops != null) { mPersistenceScheduler.scheduleFastWriteLocked(); return true; } return false; } } @Override public void clearAllModes() { synchronized (mLock) { mUidModes.clear(); mPackageModes.clear(); } } }
services/core/java/com/android/server/appop/PersistenceScheduler.java 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * 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; /** * Interface that allows callers to persist AppOpsService's internal state * to disk. */ public interface PersistenceScheduler { /** * Schedules disk writes for appOpsService and it's internal states. */ void scheduleWriteLocked(); /** * Schedules fast disk writes for appOpsService and it's internal states. */ void scheduleFastWriteLocked(); }
services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java +5 −3 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TypedXmlPullParser; import android.util.Xml; Loading Loading @@ -97,9 +98,10 @@ public class AppOpsUpgradeTest { final int defaultModeOp2 = AppOpsManager.opToDefaultMode(op2); for(int i = 0; i < uidStates.size(); i++) { final AppOpsService.UidState uidState = uidStates.valueAt(i); if (uidState.opModes != null) { final int uidMode1 = uidState.opModes.get(op1, defaultModeOp1); final int uidMode2 = uidState.opModes.get(op2, defaultModeOp2); SparseIntArray opModes = uidState.getNonDefaultUidModes(); if (opModes != null) { final int uidMode1 = opModes.get(op1, defaultModeOp1); final int uidMode2 = opModes.get(op2, defaultModeOp2); assertEquals(uidMode1, uidMode2); if (uidMode1 != defaultModeOp1) { numberOfNonDefaultOps++; Loading