Add RoleManagerAdapter to abstract out Telecom usage of RoleManager:
Adding an abstraction for Telecom rolemanager operations to remove
dependency on the action implementation which is not yet complete.
Test: Manual
Bug: 63966743
Merged-In: I4332b6a274593f378523336271541f94ebb10cdb
Change-Id: I4332b6a274593f378523336271541f94ebb10cdb
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 101ecf8..31787dc 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -287,6 +287,7 @@
/* Handler tied to thread in which CallManager was initialized. */
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final EmergencyCallHelper mEmergencyCallHelper;
+ private final RoleManagerAdapter mRoleManagerAdapter;
private final ConnectionServiceFocusManager.CallsManagerRequester mRequester =
new ConnectionServiceFocusManager.CallsManagerRequester() {
@@ -392,7 +393,8 @@
BluetoothStateReceiver bluetoothStateReceiver,
CallAudioRouteStateMachine.Factory callAudioRouteStateMachineFactory,
CallAudioModeStateMachine.Factory callAudioModeStateMachineFactory,
- InCallControllerFactory inCallControllerFactory) {
+ InCallControllerFactory inCallControllerFactory,
+ RoleManagerAdapter roleManagerAdapter) {
mContext = context;
mLock = lock;
mPhoneNumberUtilsAdapter = phoneNumberUtilsAdapter;
@@ -467,6 +469,7 @@
new ConnectionServiceRepository(mPhoneAccountRegistrar, mContext, mLock, this);
mInCallWakeLockController = inCallWakeLockControllerFactory.create(context, this);
mClockProxy = clockProxy;
+ mRoleManagerAdapter = roleManagerAdapter;
mListeners.add(mInCallWakeLockController);
mListeners.add(statusBarNotifier);
@@ -516,6 +519,10 @@
return mCallerInfoLookupHelper;
}
+ public RoleManagerAdapter getRoleManagerAdapter() {
+ return mRoleManagerAdapter;
+ }
+
@Override
public void onSuccessfulOutgoingCall(Call call, int callState) {
Log.v(this, "onSuccessfulOutgoingCall, %s", call);
@@ -3198,6 +3205,7 @@
public void onUserSwitch(UserHandle userHandle) {
mCurrentUserHandle = userHandle;
mMissedCallNotifier.setCurrentUserHandle(userHandle);
+ mRoleManagerAdapter.setCurrentUserHandle(userHandle);
final UserManager userManager = UserManager.get(mContext);
List<UserInfo> profiles = userManager.getEnabledProfiles(userHandle.getIdentifier());
for (UserInfo profile : profiles) {
@@ -3472,6 +3480,14 @@
mConnectionServiceRepository.dump(pw);
pw.decreaseIndent();
}
+
+ if (mRoleManagerAdapter != null && mRoleManagerAdapter instanceof RoleManagerAdapterImpl) {
+ RoleManagerAdapterImpl impl = (RoleManagerAdapterImpl) mRoleManagerAdapter;
+ pw.println("mRoleManager:");
+ pw.increaseIndent();
+ impl.dump(pw);
+ pw.decreaseIndent();
+ }
}
/**
diff --git a/src/com/android/server/telecom/RoleManagerAdapter.java b/src/com/android/server/telecom/RoleManagerAdapter.java
new file mode 100644
index 0000000..9a0545e
--- /dev/null
+++ b/src/com/android/server/telecom/RoleManagerAdapter.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.telecom;
+
+import android.os.UserHandle;
+
+import java.util.List;
+
+/**
+ * Provides a means of wrapping {@code RoleManager} operations which Telecom uses to aid in testing
+ * and remove direct dependencies.
+ */
+public interface RoleManagerAdapter {
+ /**
+ * Returns the package name of the app which fills the {@link android.app.role.RoleManager} call
+ * screening role.
+ * @return the package name of the app filling the role, {@code null} otherwise}.
+ */
+ String getDefaultCallScreeningApp();
+
+ /**
+ * Override the {@link android.app.role.RoleManager} call screening app with another value.
+ * Used for testing purposes only.
+ * @param packageName Package name of the app to fill the call screening role. Where
+ * {@code null}, the override is removed.
+ */
+ void setTestDefaultCallScreeningApp(String packageName);
+
+ /**
+ * Retrieves a list of package names of the app(s) which fill the
+ * {@link android.app.role.RoleManager} companion device role.
+ * @return List of package names filling the role, or empty list if there are none.
+ */
+ List<String> getCallCompanionApps();
+
+ /**
+ * Set a package to be added to the list of the {@link android.app.role.RoleManager} companion
+ * apps. Used for testing purposes only.
+ * @param packageName Package name of the app to be added or removed as an override call
+ * companion app.
+ * @param isAdded {@code true} if the specified package should be added, {@code false} if it
+ * should be removed.
+ */
+ void addOrRemoveTestCallCompanionApp(String packageName, boolean isAdded);
+
+ /**
+ * Returns the package name of the app which fills the {@link android.app.role.RoleManager}
+ * projection mode role.
+ * @return Package name of the car more app or {@code null} if there are no apps that fill this
+ * role.
+ */
+ String getCarModeDialerApp();
+
+ /**
+ * Override the {@link android.app.role.RoleManager} automotive app with another value.
+ * Used for testing purposes only.
+ * @param packageName Package name of the app to fill the automotive app role. Where
+ * {@code null}, the override is removed.
+ */
+ void setTestAutoModeApp(String packageName);
+
+ /**
+ * Using role manager needs to know the current user handle. Need to make sure the role manager
+ * adapter can pass this to role manager. As it changes, we'll pass it in.
+ * @param currentUserHandle The new user handle.
+ */
+ void setCurrentUserHandle(UserHandle currentUserHandle);
+}
diff --git a/src/com/android/server/telecom/RoleManagerAdapterImpl.java b/src/com/android/server/telecom/RoleManagerAdapterImpl.java
new file mode 100644
index 0000000..c6142f9
--- /dev/null
+++ b/src/com/android/server/telecom/RoleManagerAdapterImpl.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.telecom;
+
+import android.os.UserHandle;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class RoleManagerAdapterImpl implements RoleManagerAdapter {
+ // TODO: replace with actual role manager const.
+ private static final String ROLE_CAR_MODE_DIALER = "android.app.role.ROLE_CAR_MODE_DIALER";
+ // TODO: replace with actual role manager const.
+ private static final String ROLE_CALL_SCREENING = "android.app.role.CALL_SCREENING";
+ // TODO: replace with actual role manager const.
+ private static final String ROLE_CALL_COMPANION_APP =
+ "android.app.role.ROLE_CALL_COMPANION_APP";
+
+ private String mOverrideDefaultCallScreeningApp = null;
+ private String mOverrideDefaultCarModeApp = null;
+ private List<String> mOverrideCallCompanionApps = new ArrayList<>();
+ private UserHandle mCurrentUserHandle;
+
+ public RoleManagerAdapterImpl() {
+ }
+
+ @Override
+ public String getDefaultCallScreeningApp() {
+ if (mOverrideDefaultCallScreeningApp != null) {
+ return mOverrideDefaultCallScreeningApp;
+ }
+ return getRoleManagerCallScreeningApp();
+ }
+
+ @Override
+ public void setTestDefaultCallScreeningApp(String packageName) {
+ mOverrideDefaultCallScreeningApp = packageName;
+ }
+
+ @Override
+ public List<String> getCallCompanionApps() {
+ List<String> callCompanionApps = getRoleManagerCallCompanionApps();
+ callCompanionApps.addAll(mOverrideCallCompanionApps);
+ return callCompanionApps;
+ }
+
+ @Override
+ public void addOrRemoveTestCallCompanionApp(String packageName, boolean isAdded) {
+ if (isAdded) {
+ mOverrideCallCompanionApps.add(packageName);
+ } else {
+ mOverrideCallCompanionApps.remove(packageName);
+ }
+ }
+
+ @Override
+ public String getCarModeDialerApp() {
+ if (mOverrideDefaultCarModeApp != null) {
+ return mOverrideDefaultCarModeApp;
+ }
+ return getRoleManagerCarModeDialerApp();
+ }
+
+ @Override
+ public void setTestAutoModeApp(String packageName) {
+ mOverrideDefaultCarModeApp = packageName;
+ }
+
+ @Override
+ public void setCurrentUserHandle(UserHandle currentUserHandle) {
+ mCurrentUserHandle = currentUserHandle;
+ }
+
+ private String getRoleManagerCallScreeningApp() {
+ // TODO: Link in RoleManager
+ return null;
+ }
+
+ private String getRoleManagerCarModeDialerApp() {
+ // TODO: Link in RoleManager
+ return null;
+ }
+
+ private List<String> getRoleManagerCallCompanionApps() {
+ // TODO: Link in RoleManager
+ return Collections.emptyList();
+ }
+
+ /**
+ * Dumps the state of the {@link InCallController}.
+ *
+ * @param pw The {@code IndentingPrintWriter} to write the state to.
+ */
+ public void dump(IndentingPrintWriter pw) {
+ pw.print("DefaultCallScreeningApp: ");
+ if (mOverrideDefaultCallScreeningApp != null) {
+ pw.print("(override ");
+ pw.print(mOverrideDefaultCallScreeningApp);
+ pw.print(") ");
+ pw.print(getRoleManagerCallScreeningApp());
+ }
+ pw.println();
+
+ pw.print("DefaultCarModeDialerApp: ");
+ if (mOverrideDefaultCallScreeningApp != null) {
+ pw.print("(override ");
+ pw.print(mOverrideDefaultCarModeApp);
+ pw.print(") ");
+ pw.print(getRoleManagerCarModeDialerApp());
+ }
+ pw.println();
+
+ pw.print("DefaultCallCompanionApps: ");
+ if (mOverrideDefaultCallScreeningApp != null) {
+ pw.print("(override ");
+ pw.print(mOverrideCallCompanionApps.stream().collect(Collectors.joining(", ")));
+ pw.print(") ");
+ List<String> appsInRole = getRoleManagerCallCompanionApps();
+ if (appsInRole != null) {
+ pw.print(appsInRole.stream().collect(Collectors.joining(", ")));
+ }
+ }
+ pw.println();
+ }
+}
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 2b2408e..dc66440 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -39,6 +39,7 @@
import android.content.res.Resources;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
@@ -1666,6 +1667,71 @@
Log.endSession();
}
}
+
+ @Override
+ public void setTestDefaultCallScreeningApp(String packageName) {
+ try {
+ Log.startSession("TSI.sTDCSA");
+ enforceModifyPermission();
+ if (!Build.IS_USERDEBUG) {
+ throw new SecurityException("Test-only API.");
+ }
+ synchronized (mLock) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mCallsManager.getRoleManagerAdapter().setTestDefaultCallScreeningApp(
+ packageName);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ } finally {
+ Log.endSession();
+ }
+ }
+
+ @Override
+ public void addOrRemoveTestCallCompanionApp(String packageName, boolean isAdded) {
+ try {
+ Log.startSession("TSI.aORTCCA");
+ enforceModifyPermission();
+ if (!Build.IS_USERDEBUG) {
+ throw new SecurityException("Test-only API.");
+ }
+ synchronized (mLock) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mCallsManager.getRoleManagerAdapter().addOrRemoveTestCallCompanionApp(
+ packageName, isAdded);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ } finally {
+ Log.endSession();
+ }
+ }
+
+ @Override
+ public void setTestAutoModeApp(String packageName) {
+ try {
+ Log.startSession("TSI.sTAMA");
+ enforceModifyPermission();
+ if (!Build.IS_USERDEBUG) {
+ throw new SecurityException("Test-only API.");
+ }
+ synchronized (mLock) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mCallsManager.getRoleManagerAdapter().setTestAutoModeApp(packageName);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ } finally {
+ Log.endSession();
+ }
+ }
};
/**
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index c22bfec..9153414 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -257,6 +257,8 @@
}
};
+ RoleManagerAdapter roleManagerAdapter = new RoleManagerAdapterImpl();
+
mCallsManager = new CallsManager(
mContext,
mLock,
@@ -282,7 +284,8 @@
bluetoothStateReceiver,
callAudioRouteStateMachineFactory,
new CallAudioModeStateMachine.Factory(),
- inCallControllerFactory);
+ inCallControllerFactory,
+ roleManagerAdapter);
mIncomingCallNotifier = incomingCallNotifier;
incomingCallNotifier.setCallsManagerProxy(new IncomingCallNotifier.CallsManagerProxy() {
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index 7bfd82f..dff89c9 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -70,6 +70,7 @@
import com.android.server.telecom.PhoneNumberUtilsAdapter;
import com.android.server.telecom.ProximitySensorManager;
import com.android.server.telecom.ProximitySensorManagerFactory;
+import com.android.server.telecom.RoleManagerAdapter;
import com.android.server.telecom.SystemStateHelper;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;
@@ -149,6 +150,7 @@
@Mock private CallAudioModeStateMachine mCallAudioModeStateMachine;
@Mock private CallAudioModeStateMachine.Factory mCallAudioModeStateMachineFactory;
@Mock private BluetoothStateReceiver mBluetoothStateReceiver;
+ @Mock private RoleManagerAdapter mRoleManagerAdapter;
private CallsManager mCallsManager;
@@ -172,6 +174,7 @@
when(mClockProxy.currentTimeMillis()).thenReturn(System.currentTimeMillis());
when(mClockProxy.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime());
when(mConnSvrFocusManagerFactory.create(any())).thenReturn(mConnectionSvrFocusMgr);
+ doNothing().when(mRoleManagerAdapter).setCurrentUserHandle(any());
mCallsManager = new CallsManager(
mComponentContextFixture.getTestDouble().getApplicationContext(),
mLock,
@@ -197,7 +200,8 @@
mBluetoothStateReceiver,
mCallAudioRouteStateMachineFactory,
mCallAudioModeStateMachineFactory,
- mInCallControllerFactory);
+ mInCallControllerFactory,
+ mRoleManagerAdapter);
when(mPhoneAccountRegistrar.getPhoneAccount(
eq(SELF_MANAGED_HANDLE), any())).thenReturn(SELF_MANAGED_ACCOUNT);