NFC support in work profile

Configure NFC payment settings based on userId.

Bug: 202367033
Test: mauanl tests
Change-Id: I97e275f374d34618b64188d5de185ec6c527e0fd
diff --git a/src/com/android/settings/nfc/NfcPaymentPreferenceController.java b/src/com/android/settings/nfc/NfcPaymentPreferenceController.java
index 9d3673d..edb12dd 100644
--- a/src/com/android/settings/nfc/NfcPaymentPreferenceController.java
+++ b/src/com/android/settings/nfc/NfcPaymentPreferenceController.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.nfc.NfcAdapter;
+import android.os.UserManager;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -127,7 +128,10 @@
     public CharSequence getSummary() {
         final PaymentAppInfo defaultApp = mPaymentBackend.getDefaultApp();
         if (defaultApp != null) {
-            return defaultApp.label;
+            UserManager um = mContext.createContextAsUser(
+                    defaultApp.userHandle, /*flags=*/0).getSystemService(UserManager.class);
+
+            return defaultApp.label + " (" + um.getUserName() + ")";
         } else {
             return mContext.getText(R.string.nfc_payment_default_not_set);
         }
@@ -218,12 +222,15 @@
             }
 
             // Prevent checked callback getting called on recycled views
+            UserManager um = mContext.createContextAsUser(
+                    appInfo.userHandle, /*flags=*/0).getSystemService(UserManager.class);
+
             holder.radioButton.setOnCheckedChangeListener(null);
             holder.radioButton.setChecked(appInfo.isDefault);
-            holder.radioButton.setContentDescription(appInfo.label);
+            holder.radioButton.setContentDescription(appInfo.label + " (" + um.getUserName() + ")");
             holder.radioButton.setOnCheckedChangeListener(this);
             holder.radioButton.setTag(appInfo);
-            holder.radioButton.setText(appInfo.label);
+            holder.radioButton.setText(appInfo.label + " (" + um.getUserName() + ")");
             return convertView;
         }
 
@@ -245,7 +252,8 @@
 
         private void makeDefault(PaymentAppInfo appInfo) {
             if (!appInfo.isDefault) {
-                mPaymentBackend.setDefaultPaymentApp(appInfo.componentName);
+                mPaymentBackend.setDefaultPaymentApp(appInfo.componentName,
+                        appInfo.userHandle.getIdentifier());
             }
             final Dialog dialog = mPreference.getDialog();
             if (dialog != null) {
diff --git a/src/com/android/settings/nfc/PaymentBackend.java b/src/com/android/settings/nfc/PaymentBackend.java
index aec7343..542c95b 100644
--- a/src/com/android/settings/nfc/PaymentBackend.java
+++ b/src/com/android/settings/nfc/PaymentBackend.java
@@ -16,11 +16,10 @@
 
 package com.android.settings.nfc;
 
+import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
 import android.nfc.NfcAdapter;
 import android.nfc.cardemulation.ApduServiceInfo;
 import android.nfc.cardemulation.CardEmulation;
@@ -50,6 +49,15 @@
         boolean isDefault;
         public ComponentName componentName;
         public ComponentName settingsComponent;
+        public UserHandle userHandle;
+    }
+
+    /**
+     * ComponentName of the payment application and the userId that it belongs to.
+     */
+    public static class PaymentInfo {
+        public ComponentName componentName;
+        public int userId;
     }
 
     private final Context mContext;
@@ -80,40 +88,55 @@
 
     public void refresh() {
         PackageManager pm = mContext.getPackageManager();
-        List<ApduServiceInfo> serviceInfos =
-                mCardEmuManager.getServices(CardEmulation.CATEGORY_PAYMENT);
-        ArrayList<PaymentAppInfo> appInfos = new ArrayList<PaymentAppInfo>();
+        ArrayList<PaymentAppInfo> appInfosAllProfiles = new ArrayList<PaymentAppInfo>();
 
-        if (serviceInfos == null) {
-            makeCallbacks();
-            return;
-        }
+        UserManager um = mContext.createContextAsUser(
+                UserHandle.of(ActivityManager.getCurrentUser()), /*flags=*/0)
+                .getSystemService(UserManager.class);
+        List<UserHandle> userHandles = um.getEnabledProfiles();
 
-        ComponentName defaultAppName = getDefaultPaymentApp();
+        PaymentInfo defaultAppName = getDefaultPaymentApp();
         PaymentAppInfo foundDefaultApp = null;
-        for (ApduServiceInfo service : serviceInfos) {
-            PaymentAppInfo appInfo = new PaymentAppInfo();
-            appInfo.label = service.loadLabel(pm);
-            if (appInfo.label == null) {
-                appInfo.label = service.loadAppLabel(pm);
+        for (UserHandle uh : userHandles) {
+            List<ApduServiceInfo> serviceInfosByProfile =
+                    mCardEmuManager.getServices(CardEmulation.CATEGORY_PAYMENT, uh.getIdentifier());
+            if (serviceInfosByProfile == null) continue;
+
+            ArrayList<PaymentAppInfo> appInfos = new ArrayList<PaymentAppInfo>();
+
+            for (ApduServiceInfo service : serviceInfosByProfile) {
+                PaymentAppInfo appInfo = new PaymentAppInfo();
+                appInfo.userHandle = uh;
+                appInfo.label = service.loadLabel(pm);
+                if (appInfo.label == null) {
+                    appInfo.label = service.loadAppLabel(pm);
+                }
+                if (defaultAppName == null) {
+                    appInfo.isDefault = false;
+                } else {
+                    appInfo.isDefault =
+                            service.getComponent().equals(defaultAppName.componentName)
+                            && defaultAppName.userId == uh.getIdentifier();
+                }
+                if (appInfo.isDefault) {
+                    foundDefaultApp = appInfo;
+                }
+                appInfo.componentName = service.getComponent();
+                String settingsActivity = service.getSettingsActivityName();
+                if (settingsActivity != null) {
+                    appInfo.settingsComponent = new ComponentName(
+                            appInfo.componentName.getPackageName(),
+                            settingsActivity);
+                } else {
+                    appInfo.settingsComponent = null;
+                }
+                appInfo.description = service.getDescription();
+
+                appInfos.add(appInfo);
             }
-            appInfo.isDefault = service.getComponent().equals(defaultAppName);
-            if (appInfo.isDefault) {
-                foundDefaultApp = appInfo;
-            }
-            appInfo.componentName = service.getComponent();
-            String settingsActivity = service.getSettingsActivityName();
-            if (settingsActivity != null) {
-                appInfo.settingsComponent = new ComponentName(
-                        appInfo.componentName.getPackageName(),
-                        settingsActivity);
-            } else {
-                appInfo.settingsComponent = null;
-            }
-            appInfo.description = service.getDescription();
-            appInfos.add(appInfo);
+            appInfosAllProfiles.addAll(appInfos);
         }
-        mAppInfos = appInfos;
+        mAppInfos = appInfosAllProfiles;
         mDefaultAppInfo = foundDefaultApp;
         makeCallbacks();
     }
@@ -150,13 +173,36 @@
     }
 
     void setForegroundMode(boolean foreground) {
-        Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                Settings.Secure.NFC_PAYMENT_FOREGROUND, foreground ? 1 : 0, UserHandle.myUserId());
+        UserManager um = mContext.createContextAsUser(
+                UserHandle.of(UserHandle.myUserId()), /*flags=*/0)
+                .getSystemService(UserManager.class);
+        List<UserHandle> userHandles = um.getEnabledProfiles();
+        for (UserHandle uh : userHandles) {
+            Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.NFC_PAYMENT_FOREGROUND, foreground ? 1 : 0, uh.getIdentifier());
+        }
     }
 
-    ComponentName getDefaultPaymentApp() {
+    PaymentInfo getDefaultPaymentApp() {
+        UserManager um = mContext.createContextAsUser(
+                UserHandle.of(ActivityManager.getCurrentUser()), /*flags=*/0)
+                .getSystemService(UserManager.class);
+        List<UserHandle> userHandles = um.getEnabledProfiles();
+        for (UserHandle uh : userHandles) {
+            ComponentName defaultApp = getDefaultPaymentApp(uh.getIdentifier());
+            if (defaultApp != null) {
+                PaymentInfo appInfo = new PaymentInfo();
+                appInfo.userId = uh.getIdentifier();
+                appInfo.componentName = defaultApp;
+                return appInfo;
+            }
+        }
+        return null;
+    }
+
+    ComponentName getDefaultPaymentApp(int userId) {
         String componentString = Settings.Secure.getStringForUser(mContext.getContentResolver(),
-                Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, UserHandle.myUserId());
+                Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, userId);
         if (componentString != null) {
             return ComponentName.unflattenFromString(componentString);
         } else {
@@ -165,9 +211,29 @@
     }
 
     public void setDefaultPaymentApp(ComponentName app) {
-        Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
-                app != null ? app.flattenToString() : null, UserHandle.myUserId());
+        setDefaultPaymentApp(app, UserHandle.myUserId());
+    }
+
+    /**
+     *  Set Nfc default payment application
+     */
+    public void setDefaultPaymentApp(ComponentName app, int userId) {
+        UserManager um = mContext.createContextAsUser(
+                UserHandle.of(ActivityManager.getCurrentUser()), /*flags=*/0)
+                .getSystemService(UserManager.class);
+        List<UserHandle> userHandles = um.getEnabledProfiles();
+
+        for (UserHandle uh : userHandles) {
+            if (uh.getIdentifier() == userId) {
+                Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                        Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
+                        app != null ? app.flattenToString() : null, uh.getIdentifier());
+            } else {
+                Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                        Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
+                        null, uh.getIdentifier());
+            }
+        }
         refresh();
     }
 
diff --git a/src/com/android/settings/nfc/PaymentDefaultDialog.java b/src/com/android/settings/nfc/PaymentDefaultDialog.java
index 1aa8dca..df6d86f 100644
--- a/src/com/android/settings/nfc/PaymentDefaultDialog.java
+++ b/src/com/android/settings/nfc/PaymentDefaultDialog.java
@@ -21,12 +21,14 @@
 import android.content.Intent;
 import android.nfc.cardemulation.CardEmulation;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
 import com.android.settings.R;
 import com.android.settings.nfc.PaymentBackend.PaymentAppInfo;
+import com.android.settings.nfc.PaymentBackend.PaymentInfo;
 
 import java.util.List;
 
@@ -37,7 +39,7 @@
     private static final int PAYMENT_APP_MAX_CAPTION_LENGTH = 40;
 
     private PaymentBackend mBackend;
-    private ComponentName mNewDefault;
+    private PaymentInfo mNewDefault;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -51,9 +53,10 @@
         ComponentName component = intent.getParcelableExtra(
                 CardEmulation.EXTRA_SERVICE_COMPONENT);
         String category = intent.getStringExtra(CardEmulation.EXTRA_CATEGORY);
+        int userId = intent.getIntExtra(CardEmulation.EXTRA_USERID, UserHandle.myUserId());
 
         setResult(RESULT_CANCELED);
-        if (!buildDialog(component, category)) {
+        if (!buildDialog(component, category, userId)) {
             finish();
         }
 
@@ -63,7 +66,7 @@
     public void onClick(DialogInterface dialog, int which) {
         switch (which) {
             case BUTTON_POSITIVE:
-                mBackend.setDefaultPaymentApp(mNewDefault);
+                mBackend.setDefaultPaymentApp(mNewDefault.componentName, mNewDefault.userId);
                 setResult(RESULT_OK);
                 break;
             case BUTTON_NEGATIVE:
@@ -71,7 +74,7 @@
         }
     }
 
-    private boolean buildDialog(ComponentName component, String category) {
+    private boolean buildDialog(ComponentName component, String category, int userId) {
         if (component == null || category == null) {
             Log.e(TAG, "Component or category are null");
             return false;
@@ -88,10 +91,12 @@
 
         List<PaymentAppInfo> services = mBackend.getPaymentAppInfos();
         for (PaymentAppInfo service : services) {
-            if (component.equals(service.componentName)) {
+            // check if userId matches
+            if (component.equals(service.componentName)
+                    && service.userHandle.getIdentifier() == userId) {
                 requestedPaymentApp = service;
             }
-            if (service.isDefault) {
+            if (service.isDefault && service.userHandle.getIdentifier() == userId) {
                 defaultPaymentApp = service;
             }
         }
@@ -102,13 +107,17 @@
         }
 
         // Get current mode and default component
-        ComponentName defaultComponent = mBackend.getDefaultPaymentApp();
-        if (defaultComponent != null && defaultComponent.equals(component)) {
+        PaymentInfo defaultComponent = mBackend.getDefaultPaymentApp();
+        if (defaultComponent != null && defaultComponent.componentName.equals(component)
+                && defaultComponent.userId == userId) {
             Log.e(TAG, "Component " + component + " is already default.");
             return false;
         }
 
-        mNewDefault = component;
+        mNewDefault = new PaymentInfo();
+        mNewDefault.componentName = component;
+        mNewDefault.userId = userId;
+
         // Compose dialog; get
         final AlertController.AlertParams p = mAlertParams;
         if (defaultPaymentApp == null) {