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

Commit 23c88db8 authored by Svet Ganov's avatar Svet Ganov
Browse files

Add request object for querying historical ops

Test: atest CtsAppOpTestCases

bug:123253745

Change-Id: Ia473f9298a83214f2fdfb1062992b48357965003
parent 1dc37e96
Loading
Loading
Loading
Loading
+12 −1
Original line number Original line Diff line number Diff line
@@ -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...);
@@ -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);
+13 −2
Original line number Original line Diff line number Diff line
@@ -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);
@@ -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);
+121 −46
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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.
     *
     *
@@ -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.
@@ -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();
@@ -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.
@@ -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 {
+2 −2
Original line number Original line Diff line number Diff line
@@ -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);
+25 −25
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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);
        }
        }
    }
    }
@@ -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);
    }
    }


@@ -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;