Loading api/system-current.txt +12 −1 Original line number Original line Diff line number Diff line Loading @@ -304,7 +304,7 @@ package android.app { } } public class AppOpsManager { public class AppOpsManager { method @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(int, @Nullable String, @Nullable String[], long, long, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>); method @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>); method public static String[] getOpStrs(); method public static String[] getOpStrs(); method @Deprecated @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, String, int[]); method @Deprecated @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, String, int[]); method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...); method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...); Loading Loading @@ -394,6 +394,17 @@ package android.app { field public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR; field public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR; } } public static final class AppOpsManager.HistoricalOpsRequest { } public static final class AppOpsManager.HistoricalOpsRequest.Builder { ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build(); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setUid(int); } public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable { public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable { method public int describeContents(); method public int describeContents(); method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String); method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String); Loading api/test-current.txt +13 −2 Original line number Original line Diff line number Diff line Loading @@ -101,8 +101,8 @@ package android.app { public class AppOpsManager { public class AppOpsManager { method @RequiresPermission("android.permission.MANAGE_APPOPS") public void addHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOps); 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.MANAGE_APPOPS") public void clearHistory(); method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOps(int, @Nullable String, @Nullable String[], long, long, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>); 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<android.app.AppOpsManager.HistoricalOps>); method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOpsFromDiskRaw(int, @Nullable String, @Nullable String[], long, long, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>); 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<android.app.AppOpsManager.HistoricalOps>); method public static int getNumOps(); method public static int getNumOps(); method public static String[] getOpStrs(); method public static String[] getOpStrs(); method public boolean isOperationActive(int, int, String); method public boolean isOperationActive(int, int, String); Loading Loading @@ -206,6 +206,17 @@ package android.app { field public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR; field public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR; } } public static final class AppOpsManager.HistoricalOpsRequest { } public static final class AppOpsManager.HistoricalOpsRequest.Builder { ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build(); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setUid(int); } public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable { public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable { method public int describeContents(); method public int describeContents(); method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String); method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String); Loading core/java/android/app/AppOpsManager.java +121 −46 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,8 @@ import android.util.ArrayMap; import android.util.SparseArray; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.Immutable; import com.android.internal.app.IAppOpsActiveCallback; import com.android.internal.app.IAppOpsActiveCallback; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsNotedCallback; import com.android.internal.app.IAppOpsNotedCallback; Loading Loading @@ -2209,6 +2211,115 @@ public class AppOpsManager { void visitHistoricalOp(@NonNull HistoricalOp ops); void visitHistoricalOp(@NonNull HistoricalOp ops); } } /** * Request for getting historical app op usage. The request acts * as a filtering criteria when querying historical op usage. * * @hide */ @Immutable @TestApi @SystemApi public static final class HistoricalOpsRequest { private final int mUid; private final @Nullable String mPackageName; private final @Nullable List<String> mOpNames; private final long mBeginTimeMillis; private final long mEndTimeMillis; private HistoricalOpsRequest(int uid, @Nullable String packageName, @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis) { mUid = uid; mPackageName = packageName; mOpNames = opNames; mBeginTimeMillis = beginTimeMillis; mEndTimeMillis = endTimeMillis; } /** * Builder for creating a {@link HistoricalOpsRequest}. * * @hide */ @TestApi @SystemApi public static final class Builder { private int mUid = Process.INVALID_UID; private @Nullable String mPackageName; private @Nullable List<String> mOpNames; private final long mBeginTimeMillis; private final long mEndTimeMillis; /** * Creates a new builder. * * @param beginTimeMillis The beginning of the interval in milliseconds since * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be non * negative. * @param endTimeMillis The end of the interval in milliseconds since * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be after * {@code beginTimeMillis}. Pass {@link Long#MAX_VALUE} to get the most recent * history including ops that happen while this call is in flight. */ public Builder(long beginTimeMillis, long endTimeMillis) { Preconditions.checkArgument(beginTimeMillis >= 0 && beginTimeMillis < endTimeMillis, "beginTimeMillis must be non negative and lesser than endTimeMillis"); mBeginTimeMillis = beginTimeMillis; mEndTimeMillis = endTimeMillis; } /** * Sets the UID to query for. * * @param uid The uid. Pass {@link android.os.Process#INVALID_UID} for any uid. * @return This builder. */ public @NonNull Builder setUid(int uid) { Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0, "uid must be " + Process.INVALID_UID + " or non negative"); mUid = uid; return this; } /** * Sets the package to query for. * * @param packageName The package name. <code>Null</code> for any package. * @return This builder. */ public @NonNull Builder setPackageName(@Nullable String packageName) { mPackageName = packageName; return this; } /** * Sets the op names to query for. * * @param opNames The op names. <code>Null</code> for any op. * @return This builder. */ public @NonNull Builder setOpNames(@Nullable List<String> opNames) { if (opNames != null) { final int opCount = opNames.size(); for (int i = 0; i < opCount; i++) { Preconditions.checkArgument(AppOpsManager.strOpToOp( opNames.get(i)) != AppOpsManager.OP_NONE); } } mOpNames = opNames; return this; } /** * @return a new {@link HistoricalOpsRequest}. */ public @NonNull HistoricalOpsRequest build() { return new HistoricalOpsRequest(mUid, mPackageName, mOpNames, mBeginTimeMillis, mEndTimeMillis); } } } /** /** * This class represents historical app op state of all UIDs for a given time interval. * This class represents historical app op state of all UIDs for a given time interval. * * Loading Loading @@ -3671,26 +3782,7 @@ public class AppOpsManager { /** /** * Retrieve historical app op stats for a period. * Retrieve historical app op stats for a period. * * * <p>Historical data can be obtained * @param request A request object describing the data being queried for. * for a specific package by specifying the <code>packageName</code> argument, * for a specific UID if specifying the <code>uid</code> argument, for a * specific package in a UID by specifying the <code>packageName</code> * and the <code>uid</code> arguments, for all packages by passing * {@link android.os.Process#INVALID_UID} and <code>null</code> for the * <code>uid</code> and <code>packageName</code> arguments, respectively. * Similarly, you can specify the <code>opNames</code> argument to get * data only for these ops or <code>null</code> for all ops. * * @param uid The UID to query for. * @param packageName The package to query for. * @param beginTimeMillis The beginning of the interval in milliseconds since * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be non * negative. * @param endTimeMillis The end of the interval in milliseconds since * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be after * {@code beginTimeMillis}. Pass {@link Long#MAX_VALUE} to get the most recent * history including ops that happen while this call is in flight. * @param opNames The ops to query for. Pass {@code null} for all ops. * @param executor Executor on which to run the callback. If <code>null</code> * @param executor Executor on which to run the callback. If <code>null</code> * the callback is executed on the default executor running on the main thread. * the callback is executed on the default executor running on the main thread. * @param callback Callback on which to deliver the result. * @param callback Callback on which to deliver the result. Loading @@ -3702,13 +3794,13 @@ public class AppOpsManager { @TestApi @TestApi @SystemApi @SystemApi @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(int uid, @Nullable String packageName, public void getHistoricalOps(@NonNull HistoricalOpsRequest request, @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis, @NonNull Executor executor, @NonNull Consumer<HistoricalOps> callback) { @NonNull Executor executor, @NonNull Consumer<HistoricalOps> callback) { Preconditions.checkNotNull(executor, "executor cannot be null"); Preconditions.checkNotNull(executor, "executor cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); try { try { mService.getHistoricalOps(uid, packageName, opNames, beginTimeMillis, endTimeMillis, mService.getHistoricalOps(request.mUid, request.mPackageName, request.mOpNames, request.mBeginTimeMillis, request.mEndTimeMillis, new RemoteCallback((result) -> { new RemoteCallback((result) -> { final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS); final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS); final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); Loading @@ -3725,29 +3817,12 @@ public class AppOpsManager { /** /** * Retrieve historical app op stats for a period. * Retrieve historical app op stats for a period. * * <p>Historical data can be obtained * for a specific package by specifying the <code>packageName</code> argument, * for a specific UID if specifying the <code>uid</code> argument, for a * specific package in a UID by specifying the <code>packageName</code> * and the <code>uid</code> arguments, for all packages by passing * {@link android.os.Process#INVALID_UID} and <code>null</code> for the * <code>uid</code> and <code>packageName</code> arguments, respectively. * Similarly, you can specify the <code>opNames</code> argument to get * data only for these ops or <code>null</code> for all ops. * <p> * <p> * This method queries only the on disk state and the returned ops are raw, * This method queries only the on disk state and the returned ops are raw, * which is their times are relative to the history start as opposed to the * which is their times are relative to the history start as opposed to the * epoch start. * epoch start. * * * @param uid The UID to query for. * @param request A request object describing the data being queried for. * @param packageName The package to query for. * @param beginTimeMillis The beginning of the interval in milliseconds since * history start. History time grows as one goes into the past. * @param endTimeMillis The end of the interval in milliseconds since * history start. History time grows as one goes into the past. Must be after * {@code beginTimeMillis}. * @param opNames The ops to query for. Pass {@code null} for all ops. * @param executor Executor on which to run the callback. If <code>null</code> * @param executor Executor on which to run the callback. If <code>null</code> * the callback is executed on the default executor running on the main thread. * the callback is executed on the default executor running on the main thread. * @param callback Callback on which to deliver the result. * @param callback Callback on which to deliver the result. Loading @@ -3758,14 +3833,14 @@ public class AppOpsManager { */ */ @TestApi @TestApi @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOpsFromDiskRaw(int uid, @Nullable String packageName, public void getHistoricalOpsFromDiskRaw(@NonNull HistoricalOpsRequest request, @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis, @Nullable Executor executor, @NonNull Consumer<HistoricalOps> callback) { @Nullable Executor executor, @NonNull Consumer<HistoricalOps> callback) { Preconditions.checkNotNull(executor, "executor cannot be null"); Preconditions.checkNotNull(executor, "executor cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); try { try { mService.getHistoricalOpsFromDiskRaw(uid, packageName, opNames, beginTimeMillis, mService.getHistoricalOpsFromDiskRaw(request.mUid, request.mPackageName, endTimeMillis, new RemoteCallback((result) -> { request.mOpNames, request.mBeginTimeMillis, request.mEndTimeMillis, new RemoteCallback((result) -> { final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS); final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS); final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); try { try { Loading core/java/com/android/internal/app/IAppOpsService.aidl +2 −2 Original line number Original line Diff line number Diff line Loading @@ -44,9 +44,9 @@ interface IAppOpsService { int checkPackage(int uid, String packageName); int checkPackage(int uid, String packageName); List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops); List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops); List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops); List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops); void getHistoricalOps(int uid, String packageName, in String[] ops, long beginTimeMillis, void getHistoricalOps(int uid, String packageName, in List<String> ops, long beginTimeMillis, long endTimeMillis, in RemoteCallback callback); long endTimeMillis, in RemoteCallback callback); void getHistoricalOpsFromDiskRaw(int uid, String packageName, in String[] ops, void getHistoricalOpsFromDiskRaw(int uid, String packageName, in List<String> ops, long beginTimeMillis, long endTimeMillis, in RemoteCallback callback); long beginTimeMillis, long endTimeMillis, in RemoteCallback callback); void offsetHistory(long duration); void offsetHistory(long duration); void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep); void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep); Loading services/core/java/com/android/server/appop/AppOpsService.java +25 −25 Original line number Original line Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.app.AppOpsManager.HistoricalOps; import android.app.AppOpsManager.HistoricalOps; import android.app.AppOpsManager.HistoricalOpsRequest; import android.app.AppOpsManagerInternal; import android.app.AppOpsManagerInternal; import android.app.AppOpsManagerInternal.CheckOpsDelegate; import android.app.AppOpsManagerInternal.CheckOpsDelegate; import android.content.BroadcastReceiver; import android.content.BroadcastReceiver; Loading Loading @@ -1024,25 +1025,29 @@ public class AppOpsService extends IAppOpsService.Stub { @Override @Override public void getHistoricalOps(int uid, @NonNull String packageName, public void getHistoricalOps(int uid, @NonNull String packageName, @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis, @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis, @NonNull RemoteCallback callback) { @NonNull RemoteCallback callback) { Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0, // Use the builder to validate arguments. "uid must be " + Process.INVALID_UID + " or non negative"); final HistoricalOpsRequest request = new HistoricalOpsRequest.Builder( Preconditions.checkArgument(beginTimeMillis >= 0 && beginTimeMillis < endTimeMillis, beginTimeMillis, endTimeMillis) "beginTimeMillis must be non negative and lesser than endTimeMillis"); .setUid(uid) .setPackageName(packageName) .setOpNames(opNames) .build(); Preconditions.checkNotNull(callback, "callback cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); checkValidOpsOrNull(opNames); mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); final String[] opNamesArray = (opNames != null) ? opNames.toArray(new String[opNames.size()]) : null; if (mHistoricalRegistry.getMode() == AppOpsManager.HISTORICAL_MODE_DISABLED) { if (mHistoricalRegistry.getMode() == AppOpsManager.HISTORICAL_MODE_DISABLED) { // TODO (bug:122218838): Remove once the feature fully enabled. // TODO (bug:122218838): Remove once the feature fully enabled. getHistoricalPackagesOpsCompat(uid, packageName, opNames, beginTimeMillis, getHistoricalPackagesOpsCompat(uid, packageName, opNamesArray, beginTimeMillis, endTimeMillis, callback); endTimeMillis, callback); } else { } else { // Must not hold the appops lock // Must not hold the appops lock mHistoricalRegistry.getHistoricalOps(uid, packageName, opNames, mHistoricalRegistry.getHistoricalOps(uid, packageName, opNamesArray, beginTimeMillis, endTimeMillis, callback); beginTimeMillis, endTimeMillis, callback); } } } } Loading Loading @@ -1101,20 +1106,25 @@ public class AppOpsService extends IAppOpsService.Stub { @Override @Override public void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName, public void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName, @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis, @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis, @NonNull RemoteCallback callback) { @NonNull RemoteCallback callback) { Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0, // Use the builder to validate arguments. "uid must be " + Process.INVALID_UID + " or non negative"); final HistoricalOpsRequest request = new HistoricalOpsRequest.Builder( Preconditions.checkArgument(beginTimeMillis >= 0 && beginTimeMillis < endTimeMillis, beginTimeMillis, endTimeMillis) "beginTimeMillis must be non negative and lesser than endTimeMillis"); .setUid(uid) .setPackageName(packageName) .setOpNames(opNames) .build(); Preconditions.checkNotNull(callback, "callback cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); checkValidOpsOrNull(opNames); mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); final String[] opNamesArray = (opNames != null) ? opNames.toArray(new String[opNames.size()]) : null; // Must not hold the appops lock // Must not hold the appops lock mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNames, mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNamesArray, beginTimeMillis, endTimeMillis, callback); beginTimeMillis, endTimeMillis, callback); } } Loading Loading @@ -4266,16 +4276,6 @@ public class AppOpsService extends IAppOpsService.Stub { return packageNames; return packageNames; } } private static void checkValidOpsOrNull(String[] opNames) { if (opNames != null) { for (String opName : opNames) { if (AppOpsManager.strOpToOp(opName) == AppOpsManager.OP_NONE) { throw new IllegalArgumentException("Unknown op: " + opName); } } } } private final class ClientRestrictionState implements DeathRecipient { private final class ClientRestrictionState implements DeathRecipient { private final IBinder token; private final IBinder token; SparseArray<boolean[]> perUserRestrictions; SparseArray<boolean[]> perUserRestrictions; Loading Loading
api/system-current.txt +12 −1 Original line number Original line Diff line number Diff line Loading @@ -304,7 +304,7 @@ package android.app { } } public class AppOpsManager { public class AppOpsManager { method @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(int, @Nullable String, @Nullable String[], long, long, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>); method @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>); method public static String[] getOpStrs(); method public static String[] getOpStrs(); method @Deprecated @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, String, int[]); method @Deprecated @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, String, int[]); method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...); method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...); Loading Loading @@ -394,6 +394,17 @@ package android.app { field public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR; field public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR; } } public static final class AppOpsManager.HistoricalOpsRequest { } public static final class AppOpsManager.HistoricalOpsRequest.Builder { ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build(); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setUid(int); } public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable { public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable { method public int describeContents(); method public int describeContents(); method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String); method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String); Loading
api/test-current.txt +13 −2 Original line number Original line Diff line number Diff line Loading @@ -101,8 +101,8 @@ package android.app { public class AppOpsManager { public class AppOpsManager { method @RequiresPermission("android.permission.MANAGE_APPOPS") public void addHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOps); 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.MANAGE_APPOPS") public void clearHistory(); method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOps(int, @Nullable String, @Nullable String[], long, long, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>); 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<android.app.AppOpsManager.HistoricalOps>); method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOpsFromDiskRaw(int, @Nullable String, @Nullable String[], long, long, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>); 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<android.app.AppOpsManager.HistoricalOps>); method public static int getNumOps(); method public static int getNumOps(); method public static String[] getOpStrs(); method public static String[] getOpStrs(); method public boolean isOperationActive(int, int, String); method public boolean isOperationActive(int, int, String); Loading Loading @@ -206,6 +206,17 @@ package android.app { field public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR; field public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR; } } public static final class AppOpsManager.HistoricalOpsRequest { } public static final class AppOpsManager.HistoricalOpsRequest.Builder { ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build(); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String); method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setUid(int); } public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable { public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable { method public int describeContents(); method public int describeContents(); method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String); method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String); Loading
core/java/android/app/AppOpsManager.java +121 −46 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,8 @@ import android.util.ArrayMap; import android.util.SparseArray; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.Immutable; import com.android.internal.app.IAppOpsActiveCallback; import com.android.internal.app.IAppOpsActiveCallback; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsNotedCallback; import com.android.internal.app.IAppOpsNotedCallback; Loading Loading @@ -2209,6 +2211,115 @@ public class AppOpsManager { void visitHistoricalOp(@NonNull HistoricalOp ops); void visitHistoricalOp(@NonNull HistoricalOp ops); } } /** * Request for getting historical app op usage. The request acts * as a filtering criteria when querying historical op usage. * * @hide */ @Immutable @TestApi @SystemApi public static final class HistoricalOpsRequest { private final int mUid; private final @Nullable String mPackageName; private final @Nullable List<String> mOpNames; private final long mBeginTimeMillis; private final long mEndTimeMillis; private HistoricalOpsRequest(int uid, @Nullable String packageName, @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis) { mUid = uid; mPackageName = packageName; mOpNames = opNames; mBeginTimeMillis = beginTimeMillis; mEndTimeMillis = endTimeMillis; } /** * Builder for creating a {@link HistoricalOpsRequest}. * * @hide */ @TestApi @SystemApi public static final class Builder { private int mUid = Process.INVALID_UID; private @Nullable String mPackageName; private @Nullable List<String> mOpNames; private final long mBeginTimeMillis; private final long mEndTimeMillis; /** * Creates a new builder. * * @param beginTimeMillis The beginning of the interval in milliseconds since * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be non * negative. * @param endTimeMillis The end of the interval in milliseconds since * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be after * {@code beginTimeMillis}. Pass {@link Long#MAX_VALUE} to get the most recent * history including ops that happen while this call is in flight. */ public Builder(long beginTimeMillis, long endTimeMillis) { Preconditions.checkArgument(beginTimeMillis >= 0 && beginTimeMillis < endTimeMillis, "beginTimeMillis must be non negative and lesser than endTimeMillis"); mBeginTimeMillis = beginTimeMillis; mEndTimeMillis = endTimeMillis; } /** * Sets the UID to query for. * * @param uid The uid. Pass {@link android.os.Process#INVALID_UID} for any uid. * @return This builder. */ public @NonNull Builder setUid(int uid) { Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0, "uid must be " + Process.INVALID_UID + " or non negative"); mUid = uid; return this; } /** * Sets the package to query for. * * @param packageName The package name. <code>Null</code> for any package. * @return This builder. */ public @NonNull Builder setPackageName(@Nullable String packageName) { mPackageName = packageName; return this; } /** * Sets the op names to query for. * * @param opNames The op names. <code>Null</code> for any op. * @return This builder. */ public @NonNull Builder setOpNames(@Nullable List<String> opNames) { if (opNames != null) { final int opCount = opNames.size(); for (int i = 0; i < opCount; i++) { Preconditions.checkArgument(AppOpsManager.strOpToOp( opNames.get(i)) != AppOpsManager.OP_NONE); } } mOpNames = opNames; return this; } /** * @return a new {@link HistoricalOpsRequest}. */ public @NonNull HistoricalOpsRequest build() { return new HistoricalOpsRequest(mUid, mPackageName, mOpNames, mBeginTimeMillis, mEndTimeMillis); } } } /** /** * This class represents historical app op state of all UIDs for a given time interval. * This class represents historical app op state of all UIDs for a given time interval. * * Loading Loading @@ -3671,26 +3782,7 @@ public class AppOpsManager { /** /** * Retrieve historical app op stats for a period. * Retrieve historical app op stats for a period. * * * <p>Historical data can be obtained * @param request A request object describing the data being queried for. * for a specific package by specifying the <code>packageName</code> argument, * for a specific UID if specifying the <code>uid</code> argument, for a * specific package in a UID by specifying the <code>packageName</code> * and the <code>uid</code> arguments, for all packages by passing * {@link android.os.Process#INVALID_UID} and <code>null</code> for the * <code>uid</code> and <code>packageName</code> arguments, respectively. * Similarly, you can specify the <code>opNames</code> argument to get * data only for these ops or <code>null</code> for all ops. * * @param uid The UID to query for. * @param packageName The package to query for. * @param beginTimeMillis The beginning of the interval in milliseconds since * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be non * negative. * @param endTimeMillis The end of the interval in milliseconds since * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be after * {@code beginTimeMillis}. Pass {@link Long#MAX_VALUE} to get the most recent * history including ops that happen while this call is in flight. * @param opNames The ops to query for. Pass {@code null} for all ops. * @param executor Executor on which to run the callback. If <code>null</code> * @param executor Executor on which to run the callback. If <code>null</code> * the callback is executed on the default executor running on the main thread. * the callback is executed on the default executor running on the main thread. * @param callback Callback on which to deliver the result. * @param callback Callback on which to deliver the result. Loading @@ -3702,13 +3794,13 @@ public class AppOpsManager { @TestApi @TestApi @SystemApi @SystemApi @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(int uid, @Nullable String packageName, public void getHistoricalOps(@NonNull HistoricalOpsRequest request, @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis, @NonNull Executor executor, @NonNull Consumer<HistoricalOps> callback) { @NonNull Executor executor, @NonNull Consumer<HistoricalOps> callback) { Preconditions.checkNotNull(executor, "executor cannot be null"); Preconditions.checkNotNull(executor, "executor cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); try { try { mService.getHistoricalOps(uid, packageName, opNames, beginTimeMillis, endTimeMillis, mService.getHistoricalOps(request.mUid, request.mPackageName, request.mOpNames, request.mBeginTimeMillis, request.mEndTimeMillis, new RemoteCallback((result) -> { new RemoteCallback((result) -> { final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS); final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS); final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); Loading @@ -3725,29 +3817,12 @@ public class AppOpsManager { /** /** * Retrieve historical app op stats for a period. * Retrieve historical app op stats for a period. * * <p>Historical data can be obtained * for a specific package by specifying the <code>packageName</code> argument, * for a specific UID if specifying the <code>uid</code> argument, for a * specific package in a UID by specifying the <code>packageName</code> * and the <code>uid</code> arguments, for all packages by passing * {@link android.os.Process#INVALID_UID} and <code>null</code> for the * <code>uid</code> and <code>packageName</code> arguments, respectively. * Similarly, you can specify the <code>opNames</code> argument to get * data only for these ops or <code>null</code> for all ops. * <p> * <p> * This method queries only the on disk state and the returned ops are raw, * This method queries only the on disk state and the returned ops are raw, * which is their times are relative to the history start as opposed to the * which is their times are relative to the history start as opposed to the * epoch start. * epoch start. * * * @param uid The UID to query for. * @param request A request object describing the data being queried for. * @param packageName The package to query for. * @param beginTimeMillis The beginning of the interval in milliseconds since * history start. History time grows as one goes into the past. * @param endTimeMillis The end of the interval in milliseconds since * history start. History time grows as one goes into the past. Must be after * {@code beginTimeMillis}. * @param opNames The ops to query for. Pass {@code null} for all ops. * @param executor Executor on which to run the callback. If <code>null</code> * @param executor Executor on which to run the callback. If <code>null</code> * the callback is executed on the default executor running on the main thread. * the callback is executed on the default executor running on the main thread. * @param callback Callback on which to deliver the result. * @param callback Callback on which to deliver the result. Loading @@ -3758,14 +3833,14 @@ public class AppOpsManager { */ */ @TestApi @TestApi @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOpsFromDiskRaw(int uid, @Nullable String packageName, public void getHistoricalOpsFromDiskRaw(@NonNull HistoricalOpsRequest request, @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis, @Nullable Executor executor, @NonNull Consumer<HistoricalOps> callback) { @Nullable Executor executor, @NonNull Consumer<HistoricalOps> callback) { Preconditions.checkNotNull(executor, "executor cannot be null"); Preconditions.checkNotNull(executor, "executor cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); try { try { mService.getHistoricalOpsFromDiskRaw(uid, packageName, opNames, beginTimeMillis, mService.getHistoricalOpsFromDiskRaw(request.mUid, request.mPackageName, endTimeMillis, new RemoteCallback((result) -> { request.mOpNames, request.mBeginTimeMillis, request.mEndTimeMillis, new RemoteCallback((result) -> { final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS); final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS); final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); try { try { Loading
core/java/com/android/internal/app/IAppOpsService.aidl +2 −2 Original line number Original line Diff line number Diff line Loading @@ -44,9 +44,9 @@ interface IAppOpsService { int checkPackage(int uid, String packageName); int checkPackage(int uid, String packageName); List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops); List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops); List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops); List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops); void getHistoricalOps(int uid, String packageName, in String[] ops, long beginTimeMillis, void getHistoricalOps(int uid, String packageName, in List<String> ops, long beginTimeMillis, long endTimeMillis, in RemoteCallback callback); long endTimeMillis, in RemoteCallback callback); void getHistoricalOpsFromDiskRaw(int uid, String packageName, in String[] ops, void getHistoricalOpsFromDiskRaw(int uid, String packageName, in List<String> ops, long beginTimeMillis, long endTimeMillis, in RemoteCallback callback); long beginTimeMillis, long endTimeMillis, in RemoteCallback callback); void offsetHistory(long duration); void offsetHistory(long duration); void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep); void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep); Loading
services/core/java/com/android/server/appop/AppOpsService.java +25 −25 Original line number Original line Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.AppOpsManager; import android.app.AppOpsManager.HistoricalOps; import android.app.AppOpsManager.HistoricalOps; import android.app.AppOpsManager.HistoricalOpsRequest; import android.app.AppOpsManagerInternal; import android.app.AppOpsManagerInternal; import android.app.AppOpsManagerInternal.CheckOpsDelegate; import android.app.AppOpsManagerInternal.CheckOpsDelegate; import android.content.BroadcastReceiver; import android.content.BroadcastReceiver; Loading Loading @@ -1024,25 +1025,29 @@ public class AppOpsService extends IAppOpsService.Stub { @Override @Override public void getHistoricalOps(int uid, @NonNull String packageName, public void getHistoricalOps(int uid, @NonNull String packageName, @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis, @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis, @NonNull RemoteCallback callback) { @NonNull RemoteCallback callback) { Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0, // Use the builder to validate arguments. "uid must be " + Process.INVALID_UID + " or non negative"); final HistoricalOpsRequest request = new HistoricalOpsRequest.Builder( Preconditions.checkArgument(beginTimeMillis >= 0 && beginTimeMillis < endTimeMillis, beginTimeMillis, endTimeMillis) "beginTimeMillis must be non negative and lesser than endTimeMillis"); .setUid(uid) .setPackageName(packageName) .setOpNames(opNames) .build(); Preconditions.checkNotNull(callback, "callback cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); checkValidOpsOrNull(opNames); mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); final String[] opNamesArray = (opNames != null) ? opNames.toArray(new String[opNames.size()]) : null; if (mHistoricalRegistry.getMode() == AppOpsManager.HISTORICAL_MODE_DISABLED) { if (mHistoricalRegistry.getMode() == AppOpsManager.HISTORICAL_MODE_DISABLED) { // TODO (bug:122218838): Remove once the feature fully enabled. // TODO (bug:122218838): Remove once the feature fully enabled. getHistoricalPackagesOpsCompat(uid, packageName, opNames, beginTimeMillis, getHistoricalPackagesOpsCompat(uid, packageName, opNamesArray, beginTimeMillis, endTimeMillis, callback); endTimeMillis, callback); } else { } else { // Must not hold the appops lock // Must not hold the appops lock mHistoricalRegistry.getHistoricalOps(uid, packageName, opNames, mHistoricalRegistry.getHistoricalOps(uid, packageName, opNamesArray, beginTimeMillis, endTimeMillis, callback); beginTimeMillis, endTimeMillis, callback); } } } } Loading Loading @@ -1101,20 +1106,25 @@ public class AppOpsService extends IAppOpsService.Stub { @Override @Override public void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName, public void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName, @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis, @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis, @NonNull RemoteCallback callback) { @NonNull RemoteCallback callback) { Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0, // Use the builder to validate arguments. "uid must be " + Process.INVALID_UID + " or non negative"); final HistoricalOpsRequest request = new HistoricalOpsRequest.Builder( Preconditions.checkArgument(beginTimeMillis >= 0 && beginTimeMillis < endTimeMillis, beginTimeMillis, endTimeMillis) "beginTimeMillis must be non negative and lesser than endTimeMillis"); .setUid(uid) .setPackageName(packageName) .setOpNames(opNames) .build(); Preconditions.checkNotNull(callback, "callback cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); checkValidOpsOrNull(opNames); mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps"); final String[] opNamesArray = (opNames != null) ? opNames.toArray(new String[opNames.size()]) : null; // Must not hold the appops lock // Must not hold the appops lock mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNames, mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNamesArray, beginTimeMillis, endTimeMillis, callback); beginTimeMillis, endTimeMillis, callback); } } Loading Loading @@ -4266,16 +4276,6 @@ public class AppOpsService extends IAppOpsService.Stub { return packageNames; return packageNames; } } private static void checkValidOpsOrNull(String[] opNames) { if (opNames != null) { for (String opName : opNames) { if (AppOpsManager.strOpToOp(opName) == AppOpsManager.OP_NONE) { throw new IllegalArgumentException("Unknown op: " + opName); } } } } private final class ClientRestrictionState implements DeathRecipient { private final class ClientRestrictionState implements DeathRecipient { private final IBinder token; private final IBinder token; SparseArray<boolean[]> perUserRestrictions; SparseArray<boolean[]> perUserRestrictions; Loading