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);