Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bdea76f9 authored by Svetoslav Ganov's avatar Svetoslav Ganov Committed by Android (Google) Code Review
Browse files

Merge "Add request object for querying historical ops"

parents 86a8aab9 23c88db8
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -304,7 +304,7 @@ package android.app {
  }
  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 @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...);
@@ -394,6 +394,17 @@ package android.app {
    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 {
    method public int describeContents();
    method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
+13 −2
Original line number Diff line number Diff line
@@ -101,8 +101,8 @@ package android.app {
  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 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 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 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(@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 String[] getOpStrs();
    method public boolean isOperationActive(int, int, String);
@@ -206,6 +206,17 @@ package android.app {
    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 {
    method public int describeContents();
    method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
+121 −46
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ import android.util.ArrayMap;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;

import com.android.internal.annotations.Immutable;
import com.android.internal.app.IAppOpsActiveCallback;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsNotedCallback;
@@ -2209,6 +2211,115 @@ public class AppOpsManager {
        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.
     *
@@ -3671,26 +3782,7 @@ public class AppOpsManager {
    /**
     * 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.
     *
     * @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 request A request object describing the data being queried for.
     * @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.
     * @param callback Callback on which to deliver the result.
@@ -3702,13 +3794,13 @@ public class AppOpsManager {
    @TestApi
    @SystemApi
    @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
    public void getHistoricalOps(int uid, @Nullable String packageName,
            @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis,
    public void getHistoricalOps(@NonNull HistoricalOpsRequest request,
            @NonNull Executor executor, @NonNull Consumer<HistoricalOps> callback) {
        Preconditions.checkNotNull(executor, "executor cannot be null");
        Preconditions.checkNotNull(callback, "callback cannot be null");
        try {
            mService.getHistoricalOps(uid, packageName, opNames, beginTimeMillis, endTimeMillis,
            mService.getHistoricalOps(request.mUid, request.mPackageName, request.mOpNames,
                    request.mBeginTimeMillis, request.mEndTimeMillis,
                    new RemoteCallback((result) -> {
                final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS);
                final long identity = Binder.clearCallingIdentity();
@@ -3725,29 +3817,12 @@ public class AppOpsManager {

    /**
     * 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>
     *  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
     *  epoch start.
     *
     * @param uid The UID to query 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 request A request object describing the data being queried for.
     * @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.
     * @param callback Callback on which to deliver the result.
@@ -3758,14 +3833,14 @@ public class AppOpsManager {
     */
    @TestApi
    @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
    public void getHistoricalOpsFromDiskRaw(int uid, @Nullable String packageName,
            @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis,
    public void getHistoricalOpsFromDiskRaw(@NonNull HistoricalOpsRequest request,
            @Nullable Executor executor, @NonNull Consumer<HistoricalOps> callback) {
        Preconditions.checkNotNull(executor, "executor cannot be null");
        Preconditions.checkNotNull(callback, "callback cannot be null");
        try {
            mService.getHistoricalOpsFromDiskRaw(uid, packageName, opNames, beginTimeMillis,
                    endTimeMillis, new RemoteCallback((result) -> {
            mService.getHistoricalOpsFromDiskRaw(request.mUid, request.mPackageName,
                    request.mOpNames, request.mBeginTimeMillis, request.mEndTimeMillis,
                    new RemoteCallback((result) -> {
                final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS);
                final long identity = Binder.clearCallingIdentity();
                try {
+2 −2
Original line number Diff line number Diff line
@@ -44,9 +44,9 @@ interface IAppOpsService {
    int checkPackage(int uid, String packageName);
    List<AppOpsManager.PackageOps> getPackagesForOps(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);
    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);
    void offsetHistory(long duration);
    void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep);
+25 −25
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AppOpsManager.HistoricalOps;
import android.app.AppOpsManager.HistoricalOpsRequest;
import android.app.AppOpsManagerInternal;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
import android.content.BroadcastReceiver;
@@ -1024,25 +1025,29 @@ public class AppOpsService extends IAppOpsService.Stub {

    @Override
    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) {
        Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0,
                "uid must be " + Process.INVALID_UID + " or non negative");
        Preconditions.checkArgument(beginTimeMillis >= 0 && beginTimeMillis < endTimeMillis,
                "beginTimeMillis must be non negative and lesser than endTimeMillis");
        // Use the builder to validate arguments.
        final HistoricalOpsRequest request = new HistoricalOpsRequest.Builder(
                beginTimeMillis, endTimeMillis)
                .setUid(uid)
                .setPackageName(packageName)
                .setOpNames(opNames)
                .build();
        Preconditions.checkNotNull(callback, "callback cannot be null");
        checkValidOpsOrNull(opNames);

        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
                Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");

        final String[] opNamesArray = (opNames != null)
                ? opNames.toArray(new String[opNames.size()]) : null;
        if (mHistoricalRegistry.getMode() == AppOpsManager.HISTORICAL_MODE_DISABLED) {
            // TODO (bug:122218838): Remove once the feature fully enabled.
            getHistoricalPackagesOpsCompat(uid, packageName, opNames, beginTimeMillis,
            getHistoricalPackagesOpsCompat(uid, packageName, opNamesArray, beginTimeMillis,
                    endTimeMillis, callback);
        } else {
            // Must not hold the appops lock
            mHistoricalRegistry.getHistoricalOps(uid, packageName, opNames,
            mHistoricalRegistry.getHistoricalOps(uid, packageName, opNamesArray,
                    beginTimeMillis, endTimeMillis, callback);
        }
    }
@@ -1101,20 +1106,25 @@ public class AppOpsService extends IAppOpsService.Stub {

    @Override
    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) {
        Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0,
                "uid must be " + Process.INVALID_UID + " or non negative");
        Preconditions.checkArgument(beginTimeMillis >= 0 && beginTimeMillis < endTimeMillis,
                "beginTimeMillis must be non negative and lesser than endTimeMillis");
        // Use the builder to validate arguments.
        final HistoricalOpsRequest request = new HistoricalOpsRequest.Builder(
                beginTimeMillis, endTimeMillis)
                .setUid(uid)
                .setPackageName(packageName)
                .setOpNames(opNames)
                .build();
        Preconditions.checkNotNull(callback, "callback cannot be null");
        checkValidOpsOrNull(opNames);

        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
                Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");

        final String[] opNamesArray = (opNames != null)
                ? opNames.toArray(new String[opNames.size()]) : null;

        // Must not hold the appops lock
        mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNames,
        mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNamesArray,
                beginTimeMillis, endTimeMillis, callback);
    }

@@ -4266,16 +4276,6 @@ public class AppOpsService extends IAppOpsService.Stub {
        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 IBinder token;
        SparseArray<boolean[]> perUserRestrictions;