Loading core/java/android/app/AppOpsManager.java +15 −0 Original line number Diff line number Diff line Loading @@ -3120,6 +3120,15 @@ public class AppOpsManager { return mHistoricalUidOps.get(uid); } /** @hide */ public void clearHistory(int uid, @NonNull String packageName) { HistoricalUidOps historicalUidOps = getOrCreateHistoricalUidOps(uid); historicalUidOps.clearHistory(packageName); if (historicalUidOps.isEmpty()) { mHistoricalUidOps.remove(uid); } } @Override public int describeContents() { return 0; Loading Loading @@ -3397,6 +3406,12 @@ public class AppOpsManager { return mHistoricalPackageOps.get(packageName); } private void clearHistory(@NonNull String packageName) { if (mHistoricalPackageOps != null) { mHistoricalPackageOps.remove(packageName); } } @Override public int describeContents() { return 0; Loading services/core/java/com/android/server/appop/AppOpsService.java +2 −0 Original line number Diff line number Diff line Loading @@ -905,6 +905,8 @@ public class AppOpsService extends IAppOpsService.Stub { } } } mHistoricalRegistry.clearHistory(uid, packageName); } } Loading services/core/java/com/android/server/appop/HistoricalRegistry.java +35 −0 Original line number Diff line number Diff line Loading @@ -472,6 +472,25 @@ final class HistoricalRegistry { DEFAULT_COMPRESSION_STEP); } void clearHistory(int uid, String packageName) { synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { if (mMode != AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) { return; } for (int index = 0; index < mPendingWrites.size(); index++) { mPendingWrites.get(index).clearHistory(uid, packageName); } getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis()) .clearHistory(uid, packageName); mPersistence.clearHistoryDLocked(uid, packageName); } } } void clearHistory() { synchronized (mOnDiskLock) { clearHistoryOnDiskLocked(); Loading Loading @@ -628,6 +647,22 @@ final class HistoricalRegistry { return new File(baseDir, Long.toString(globalBeginMillis) + HISTORY_FILE_SUFFIX); } void clearHistoryDLocked(int uid, String packageName) { List<HistoricalOps> historicalOps = readHistoryDLocked(); if (historicalOps == null) { return; } for (int index = 0; index < historicalOps.size(); index++) { historicalOps.get(index).clearHistory(uid, packageName); } clearHistoryDLocked(); persistHistoricalOpsDLocked(historicalOps); } void clearHistoryDLocked() { mHistoricalAppOpsDir.delete(); } Loading services/tests/mockingservicestests/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" /> <uses-permission android:name="android.permission.HARDWARE_TEST"/> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.MANAGE_APPOPS"/> <application android:testOnly="true" android:debuggable="true"> Loading services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java +45 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.AppOpsManager.OpEntry; import android.app.AppOpsManager.PackageOps; import android.content.Context; Loading @@ -48,6 +49,7 @@ import android.content.pm.PackageManagerInternal; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; import android.os.RemoteCallback; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; Loading @@ -64,6 +66,9 @@ import org.mockito.quality.Strictness; import java.io.File; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; /** * Unit tests for AppOpsService. Covers functionality that is difficult to test using CTS tests Loading Loading @@ -258,6 +263,46 @@ public class AppOpsServiceTest { assertThat(getLoggedOps()).isNull(); } @Test public void testPackageRemovedHistoricalOps() throws InterruptedException { mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED); mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName); AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000); historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName, AppOpsManager.UID_STATE_PERSISTENT, 0, 1); mAppOpsService.addHistoricalOps(historicalOps); AtomicReference<AppOpsManager.HistoricalOps> resultOpsRef = new AtomicReference<>(); AtomicReference<CountDownLatch> latchRef = new AtomicReference<>(new CountDownLatch(1)); RemoteCallback callback = new RemoteCallback(result -> { resultOpsRef.set(result.getParcelable(AppOpsManager.KEY_HISTORICAL_OPS)); latchRef.get().countDown(); }); // First, do a fetch to ensure it's written mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, 0, Long.MAX_VALUE, 0, callback); latchRef.get().await(5, TimeUnit.SECONDS); assertThat(latchRef.get().getCount()).isEqualTo(0); assertThat(resultOpsRef.get().isEmpty()).isFalse(); // Then, check it's deleted on removal mAppOpsService.packageRemoved(mMyUid, sMyPackageName); latchRef.set(new CountDownLatch(1)); mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, 0, Long.MAX_VALUE, 0, callback); latchRef.get().await(5, TimeUnit.SECONDS); assertThat(latchRef.get().getCount()).isEqualTo(0); assertThat(resultOpsRef.get().isEmpty()).isTrue(); } @Test public void testUidRemoved() { mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED); Loading Loading
core/java/android/app/AppOpsManager.java +15 −0 Original line number Diff line number Diff line Loading @@ -3120,6 +3120,15 @@ public class AppOpsManager { return mHistoricalUidOps.get(uid); } /** @hide */ public void clearHistory(int uid, @NonNull String packageName) { HistoricalUidOps historicalUidOps = getOrCreateHistoricalUidOps(uid); historicalUidOps.clearHistory(packageName); if (historicalUidOps.isEmpty()) { mHistoricalUidOps.remove(uid); } } @Override public int describeContents() { return 0; Loading Loading @@ -3397,6 +3406,12 @@ public class AppOpsManager { return mHistoricalPackageOps.get(packageName); } private void clearHistory(@NonNull String packageName) { if (mHistoricalPackageOps != null) { mHistoricalPackageOps.remove(packageName); } } @Override public int describeContents() { return 0; Loading
services/core/java/com/android/server/appop/AppOpsService.java +2 −0 Original line number Diff line number Diff line Loading @@ -905,6 +905,8 @@ public class AppOpsService extends IAppOpsService.Stub { } } } mHistoricalRegistry.clearHistory(uid, packageName); } } Loading
services/core/java/com/android/server/appop/HistoricalRegistry.java +35 −0 Original line number Diff line number Diff line Loading @@ -472,6 +472,25 @@ final class HistoricalRegistry { DEFAULT_COMPRESSION_STEP); } void clearHistory(int uid, String packageName) { synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { if (mMode != AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) { return; } for (int index = 0; index < mPendingWrites.size(); index++) { mPendingWrites.get(index).clearHistory(uid, packageName); } getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis()) .clearHistory(uid, packageName); mPersistence.clearHistoryDLocked(uid, packageName); } } } void clearHistory() { synchronized (mOnDiskLock) { clearHistoryOnDiskLocked(); Loading Loading @@ -628,6 +647,22 @@ final class HistoricalRegistry { return new File(baseDir, Long.toString(globalBeginMillis) + HISTORY_FILE_SUFFIX); } void clearHistoryDLocked(int uid, String packageName) { List<HistoricalOps> historicalOps = readHistoryDLocked(); if (historicalOps == null) { return; } for (int index = 0; index < historicalOps.size(); index++) { historicalOps.get(index).clearHistory(uid, packageName); } clearHistoryDLocked(); persistHistoricalOpsDLocked(historicalOps); } void clearHistoryDLocked() { mHistoricalAppOpsDir.delete(); } Loading
services/tests/mockingservicestests/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" /> <uses-permission android:name="android.permission.HARDWARE_TEST"/> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.MANAGE_APPOPS"/> <application android:testOnly="true" android:debuggable="true"> Loading
services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java +45 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.AppOpsManager.OpEntry; import android.app.AppOpsManager.PackageOps; import android.content.Context; Loading @@ -48,6 +49,7 @@ import android.content.pm.PackageManagerInternal; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; import android.os.RemoteCallback; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; Loading @@ -64,6 +66,9 @@ import org.mockito.quality.Strictness; import java.io.File; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; /** * Unit tests for AppOpsService. Covers functionality that is difficult to test using CTS tests Loading Loading @@ -258,6 +263,46 @@ public class AppOpsServiceTest { assertThat(getLoggedOps()).isNull(); } @Test public void testPackageRemovedHistoricalOps() throws InterruptedException { mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED); mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName); AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000); historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName, AppOpsManager.UID_STATE_PERSISTENT, 0, 1); mAppOpsService.addHistoricalOps(historicalOps); AtomicReference<AppOpsManager.HistoricalOps> resultOpsRef = new AtomicReference<>(); AtomicReference<CountDownLatch> latchRef = new AtomicReference<>(new CountDownLatch(1)); RemoteCallback callback = new RemoteCallback(result -> { resultOpsRef.set(result.getParcelable(AppOpsManager.KEY_HISTORICAL_OPS)); latchRef.get().countDown(); }); // First, do a fetch to ensure it's written mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, 0, Long.MAX_VALUE, 0, callback); latchRef.get().await(5, TimeUnit.SECONDS); assertThat(latchRef.get().getCount()).isEqualTo(0); assertThat(resultOpsRef.get().isEmpty()).isFalse(); // Then, check it's deleted on removal mAppOpsService.packageRemoved(mMyUid, sMyPackageName); latchRef.set(new CountDownLatch(1)); mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, 0, Long.MAX_VALUE, 0, callback); latchRef.get().await(5, TimeUnit.SECONDS); assertThat(latchRef.get().getCount()).isEqualTo(0); assertThat(resultOpsRef.get().isEmpty()).isTrue(); } @Test public void testUidRemoved() { mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED); Loading