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

Commit 72dd0556 authored by James Willcox's avatar James Willcox
Browse files

Support cross-profile Wallet role in QuickAccessWalletClient

Bug: 356107987
Test: atest QuickAccessWalletClientTest
Flag: android.permission.flags.wallet_role_cross_user_enabled
Change-Id: I6f1be37d812cd052cd6d79ece6f9d48588401288
parent cc63b2fa
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -65,13 +65,13 @@ aconfig_declarations_group {
        "android.sdk.flags-aconfig-java",
        "android.security.flags-aconfig-java",
        "android.server.app.flags-aconfig-java",
        "android.service.appprediction.flags-aconfig-java",
        "android.service.autofill.flags-aconfig-java",
        "android.service.chooser.flags-aconfig-java",
        "android.service.compat.flags-aconfig-java",
        "android.service.controls.flags-aconfig-java",
        "android.service.dreams.flags-aconfig-java",
        "android.service.notification.flags-aconfig-java",
        "android.service.appprediction.flags-aconfig-java",
        "android.service.quickaccesswallet.flags-aconfig-java",
        "android.service.voice.flags-aconfig-java",
        "android.speech.flags-aconfig-java",
@@ -102,6 +102,7 @@ aconfig_declarations_group {
        "com.android.media.flags.projection-aconfig-java",
        "com.android.net.http.flags-aconfig-exported-java",
        "com.android.net.thread.platform.flags-aconfig-java",
        "com.android.permission.flags-aconfig-java-export",
        "com.android.ranging.flags.ranging-aconfig-java-export",
        "com.android.server.contextualsearch.flags-java",
        "com.android.server.flags.services-aconfig-java",
@@ -827,8 +828,8 @@ java_aconfig_library {
    min_sdk_version: "30",
    apex_available: [
        "//apex_available:platform",
        "com.android.permission",
        "com.android.nfcservices",
        "com.android.permission",
    ],
}

+10 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;

import java.io.Closeable;
import java.util.concurrent.Executor;
@@ -231,6 +232,15 @@ public interface QuickAccessWalletClient extends Closeable {
    @Nullable
    Drawable getTileIcon();

    /**
     * Returns the user that should receive the wallet intents
     *
     * @return UserHandle
     * @hide
     */
    @Nullable
    UserHandle getUser();

    /**
     * Returns the service label specified by {@code android:label} in the service manifest entry.
     *
+14 −4
Original line number Diff line number Diff line
@@ -243,8 +243,9 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
            return null;
        }
        String packageName = mServiceInfo.getComponentName().getPackageName();
        int userId = mServiceInfo.getUserId();
        String walletActivity = mServiceInfo.getWalletActivity();
        return createIntent(walletActivity, packageName, ACTION_VIEW_WALLET);
        return createIntent(walletActivity, packageName, userId, ACTION_VIEW_WALLET);
    }

    @Override
@@ -302,12 +303,15 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
        }
        String packageName = mServiceInfo.getComponentName().getPackageName();
        String settingsActivity = mServiceInfo.getSettingsActivity();
        return createIntent(settingsActivity, packageName, ACTION_VIEW_WALLET_SETTINGS);
        return createIntent(settingsActivity, packageName, UserHandle.myUserId(),
                ACTION_VIEW_WALLET_SETTINGS);
    }

    @Nullable
    private Intent createIntent(@Nullable String activityName, String packageName, String action) {
        PackageManager pm = mContext.getPackageManager();
    private Intent createIntent(@Nullable String activityName, String packageName,
            int userId, String action) {
        Context userContext = mContext.createContextAsUser(UserHandle.of(userId), 0);
        PackageManager pm = userContext.getPackageManager();
        if (TextUtils.isEmpty(activityName)) {
            activityName = queryActivityForAction(pm, packageName, action);
        }
@@ -361,6 +365,12 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
        return mServiceInfo == null ? null : mServiceInfo.getTileIcon();
    }

    @Nullable
    @Override
    public UserHandle getUser() {
        return mServiceInfo == null ? null : UserHandle.of(mServiceInfo.getUserId());
    }

    @Override
    @Nullable
    public CharSequence getServiceLabel() {
+45 −10
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package android.service.quickaccesswallet;

import static android.permission.flags.Flags.walletRoleCrossUserEnabled;

import static com.android.permission.flags.Flags.crossUserRoleEnabled;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -32,10 +36,12 @@ import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.os.Binder;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
import android.util.Xml;

import com.android.internal.R;
@@ -59,22 +65,29 @@ class QuickAccessWalletServiceInfo {
    private final ServiceInfo mServiceInfo;
    private final ServiceMetadata mServiceMetadata;
    private final TileServiceMetadata mTileServiceMetadata;
    private final int mUserId;

    private QuickAccessWalletServiceInfo(
            @NonNull ServiceInfo serviceInfo,
            @NonNull ServiceMetadata metadata,
            @NonNull TileServiceMetadata tileServiceMetadata) {
            @NonNull TileServiceMetadata tileServiceMetadata,
            int userId) {
        mServiceInfo = serviceInfo;
        mServiceMetadata = metadata;
        mTileServiceMetadata = tileServiceMetadata;
        mUserId = userId;
    }

    @Nullable
    static QuickAccessWalletServiceInfo tryCreate(@NonNull Context context) {
        String defaultAppPackageName = null;

        int defaultAppUser = UserHandle.myUserId();

        if (isWalletRoleAvailable(context)) {
            defaultAppPackageName = getDefaultWalletApp(context);
            Pair<String, Integer> roleAndUser = getDefaultWalletApp(context);
            defaultAppPackageName = roleAndUser.first;
            defaultAppUser = roleAndUser.second;
        } else {
            ComponentName defaultPaymentApp = getDefaultPaymentApp(context);
            if (defaultPaymentApp == null) {
@@ -83,7 +96,8 @@ class QuickAccessWalletServiceInfo {
            defaultAppPackageName = defaultPaymentApp.getPackageName();
        }

        ServiceInfo serviceInfo = getWalletServiceInfo(context, defaultAppPackageName);
        ServiceInfo serviceInfo = getWalletServiceInfo(context, defaultAppPackageName,
                defaultAppUser);
        if (serviceInfo == null) {
            return null;
        }
@@ -98,15 +112,32 @@ class QuickAccessWalletServiceInfo {
        ServiceMetadata metadata = parseServiceMetadata(context, serviceInfo);
        TileServiceMetadata tileServiceMetadata =
                new TileServiceMetadata(parseTileServiceMetadata(context, serviceInfo));
        return new QuickAccessWalletServiceInfo(serviceInfo, metadata, tileServiceMetadata);
        return new QuickAccessWalletServiceInfo(serviceInfo, metadata, tileServiceMetadata,
                defaultAppUser);
    }

    private static String getDefaultWalletApp(Context context) {
    @NonNull
    private static Pair<String, Integer> getDefaultWalletApp(Context context) {
        UserHandle user = UserHandle.of(UserHandle.myUserId());

        final long token = Binder.clearCallingIdentity();
        try {
            RoleManager roleManager = context.getSystemService(RoleManager.class);
            List<String> roleHolders = roleManager.getRoleHolders(RoleManager.ROLE_WALLET);
            return roleHolders.isEmpty() ? null : roleHolders.get(0);

            if (walletRoleCrossUserEnabled()
                    && crossUserRoleEnabled()
                    && context.checkCallingOrSelfPermission(
                    Manifest.permission.INTERACT_ACROSS_USERS_FULL)
                    == PackageManager.PERMISSION_GRANTED) {
                user = roleManager.getActiveUserForRole(RoleManager.ROLE_WALLET);
                if (user == null) {
                    return new Pair<>(null, user.getIdentifier());
                }
            }
            List<String> roleHolders = roleManager.getRoleHoldersAsUser(RoleManager.ROLE_WALLET,
                    user);
            return new Pair<>(roleHolders.isEmpty() ? null : roleHolders.get(0),
                    user.getIdentifier());
        } finally {
            Binder.restoreCallingIdentity(token);
        }
@@ -128,15 +159,16 @@ class QuickAccessWalletServiceInfo {
        return comp == null ? null : ComponentName.unflattenFromString(comp);
    }

    private static ServiceInfo getWalletServiceInfo(Context context, String packageName) {
    private static ServiceInfo getWalletServiceInfo(Context context, String packageName,
            int userId) {
        Intent intent = new Intent(QuickAccessWalletService.SERVICE_INTERFACE);
        intent.setPackage(packageName);
        List<ResolveInfo> resolveInfos =
                context.getPackageManager().queryIntentServices(intent,
                context.getPackageManager().queryIntentServicesAsUser(intent,
                        PackageManager.MATCH_DIRECT_BOOT_AWARE
                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                        | PackageManager.MATCH_DEFAULT_ONLY
                        | PackageManager.GET_META_DATA);
                        | PackageManager.GET_META_DATA, userId);
        return resolveInfos.isEmpty() ? null : resolveInfos.get(0).serviceInfo;
    }

@@ -247,6 +279,9 @@ class QuickAccessWalletServiceInfo {
        return mServiceInfo.getComponentName();
    }

    int getUserId() {
        return mUserId;
    }
    /**
     * @return the fully qualified name of the activity that hosts the full wallet. If available,
     * this intent should be started with the action
+5 −0
Original line number Diff line number Diff line
@@ -140,6 +140,11 @@ public interface ActivityStarter {
    void postStartActivityDismissingKeyguard(Intent intent, int delay,
            @Nullable ActivityTransitionAnimator.Controller animationController,
            @Nullable String customMessage);
    /** Posts a start activity intent that dismisses keyguard. */
    void postStartActivityDismissingKeyguard(Intent intent, int delay,
            @Nullable ActivityTransitionAnimator.Controller animationController,
            @Nullable String customMessage,
            @Nullable UserHandle userHandle);
    void postStartActivityDismissingKeyguard(PendingIntent intent);

    /**
Loading