From 8e5bf968c15837f048a9c5ae57b379540044e39b Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Tue, 19 Mar 2019 23:59:03 -0700 Subject: [PATCH] Fix reading app ops data - framework There was an optimized code path that is hit if the op has not been accessed that does not write the uid state information which did not add the closing tag which resulted in producing a malformed XML. Test: atest android.app.appops.cts.AppOpsTest#testNonHistoricalStatePersistence bug:128872367 Change-Id: Iaddcce09b41f3e124e1838b65731d8dac9ca64e3 --- api/test-current.txt | 5 ++++- core/java/android/app/AppOpsManager.java | 19 ++++++++++++++++++- .../android/internal/app/IAppOpsService.aidl | 2 ++ .../android/server/appop/AppOpsService.java | 11 ++++++++++- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/api/test-current.txt b/api/test-current.txt index 0fcf72702f1b9..17ef7ee02e245 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -134,16 +134,19 @@ package android.app { method @RequiresPermission("android.permission.MANAGE_APPOPS") public void addHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOps); method @RequiresPermission("android.permission.MANAGE_APPOPS") public void clearHistory(); method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); - method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOpsFromDiskRaw(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer); + method @RequiresPermission("android.permission.MANAGE_APPOPS") public void getHistoricalOpsFromDiskRaw(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method public static int getNumOps(); method public static String[] getOpStrs(); method public boolean isOperationActive(int, int, String); method @RequiresPermission("android.permission.MANAGE_APPOPS") public void offsetHistory(long); + method public static int opToDefaultMode(@NonNull String); method public static String opToPermission(int); method public static int permissionToOpCode(String); + method @RequiresPermission("android.permission.MANAGE_APPOPS") public void reloadNonHistoricalState(); method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetHistoryParameters(); method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int); method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(int, int, String, int); + method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(String, int, String, int); method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(String, int, int); method public void startWatchingActive(@NonNull int[], @NonNull android.app.AppOpsManager.OnOpActiveChangedListener); method public void stopWatchingActive(@NonNull android.app.AppOpsManager.OnOpActiveChangedListener); diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 1066fc7598e9d..fab61b282c558 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -2153,6 +2153,7 @@ public class AppOpsManager { * * @hide */ + @TestApi @SystemApi public static int opToDefaultMode(@NonNull String appOp) { return opToDefaultMode(strOpToOp(appOp)); @@ -4465,7 +4466,7 @@ public class AppOpsManager { * @hide */ @TestApi - @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) + @RequiresPermission(Manifest.permission.MANAGE_APPOPS) public void getHistoricalOpsFromDiskRaw(@NonNull HistoricalOpsRequest request, @Nullable Executor executor, @NonNull Consumer callback) { Preconditions.checkNotNull(executor, "executor cannot be null"); @@ -4487,6 +4488,21 @@ public class AppOpsManager { } } + /** + * Reloads the non historical state to allow testing the read/write path. + * + * @hide + */ + @TestApi + @RequiresPermission(Manifest.permission.MANAGE_APPOPS) + public void reloadNonHistoricalState() { + try { + mService.reloadNonHistoricalState(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Sets given app op in the specified mode for app ops in the UID. * This applies to all apps currently in the UID or installed in @@ -4570,6 +4586,7 @@ public class AppOpsManager { * be changed. * @hide */ + @TestApi @SystemApi @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) public void setMode(String op, int uid, String packageName, @Mode int mode) { diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index c4af4c797d374..1c901823566ab 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -79,4 +79,6 @@ interface IAppOpsService { void stopWatchingNoted(IAppOpsNotedCallback callback); int checkOperationRaw(int code, int uid, String packageName); + + void reloadNonHistoricalState(); } diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 9c26526920a03..10b67c1047cf3 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -1132,7 +1132,7 @@ public class AppOpsService extends IAppOpsService.Stub { .build(); Preconditions.checkNotNull(callback, "callback cannot be null"); - mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, + mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS, Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); final String[] opNamesArray = (opNames != null) @@ -1143,6 +1143,14 @@ public class AppOpsService extends IAppOpsService.Stub { beginTimeMillis, endTimeMillis, flags, callback); } + @Override + public void reloadNonHistoricalState() { + mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS, + Binder.getCallingPid(), Binder.getCallingUid(), "reloadNonHistoricalState"); + writeState(); + readState(); + } + @Override public List getUidOps(int uid, int[] ops) { mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, @@ -2998,6 +3006,7 @@ public class AppOpsService extends IAppOpsService.Stub { final LongSparseArray keys = op.collectKeys(); if (keys == null || keys.size() <= 0) { + out.endTag(null, "op"); continue; }