• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.nfc.cardemulation;
18 
19 import android.app.role.OnRoleHoldersChangedListener;
20 import android.app.role.RoleManager;
21 import android.content.Context;
22 import android.os.Binder;
23 import android.os.UserHandle;
24 import android.permission.flags.Flags;
25 import android.util.Log;
26 
27 import com.android.internal.annotations.VisibleForTesting;
28 import com.android.nfc.NfcEventLog;
29 import com.android.nfc.NfcInjector;
30 import com.android.nfc.proto.NfcEventProto;
31 
32 import java.util.List;
33 
34 public class WalletRoleObserver {
35     private static final String TAG = "WalletRoleObserver";
36 
37     public interface Callback {
onWalletRoleHolderChanged(String holder, int userId)38         void onWalletRoleHolderChanged(String holder, int userId);
39     }
40     private Context mContext;
41     private NfcEventLog mNfcEventLog;
42     private RoleManager mRoleManager;
43     @VisibleForTesting
44     final OnRoleHoldersChangedListener mOnRoleHoldersChangedListener;
45     private Callback mCallback;
46 
WalletRoleObserver(Context context, RoleManager roleManager, Callback callback, NfcInjector nfcInjector)47     public WalletRoleObserver(Context context, RoleManager roleManager,
48             Callback callback, NfcInjector nfcInjector) {
49         this.mContext = context;
50         this.mRoleManager = roleManager;
51         this.mCallback = callback;
52         this.mNfcEventLog = nfcInjector.getNfcEventLog();
53         this.mOnRoleHoldersChangedListener = (roleName, user) -> {
54             if (!roleName.equals(RoleManager.ROLE_WALLET)) {
55                 return;
56             }
57             List<String> roleHolders = roleManager.getRoleHolders(RoleManager.ROLE_WALLET);
58             String roleHolder = roleHolders.isEmpty() ? null : roleHolders.get(0);
59             Log.i(TAG, "Wallet role changed for user " + user.getIdentifier() + " to "
60                        + roleHolder);
61             mNfcEventLog.logEvent(
62                     NfcEventProto.EventType.newBuilder()
63                             .setWalletRoleHolderChange(
64                                 NfcEventProto.NfcWalletRoleHolderChange.newBuilder()
65                                 .setPackageName(roleHolder != null ? roleHolder : "none")
66                                 .build())
67                             .build());
68             callback.onWalletRoleHolderChanged(roleHolder, user.getIdentifier());
69         };
70         this.mRoleManager.addOnRoleHoldersChangedListenerAsUser(context.getMainExecutor(),
71                 mOnRoleHoldersChangedListener, UserHandle.ALL);
72     }
73 
getDefaultWalletRoleHolder(int userId)74     public String getDefaultWalletRoleHolder(int userId) {
75         final long token = Binder.clearCallingIdentity();
76         try {
77             if (!mRoleManager.isRoleAvailable(RoleManager.ROLE_WALLET)) {
78                 return null;
79             }
80             List<String> roleHolders = mRoleManager.getRoleHoldersAsUser(RoleManager.ROLE_WALLET,
81                     UserHandle.of(userId));
82             return roleHolders.isEmpty() ? null : roleHolders.get(0);
83         } finally {
84             Binder.restoreCallingIdentity(token);
85         }
86     }
87 
isWalletRoleFeatureEnabled()88      boolean isWalletRoleFeatureEnabled() {
89         final long token = Binder.clearCallingIdentity();
90         try {
91             return Flags.walletRoleEnabled();
92         } finally {
93             Binder.restoreCallingIdentity(token);
94         }
95     }
96 
onUserSwitched(int userId)97     public void onUserSwitched(int userId) {
98         String roleHolder = getDefaultWalletRoleHolder(userId);
99         Log.i(TAG, "Wallet role for user " + userId + ": " + roleHolder);
100         mCallback.onWalletRoleHolderChanged(roleHolder, userId);
101     }
102 }
103