Loading core/java/android/app/AppOpsManager.java +15 −0 Original line number Diff line number Diff line Loading @@ -3119,6 +3119,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 @@ -3396,6 +3405,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/servicestests/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" /> <uses-permission android:name="android.permission.HARDWARE_TEST"/> <uses-permission android:name="android.permission.MANAGE_APPOPS"/> <!-- Uses API introduced in O (26) --> <uses-sdk android:minSdkVersion="1" Loading services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java +44 −2 Original line number Diff line number Diff line Loading @@ -29,25 +29,28 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.AppOpsManager.OpEntry; import android.app.AppOpsManager.PackageOps; import android.content.Context; 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; import androidx.test.runner.AndroidJUnit4; import com.android.server.appop.AppOpsService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; 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 @@ -215,6 +218,45 @@ public class AppOpsServiceTest { assertThat(getLoggedOps()).isNull(); } @Test public void testPackageRemovedHistoricalOps() throws InterruptedException { mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED); mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, mMyPackageName); AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000); historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, mMyPackageName, 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, mMyPackageName, 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, mMyPackageName); latchRef.set(new CountDownLatch(1)); mAppOpsService.getHistoricalOps(mMyUid, mMyPackageName, 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, mMyPackageName, MODE_ALLOWED); Loading Loading
core/java/android/app/AppOpsManager.java +15 −0 Original line number Diff line number Diff line Loading @@ -3119,6 +3119,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 @@ -3396,6 +3405,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/servicestests/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" /> <uses-permission android:name="android.permission.HARDWARE_TEST"/> <uses-permission android:name="android.permission.MANAGE_APPOPS"/> <!-- Uses API introduced in O (26) --> <uses-sdk android:minSdkVersion="1" Loading
services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java +44 −2 Original line number Diff line number Diff line Loading @@ -29,25 +29,28 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.AppOpsManager.OpEntry; import android.app.AppOpsManager.PackageOps; import android.content.Context; 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; import androidx.test.runner.AndroidJUnit4; import com.android.server.appop.AppOpsService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; 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 @@ -215,6 +218,45 @@ public class AppOpsServiceTest { assertThat(getLoggedOps()).isNull(); } @Test public void testPackageRemovedHistoricalOps() throws InterruptedException { mAppOpsService.setMode(OP_READ_SMS, mMyUid, mMyPackageName, MODE_ALLOWED); mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, mMyPackageName); AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000); historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, mMyPackageName, 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, mMyPackageName, 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, mMyPackageName); latchRef.set(new CountDownLatch(1)); mAppOpsService.getHistoricalOps(mMyUid, mMyPackageName, 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, mMyPackageName, MODE_ALLOWED); Loading