/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.permission;

import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
import static android.permission.PermissionControllerService.SERVICE_INTERFACE;

import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkArgumentNonnegative;
import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
import static com.android.internal.util.Preconditions.checkFlagsArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkStringNotEmpty;

import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.app.admin.DevicePolicyManager.PermissionGrantState;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.infra.RemoteStream;
import com.android.internal.infra.ServiceConnector;
import com.android.internal.util.CollectionUtils;

import libcore.util.EmptyArray;

import java.io.FileDescriptor;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * Interface for communicating with the permission controller.
 *
 * @hide
 */
@TestApi
@SystemApi
@SystemService(Context.PERMISSION_CONTROLLER_SERVICE)
public final class PermissionControllerManager {
    private static final String TAG = PermissionControllerManager.class.getSimpleName();

    private static final long REQUEST_TIMEOUT_MILLIS = 60000;
    private static final long UNBIND_TIMEOUT_MILLIS = 10000;
    private static final int CHUNK_SIZE = 4 * 1024;

    private static final Object sLock = new Object();

    /**
     * Global remote services (per user) used by all {@link PermissionControllerManager managers}
     */
    @GuardedBy("sLock")
    private static ArrayMap<Pair<Integer, Thread>, ServiceConnector<IPermissionController>>
            sRemoteServices = new ArrayMap<>(1);

    /** @hide */
    @IntDef(prefix = { "REASON_" }, value = {
            REASON_MALWARE,
            REASON_INSTALLER_POLICY_VIOLATION,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Reason {}

    /** The permissions are revoked because the apps holding the permissions are malware */
    public static final int REASON_MALWARE = 1;

    /**
     * The permissions are revoked because the apps holding the permissions violate a policy of the
     * app that installed it.
     *
     * <p>If this reason is used only permissions of apps that are installed by the caller of the
     * API can be revoked.
     */
    public static final int REASON_INSTALLER_POLICY_VIOLATION = 2;

    /** @hide */
    @IntDef(prefix = { "COUNT_" }, value = {
            COUNT_ONLY_WHEN_GRANTED,
            COUNT_WHEN_SYSTEM,
    }, flag = true)
    @Retention(RetentionPolicy.SOURCE)
    public @interface CountPermissionAppsFlag {}

    /** Count an app only if the permission is granted to the app. */
    public static final int COUNT_ONLY_WHEN_GRANTED = 1;

    /** Count and app even if it is a system app. */
    public static final int COUNT_WHEN_SYSTEM = 2;

    /**
     * Callback for delivering the result of {@link #revokeRuntimePermissions}.
     */
    public abstract static class OnRevokeRuntimePermissionsCallback {
        /**
         * The result for {@link #revokeRuntimePermissions}.
         *
         * @param revoked The actually revoked permissions as
         *                {@code Map<packageName, List<permission>>}
         */
        public abstract void onRevokeRuntimePermissions(@NonNull Map<String, List<String>> revoked);
    }

    /**
     * Callback for delivering the result of {@link #getAppPermissions}.
     *
     * @hide
     */
    @TestApi
    public interface OnGetAppPermissionResultCallback {
        /**
         * The result for {@link #getAppPermissions(String, OnGetAppPermissionResultCallback,
         * Handler)}.
         *
         * @param permissions The permissions list.
         */
        void onGetAppPermissions(@NonNull List<RuntimePermissionPresentationInfo> permissions);
    }

    /**
     * Callback for delivering the result of {@link #countPermissionApps}.
     *
     * @hide
     */
    @TestApi
    public interface OnCountPermissionAppsResultCallback {
        /**
         * The result for {@link #countPermissionApps(List, int,
         * OnCountPermissionAppsResultCallback, Handler)}.
         *
         * @param numApps The number of apps that have one of the permissions
         */
        void onCountPermissionApps(int numApps);
    }

    /**
     * Callback for delivering the result of {@link #getPermissionUsages}.
     *
     * @hide
     */
    public interface OnPermissionUsageResultCallback {
        /**
         * The result for {@link #getPermissionUsages}.
         *
         * @param users The users list.
         */
        void onPermissionUsageResult(@NonNull List<RuntimePermissionUsageInfo> users);
    }

    private final @NonNull Context mContext;
    private final @NonNull ServiceConnector<IPermissionController> mRemoteService;
    private final @NonNull Handler mHandler;

    /**
     * Create a new {@link PermissionControllerManager}.
     *
     * @param context to create the manager for
     * @param handler handler to schedule work
     *
     * @hide
     */
    public PermissionControllerManager(@NonNull Context context, @NonNull Handler handler) {
        synchronized (sLock) {
            Pair<Integer, Thread> key = new Pair<>(context.getUserId(),
                    handler.getLooper().getThread());
            ServiceConnector<IPermissionController> remoteService = sRemoteServices.get(key);
            if (remoteService == null) {
                Intent intent = new Intent(SERVICE_INTERFACE);
                intent.setPackage(context.getPackageManager().getPermissionControllerPackageName());
                ResolveInfo serviceInfo = context.getPackageManager().resolveService(intent, 0);
                remoteService = new ServiceConnector.Impl<IPermissionController>(
                        ActivityThread.currentApplication() /* context */,
                        new Intent(SERVICE_INTERFACE)
                                .setComponent(serviceInfo.getComponentInfo().getComponentName()),
                        0 /* bindingFlags */, context.getUserId(),
                        IPermissionController.Stub::asInterface) {

                    @Override
                    protected Handler getJobHandler() {
                        return handler;
                    }

                    @Override
                    protected long getRequestTimeoutMs() {
                        return REQUEST_TIMEOUT_MILLIS;
                    }

                    @Override
                    protected long getAutoDisconnectTimeoutMs() {
                        return UNBIND_TIMEOUT_MILLIS;
                    }
                };
                sRemoteServices.put(key, remoteService);
            }

            mRemoteService = remoteService;
        }

        mContext = context;
        mHandler = handler;
    }

    /**
     * Throw a {@link SecurityException} if not at least one of the permissions is granted.
     *
     * @param requiredPermissions A list of permissions. Any of of them if sufficient to pass the
     *                            check
     */
    private void enforceSomePermissionsGrantedToSelf(@NonNull String... requiredPermissions) {
        for (String requiredPermission : requiredPermissions) {
            if (mContext.checkSelfPermission(requiredPermission)
                    == PackageManager.PERMISSION_GRANTED) {
                return;
            }
        }

        throw new SecurityException("At lest one of the following permissions is required: "
                + Arrays.toString(requiredPermissions));
    }

    /**
     * Revoke a set of runtime permissions for various apps.
     *
     * @param request The permissions to revoke as {@code Map<packageName, List<permission>>}
     * @param doDryRun Compute the permissions that would be revoked, but not actually revoke them
     * @param reason Why the permission should be revoked
     * @param executor Executor on which to invoke the callback
     * @param callback Callback to receive the result
     */
    @RequiresPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
    public void revokeRuntimePermissions(@NonNull Map<String, List<String>> request,
            boolean doDryRun, @Reason int reason, @NonNull @CallbackExecutor Executor executor,
            @NonNull OnRevokeRuntimePermissionsCallback callback) {
        // Check input to fail immediately instead of inside the async request
        checkNotNull(executor);
        checkNotNull(callback);
        checkNotNull(request);
        for (Map.Entry<String, List<String>> appRequest : request.entrySet()) {
            checkNotNull(appRequest.getKey());
            checkCollectionElementsNotNull(appRequest.getValue(), "permissions");
        }

        // Check required permission to fail immediately instead of inside the oneway binder call
        enforceSomePermissionsGrantedToSelf(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);

        mRemoteService.postAsync(service -> {
            Bundle bundledizedRequest = new Bundle();
            for (Map.Entry<String, List<String>> appRequest : request.entrySet()) {
                bundledizedRequest.putStringArrayList(appRequest.getKey(),
                        new ArrayList<>(appRequest.getValue()));
            }

            AndroidFuture<Map<String, List<String>>> revokeRuntimePermissionsResult =
                    new AndroidFuture<>();
            service.revokeRuntimePermissions(bundledizedRequest, doDryRun, reason,
                    mContext.getPackageName(),
                    revokeRuntimePermissionsResult);
            return revokeRuntimePermissionsResult;
        }).whenCompleteAsync((revoked, err) -> {
            long token = Binder.clearCallingIdentity();
            try {
                if (err != null) {
                    Log.e(TAG, "Failure when revoking runtime permissions " + revoked, err);
                    callback.onRevokeRuntimePermissions(Collections.emptyMap());
                } else {
                    callback.onRevokeRuntimePermissions(revoked);
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }, executor);
    }

    /**
     * Set the runtime permission state from a device admin.
     *
     * @param callerPackageName The package name of the admin requesting the change
     * @param packageName Package the permission belongs to
     * @param permission Permission to change
     * @param grantState State to set the permission into
     * @param executor Executor to run the {@code callback} on
     * @param callback The callback
     *
     * @hide
     */
    @RequiresPermission(allOf = {Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
            Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
            Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY},
            conditional = true)
    public void setRuntimePermissionGrantStateByDeviceAdmin(@NonNull String callerPackageName,
            @NonNull String packageName, @NonNull String permission,
            @PermissionGrantState int grantState, @NonNull @CallbackExecutor Executor executor,
            @NonNull Consumer<Boolean> callback) {
        checkStringNotEmpty(callerPackageName);
        checkStringNotEmpty(packageName);
        checkStringNotEmpty(permission);
        checkArgument(grantState == PERMISSION_GRANT_STATE_GRANTED
                || grantState == PERMISSION_GRANT_STATE_DENIED
                || grantState == PERMISSION_GRANT_STATE_DEFAULT);
        checkNotNull(executor);
        checkNotNull(callback);

        mRemoteService.postAsync(service -> {
            AndroidFuture<Boolean> setRuntimePermissionGrantStateResult = new AndroidFuture<>();
            service.setRuntimePermissionGrantStateByDeviceAdmin(
                    callerPackageName, packageName, permission, grantState,
                    setRuntimePermissionGrantStateResult);
            return setRuntimePermissionGrantStateResult;
        }).whenCompleteAsync((setRuntimePermissionGrantStateResult, err) -> {
            long token = Binder.clearCallingIdentity();
            try {
                if (err != null) {
                    Log.e(TAG, "Error setting permissions state for device admin " + packageName,
                            err);
                    callback.accept(false);
                } else {
                    callback.accept(Boolean.TRUE.equals(setRuntimePermissionGrantStateResult));
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }, executor);
    }

    /**
     * Create a backup of the runtime permissions.
     *
     * @param user The user to be backed up
     * @param executor Executor on which to invoke the callback
     * @param callback Callback to receive the result. The resulting backup-file is opaque and no
     *                 guarantees are made other than that the file can be send to
     *                 {@link #restoreRuntimePermissionBackup} in this and future versions of
     *                 Android.
     */
    @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
    public void getRuntimePermissionBackup(@NonNull UserHandle user,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull Consumer<byte[]> callback) {
        checkNotNull(user);
        checkNotNull(executor);
        checkNotNull(callback);

        // Check required permission to fail immediately instead of inside the oneway binder call
        enforceSomePermissionsGrantedToSelf(Manifest.permission.GET_RUNTIME_PERMISSIONS);

        mRemoteService.postAsync(service -> RemoteStream.receiveBytes(remotePipe -> {
            service.getRuntimePermissionBackup(user, remotePipe);
        })).whenCompleteAsync((bytes, err) -> {
            if (err != null) {
                Log.e(TAG, "Error getting permission backup", err);
                callback.accept(EmptyArray.BYTE);
            } else {
                callback.accept(bytes);
            }
        }, executor);
    }

    /**
     * Restore a {@link #getRuntimePermissionBackup backup-file} of the runtime permissions.
     *
     * <p>This might leave some part of the backup-file unapplied if an package mentioned in the
     * backup-file is not yet installed. It is required that
     * {@link #applyStagedRuntimePermissionBackup} is called after any package is installed to
     * apply the rest of the backup-file.
     *
     * @param backup the backup-file to restore. The backup is sent asynchronously, hence it should
     *               not be modified after calling this method.
     * @param user The user to be restore
     */
    @RequiresPermission(anyOf = {
            Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
            Manifest.permission.RESTORE_RUNTIME_PERMISSIONS
    })
    public void stageAndApplyRuntimePermissionsBackup(@NonNull byte[] backup,
            @NonNull UserHandle user) {
        checkNotNull(backup);
        checkNotNull(user);

        // Check required permission to fail immediately instead of inside the oneway binder call
        enforceSomePermissionsGrantedToSelf(Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
                Manifest.permission.RESTORE_RUNTIME_PERMISSIONS);

        mRemoteService.postAsync(service -> RemoteStream.sendBytes(remotePipe -> {
            service.stageAndApplyRuntimePermissionsBackup(user, remotePipe);
        }, backup))
                .whenComplete((nullResult, err) -> {
                    if (err != null) {
                        Log.e(TAG, "Error sending permission backup", err);
                    }
                });
    }

    /**
     * Restore unapplied parts of a {@link #stageAndApplyRuntimePermissionsBackup previously staged}
     * backup-file of the runtime permissions.
     *
     * <p>This should be called every time after a package is installed until the callback
     * reports that there is no more unapplied backup left.
     *
     * @param packageName The package that is ready to have it's permissions restored.
     * @param user The user the package belongs to
     * @param executor Executor to execute the callback on
     * @param callback Is called with {@code true} iff there is still more unapplied backup left
     */
    @RequiresPermission(anyOf = {
            Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
            Manifest.permission.RESTORE_RUNTIME_PERMISSIONS
    })
    public void applyStagedRuntimePermissionBackup(@NonNull String packageName,
            @NonNull UserHandle user,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull Consumer<Boolean> callback) {
        checkNotNull(packageName);
        checkNotNull(user);
        checkNotNull(executor);
        checkNotNull(callback);

        // Check required permission to fail immediately instead of inside the oneway binder call
        enforceSomePermissionsGrantedToSelf(Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
                Manifest.permission.RESTORE_RUNTIME_PERMISSIONS);

        mRemoteService.postAsync(service -> {
            AndroidFuture<Boolean> applyStagedRuntimePermissionBackupResult =
                    new AndroidFuture<>();
            service.applyStagedRuntimePermissionBackup(packageName, user,
                    applyStagedRuntimePermissionBackupResult);
            return applyStagedRuntimePermissionBackupResult;
        }).whenCompleteAsync((applyStagedRuntimePermissionBackupResult, err) -> {
            long token = Binder.clearCallingIdentity();
            try {
                if (err != null) {
                    Log.e(TAG, "Error restoring delayed permissions for " + packageName, err);
                    callback.accept(true);
                } else {
                    callback.accept(
                            Boolean.TRUE.equals(applyStagedRuntimePermissionBackupResult));
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }, executor);
    }

    /**
     * Dump permission controller state.
     *
     * @hide
     */
    public void dump(@NonNull FileDescriptor fd, @Nullable String[] args) {
        try {
            mRemoteService.post(service -> service.asBinder().dump(fd, args))
                    .get(REQUEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            Log.e(TAG, "Could not get dump", e);
        }
    }

    /**
     * Gets the runtime permissions for an app.
     *
     * @param packageName The package for which to query.
     * @param callback Callback to receive the result.
     * @param handler Handler on which to invoke the callback.
     *
     * @hide
     */
    @TestApi
    @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
    public void getAppPermissions(@NonNull String packageName,
            @NonNull OnGetAppPermissionResultCallback callback, @Nullable Handler handler) {
        checkNotNull(packageName);
        checkNotNull(callback);
        Handler finalHandler = handler != null ? handler : mHandler;

        mRemoteService.postAsync(service -> {
            AndroidFuture<List<RuntimePermissionPresentationInfo>> getAppPermissionsResult =
                    new AndroidFuture<>();
            service.getAppPermissions(packageName, getAppPermissionsResult);
            return getAppPermissionsResult;
        }).whenComplete((getAppPermissionsResult, err) -> finalHandler.post(() -> {
            if (err != null) {
                Log.e(TAG, "Error getting app permission", err);
                callback.onGetAppPermissions(Collections.emptyList());
            } else {
                callback.onGetAppPermissions(CollectionUtils.emptyIfNull(getAppPermissionsResult));
            }
        }));
    }

    /**
     * Revoke the permission {@code permissionName} for app {@code packageName}
     *
     * @param packageName The package for which to revoke
     * @param permissionName The permission to revoke
     *
     * @hide
     */
    @TestApi
    @RequiresPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
    public void revokeRuntimePermission(@NonNull String packageName,
            @NonNull String permissionName) {
        checkNotNull(packageName);
        checkNotNull(permissionName);

        mRemoteService.run(service -> service.revokeRuntimePermission(packageName, permissionName));
    }

    /**
     * Count how many apps have one of a set of permissions.
     *
     * @param permissionNames The permissions the app might have
     * @param flags Modify which apps to count. By default all non-system apps that request a
     *              permission are counted
     * @param callback Callback to receive the result
     * @param handler Handler on which to invoke the callback
     *
     * @hide
     */
    @TestApi
    @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
    public void countPermissionApps(@NonNull List<String> permissionNames,
            @CountPermissionAppsFlag int flags,
            @NonNull OnCountPermissionAppsResultCallback callback, @Nullable Handler handler) {
        checkCollectionElementsNotNull(permissionNames, "permissionNames");
        checkFlagsArgument(flags, COUNT_WHEN_SYSTEM | COUNT_ONLY_WHEN_GRANTED);
        checkNotNull(callback);
        Handler finalHandler = handler != null ? handler : mHandler;

        mRemoteService.postAsync(service -> {
            AndroidFuture<Integer> countPermissionAppsResult = new AndroidFuture<>();
            service.countPermissionApps(permissionNames, flags, countPermissionAppsResult);
            return countPermissionAppsResult;
        }).whenComplete((countPermissionAppsResult, err) -> finalHandler.post(() -> {
            if (err != null) {
                Log.e(TAG, "Error counting permission apps", err);
                callback.onCountPermissionApps(0);
            } else {
                callback.onCountPermissionApps(countPermissionAppsResult);
            }
        }));
    }

    /**
     * Count how many apps have used permissions.
     *
     * @param countSystem Also count system apps
     * @param numMillis The number of milliseconds in the past to check for uses
     * @param executor Executor on which to invoke the callback
     * @param callback Callback to receive the result
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
    public void getPermissionUsages(boolean countSystem, long numMillis,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnPermissionUsageResultCallback callback) {
        checkArgumentNonnegative(numMillis);
        checkNotNull(executor);
        checkNotNull(callback);


        mRemoteService.postAsync(service -> {
            AndroidFuture<List<RuntimePermissionUsageInfo>> getPermissionUsagesResult =
                    new AndroidFuture<>();
            service.getPermissionUsages(countSystem, numMillis, getPermissionUsagesResult);
            return getPermissionUsagesResult;
        }).whenCompleteAsync((getPermissionUsagesResult, err) -> {
            if (err != null) {
                Log.e(TAG, "Error getting permission usages", err);
                callback.onPermissionUsageResult(Collections.emptyList());
            } else {
                long token = Binder.clearCallingIdentity();
                try {
                    callback.onPermissionUsageResult(
                            CollectionUtils.emptyIfNull(getPermissionUsagesResult));
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        }, executor);
    }

    /**
     * Grant or upgrade runtime permissions. The upgrade could be performed
     * based on whether the device upgraded, whether the permission database
     * version is old, or because the permission policy changed.
     *
     * @param executor Executor on which to invoke the callback
     * @param callback Callback to receive the result
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY)
    public void grantOrUpgradeDefaultRuntimePermissions(
            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
        mRemoteService.postAsync(service -> {
            AndroidFuture<Boolean> grantOrUpgradeDefaultRuntimePermissionsResult =
                    new AndroidFuture<>();
            service.grantOrUpgradeDefaultRuntimePermissions(
                    grantOrUpgradeDefaultRuntimePermissionsResult);
            return grantOrUpgradeDefaultRuntimePermissionsResult;
        }).whenCompleteAsync((grantOrUpgradeDefaultRuntimePermissionsResult, err) -> {
            if (err != null) {
                Log.e(TAG, "Error granting or upgrading runtime permissions", err);
                callback.accept(false);
            } else {
                callback.accept(Boolean.TRUE.equals(grantOrUpgradeDefaultRuntimePermissionsResult));
            }
        }, executor);
    }

    /**
     * @see PermissionControllerManager#updateUserSensitiveForApp
     * @hide
     */
    public void updateUserSensitive() {
        updateUserSensitiveForApp(Process.INVALID_UID);
    }

    /**
     * @see PermissionControllerService#onUpdateUserSensitiveForApp
     * @hide
     */
    public void updateUserSensitiveForApp(int uid) {
        mRemoteService.postAsync(service -> {
            AndroidFuture<Void> future = new AndroidFuture<>();
            service.updateUserSensitiveForApp(uid, future);
            return future;
        }).whenComplete((res, err) -> {
            if (err != null) {
                Log.e(TAG, "Error updating user_sensitive flags for uid " + uid, err);
            }
        });
    }

    /**
     * Called when a package that has permissions registered as "one-time" is considered
     * inactive.
     *
     * @param packageName The package which became inactive
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
    public void notifyOneTimePermissionSessionTimeout(@NonNull String packageName) {
        mRemoteService.run(
                service -> service.notifyOneTimePermissionSessionTimeout(packageName));
    }
}
