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

Commit 64a3e702 authored by Hai Zhang's avatar Hai Zhang
Browse files

Add don't ask again when requesting role.

Bug: 128713569
Test: manual
Change-Id: I9e870655feaa2b7bb2c6824214e7e8e24b179a00
parent 059640e4
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -272,6 +272,14 @@
            </intent-filter>
        </service>

        <receiver android:name="com.android.packageinstaller.role.service.ClearUserDeniedReceiver">
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
                <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED"/>
                <data android:scheme="package" />
            </intent-filter>
        </receiver>

        <!-- Debug report authorization (bugreport and incident report) -->
        <receiver android:name="com.android.packageinstaller.incident.ConfirmationReceiver"
            android:exported="true">
+5 −1
Original line number Diff line number Diff line
@@ -30,7 +30,8 @@
    <ImageView
        android:id="@+id/icon"
        android:layout_width="32dp"
        android:layout_height="32dp" />
        android:layout_height="32dp"
        android:duplicateParentState="true" />

    <LinearLayout
        android:id="@+id/title_and_subtitle"
@@ -39,12 +40,14 @@
        android:layout_weight="1"
        android:layout_marginStart="16dp"
        android:animateLayoutChanges="true"
        android:duplicateParentState="true"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:duplicateParentState="true"
            android:textAppearance="?android:textAppearanceListItem"
            android:textColor="?android:textColorAlertDialogListItem"
            android:singleLine="true"
@@ -54,6 +57,7 @@
            android:id="@+id/subtitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:duplicateParentState="true"
            android:textAppearance="?android:textAppearanceListItemSecondary"
            android:textColor="?android:textColorSecondary" />
    </LinearLayout>
+36 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>

<!--
  ~ Copyright (C) 2019 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.
  -->

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingStart="?android:dialogPreferredPadding"
    android:paddingEnd="?android:dialogPreferredPadding"
    android:clipChildren="false"
    android:clipToPadding="false">

    <CheckBox
        android:id="@+id/dont_ask_again"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="40dp"
        android:paddingStart="16dp"
        android:text="@string/request_role_dont_ask_again"
        android:textAppearance="@style/android:TextAppearance.Material.Subhead" />
</FrameLayout>
+17 −0
Original line number Diff line number Diff line
@@ -118,4 +118,21 @@ public class Constants {
     * yet.
     */
    public static final String DELAYED_RESTORE_PERMISSIONS_FILE = "delayed_restore_permissions.xml";

    /**
     * Name of file containing the user denied status for requesting roles.
     */
    public static final String REQUEST_ROLE_USER_DENIED_FILE = "request_role_user_denied";

    /**
     * Key in the user denied status for requesting roles shared preferences that stores a string
     * set for the names of the roles that an application has been denied for once.
     */
    public static final String REQUEST_ROLE_USER_DENIED_ONCE_KEY_PREFIX = "denied_once:";

    /**
     * Key in the user denied status for requesting roles shared preferences that stores a string
     * set for the names of the roles that an application is always denied for.
     */
    public static final String REQUEST_ROLE_USER_DENIED_ALWAYS_KEY_PREFIX = "denied_always:";
}
+160 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 com.android.packageinstaller.role.model;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.ArraySet;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.packageinstaller.Constants;

import java.util.Collections;
import java.util.Set;

/**
 * Manages user denied status for requesting roles.
 */
public class UserDeniedManager {

    @Nullable
    private static UserDeniedManager sInstance;

    private final SharedPreferences mPreferences;

    /**
     * Get a singleton instance of this class
     *
     * @param context the context for retrieving shared preferences.
     *
     * @return the singleton instance of this class
     */
    @NonNull
    public static UserDeniedManager getInstance(@NonNull Context context) {
        if (sInstance == null) {
            sInstance = new UserDeniedManager(context);
        }
        return sInstance;
    }

    private UserDeniedManager(@NonNull Context context) {
        context = context.getApplicationContext();
        mPreferences = context.getSharedPreferences(Constants.REQUEST_ROLE_USER_DENIED_FILE,
                Context.MODE_PRIVATE);
    }

    /**
     * Check whether an application has been denied for a role once.
     *
     * @param roleName the name of the role
     * @param packageName the package name of the application
     *
     * @return whether the application has been denied for the role once
     */
    public boolean isDeniedOnce(@NonNull String roleName, @NonNull String packageName) {
        return isDenied(roleName, packageName, false);
    }

    /**
     * Remember that an application has been denied for a role once.
     *
     * @param roleName the name of the role
     * @param packageName the package name of the application
     */
    public void setDeniedOnce(@NonNull String roleName, @NonNull String packageName) {
        setDenied(roleName, packageName, false, true);
    }

    /**
     * Check whether an application is always denied for a role.
     *
     * @param roleName the name of the role
     * @param packageName the package name of the application
     *
     * @return whether the application is always denied for the role
     */
    public boolean isDeniedAlways(@NonNull String roleName, @NonNull String packageName) {
        return isDenied(roleName, packageName, true);
    }

    /**
     * Remember that an application is always denied for a role.
     *
     * @param roleName the name of the role
     * @param packageName the package name of the application
     */
    public void setDeniedAlways(@NonNull String roleName, @NonNull String packageName) {
        setDenied(roleName, packageName, true, true);
    }

    /**
     * Forget about whether an application is denied for a role, once or always.
     *
     * @param roleName the name of the role
     * @param packageName the package name of the application
     */
    public void clearDenied(@NonNull String roleName, @NonNull String packageName) {
        setDenied(roleName, packageName, false, false);
        setDenied(roleName, packageName, true, false);
    }

    /**
     * Forget about whether an application is denied for any of the roles, once or always.
     *
     * @param packageName the package name of the application
     */
    public void clearPackageDenied(@NonNull String packageName) {
        mPreferences.edit()
                .remove(getKey(packageName, false))
                .remove(getKey(packageName, true))
                .apply();
    }

    @NonNull
    private static String getKey(@NonNull String packageName, boolean always) {
        return (always ? Constants.REQUEST_ROLE_USER_DENIED_ALWAYS_KEY_PREFIX
                : Constants.REQUEST_ROLE_USER_DENIED_ONCE_KEY_PREFIX) + packageName;
    }

    private boolean isDenied(@NonNull String roleName, @NonNull String packageName,
            boolean always) {
        String key = getKey(packageName, always);
        return mPreferences.getStringSet(key, Collections.emptySet()).contains(roleName);
    }

    private void setDenied(@NonNull String roleName, @NonNull String packageName, boolean always,
            boolean denied) {
        String key = getKey(packageName, always);
        Set<String> roleNames = mPreferences.getStringSet(key, Collections.emptySet());
        if (roleNames.contains(roleName) == denied) {
            return;
        }
        roleNames = new ArraySet<>(roleNames);
        if (denied) {
            roleNames.add(roleName);
        } else {
            roleNames.remove(roleName);
        }
        if (roleName.isEmpty()) {
            mPreferences.edit().remove(key).apply();
        } else {
            mPreferences.edit().putStringSet(key, roleNames).apply();
        }
    }
}
Loading