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

Commit b20a16b1 authored by Hai Zhang's avatar Hai Zhang
Browse files

Add special app access UI based on roles.

This change adds the special app access UI based on roles.

Bug: 110557011
Test: manual
Change-Id: Ibd277d3d7a004ecd827a4a8f068f76526d9a0e3f
parent 466e3f80
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -155,6 +155,20 @@
        <activity android:name="com.android.packageinstaller.role.ui.DefaultAppActivity"
                  android:theme="@style/Settings" />

        <activity android:name="com.android.packageinstaller.role.ui.SpecialAppAccessListActivity"
                  android:label="@string/special_app_access"
                  android:permission="android.permission.MANAGE_ROLE_HOLDERS"
                  android:theme="@style/Settings">
            <intent-filter android:priority="1">
                <action android:name="android.intent.action.MANAGE_SPECIAL_APP_ACCESSES" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <!-- TODO: STOPSHIP: Override other Settings intents. -->
        <activity android:name="com.android.packageinstaller.role.ui.SpecialAppAccessActivity"
                  android:theme="@style/Settings" />

        <provider android:name="com.android.packageinstaller.permission.service.PermissionSearchIndexablesProvider"
            android:authorities="com.android.permissioncontroller"
            android:multiprocess="false"
+13 −0
Original line number Diff line number Diff line
@@ -504,6 +504,19 @@
    <!-- Label when there are no apps available for a default app [CHAR LIMIT=30] -->
    <string name="default_app_no_apps">No apps</string>

    <!-- Title for page of managing special app access. [CHAR LIMIT=30] -->
    <string name="special_app_access">Special app access</string>

    <!-- TODO: STOPSHIP: I cannot find its value in Settings. -->
    <!-- Help URI, special app access [DO NOT TRANSLATE] -->
    <string name="help_uri_special_app_access" translatable="false"></string>

    <!-- Label when there is no special app access [CHAR LIMIT=30] -->
    <string name="no_special_app_access">No special app access</string>

    <!-- Label when there are no apps available for a special app access [CHAR LIMIT=30] -->
    <string name="special_app_access_no_apps">No apps</string>

    <!-- TODO: STOPSHIP: Migrate all default app titles from packages/apps/Settings/res/values/strings.xml . -->

    <!-- Label for the dialer role. [CHAR LIMIT=30] -->
+72 −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.ui;

import android.content.Context;
import android.util.AttributeSet;

import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreference;

/**
 * {@link SwitchPreference} with {@link AppIconPreference.Mixin}.
 */
public class AppIconSwitchPreference extends SwitchPreference {

    private AppIconPreference.Mixin mMixin;

    public AppIconSwitchPreference(@NonNull Context context) {
        super(context);

        init();
    }

    public AppIconSwitchPreference(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        init();
    }

    public AppIconSwitchPreference(@NonNull Context context, @Nullable AttributeSet attrs,
            @AttrRes int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init();
    }

    public AppIconSwitchPreference(@NonNull Context context, @Nullable AttributeSet attrs,
            @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        init();
    }

    private void init() {
        mMixin = new AppIconPreference.Mixin(getContext());
    }

    @Override
    public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
        super.onBindViewHolder(holder);

        mMixin.onBindViewHolder(holder);
    }
}
+24 −26
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -32,7 +33,6 @@ import androidx.lifecycle.ViewModelProviders;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.TwoStatePreference;

import com.android.packageinstaller.permission.utils.IconDrawableFactory;
import com.android.packageinstaller.permission.utils.Utils;
@@ -99,8 +99,9 @@ public class DefaultAppFragment extends SettingsFragment

        mViewModel = ViewModelProviders.of(this, new DefaultAppViewModel.Factory(mRole, mUser,
                activity.getApplication())).get(DefaultAppViewModel.class);
        mViewModel.getRoleLiveData().observe(this, this::onRoleInfoChanged);
        mViewModel.getAddRoleHolderStateLiveData().observe(this, this::onAddRoleHolderStateChanged);
        mViewModel.getRoleLiveData().observe(this, this::onRoleChanged);
        mViewModel.getManageRoleHolderStateLiveData().observe(this,
                this::onManageRoleHolderStateChanged);
    }

    @Override
@@ -109,7 +110,8 @@ public class DefaultAppFragment extends SettingsFragment
        return R.string.default_app_no_apps;
    }

    private void onRoleInfoChanged(@NonNull RoleInfo roleInfo) {
    private void onRoleChanged(
            @NonNull List<Pair<ApplicationInfo, Boolean>> qualifyingApplications) {
        PreferenceManager preferenceManager = getPreferenceManager();
        Context context = preferenceManager.getContext();

@@ -127,16 +129,15 @@ public class DefaultAppFragment extends SettingsFragment
            }
        }

        List<ApplicationInfo> qualifyingApplicationInfos = roleInfo.getQualifyingApplicationInfos();
        List<String> holderPackageNames = roleInfo.getHolderPackageNames();
        int qualifyingApplicationInfosSize = qualifyingApplicationInfos.size();
        for (int i = 0; i < qualifyingApplicationInfosSize; i++) {
            ApplicationInfo qualifyingApplicationInfo = qualifyingApplicationInfos.get(i);
        int qualifyingApplicationsSize = qualifyingApplications.size();
        for (int i = 0; i < qualifyingApplicationsSize; i++) {
            Pair<ApplicationInfo, Boolean> qualifyingApplication = qualifyingApplications.get(i);
            ApplicationInfo qualifyingApplicationInfo = qualifyingApplication.first;
            boolean isHolderPackage = qualifyingApplication.second;

            TwoStatePreference preference = (TwoStatePreference) oldPreferences.get(
                    qualifyingApplicationInfo.packageName);
            AppIconRadioButtonPreference preference = (AppIconRadioButtonPreference)
                    oldPreferences.get(qualifyingApplicationInfo.packageName);
            if (preference == null) {
                // TODO: STOPSHIP: Support multiple role holders.
                preference = new AppIconRadioButtonPreference(context);
                preference.setKey(qualifyingApplicationInfo.packageName);
                preference.setIcon(IconDrawableFactory.getBadgedIcon(context,
@@ -144,11 +145,11 @@ public class DefaultAppFragment extends SettingsFragment
                                qualifyingApplicationInfo.uid)));
                preference.setTitle(Utils.getAppLabel(qualifyingApplicationInfo, context));
                preference.setPersistent(false);
                preference.setOnPreferenceChangeListener((preference2, newValue) -> false);
                preference.setOnPreferenceClickListener(this);
            }

            preference.setChecked(holderPackageNames.contains(
                    qualifyingApplicationInfo.packageName));
            preference.setChecked(isHolderPackage);

            // TODO: Ordering?
            preferenceScreen.addPreference(preference);
@@ -157,32 +158,29 @@ public class DefaultAppFragment extends SettingsFragment
        updateState();
    }

    private void onAddRoleHolderStateChanged(int state) {
        AddRoleHolderStateLiveData addRoleHolderStateLiveData =
                mViewModel.getAddRoleHolderStateLiveData();
    private void onManageRoleHolderStateChanged(int state) {
        ManageRoleHolderStateLiveData liveData = mViewModel.getManageRoleHolderStateLiveData();
        switch (state) {
            case AddRoleHolderStateLiveData.STATE_SUCCESS:
                addRoleHolderStateLiveData.resetState();
            case ManageRoleHolderStateLiveData.STATE_SUCCESS:
                liveData.resetState();
                break;
            case AddRoleHolderStateLiveData.STATE_FAILURE:
            case ManageRoleHolderStateLiveData.STATE_FAILURE:
                // TODO: STOPSHIP: Notify user.
                addRoleHolderStateLiveData.resetState();
                liveData.resetState();
                break;
        }
    }

    @Override
    public boolean onPreferenceClick(@NonNull Preference preference) {
        AddRoleHolderStateLiveData addRoleHolderStateLiveData =
                mViewModel.getAddRoleHolderStateLiveData();
        if (addRoleHolderStateLiveData.getValue() != AddRoleHolderStateLiveData.STATE_IDLE) {
        ManageRoleHolderStateLiveData liveData = mViewModel.getManageRoleHolderStateLiveData();
        if (liveData.getValue() != ManageRoleHolderStateLiveData.STATE_IDLE) {
            Log.i(LOG_TAG, "Trying to set default app while another request is on-going");
            return true;
        }

        String packageName = preference.getKey();
        addRoleHolderStateLiveData.addRoleHolderAsUser(mRoleName, packageName, mUser,
                requireContext());
        liveData.manageRoleHolderAsUser(mRoleName, packageName, mUser, true, requireContext());
        return true;
    }
}
+2 −3
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ public class DefaultAppListFragment extends SettingsFragment

    private static final String PREFERENCE_KEY_WORK_CATEGORY = "work_category";

    private RoleListViewModel mViewModel;
    private DefaultAppListViewModel mViewModel;

    /**
     * Create a new instance of this fragment.
@@ -66,8 +66,7 @@ public class DefaultAppListFragment extends SettingsFragment
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mViewModel = ViewModelProviders.of(this, new RoleListViewModel.Factory(true,
                requireActivity().getApplication())).get(RoleListViewModel.class);
        mViewModel = ViewModelProviders.of(this).get(DefaultAppListViewModel.class);
        mViewModel.getLiveData().observe(this, roleItems -> onRoleListChanged());
        if (mViewModel.hasWorkProfile()) {
            mViewModel.getWorkLiveData().observe(this, roleItems -> onRoleListChanged());
Loading