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

Commit 4883f3b6 authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

Fall back to default assistant

If an alterante assistant is seleceted and gets uninstalled, we want to
fall back to the default assistant. We still want to support the user
choose to explicitly selecting no assistant at all.

From the system perspective there is no difference between "the user
choose to not select a role holder" and "try to fall back to a role
holder". The permission controller stores the difference between these
choices in a shared preference and checks it when appropriate.

Test: - Selected alternate assistant and removed it -> default assistant
        was chosen
      - Selected no assistant -> settings was honored
      - Selected no assistant and triggered grantDefaultRoles -> no
        change
Bug: 110557011
Change-Id: I8b0c541e2d2483f3232e3cbe86caefb3a7bf600c
parent 4f85de48
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -63,4 +63,10 @@ public class Constants {
     */
    public static final String KEY_LAST_LOCATION_ACCESS_NOTIFICATION_SHOWN =
            "last_location_access_notification_shown";

    /**
     * Key in the generic shared preferences that stores if the user manually selected the "none"
     * role holder for a role.
     */
    public static final String IS_NONE_ROLE_HOLDER_SELECTED_KEY = "is_none_role_holder_selected:";
}
+9 −3
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

@@ -69,12 +68,19 @@ public class AssistantRoleBehavior implements RoleBehavior {
    @NonNull
    @Override
    public List<String> getDefaultHolders(@NonNull Role role, @NonNull Context context) {
        return CollectionUtils.singletonOrEmpty(getFallbackHolder(role, context));
    }

    @Nullable
    @Override
    public String getFallbackHolder(@NonNull Role role, @NonNull Context context) {
        String defaultPackageName = CollectionUtils.firstOrNull(DefaultRoleHolders.get(context).get(
                role.getName()));
        if (defaultPackageName == null || !isPackageQualified(role, defaultPackageName, context)) {
            return Collections.emptyList();
            return null;
        }
        return Collections.singletonList(defaultPackageName);

        return defaultPackageName;
    }

    @Nullable
+40 −1
Original line number Diff line number Diff line
@@ -31,7 +31,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;

import com.android.packageinstaller.Constants;
import com.android.packageinstaller.role.utils.PackageUtils;
import com.android.packageinstaller.role.utils.UserUtils;

import java.util.ArrayList;
import java.util.Collections;
@@ -230,7 +232,7 @@ public class Role {
     */
    @Nullable
    public String getFallbackHolder(@NonNull Context context) {
        if (mBehavior != null) {
        if (mBehavior != null && !isNoneHolderSelected(context)) {
            return mBehavior.getFallbackHolder(this, context);
        }
        return null;
@@ -499,6 +501,43 @@ public class Role {
        activityManager.killUid(applicationInfo.uid, "Permission or app op changed");
    }

    /**
     * Did the user selected the "none" role holder.
     *
     * @param context A context to use
     *
     * @return {@code true} iff the user selected the "none" role holder
     */
    private boolean isNoneHolderSelected(@NonNull Context context) {
        return context.getSharedPreferences(Constants.PREFERENCES_FILE, Context.MODE_PRIVATE)
                .getBoolean(Constants.IS_NONE_ROLE_HOLDER_SELECTED_KEY + mName, false);
    }

    /**
     * Indicate that the any other holder than "none" was selected.
     *
     * @param context A context to use
     * @param user the user the role belongs to
     */
    public void onHolderSelectedAsUser(@NonNull Context context, @NonNull UserHandle user) {
        UserUtils.getUserContext(context, user)
                .getSharedPreferences(Constants.PREFERENCES_FILE, Context.MODE_PRIVATE)
                .edit().remove(Constants.IS_NONE_ROLE_HOLDER_SELECTED_KEY + mName).apply();
    }

    /**
     * Indicate that the "none" role holder was selected.
     *
     * @param context A context to use
     * @param user the user the role belongs to
     */
    public void onNoneHolderSelectedAsUser(@NonNull Context context, @NonNull UserHandle user) {
        UserUtils.getUserContext(context, user)
                .getSharedPreferences(Constants.PREFERENCES_FILE, Context.MODE_PRIVATE)
                .edit().putBoolean(Constants.IS_NONE_ROLE_HOLDER_SELECTED_KEY + mName, true)
                .apply();
    }

    @Override
    public String toString() {
        return "Role{"
+3 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.app.role.RoleManagerCallback;
import android.content.pm.ApplicationInfo;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.os.UserHandle;
import android.rolecontrollerservice.RoleControllerService;
import android.text.TextUtils;
@@ -301,6 +302,8 @@ public class RoleControllerServiceImpl extends RoleControllerService {
            return;
        }

        role.onHolderSelectedAsUser(this, Process.myUserHandle());

        callback.onSuccess();
    }

+4 −2
Original line number Diff line number Diff line
@@ -207,7 +207,7 @@ public class DefaultAppFragment extends SettingsFragment
    public boolean onPreferenceClick(@NonNull Preference preference) {
        String key = preference.getKey();
        if (Objects.equals(key, PREFERENCE_KEY_NONE)) {
            clearDefaultApp();
            setNoneDefaultApp();
        } else {
            String packageName = key;
            CharSequence confirmationMessage = mRole.getConfirmationMessage(packageName,
@@ -231,7 +231,9 @@ public class DefaultAppFragment extends SettingsFragment
        liveData.setRoleHolderAsUser(mRoleName, packageName, true, mUser, requireContext());
    }

    private void clearDefaultApp() {
    private void setNoneDefaultApp() {
        mRole.onNoneHolderSelectedAsUser(requireContext(), mUser);

        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");
Loading