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

Commit 2bce8820 authored by Manjeet Rulhania's avatar Manjeet Rulhania Committed by Android (Google) Code Review
Browse files

Merge "Add device support for permission APIs in Activity"

parents d0078075 3b0a4e44
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -4458,6 +4458,7 @@ package android.app {
    method public void onProvideAssistData(android.os.Bundle);
    method public void onProvideAssistData(android.os.Bundle);
    method public android.net.Uri onProvideReferrer();
    method public android.net.Uri onProvideReferrer();
    method public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[]);
    method public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[]);
    method public void onRequestPermissionsResult(int, @NonNull String[], @NonNull int[], int);
    method @CallSuper protected void onRestart();
    method @CallSuper protected void onRestart();
    method protected void onRestoreInstanceState(@NonNull android.os.Bundle);
    method protected void onRestoreInstanceState(@NonNull android.os.Bundle);
    method public void onRestoreInstanceState(@Nullable android.os.Bundle, @Nullable android.os.PersistableBundle);
    method public void onRestoreInstanceState(@Nullable android.os.Bundle, @Nullable android.os.PersistableBundle);
@@ -4499,6 +4500,7 @@ package android.app {
    method public android.view.DragAndDropPermissions requestDragAndDropPermissions(android.view.DragEvent);
    method public android.view.DragAndDropPermissions requestDragAndDropPermissions(android.view.DragEvent);
    method public void requestFullscreenMode(int, @Nullable android.os.OutcomeReceiver<java.lang.Void,java.lang.Throwable>);
    method public void requestFullscreenMode(int, @Nullable android.os.OutcomeReceiver<java.lang.Void,java.lang.Throwable>);
    method public final void requestPermissions(@NonNull String[], int);
    method public final void requestPermissions(@NonNull String[], int);
    method public final void requestPermissions(@NonNull String[], int, int);
    method public final void requestShowKeyboardShortcuts();
    method public final void requestShowKeyboardShortcuts();
    method @Deprecated public boolean requestVisibleBehind(boolean);
    method @Deprecated public boolean requestVisibleBehind(boolean);
    method public final boolean requestWindowFeature(int);
    method public final boolean requestWindowFeature(int);
@@ -4546,6 +4548,7 @@ package android.app {
    method public void setVrModeEnabled(boolean, @NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
    method public void setVrModeEnabled(boolean, @NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
    method public boolean shouldDockBigOverlays();
    method public boolean shouldDockBigOverlays();
    method public boolean shouldShowRequestPermissionRationale(@NonNull String);
    method public boolean shouldShowRequestPermissionRationale(@NonNull String);
    method public boolean shouldShowRequestPermissionRationale(@NonNull String, int);
    method public boolean shouldUpRecreateTask(android.content.Intent);
    method public boolean shouldUpRecreateTask(android.content.Intent);
    method public boolean showAssist(android.os.Bundle);
    method public boolean showAssist(android.os.Bundle);
    method @Deprecated public final void showDialog(int);
    method @Deprecated public final void showDialog(int);
+1 −0
Original line number Original line Diff line number Diff line
@@ -3924,6 +3924,7 @@ package android.content.pm {
    field public static final int DELETE_FAILED_OWNER_BLOCKED = -4; // 0xfffffffc
    field public static final int DELETE_FAILED_OWNER_BLOCKED = -4; // 0xfffffffc
    field public static final int DELETE_KEEP_DATA = 1; // 0x1
    field public static final int DELETE_KEEP_DATA = 1; // 0x1
    field public static final int DELETE_SUCCEEDED = 1; // 0x1
    field public static final int DELETE_SUCCEEDED = 1; // 0x1
    field public static final String EXTRA_REQUEST_PERMISSIONS_DEVICE_ID = "android.content.pm.extra.REQUEST_PERMISSIONS_DEVICE_ID";
    field public static final String EXTRA_REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES";
    field public static final String EXTRA_REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES";
    field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
    field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
    field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
    field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
+145 −24
Original line number Original line Diff line number Diff line
@@ -5445,14 +5445,14 @@ public class Activity extends ContextThemeWrapper
     * the signature of the app declaring the permissions.
     * the signature of the app declaring the permissions.
     * </p>
     * </p>
     * <p>
     * <p>
     * Call {@link #shouldShowRequestPermissionRationale(String)} before calling this API to
     * Call {@link #shouldShowRequestPermissionRationale} before calling this API to
     * check if the system recommends to show a rationale UI before asking for a permission.
     * check if the system recommends to show a rationale UI before asking for a permission.
     * </p>
     * </p>
     * <p>
     * <p>
     * If your app does not have the requested permissions the user will be presented
     * If your app does not have the requested permissions the user will be presented
     * with UI for accepting them. After the user has accepted or rejected the
     * with UI for accepting them. After the user has accepted or rejected the
     * requested permissions you will receive a callback on {@link
     * requested permissions you will receive a callback on {@link
     * #onRequestPermissionsResult(int, String[], int[])} reporting whether the
     * #onRequestPermissionsResult} reporting whether the
     * permissions were granted or not.
     * permissions were granted or not.
     * </p>
     * </p>
     * <p>
     * <p>
@@ -5464,8 +5464,7 @@ public class Activity extends ContextThemeWrapper
     * to grant and which to reject. Hence, you should be prepared that your activity
     * to grant and which to reject. Hence, you should be prepared that your activity
     * may be paused and resumed. Further, granting some permissions may require
     * may be paused and resumed. Further, granting some permissions may require
     * a restart of you application. In such a case, the system will recreate the
     * a restart of you application. In such a case, the system will recreate the
     * activity stack before delivering the result to {@link
     * activity stack before delivering the result to {@link #onRequestPermissionsResult}.
     * #onRequestPermissionsResult(int, String[], int[])}.
     * </p>
     * </p>
     * <p>
     * <p>
     * When checking whether you have a permission you should use {@link
     * When checking whether you have a permission you should use {@link
@@ -5475,7 +5474,7 @@ public class Activity extends ContextThemeWrapper
     * You cannot request a permission if your activity sets {@link
     * You cannot request a permission if your activity sets {@link
     * android.R.styleable#AndroidManifestActivity_noHistory noHistory} to
     * android.R.styleable#AndroidManifestActivity_noHistory noHistory} to
     * <code>true</code> because in this case the activity would not receive
     * <code>true</code> because in this case the activity would not receive
     * result callbacks including {@link #onRequestPermissionsResult(int, String[], int[])}.
     * result callbacks including {@link #onRequestPermissionsResult}.
     * </p>
     * </p>
     * <p>
     * <p>
     * The <a href="https://github.com/android/platform-samples/tree/main/samples/privacy/permissions">
     * The <a href="https://github.com/android/platform-samples/tree/main/samples/privacy/permissions">
@@ -5483,18 +5482,89 @@ public class Activity extends ContextThemeWrapper
     * request permissions at run time.
     * request permissions at run time.
     * </p>
     * </p>
     *
     *
     * @param permissions The requested permissions. Must me non-null and not empty.
     * @param permissions The requested permissions. Must be non-null and not empty.
     * @param requestCode Application specific request code to match with a result
     * @param requestCode Application specific request code to match with a result
     *    reported to {@link #onRequestPermissionsResult(int, String[], int[])}.
     *                    reported to {@link #onRequestPermissionsResult}.
     *                    Should be >= 0.
     *                    Should be >= 0.
     *
     *
     * @throws IllegalArgumentException if requestCode is negative.
     * @throws IllegalArgumentException if requestCode is negative.
     *
     *
     * @see #onRequestPermissionsResult(int, String[], int[])
     * @see #onRequestPermissionsResult
     * @see #checkSelfPermission(String)
     * @see #checkSelfPermission
     * @see #shouldShowRequestPermissionRationale(String)
     * @see #shouldShowRequestPermissionRationale
     */
     */
    public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
    public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
        requestPermissions(permissions, requestCode, getDeviceId());
    }

    /**
     * Requests permissions to be granted to this application. These permissions
     * must be requested in your manifest, they should not be granted to your app,
     * and they should have protection level {@link
     * android.content.pm.PermissionInfo#PROTECTION_DANGEROUS dangerous}, regardless
     * whether they are declared by the platform or a third-party app.
     * <p>
     * Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL}
     * are granted at install time if requested in the manifest. Signature permissions
     * {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at
     * install time if requested in the manifest and the signature of your app matches
     * the signature of the app declaring the permissions.
     * </p>
     * <p>
     * Call {@link #shouldShowRequestPermissionRationale} before calling this API to
     * check if the system recommends to show a rationale UI before asking for a permission.
     * </p>
     * <p>
     * If your app does not have the requested permissions the user will be presented
     * with UI for accepting them. After the user has accepted or rejected the
     * requested permissions you will receive a callback on {@link #onRequestPermissionsResult}
     * reporting whether the permissions were granted or not.
     * </p>
     * <p>
     * Note that requesting a permission does not guarantee it will be granted and
     * your app should be able to run without having this permission.
     * </p>
     * <p>
     * This method may start an activity allowing the user to choose which permissions
     * to grant and which to reject. Hence, you should be prepared that your activity
     * may be paused and resumed. Further, granting some permissions may require
     * a restart of you application. In such a case, the system will recreate the
     * activity stack before delivering the result to {@link #onRequestPermissionsResult}.
     * </p>
     * <p>
     * When checking whether you have a permission you should use {@link
     * #checkSelfPermission(String)}.
     * </p>
     * <p>
     * You cannot request a permission if your activity sets {@link
     * android.R.styleable#AndroidManifestActivity_noHistory noHistory} to
     * <code>true</code> because in this case the activity would not receive
     * result callbacks including {@link #onRequestPermissionsResult}.
     * </p>
     * <p>
     * The <a href="https://github.com/android/platform-samples/tree/main/samples/privacy/permissions">
     * permissions samples</a> repo demonstrates how to use this method to
     * request permissions at run time.
     * </p>
     *
     * @param permissions The requested permissions. Must be non-null and not empty.
     * @param requestCode Application specific request code to match with a result
     *                    reported to {@link #onRequestPermissionsResult}.
     *                    Should be >= 0.
     * @param deviceId The app is requesting permissions for this device. The primary/physical
     *                 device is assigned {@link Context#DEVICE_ID_DEFAULT}, and {@link
     *                 android.companion.virtual.VirtualDeviceManager.VirtualDevice virtual devices}
     *                 are assigned unique device Ids.
     *
     * @throws IllegalArgumentException if requestCode is negative.
     *
     * @see #onRequestPermissionsResult
     * @see #checkSelfPermission
     * @see #shouldShowRequestPermissionRationale
     * @see Context#DEVICE_ID_DEFAULT
     */
    public final void requestPermissions(@NonNull String[] permissions, int requestCode,
            int deviceId) {
        if (requestCode < 0) {
        if (requestCode < 0) {
            throw new IllegalArgumentException("requestCode should be >= 0");
            throw new IllegalArgumentException("requestCode should be >= 0");
        }
        }
@@ -5502,7 +5572,7 @@ public class Activity extends ContextThemeWrapper
        if (mHasCurrentPermissionsRequest) {
        if (mHasCurrentPermissionsRequest) {
            Log.w(TAG, "Can request only one set of permissions at a time");
            Log.w(TAG, "Can request only one set of permissions at a time");
            // Dispatch the callback with empty arrays which means a cancellation.
            // Dispatch the callback with empty arrays which means a cancellation.
            onRequestPermissionsResult(requestCode, new String[0], new int[0]);
            onRequestPermissionsResult(requestCode, new String[0], new int[0], deviceId);
            return;
            return;
        }
        }


@@ -5516,47 +5586,95 @@ public class Activity extends ContextThemeWrapper
            }
            }
        }
        }


        final Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
        PackageManager packageManager = getDeviceId() == deviceId ? getPackageManager()
                : createDeviceContext(deviceId).getPackageManager();
        final Intent intent = packageManager.buildRequestPermissionsIntent(permissions);
        startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
        startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
        mHasCurrentPermissionsRequest = true;
        mHasCurrentPermissionsRequest = true;
    }
    }


    /**
    /**
     * Callback for the result from requesting permissions. This method
     * Callback for the result from requesting permissions. This method
     * is invoked for every call on {@link #requestPermissions(String[], int)}.
     * is invoked for every call on {@link #requestPermissions}
     * <p>
     * <p>
     * <strong>Note:</strong> It is possible that the permissions request interaction
     * <strong>Note:</strong> It is possible that the permissions request interaction
     * with the user is interrupted. In this case you will receive empty permissions
     * with the user is interrupted. In this case you will receive empty permissions
     * and results arrays which should be treated as a cancellation.
     * and results arrays which should be treated as a cancellation.
     * </p>
     * </p>
     *
     *
     * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}.
     * @param requestCode The request code passed in {@link #requestPermissions}.
     * @param permissions The requested permissions. Never null.
     * @param permissions The requested permissions. Never null.
     * @param grantResults The grant results for the corresponding permissions
     * @param grantResults The grant results for the corresponding permissions which is either
     *     which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED}
     *                     {@link android.content.pm.PackageManager#PERMISSION_GRANTED} or
     *     or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null.
     *                     {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null.
     *
     *
     * @see #requestPermissions(String[], int)
     * @see #requestPermissions
     */
     */
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
            @NonNull int[] grantResults) {
        /* callback - no nothing */
        /* callback - no nothing */
    }
    }


    /**
     * Callback for the result from requesting permissions. This method
     * is invoked for every call on {@link #requestPermissions}.
     * <p>
     * <strong>Note:</strong> It is possible that the permissions request interaction
     * with the user is interrupted. In this case you will receive empty permissions
     * and results arrays which should be treated as a cancellation.
     * </p>
     *
     * @param requestCode The request code passed in {@link #requestPermissions}.
     * @param permissions The requested permissions. Never null.
     * @param grantResults The grant results for the corresponding permissions which is either
     *                     {@link android.content.pm.PackageManager#PERMISSION_GRANTED} or
     *                     {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null.
     * @param deviceId The deviceId for which permissions were requested. The primary/physical
     *                 device is assigned {@link Context#DEVICE_ID_DEFAULT}, and {@link
     *                 android.companion.virtual.VirtualDeviceManager.VirtualDevice virtual devices}
     *                 are assigned unique device Ids.
     *
     * @see #requestPermissions
     */
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults, int deviceId) {
        onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    /**
    /**
     * Gets whether you should show UI with rationale before requesting a permission.
     * Gets whether you should show UI with rationale before requesting a permission.
     *
     *
     * @param permission A permission your app wants to request.
     * @param permission A permission your app wants to request.
     * @return Whether you should show permission rationale UI.
     * @return Whether you should show permission rationale UI.
     *
     *
     * @see #checkSelfPermission(String)
     * @see #checkSelfPermission
     * @see #requestPermissions(String[], int)
     * @see #requestPermissions
     * @see #onRequestPermissionsResult(int, String[], int[])
     * @see #onRequestPermissionsResult
     */
     */
    public boolean shouldShowRequestPermissionRationale(@NonNull String permission) {
    public boolean shouldShowRequestPermissionRationale(@NonNull String permission) {
        return getPackageManager().shouldShowRequestPermissionRationale(permission);
        return getPackageManager().shouldShowRequestPermissionRationale(permission);
    }
    }


    /**
     * Gets whether you should show UI with rationale before requesting a permission.
     *
     * @param permission A permission your app wants to request.
     * @param deviceId The app is requesting permissions for this device. The primary/physical
     *                 device is assigned {@link Context#DEVICE_ID_DEFAULT}, and {@link
     *                 android.companion.virtual.VirtualDeviceManager.VirtualDevice virtual devices}
     *                 are assigned unique device Ids.
     * @return Whether you should show permission rationale UI.
     *
     * @see #checkSelfPermission
     * @see #requestPermissions
     * @see #onRequestPermissionsResult
     */
    public boolean shouldShowRequestPermissionRationale(@NonNull String permission, int deviceId) {
        final PackageManager packageManager = getDeviceId() == deviceId ? getPackageManager()
                : createDeviceContext(deviceId).getPackageManager();
        return packageManager.shouldShowRequestPermissionRationale(permission);
    }

    /**
    /**
     * Same as calling {@link #startActivityForResult(Intent, int, Bundle)}
     * Same as calling {@link #startActivityForResult(Intent, int, Bundle)}
     * with no options.
     * with no options.
@@ -9107,12 +9225,15 @@ public class Activity extends ContextThemeWrapper


    private void dispatchRequestPermissionsResult(int requestCode, Intent data) {
    private void dispatchRequestPermissionsResult(int requestCode, Intent data) {
        mHasCurrentPermissionsRequest = false;
        mHasCurrentPermissionsRequest = false;
        // If the package installer crashed we may have not data - best effort.
        // If the package installer crashed we may have no data - best effort.
        String[] permissions = (data != null) ? data.getStringArrayExtra(
        String[] permissions = (data != null) ? data.getStringArrayExtra(
                PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES) : new String[0];
                PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES) : new String[0];
        final int[] grantResults = (data != null) ? data.getIntArrayExtra(
        final int[] grantResults = (data != null) ? data.getIntArrayExtra(
                PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS) : new int[0];
                PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS) : new int[0];
        onRequestPermissionsResult(requestCode, permissions, grantResults);
        final int deviceId = (data != null) ? data.getIntExtra(
                PackageManager.EXTRA_REQUEST_PERMISSIONS_DEVICE_ID, Context.DEVICE_ID_DEFAULT
        ) : Context.DEVICE_ID_DEFAULT;
        onRequestPermissionsResult(requestCode, permissions, grantResults, deviceId);
    }
    }


    private void dispatchRequestPermissionsResultToFragment(int requestCode, Intent data,
    private void dispatchRequestPermissionsResultToFragment(int requestCode, Intent data,
+7 −0
Original line number Original line Diff line number Diff line
@@ -941,6 +941,13 @@ public class ApplicationPackageManager extends PackageManager {
        return getPermissionManager().shouldShowRequestPermissionRationale(permName);
        return getPermissionManager().shouldShowRequestPermissionRationale(permName);
    }
    }


    @Override
    public Intent buildRequestPermissionsIntent(@NonNull String[] permissions) {
        Intent intent = super.buildRequestPermissionsIntent(permissions);
        intent.putExtra(EXTRA_REQUEST_PERMISSIONS_DEVICE_ID, mContext.getDeviceId());
        return intent;
    }

    @Override
    @Override
    public CharSequence getBackgroundPermissionOptionLabel() {
    public CharSequence getBackgroundPermissionOptionLabel() {
        try {
        try {
+14 −1
Original line number Original line Diff line number Diff line
@@ -4611,6 +4611,19 @@ public abstract class PackageManager {
    public static final String EXTRA_REQUEST_PERMISSIONS_NAMES =
    public static final String EXTRA_REQUEST_PERMISSIONS_NAMES =
            "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
            "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";


    /**
     * The deviceId for which the permissions are requested, {@link Context#DEVICE_ID_DEFAULT}
     * is the default device ID.
     * <p>
     * <strong>Type:</strong> int
     * </p>
     *
     * @hide
     */
    @SystemApi
    public static final String EXTRA_REQUEST_PERMISSIONS_DEVICE_ID =
            "android.content.pm.extra.REQUEST_PERMISSIONS_DEVICE_ID";

    /**
    /**
     * The results from the permissions request.
     * The results from the permissions request.
     * <p>
     * <p>