Merge "Resolve referencing for preferred audio routing" into main
diff --git a/flags/telecom_connection_service_wrapper_flags.aconfig b/flags/telecom_connection_service_wrapper_flags.aconfig
index 38e5e13..8e77af5 100644
--- a/flags/telecom_connection_service_wrapper_flags.aconfig
+++ b/flags/telecom_connection_service_wrapper_flags.aconfig
@@ -7,4 +7,15 @@
namespace: "telecom"
description: "Ensure that the associatedCallCount of CS and RCS is accurately being tracked."
bug: "286154316"
+}
+
+# OWNER=tjstuart TARGET=24Q4
+flag {
+ name: "csw_service_interface_is_null"
+ namespace: "telecom"
+ description: "fix potential NPE in onCreateConnection when the ServiceInterface is cleared out"
+ bug: "364811868"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
\ No newline at end of file
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index 0a99903..4283b7b 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -2110,8 +2110,9 @@
private int getCurrentCallSupportedRoutes() {
int supportedRoutes = CallAudioState.ROUTE_ALL;
- if (mCallsManager.getForegroundCall() != null) {
- supportedRoutes &= mCallsManager.getForegroundCall().getSupportedAudioRoutes();
+ Call foregroundCall = mCallsManager.getForegroundCall();
+ if (foregroundCall != null) {
+ supportedRoutes &= foregroundCall.getSupportedAudioRoutes();
}
return supportedRoutes;
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/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 5e00a72..44686b7 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -1712,14 +1712,19 @@
.setRttPipeToInCall(call.getCsToInCallRttPipeForCs())
.build();
try {
- mServiceInterface.createConnection(
- call.getConnectionManagerPhoneAccount(),
- callId,
- connectionRequest,
- call.shouldAttachToExistingConnection(),
- call.isUnknown(),
- Log.getExternalSession(TELECOM_ABBREVIATION));
-
+ if (mFlags.cswServiceInterfaceIsNull() && mServiceInterface == null) {
+ mPendingResponses.remove(callId).handleCreateConnectionFailure(
+ new DisconnectCause(DisconnectCause.ERROR,
+ "CSW#oCC ServiceInterface is null"));
+ } else {
+ mServiceInterface.createConnection(
+ call.getConnectionManagerPhoneAccount(),
+ callId,
+ connectionRequest,
+ call.shouldAttachToExistingConnection(),
+ call.isUnknown(),
+ Log.getExternalSession(TELECOM_ABBREVIATION));
+ }
} catch (RemoteException e) {
Log.e(this, e, "Failure to createConnection -- %s", getComponentName());
mPendingResponses.remove(callId).handleCreateConnectionFailure(
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;