1 /*
2  * Copyright (C) 2014 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 package com.android.nfc.cardemulation;
17 
18 import android.annotation.TargetApi;
19 import android.app.ActivityManager;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.database.ContentObserver;
23 import android.net.Uri;
24 import android.nfc.Constants;
25 import android.nfc.cardemulation.ApduServiceInfo;
26 import android.nfc.cardemulation.CardEmulation;
27 import android.nfc.cardemulation.Utils;
28 import android.os.Build;
29 import android.os.Handler;
30 import android.os.Looper;
31 import android.os.UserHandle;
32 import android.os.UserManager;
33 import android.permission.flags.Flags;
34 
35 import android.provider.Settings;
36 import android.provider.Settings.SettingNotFoundException;
37 import android.sysprop.NfcProperties;
38 import android.util.Log;
39 import android.util.proto.ProtoOutputStream;
40 
41 import com.android.nfc.ForegroundUtils;
42 
43 import java.io.FileDescriptor;
44 import java.io.PrintWriter;
45 import java.util.ArrayList;
46 import java.util.List;
47 import java.util.Objects;
48 
49 /**
50  * This class keeps track of what HCE/SE-based services are
51  * preferred by the user. It currently has 3 inputs:
52  * 1) The default set in tap&pay menu for payment category
53  * 2) An app in the foreground asking for a specific
54  *    service for a specific category
55  * 3) If we had to disambiguate a previous tap (because no
56  *    preferred service was there), we need to temporarily
57  *    store the user's choice for the next tap.
58  *
59  * This class keeps track of all 3 inputs, and computes a new
60  * preferred services as needed. It then passes this service
61  * (if it changed) through a callback, which allows other components
62  * to adapt as necessary (ie the AID cache can update its AID
63  * mappings and the routing table).
64  */
65 public class PreferredServices implements com.android.nfc.ForegroundUtils.Callback {
66     static final String TAG = "PreferredCardEmulationServices";
67     static final boolean DBG = NfcProperties.debug_enabled().orElse(true);
68     static final Uri paymentDefaultUri = Settings.Secure.getUriFor(
69             Constants.SETTINGS_SECURE_NFC_PAYMENT_DEFAULT_COMPONENT);
70     static final Uri paymentForegroundUri = Settings.Secure.getUriFor(
71             Constants.SETTINGS_SECURE_NFC_PAYMENT_FOREGROUND);
72 
73     final SettingsObserver mSettingsObserver;
74     final Context mContext;
75     final WalletRoleObserver mWalletRoleObserver;
76     final RegisteredServicesCache mServiceCache;
77     final RegisteredAidCache mAidCache;
78     final Callback mCallback;
79     final ForegroundUtils mForegroundUtils;
80     final Handler mHandler = new Handler(Looper.getMainLooper());
81 
82     final class PaymentDefaults {
83         boolean preferForeground; // The current selection mode for this category
84         ComponentName settingsDefault; // The component preferred in settings (eg Tap&Pay)
85         ComponentName currentPreferred; // The computed preferred component
86         UserHandle mUserHandle;
87     }
88 
89     final Object mLock = new Object();
90     // Variables below synchronized on mLock
91     PaymentDefaults mPaymentDefaults = new PaymentDefaults();
92 
93     ComponentName mForegroundRequested; // The component preferred by fg app
94     int mForegroundUid; // The UID of the fg app, or -1 if fg app didn't request
95 
96     ComponentName mNextTapDefault; // The component preferred by active disambig dialog
97     int mNextTapDefaultUserId;
98     boolean mClearNextTapDefault = false; // Set when the next tap default must be cleared
99 
100     ComponentName mForegroundCurrent; // The currently computed foreground component
101     int mForegroundCurrentUid; // The UID of the currently computed foreground component
102 
103     ComponentName mDefaultWalletHolderPaymentService;
104 
105     int mUserIdDefaultWalletHolder;
106 
107     public interface Callback {
108         /**
109          * Notify when preferred payment service is changed
110          */
onPreferredPaymentServiceChanged(int userId, ComponentName service)111         void onPreferredPaymentServiceChanged(int userId, ComponentName service);
112         /**
113          * Notify when preferred foreground service is changed
114          */
onPreferredForegroundServiceChanged(int userId, ComponentName service)115         void onPreferredForegroundServiceChanged(int userId, ComponentName service);
116     }
117 
PreferredServices(Context context, RegisteredServicesCache serviceCache, RegisteredAidCache aidCache, WalletRoleObserver walletRoleObserver, Callback callback)118     public PreferredServices(Context context, RegisteredServicesCache serviceCache,
119             RegisteredAidCache aidCache, WalletRoleObserver walletRoleObserver,
120             Callback callback) {
121         mContext = context;
122         mWalletRoleObserver = walletRoleObserver;
123         mForegroundUtils = ForegroundUtils.getInstance(
124                 context.getSystemService(ActivityManager.class));
125         mServiceCache = serviceCache;
126         mAidCache = aidCache;
127         mCallback = callback;
128         mSettingsObserver = new SettingsObserver(mHandler);
129         mContext.getContentResolver().registerContentObserverAsUser(
130                 paymentDefaultUri,
131                 true, mSettingsObserver, UserHandle.ALL);
132 
133         mContext.getContentResolver().registerContentObserverAsUser(
134                 paymentForegroundUri,
135                 true, mSettingsObserver, UserHandle.ALL);
136 
137         int currentUserId = ActivityManager.getCurrentUser();
138 
139         // Load current settings defaults for payments
140         loadDefaultsFromSettings(currentUserId, false);
141 
142         if (mWalletRoleObserver.isWalletRoleFeatureEnabled()) {
143             String holder = mWalletRoleObserver.getDefaultWalletRoleHolder(currentUserId);
144             onWalletRoleHolderChanged(holder, currentUserId);
145         }
146     }
147 
148     private final class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler)149         public SettingsObserver(Handler handler) {
150             super(handler);
151         }
152 
153         @Override
onChange(boolean selfChange, Uri uri)154         public void onChange(boolean selfChange, Uri uri) {
155             super.onChange(selfChange, uri);
156             // Do it just for the current user. If it was in fact
157             // a change made for another user, we'll sync it down
158             // on user switch.
159             int currentUser = ActivityManager.getCurrentUser();
160             loadDefaultsFromSettings(currentUser, false);
161         }
162     };
163 
164     @TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
onWalletRoleHolderChanged(String defaultWalletHolderPackageName, int userId)165     public void onWalletRoleHolderChanged(String defaultWalletHolderPackageName, int userId) {
166         if (defaultWalletHolderPackageName == null) {
167             mDefaultWalletHolderPaymentService = null;
168             mCallback.onPreferredPaymentServiceChanged(userId, null);
169             return;
170         }
171         List<ApduServiceInfo> serviceInfos = mServiceCache.getInstalledServices(userId);
172         List<ComponentName> roleHolderPaymentServices = new ArrayList<>();
173         int servicesCount = serviceInfos.size();
174         for(int i = 0; i < servicesCount; i++) {
175             ApduServiceInfo serviceInfo = serviceInfos.get(i);
176             ComponentName componentName = serviceInfo.getComponent();
177             if (componentName.getPackageName()
178                     .equals(defaultWalletHolderPackageName)) {
179                 List<String> aids = serviceInfo.getAids();
180                 int aidsCount = aids.size();
181                 for (int j = 0; j < aidsCount; j++) {
182                     String aid = aids.get(j);
183                     if (serviceInfo.getCategoryForAid(aid)
184                             .equals(CardEmulation.CATEGORY_PAYMENT)) {
185                         roleHolderPaymentServices.add(componentName);
186                         break;
187                     }
188                 }
189             }
190         }
191         mUserIdDefaultWalletHolder = userId;
192         ComponentName candidate = !roleHolderPaymentServices.isEmpty()
193                 ? roleHolderPaymentServices.get(0) : null;
194         if (!Objects.equals(candidate, mDefaultWalletHolderPaymentService)) {
195             mCallback.onPreferredPaymentServiceChanged(userId, candidate);
196         }
197         mDefaultWalletHolderPaymentService = candidate;
198     }
199 
loadDefaultsFromSettings(int userId, boolean force)200     void loadDefaultsFromSettings(int userId, boolean force) {
201         boolean paymentDefaultChanged = false;
202         boolean paymentPreferForegroundChanged = false;
203         // Load current payment default from settings
204         UserHandle currentUser = UserHandle.of(ActivityManager.getCurrentUser());
205         UserManager um = mContext.createContextAsUser(currentUser, /*flags=*/0)
206                 .getSystemService(UserManager.class);
207         List<UserHandle> userHandles = um.getEnabledProfiles();
208 
209         String name = null;
210         String newDefaultName = null;
211         UserHandle newUser = null;
212         // search for default payment setting within enabled profiles
213         for (UserHandle uh : userHandles) {
214             try {
215                 name = Settings.Secure.getString(
216                         mContext.createContextAsUser(uh, 0).getContentResolver(),
217                         Constants.SETTINGS_SECURE_NFC_PAYMENT_DEFAULT_COMPONENT);
218             } catch (IllegalStateException e) {
219                 Log.d(TAG, "Fail to get PackageManager for user: " + uh);
220                 continue;
221             }
222 
223             if (name != null) {
224                 newUser = uh;
225                 newDefaultName = name;
226             }
227             if (uh.getIdentifier() == userId) {
228                 currentUser = uh;
229             }
230         }
231         if (currentUser == null) {
232             Log.e(TAG, "NULL/ Error fetching currentUser info");
233             return;
234         }
235         // no default payment setting in all profles
236         if (newUser == null) {
237             newUser = currentUser;
238         }
239         ComponentName newDefault = newDefaultName != null
240                 ? ComponentName.unflattenFromString(newDefaultName) : null;
241         boolean preferForeground = false;
242         try {
243             // get the setting from the main user instead of from the user profiles.
244             preferForeground = mWalletRoleObserver.isWalletRoleFeatureEnabled()
245                     || Settings.Secure.getInt(mContext
246                             .createContextAsUser(currentUser, 0).getContentResolver(),
247                     Constants.SETTINGS_SECURE_NFC_PAYMENT_FOREGROUND) != 0;
248         } catch (SettingNotFoundException e) {
249         }
250         synchronized (mLock) {
251             paymentPreferForegroundChanged = (preferForeground != mPaymentDefaults.preferForeground);
252             mPaymentDefaults.preferForeground = preferForeground;
253 
254             mPaymentDefaults.settingsDefault = newDefault;
255             if (newDefault != null && (!newDefault.equals(mPaymentDefaults.currentPreferred)
256                     || mPaymentDefaults.mUserHandle.getIdentifier() != newUser.getIdentifier())) {
257                 paymentDefaultChanged = true;
258                 mPaymentDefaults.currentPreferred = newDefault;
259                 mPaymentDefaults.mUserHandle = newUser;
260             } else if (newDefault == null && mPaymentDefaults.currentPreferred != null) {
261                 paymentDefaultChanged = true;
262                 mPaymentDefaults.currentPreferred = newDefault;
263                 mPaymentDefaults.mUserHandle = newUser;
264             } else {
265                 // Same default as before
266             }
267         }
268         // Notify if anything changed
269         if (!mWalletRoleObserver.isWalletRoleFeatureEnabled() && (paymentDefaultChanged || force)) {
270             mCallback.onPreferredPaymentServiceChanged(newUser.getIdentifier(), newDefault);
271         }
272         if (paymentPreferForegroundChanged || force) {
273             computePreferredForegroundService();
274         }
275     }
276 
computePreferredForegroundService()277     void computePreferredForegroundService() {
278         ComponentName preferredService = null;
279         int preferredServiceUserId;
280         boolean changed = false;
281         synchronized (mLock) {
282             // Prio 1: next tap default
283             preferredService = mNextTapDefault;
284             preferredServiceUserId = mNextTapDefaultUserId;
285             if (preferredService == null) {
286                 // Prio 2: foreground requested by app
287                 preferredService = mForegroundRequested;
288                 preferredServiceUserId =
289                         UserHandle.getUserHandleForUid(mForegroundUid).getIdentifier();
290             }
291             if (preferredService != null && (!preferredService.equals(mForegroundCurrent)
292                       || preferredServiceUserId
293                       != UserHandle.getUserHandleForUid(mForegroundCurrentUid).getIdentifier())) {
294                 mForegroundCurrent = preferredService;
295                 mForegroundCurrentUid = mForegroundUid;
296                 changed = true;
297             } else if (preferredService == null && mForegroundCurrent != null){
298                 mForegroundCurrent = preferredService;
299                 mForegroundCurrentUid = mForegroundUid;
300                 changed = true;
301             }
302         }
303         // Notify if anything changed
304         if (changed) {
305             mCallback.onPreferredForegroundServiceChanged(preferredServiceUserId, preferredService);
306         }
307     }
308 
309     /**
310      *  Set default service for next tap
311      */
setDefaultForNextTap(int userId, ComponentName service)312     public boolean setDefaultForNextTap(int userId, ComponentName service) {
313         // This is a trusted API, so update without checking
314         synchronized (mLock) {
315             mNextTapDefault = service;
316             mNextTapDefaultUserId = userId;
317         }
318         computePreferredForegroundService();
319         return true;
320     }
321 
onServicesUpdated()322     public void onServicesUpdated() {
323         // If this service is the current foreground service, verify
324         // there are no conflicts
325         boolean foregroundChanged = false;
326         synchronized (mLock) {
327             // Check if the current foreground service is still allowed to override;
328             // it could have registered new AIDs that make it conflict with user
329             // preferences.
330             if (mForegroundCurrent != null) {
331                 if (!isForegroundAllowedLocked(mForegroundCurrent, mForegroundCurrentUid))  {
332                     Log.d(TAG, "Removing foreground preferred service.");
333                     mForegroundRequested = null;
334                     mForegroundUid = -1;
335                     mForegroundCurrentUid = -1;
336                     foregroundChanged = true;
337                 }
338             } else {
339                 // Don't care about this service
340             }
341         }
342         if (foregroundChanged) {
343             computePreferredForegroundService();
344         }
345 
346         if(mWalletRoleObserver.isWalletRoleFeatureEnabled()
347                 && mUserIdDefaultWalletHolder >= 0) {
348             onWalletRoleHolderChanged(mWalletRoleObserver
349                             .getDefaultWalletRoleHolder(mUserIdDefaultWalletHolder),
350                     mUserIdDefaultWalletHolder);
351         }
352     }
353 
354     // Verifies whether a service is allowed to register as preferred
isForegroundAllowedLocked(ComponentName service, int callingUid)355     boolean isForegroundAllowedLocked(ComponentName service, int callingUid) {
356         if (service.equals(mPaymentDefaults.currentPreferred)) {
357             // If the requester is already the payment default, allow it to request foreground
358             // override as well (it could use this to make sure it handles AIDs of category OTHER)
359             return true;
360         }
361         ApduServiceInfo serviceInfo = mServiceCache.getService(
362                 UserHandle.getUserHandleForUid(callingUid).getIdentifier(), service);
363         if (serviceInfo == null) {
364             Log.d(TAG, "Requested foreground service unexpectedly removed");
365             return false;
366         }
367         // Do some quick checking
368         if (!mPaymentDefaults.preferForeground) {
369             // Foreground apps are not allowed to override payment default
370             // Check if this app registers payment AIDs, in which case we'll fail anyway
371             if (serviceInfo.hasCategory(CardEmulation.CATEGORY_PAYMENT)) {
372                 Log.d(TAG, "User doesn't allow payment services to be overridden.");
373                 return false;
374             }
375             // If no payment AIDs, get AIDs of category other, and see if there's any
376             // conflict with payment AIDs of current default payment app. That means
377             // the current default payment app said this was a payment AID, and the
378             // foreground app says it was not. In this case we'll still prefer the payment
379             // app, since that is the one that the user has explicitly selected (and said
380             // it's not allowed to be overridden).
381             final List<String> otherAids = serviceInfo.getAids();
382             ApduServiceInfo paymentServiceInfo = mServiceCache.getService(
383                     mPaymentDefaults.mUserHandle.getIdentifier(),
384                     mPaymentDefaults.currentPreferred);
385             if (paymentServiceInfo != null && otherAids != null && otherAids.size() > 0) {
386                 for (String aid : otherAids) {
387                     RegisteredAidCache.AidResolveInfo resolveInfo = mAidCache.resolveAid(aid);
388                     if (CardEmulation.CATEGORY_PAYMENT.equals(resolveInfo.category) &&
389                             paymentServiceInfo.equals(resolveInfo.defaultService)) {
390                         if (DBG) Log.d(TAG, "AID " + aid + " is handled by the default payment app,"
391                                 + " and the user has not allowed payments to be overridden.");
392                         return false;
393                     }
394                 }
395                 return true;
396             } else {
397                 // Could not find payment service or fg app doesn't register other AIDs;
398                 // okay to proceed.
399                 return true;
400             }
401         } else {
402             // Payment allows override, so allow anything.
403             return true;
404         }
405     }
406 
registerPreferredForegroundService(ComponentName service, int callingUid)407     public boolean registerPreferredForegroundService(ComponentName service, int callingUid) {
408         boolean success = false;
409         synchronized (mLock) {
410             if (isForegroundAllowedLocked(service, callingUid)) {
411                 if (mForegroundUtils.registerUidToBackgroundCallback(this, callingUid)) {
412                     mForegroundRequested = service;
413                     mForegroundUid = callingUid;
414                     success = true;
415                 } else {
416                     Log.e(TAG, "Calling UID is not in the foreground, ignorning!");
417                     success = false;
418                 }
419             } else {
420                 Log.e(TAG, "Requested foreground service conflicts or was removed.");
421             }
422         }
423         if (success) {
424             computePreferredForegroundService();
425         }
426         return success;
427     }
428 
unregisterForegroundService(int uid)429     boolean unregisterForegroundService(int uid) {
430         boolean success = false;
431         synchronized (mLock) {
432             if (mForegroundUid == uid) {
433                 mForegroundRequested = null;
434                 mForegroundUid = -1;
435                 success = true;
436             } // else, other UID in foreground
437         }
438         if (success) {
439             computePreferredForegroundService();
440         }
441         return success;
442     }
443 
unregisteredPreferredForegroundService(int callingUid)444     public boolean unregisteredPreferredForegroundService(int callingUid) {
445         // Verify the calling UID is in the foreground
446         if (mForegroundUtils.isInForeground(callingUid)) {
447             return unregisterForegroundService(callingUid);
448         } else {
449             Log.e(TAG, "Calling UID is not in the foreground, ignorning!");
450             return false;
451         }
452     }
453 
454     @Override
onUidToBackground(int uid)455     public void onUidToBackground(int uid) {
456         unregisterForegroundService(uid);
457     }
458 
onHostEmulationActivated()459     public void onHostEmulationActivated() {
460         synchronized (mLock) {
461             mClearNextTapDefault = (mNextTapDefault != null);
462         }
463     }
464 
onHostEmulationDeactivated()465     public void onHostEmulationDeactivated() {
466         // If we had any next tap defaults set, clear them out
467         boolean changed = false;
468         synchronized (mLock) {
469             if (mClearNextTapDefault) {
470                 // The reason we need to check this boolean is because the next tap
471                 // default may have been set while the user held the phone
472                 // on the reader; when the user then removes his phone from
473                 // the reader (causing the "onHostEmulationDeactivated" event),
474                 // the next tap default would immediately be cleared
475                 // again. Instead, clear out defaults only if a next tap default
476                 // had already been set at time of activation, which is captured
477                 // by mClearNextTapDefault.
478                 if (mNextTapDefault != null) {
479                     mNextTapDefault = null;
480                     changed = true;
481                 }
482                 mClearNextTapDefault = false;
483             }
484         }
485         if (changed) {
486             computePreferredForegroundService();
487         }
488     }
489 
onUserSwitched(int userId)490     public void onUserSwitched(int userId) {
491         loadDefaultsFromSettings(userId, true);
492     }
493 
packageHasPreferredService(String packageName)494     public boolean packageHasPreferredService(String packageName) {
495         if (packageName == null) return false;
496         synchronized (mLock) {
497             if (mPaymentDefaults.currentPreferred != null
498                     && packageName.equals(mPaymentDefaults.currentPreferred.getPackageName())) {
499                 return true;
500             }
501             return (mForegroundCurrent != null
502                 && packageName.equals(mForegroundCurrent.getPackageName()));
503         }
504     }
505 
dump(FileDescriptor fd, PrintWriter pw, String[] args)506     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
507         synchronized (mLock) {
508             pw.println("Preferred services (in order of importance): ");
509             pw.println("    *** Current preferred foreground service: " + mForegroundCurrent
510                     + " (UID:" + mForegroundCurrentUid + ")");
511             if (mWalletRoleObserver.isWalletRoleFeatureEnabled()) {
512                 boolean roleNotSet = mDefaultWalletHolderPaymentService == null;
513                 pw.println("    *** Current wallet payment service: "
514                         + (roleNotSet ? "null" :
515                         mDefaultWalletHolderPaymentService) + "("
516                         + (roleNotSet ? "no user"
517                         : getUserName(UserHandle.of(mUserIdDefaultWalletHolder))) + ")");
518             }
519             pw.println("    *** Current preferred payment service: "
520                     + mPaymentDefaults.currentPreferred + "("
521                     + getUserName(mPaymentDefaults.mUserHandle) + ")");
522             pw.println("        Next tap default: " + mNextTapDefault
523                     + " (" + getUserName(UserHandle.of(mNextTapDefaultUserId)) + ")");
524             pw.println("        Default for foreground app (UID: " + mForegroundUid
525                     + "): " + mForegroundRequested);
526             if (!mWalletRoleObserver.isWalletRoleFeatureEnabled()) {
527                 pw.println("        Default in payment settings: " + mPaymentDefaults.settingsDefault
528                         + "(" + getUserName(mPaymentDefaults.mUserHandle) + ")");
529                 pw.println("        Payment settings allows override: "
530                         + mPaymentDefaults.preferForeground);
531             }
532             pw.println("");
533         }
534     }
535 
getUserName(UserHandle uh)536     private String getUserName(UserHandle uh) {
537         if (uh == null) {
538             return null;
539         }
540         UserManager um = mContext.createContextAsUser(
541                 uh, /*flags=*/0).getSystemService(UserManager.class);
542         if (um == null) {
543             return null;
544         }
545         return com.android.nfc.Utils.maskSubstring(um.getUserName(), 3);
546     }
547 
548     /**
549      * Dump debugging information as a PreferredServicesProto
550      *
551      * Note:
552      * See proto definition in frameworks/base/core/proto/android/nfc/card_emulation.proto
553      * When writing a nested message, must call {@link ProtoOutputStream#start(long)} before and
554      * {@link ProtoOutputStream#end(long)} after.
555      * Never reuse a proto field number. When removing a field, mark it as reserved.
556      */
dumpDebug(ProtoOutputStream proto)557     void dumpDebug(ProtoOutputStream proto) {
558         synchronized (mLock) {
559             if (mForegroundCurrent != null) {
560                 Utils.dumpDebugComponentName(
561                         mForegroundCurrent, proto, PreferredServicesProto.FOREGROUND_CURRENT);
562             }
563             if (mPaymentDefaults.currentPreferred != null) {
564                 Utils.dumpDebugComponentName(
565                         mPaymentDefaults.currentPreferred, proto,
566                         PreferredServicesProto.FOREGROUND_CURRENT);
567             }
568             if (mWalletRoleObserver.isWalletRoleFeatureEnabled()) {
569                 if (mDefaultWalletHolderPaymentService != null) {
570                     Utils.dumpDebugComponentName(
571                             mDefaultWalletHolderPaymentService, proto,
572                             PreferredServicesProto.WALLET_ROLE_HOLDER_PAYMENT_SERVICE);
573                 }
574             }
575             if (mNextTapDefault != null) {
576                 Utils.dumpDebugComponentName(
577                         mNextTapDefault, proto, PreferredServicesProto.NEXT_TAP_DEFAULT);
578             }
579             proto.write(PreferredServicesProto.FOREGROUND_UID, mForegroundUid);
580             if (mForegroundRequested != null) {
581                 Utils.dumpDebugComponentName(
582                         mForegroundRequested, proto, PreferredServicesProto.FOREGROUND_REQUESTED);
583             }
584             if (!mWalletRoleObserver.isWalletRoleFeatureEnabled()) {
585                 if (mPaymentDefaults.settingsDefault != null) {
586                     Utils.dumpDebugComponentName(
587                             mPaymentDefaults.settingsDefault, proto,
588                             PreferredServicesProto.SETTINGS_DEFAULT);
589                 }
590                 proto.write(PreferredServicesProto.PREFER_FOREGROUND,
591                         mPaymentDefaults.preferForeground);
592             }
593         }
594     }
595 }
596