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

Commit ad79ec6a authored by Hai Zhang's avatar Hai Zhang Committed by Heemin Seog
Browse files

Separate business logic and UI detail for default app settings.

By moving the role-related business logic into a child fragment. This
way we can re-use it for any form factor.

The refactor for special app access will come in a later CL.

Bug: 124452117
Test: manual
Change-Id: Ie28ce756452277992d5f22839e17a70d41f05676
parent f7b94b09
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ import androidx.annotation.Nullable;
import androidx.preference.Preference;

import com.android.packageinstaller.permission.utils.CollectionUtils;
import com.android.packageinstaller.role.ui.SettingsButtonPreference;
import com.android.packageinstaller.role.ui.TwoTargetPreference;
import com.android.packageinstaller.role.utils.UserUtils;
import com.android.permissioncontroller.R;

@@ -99,10 +99,9 @@ public class HomeRoleBehavior implements RoleBehavior {
    }

    @Override
    public void preparePreferenceAsUser(@NonNull Role role,
            @NonNull SettingsButtonPreference preference, @NonNull UserHandle user,
            @NonNull Context context) {
        SettingsButtonPreference.OnSettingsButtonClickListener listener = null;
    public void preparePreferenceAsUser(@NonNull Role role, @NonNull TwoTargetPreference preference,
            @NonNull UserHandle user, @NonNull Context context) {
        TwoTargetPreference.OnSecondTargetClickListener listener = null;
        RoleManager roleManager = context.getSystemService(RoleManager.class);
        String packageName = CollectionUtils.firstOrNull(roleManager.getRoleHoldersAsUser(
                role.getName(), user));
@@ -123,7 +122,7 @@ public class HomeRoleBehavior implements RoleBehavior {
                };
            }
        }
        preference.setOnSettingsButtonClickListener(listener);
        preference.setOnSecondTargetClickListener(listener);
    }

    @Override
+2 −2
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ import androidx.preference.Preference;

import com.android.packageinstaller.Constants;
import com.android.packageinstaller.permission.utils.Utils;
import com.android.packageinstaller.role.ui.SettingsButtonPreference;
import com.android.packageinstaller.role.ui.TwoTargetPreference;
import com.android.packageinstaller.role.utils.PackageUtils;
import com.android.packageinstaller.role.utils.UserUtils;

@@ -361,7 +361,7 @@ public class Role {
     * @param user the user for this role
     * @param context the {@code Context} to retrieve system services
     */
    public void preparePreferenceAsUser(@NonNull SettingsButtonPreference preference,
    public void preparePreferenceAsUser(@NonNull TwoTargetPreference preference,
            @NonNull UserHandle user, @NonNull Context context) {
        if (mBehavior != null) {
            mBehavior.preparePreferenceAsUser(this, preference, user, context);
+3 −3
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;

import com.android.packageinstaller.role.ui.SettingsButtonPreference;
import com.android.packageinstaller.role.ui.TwoTargetPreference;

import java.util.Collections;
import java.util.List;
@@ -77,10 +77,10 @@ public interface RoleBehavior {
    }

    /**
     * @see Role#preparePreferenceAsUser(SettingsButtonPreference, UserHandle, Context)
     * @see Role#preparePreferenceAsUser(TwoTargetPreference, UserHandle, Context)
     */
    default void preparePreferenceAsUser(@NonNull Role role,
            @NonNull SettingsButtonPreference preference, @NonNull UserHandle user,
            @NonNull TwoTargetPreference preference, @NonNull UserHandle user,
            @NonNull Context context) {}

    /**
+3 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import androidx.fragment.app.FragmentActivity;

import com.android.packageinstaller.role.model.Role;
import com.android.packageinstaller.role.model.Roles;
import com.android.packageinstaller.role.ui.handheld.HandheldDefaultAppFragment;

/**
 * Activity for a default app.
@@ -88,7 +89,8 @@ public class DefaultAppActivity extends FragmentActivity {
        }

        if (savedInstanceState == null) {
            DefaultAppFragment fragment = DefaultAppFragment.newInstance(roleName, user);
            HandheldDefaultAppFragment fragment = HandheldDefaultAppFragment.newInstance(roleName,
                    user);
            getSupportFragmentManager().beginTransaction()
                    .add(android.R.id.content, fragment)
                    .commit();
+67 −40
Original line number Diff line number Diff line
@@ -24,17 +24,18 @@ import android.graphics.drawable.Drawable;
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;
import androidx.annotation.StringRes;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.TwoStatePreference;

import com.android.packageinstaller.permission.utils.Utils;
import com.android.packageinstaller.role.model.Role;
@@ -45,18 +46,20 @@ import java.util.List;
import java.util.Objects;

/**
 * Fragment for a default app.
 * Child fragment for a default app. Must be added as a child fragment and its parent fragment must
 * be a {@link PreferenceFragmentCompat} which implements {@link Parent}.
 *
 * @param <PF> type of the parent fragment
 */
public class DefaultAppFragment extends SettingsFragment
public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat
        & DefaultAppChildFragment.Parent> extends Fragment
        implements DefaultAppConfirmationDialogFragment.Listener,
        Preference.OnPreferenceClickListener {

    private static final String LOG_TAG = DefaultAppFragment.class.getSimpleName();

    private static final String PREFERENCE_KEY_NONE = DefaultAppFragment.class.getName()
    private static final String PREFERENCE_KEY_NONE = DefaultAppChildFragment.class.getName()
            + ".preference.NONE";

    private static final String PREFERENCE_KEY_DESCRIPTION = DefaultAppFragment.class.getName()
    private static final String PREFERENCE_KEY_DESCRIPTION = DefaultAppChildFragment.class.getName()
            + ".preference.DESCRIPTION";

    private String mRoleName;
@@ -76,9 +79,9 @@ public class DefaultAppFragment extends SettingsFragment
     * @return a new instance of this fragment
     */
    @NonNull
    public static DefaultAppFragment newInstance(@NonNull String roleName,
    public static DefaultAppChildFragment newInstance(@NonNull String roleName,
            @NonNull UserHandle user) {
        DefaultAppFragment fragment = new DefaultAppFragment();
        DefaultAppChildFragment fragment = new DefaultAppChildFragment();
        Bundle arguments = new Bundle();
        arguments.putString(Intent.EXTRA_ROLE_NAME, roleName);
        arguments.putParcelable(Intent.EXTRA_USER, user);
@@ -99,9 +102,10 @@ public class DefaultAppFragment extends SettingsFragment
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        PF preferenceFragment = requirePreferenceFragment();
        Activity activity = requireActivity();
        mRole = Roles.get(activity).get(mRoleName);
        activity.setTitle(mRole.getLabelResource());
        preferenceFragment.setTitle(getString(mRole.getLabelResource()));

        mViewModel = ViewModelProviders.of(this, new DefaultAppViewModel.Factory(mRole, mUser,
                activity.getApplication())).get(DefaultAppViewModel.class);
@@ -110,23 +114,18 @@ public class DefaultAppFragment extends SettingsFragment
                this::onManageRoleHolderStateChanged);
    }

    @Override
    @StringRes
    protected int getEmptyTextResource() {
        return R.string.default_app_no_apps;
    }

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

        PreferenceScreen preferenceScreen = getPreferenceScreen();
        PreferenceScreen preferenceScreen = preferenceFragment.getPreferenceScreen();
        Preference oldDescriptionPreference = null;
        ArrayMap<String, Preference> oldPreferences = new ArrayMap<>();
        if (preferenceScreen == null) {
            preferenceScreen = preferenceManager.createPreferenceScreen(context);
            setPreferenceScreen(preferenceScreen);
            preferenceFragment.setPreferenceScreen(preferenceScreen);
        } else {
            oldDescriptionPreference = preferenceScreen.findPreference(PREFERENCE_KEY_DESCRIPTION);
            for (int i = preferenceScreen.getPreferenceCount() - 1; i >= 0; --i) {
@@ -160,13 +159,13 @@ public class DefaultAppFragment extends SettingsFragment

        Preference descriptionPreference = oldDescriptionPreference;
        if (descriptionPreference == null) {
            descriptionPreference = new FooterPreference(context);
            descriptionPreference = preferenceFragment.createFooterPreference(context);
            descriptionPreference.setKey(PREFERENCE_KEY_DESCRIPTION);
            descriptionPreference.setSummary(mRole.getDescriptionResource());
        }
        preferenceScreen.addPreference(descriptionPreference);

        updateState();
        preferenceFragment.onPreferenceScreenChanged();
    }

    private static boolean hasHolderApplication(
@@ -187,10 +186,9 @@ public class DefaultAppFragment extends SettingsFragment
            @NonNull CharSequence title, boolean checked, @Nullable ApplicationInfo applicationInfo,
            @NonNull ArrayMap<String, Preference> oldPreferences,
            @NonNull PreferenceScreen preferenceScreen, @NonNull Context context) {
        AppIconRadioButtonPreference preference = (AppIconRadioButtonPreference) oldPreferences.get(
                key);
        TwoStatePreference preference = (TwoStatePreference) oldPreferences.get(key);
        if (preference == null) {
            preference = new AppIconRadioButtonPreference(context);
            preference = requirePreferenceFragment().createApplicationPreference(context);
            preference.setKey(key);
            preference.setIcon(icon);
            preference.setTitle(title);
@@ -229,7 +227,7 @@ public class DefaultAppFragment extends SettingsFragment
    public boolean onPreferenceClick(@NonNull Preference preference) {
        String key = preference.getKey();
        if (Objects.equals(key, PREFERENCE_KEY_NONE)) {
            setNoneDefaultApp();
            mViewModel.setNoneDefaultApp();
        } else {
            String packageName = key;
            CharSequence confirmationMessage = mRole.getConfirmationMessage(packageName,
@@ -245,22 +243,51 @@ public class DefaultAppFragment extends SettingsFragment

    @Override
    public void setDefaultApp(@NonNull String packageName) {
        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;
        mViewModel.setDefaultApp(packageName);
    }
        liveData.setRoleHolderAsUser(mRoleName, packageName, true, 0, mUser, requireContext());

    @NonNull
    private PF requirePreferenceFragment() {
        //noinspection unchecked
        return (PF) requireParentFragment();
    }

    private void setNoneDefaultApp() {
        mRole.onNoneHolderSelectedAsUser(mUser, requireContext());
    /**
     * Interface that the parent fragment must implement.
     */
    public interface Parent {

        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;
        }
        liveData.clearRoleHoldersAsUser(mRoleName, 0, mUser, requireContext());
        /**
         * Set the title of the current settings page.
         *
         * @param title the title of the current settings page
         */
        void setTitle(@NonNull CharSequence title);

        /**
         * Create a new preference for an application.
         *
         * @param context the {@code Context} to use when creating the preference.
         *
         * @return a new preference for an application
         */
        @NonNull
        TwoStatePreference createApplicationPreference(@NonNull Context context);

        /**
         * Create a new preference for the footer.
         *
         * @param context the {@code Context} to use when creating the preference.
         *
         * @return a new preference for the footer
         */
        @NonNull
        Preference createFooterPreference(@NonNull Context context);

        /**
         * Callback when changes have been made to the {@link PreferenceScreen} of the parent
         * {@link PreferenceFragmentCompat}.
         */
        void onPreferenceScreenChanged();
    }
}
Loading