Merge "Ensure current user is used when setting the PhoneAccountSuggestionService." into main
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index a7ad3b8..1e6d2bc 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -2066,7 +2066,8 @@
                         return CompletableFuture.completedFuture(
                                 Collections.singletonList(suggestion));
                     }
-                    return PhoneAccountSuggestionHelper.bindAndGetSuggestions(mContext,
+                    Context userContext = mContext.createContextAsUser(getCurrentUserHandle(), 0);
+                    return PhoneAccountSuggestionHelper.bindAndGetSuggestions(userContext,
                             finalCall.getHandle(), potentialPhoneAccounts);
                 }, new LoggedHandlerExecutor(outgoingCallHandler, "CM.cOCSS", mLock));
 
diff --git a/src/com/android/server/telecom/PhoneAccountSuggestionHelper.java b/src/com/android/server/telecom/PhoneAccountSuggestionHelper.java
index 438ee68..ab55703 100644
--- a/src/com/android/server/telecom/PhoneAccountSuggestionHelper.java
+++ b/src/com/android/server/telecom/PhoneAccountSuggestionHelper.java
@@ -27,6 +27,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.telecom.Log;
 import android.telecom.Logging.Session;
 import android.telecom.PhoneAccountHandle;
@@ -46,6 +47,7 @@
 public class PhoneAccountSuggestionHelper {
     private static final String TAG = PhoneAccountSuggestionHelper.class.getSimpleName();
     private static ComponentName sOverrideComponent;
+    private static UserHandle sOverrideUserHandle;
 
     /**
      * @return A future (possible already complete) that contains a list of suggestions.
@@ -53,6 +55,15 @@
     public static CompletableFuture<List<PhoneAccountSuggestion>>
     bindAndGetSuggestions(Context context, Uri handle,
             List<PhoneAccountHandle> availablePhoneAccounts) {
+        Context userContext;
+        if (sOverrideUserHandle != null) {
+            userContext = context.createContextAsUser(sOverrideUserHandle, 0);
+            Log.i(TAG, "bindAndGetSuggestions created context as user;  userContext=%s",
+                    userContext);
+        } else {
+            userContext = context;
+        }
+
         // Use the default list if there's no handle
         if (handle == null) {
             return CompletableFuture.completedFuture(getDefaultSuggestions(availablePhoneAccounts));
@@ -60,7 +71,7 @@
         String number = PhoneNumberUtils.extractNetworkPortion(handle.getSchemeSpecificPart());
 
         // Use the default list if there's no service on the device.
-        ServiceInfo suggestionServiceInfo = getSuggestionServiceInfo(context);
+        ServiceInfo suggestionServiceInfo = getSuggestionServiceInfo(userContext);
         if (suggestionServiceInfo == null) {
             return CompletableFuture.completedFuture(getDefaultSuggestions(availablePhoneAccounts));
         }
@@ -124,7 +135,7 @@
             }
         };
 
-        if (!context.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE)) {
+        if (!userContext.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE)) {
             Log.i(TAG, "Cancelling suggestion process due to bind failure.");
             future.complete(getDefaultSuggestions(availablePhoneAccounts));
         }
@@ -143,7 +154,7 @@
                         Log.endSession();
                     }
                 },
-                Timeouts.getPhoneAccountSuggestionServiceTimeout(context.getContentResolver()));
+                Timeouts.getPhoneAccountSuggestionServiceTimeout(userContext.getContentResolver()));
         return future;
     }
 
@@ -162,10 +173,25 @@
     }
 
     private static ServiceInfo getSuggestionServiceInfo(Context context) {
-        PackageManager packageManager = context.getPackageManager();
+        Context userContext;
+        if (sOverrideUserHandle != null) {
+            userContext = context.createContextAsUser(sOverrideUserHandle, 0);
+            Log.i(TAG, "getSuggestionServiceInfo: Created context as user; userContext= %s",
+                    userContext);
+        } else {
+            userContext = context;
+        }
+
+        PackageManager packageManager = userContext.getPackageManager();
+
         Intent queryIntent = new Intent();
         queryIntent.setAction(PhoneAccountSuggestionService.SERVICE_INTERFACE);
 
+        if (packageManager == null) {
+            Log.i(TAG, "getSuggestionServiceInfo: PackageManager is null. Using defaults.");
+            return null;
+        }
+
         List<ResolveInfo> services;
         if (sOverrideComponent == null) {
             services = packageManager.queryIntentServices(queryIntent,
@@ -199,6 +225,15 @@
         }
     }
 
+    static void setOverrideUserHandle(UserHandle userHandle) {
+        try {
+            sOverrideUserHandle = userHandle;
+        } catch (Exception e) {
+            sOverrideUserHandle = null;
+            throw e;
+        }
+    }
+
     private static List<PhoneAccountSuggestion> getDefaultSuggestions(
             List<PhoneAccountHandle> phoneAccountHandles) {
         return phoneAccountHandles.stream().map(phoneAccountHandle ->
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 20320f2..b8141bf 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -2555,7 +2555,8 @@
         }
 
         @Override
-        public void setTestPhoneAcctSuggestionComponent(String flattenedComponentName) {
+        public void setTestPhoneAcctSuggestionComponent(String flattenedComponentName,
+                UserHandle userHandle) {
             try {
                 Log.startSession("TSI.sPASA");
                 enforceModifyPermission();
@@ -2565,6 +2566,7 @@
                 }
                 synchronized (mLock) {
                     PhoneAccountSuggestionHelper.setOverrideServiceName(flattenedComponentName);
+                    PhoneAccountSuggestionHelper.setOverrideUserHandle(userHandle);
                 }
             } finally {
                 Log.endSession();
diff --git a/src/com/android/server/telecom/TelecomShellCommand.java b/src/com/android/server/telecom/TelecomShellCommand.java
index 557002c..11ceb26 100644
--- a/src/com/android/server/telecom/TelecomShellCommand.java
+++ b/src/com/android/server/telecom/TelecomShellCommand.java
@@ -341,7 +341,8 @@
 
     private void runSetTestPhoneAcctSuggestionComponent() throws RemoteException {
         final String componentName = getNextArg();
-        mTelecomService.setTestPhoneAcctSuggestionComponent(componentName);
+        final UserHandle userHandle = getUserHandleFromArgs();
+        mTelecomService.setTestPhoneAcctSuggestionComponent(componentName, userHandle);
     }
 
     private void runSetUserSelectedOutgoingPhoneAccount() throws RemoteException {
@@ -457,6 +458,22 @@
         mTelecomService.requestLogMark(message);
     }
 
+    private UserHandle getUserHandleFromArgs() throws RemoteException {
+        if (TextUtils.isEmpty(peekNextArg())) {
+            return null;
+        }
+        final String userSnInStr = getNextArgRequired();
+        UserHandle userHandle;
+        try {
+            final int userSn = Integer.parseInt(userSnInStr);
+            userHandle = UserHandle.of(getUserManager().getUserHandle(userSn));
+        } catch (NumberFormatException ex) {
+            Log.w(this, "getPhoneAccountHandleFromArgs - invalid user %s", userSnInStr);
+            throw new IllegalArgumentException ("Invalid user serial number " + userSnInStr);
+        }
+        return userHandle;
+    }
+
     private PhoneAccountHandle getPhoneAccountHandleFromArgs() throws RemoteException {
         if (TextUtils.isEmpty(peekNextArg())) {
             return null;