Merge "Add more detail to exception message"
diff --git a/src/com/android/phone/RcsProvisioningMonitor.java b/src/com/android/phone/RcsProvisioningMonitor.java
index 98003bd..c4f367d 100644
--- a/src/com/android/phone/RcsProvisioningMonitor.java
+++ b/src/com/android/phone/RcsProvisioningMonitor.java
@@ -47,8 +47,10 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
 
 /**
  * Class to monitor RCS Provisioning Status
@@ -81,6 +83,7 @@
     private final DmaChangedListener mDmaChangedListener;
     private final SubscriptionManager mSubscriptionManager;
     private final TelephonyRegistryManager mTelephonyRegistryManager;
+    private final RoleManagerAdapter mRoleManager;
 
     private static RcsProvisioningMonitor sInstance;
 
@@ -111,8 +114,6 @@
     };
 
     private final class DmaChangedListener implements OnRoleHoldersChangedListener {
-        private RoleManager mRoleManager;
-
         @Override
         public void onRoleHoldersChanged(String role, UserHandle user) {
             if (RoleManager.ROLE_SMS.equals(role)) {
@@ -123,24 +124,19 @@
         }
 
         public void register() {
-            mRoleManager = mPhone.getSystemService(RoleManager.class);
-            if (mRoleManager != null) {
-                try {
-                    mRoleManager.addOnRoleHoldersChangedListenerAsUser(
-                            mPhone.getMainExecutor(), this, UserHandle.SYSTEM);
-                } catch (RuntimeException e) {
-                    loge("Could not register dma change listener due to " + e);
-                }
+            try {
+                mRoleManager.addOnRoleHoldersChangedListenerAsUser(
+                        mPhone.getMainExecutor(), this, UserHandle.SYSTEM);
+            } catch (RuntimeException e) {
+                loge("Could not register dma change listener due to " + e);
             }
         }
 
         public void unregister() {
-            if (mRoleManager != null) {
-                try {
-                    mRoleManager.removeOnRoleHoldersChangedListenerAsUser(this, UserHandle.SYSTEM);
-                } catch (RuntimeException e) {
-                    loge("Could not unregister dma change listener due to " + e);
-                }
+            try {
+                mRoleManager.removeOnRoleHoldersChangedListenerAsUser(this, UserHandle.SYSTEM);
+            } catch (RuntimeException e) {
+                loge("Could not unregister dma change listener due to " + e);
             }
         }
     }
@@ -190,12 +186,13 @@
     }
 
     @VisibleForTesting
-    public RcsProvisioningMonitor(PhoneGlobals app, Looper looper) {
+    public RcsProvisioningMonitor(PhoneGlobals app, Looper looper, RoleManagerAdapter roleManager) {
         mPhone = app;
         mHandler = new MyHandler(looper);
         mCarrierConfigManager = mPhone.getSystemService(CarrierConfigManager.class);
         mSubscriptionManager = mPhone.getSystemService(SubscriptionManager.class);
         mTelephonyRegistryManager = mPhone.getSystemService(TelephonyRegistryManager.class);
+        mRoleManager = roleManager;
         mDmaPackageName = getDmaPackageName();
         logv("DMA is " + mDmaPackageName);
         IntentFilter filter = new IntentFilter();
@@ -217,7 +214,8 @@
             logd("RcsProvisioningMonitor created.");
             HandlerThread handlerThread = new HandlerThread(TAG);
             handlerThread.start();
-            sInstance = new RcsProvisioningMonitor(app, handlerThread.getLooper());
+            sInstance = new RcsProvisioningMonitor(app, handlerThread.getLooper(),
+                    new RoleManagerAdapterImpl(app));
         }
         return sInstance;
     }
@@ -490,8 +488,7 @@
 
     private String getDmaPackageName() {
         try {
-            return CollectionUtils.firstOrNull(mPhone.getSystemService(RoleManager.class)
-                    .getRoleHolders(RoleManager.ROLE_SMS));
+            return CollectionUtils.firstOrNull(mRoleManager.getRoleHolders(RoleManager.ROLE_SMS));
         } catch (RuntimeException e) {
             loge("Could not get dma name due to " + e);
             return null;
@@ -517,4 +514,44 @@
     private static void loge(String msg) {
         Rlog.e(TAG, msg);
     }
+
+    /**
+     * {@link RoleManager} is final so we have to wrap the implementation for testing.
+     */
+    @VisibleForTesting
+    public interface RoleManagerAdapter {
+        /** See {@link RoleManager#getRoleHolders(String)} */
+        List<String> getRoleHolders(String roleName);
+        /** See {@link RoleManager#addOnRoleHoldersChangedListenerAsUser} */
+        void addOnRoleHoldersChangedListenerAsUser(Executor executor,
+                OnRoleHoldersChangedListener listener, UserHandle user);
+        /** See {@link RoleManager#removeOnRoleHoldersChangedListenerAsUser} */
+        void removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener,
+                UserHandle user);
+    }
+
+    private static class RoleManagerAdapterImpl implements RoleManagerAdapter {
+        private final RoleManager mRoleManager;
+
+        private RoleManagerAdapterImpl(Context context) {
+            mRoleManager = context.getSystemService(RoleManager.class);
+        }
+
+        @Override
+        public List<String> getRoleHolders(String roleName) {
+            return mRoleManager.getRoleHolders(roleName);
+        }
+
+        @Override
+        public void addOnRoleHoldersChangedListenerAsUser(Executor executor,
+                OnRoleHoldersChangedListener listener, UserHandle user) {
+            mRoleManager.addOnRoleHoldersChangedListenerAsUser(executor, listener, user);
+        }
+
+        @Override
+        public void removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener,
+                UserHandle user) {
+            mRoleManager.removeOnRoleHoldersChangedListenerAsUser(listener, user);
+        }
+    }
 }
diff --git a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
index 5035284..fb1e502 100644
--- a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
+++ b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
@@ -24,18 +24,15 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.app.role.IOnRoleHoldersChangedListener;
-import android.app.role.IRoleManager;
+import android.app.role.OnRoleHoldersChangedListener;
 import android.app.role.RoleManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentValues;
@@ -46,12 +43,8 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.IInterface;
 import android.os.Looper;
 import android.os.PersistableBundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Telephony.SimInfo;
 import android.telephony.CarrierConfigManager;
@@ -76,15 +69,12 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoSession;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
-import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.Executor;
 
 /**
@@ -115,7 +105,6 @@
     private static final String DEFAULT_MESSAGING_APP1 = "DMA1";
     private static final String DEFAULT_MESSAGING_APP2 = "DMA2";
 
-    private MockitoSession mSession;
     private RcsProvisioningMonitor mRcsProvisioningMonitor;
     private Handler mHandler;
     private HandlerThread mHandlerThread;
@@ -133,10 +122,9 @@
     private TelephonyRegistryManager mTelephonyRegistryManager;
     @Mock
     private CarrierConfigManager mCarrierConfigManager;
-    private IOnRoleHoldersChangedListener.Stub mRoleHolderChangedListener;
-    private RoleManager mRoleManager;
+    private OnRoleHoldersChangedListener mRoleHolderChangedListener;
     @Mock
-    private IRoleManager.Stub mIRoleManager;
+    private RcsProvisioningMonitor.RoleManagerAdapter mRoleManager;
     @Mock
     private ITelephony.Stub mITelephony;
     @Mock
@@ -189,8 +177,6 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
-        replaceService(Context.ROLE_SERVICE, mIRoleManager);
-        mRoleManager = new RoleManager(mPhone);
         when(mPhone.getResources()).thenReturn(mResources);
         when(mResources.getBoolean(
                 eq(R.bool.config_rcsVolteSingleRegistrationEnabled))).thenReturn(true);
@@ -209,8 +195,6 @@
                 .thenReturn(mSubscriptionManager);
         when(mPhone.getSystemService(eq(Context.TELEPHONY_REGISTRY_SERVICE)))
                 .thenReturn(mTelephonyRegistryManager);
-        when(mPhone.getSystemService(eq(Context.ROLE_SERVICE)))
-                .thenReturn(mRoleManager);
 
         mBundle = new PersistableBundle();
         when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mBundle);
@@ -237,15 +221,15 @@
         doAnswer(new Answer<Void>() {
             @Override
             public Void answer(InvocationOnMock invocation) throws Throwable {
-                mRoleHolderChangedListener = (IOnRoleHoldersChangedListener.Stub)
-                        invocation.getArguments()[0];
+                mRoleHolderChangedListener = (OnRoleHoldersChangedListener)
+                        invocation.getArguments()[1];
                 return null;
             }
-        }).when(mIRoleManager).addOnRoleHoldersChangedListenerAsUser(
-                any(IOnRoleHoldersChangedListener.Stub.class), anyInt());
+        }).when(mRoleManager).addOnRoleHoldersChangedListenerAsUser(any(Executor.class),
+                any(OnRoleHoldersChangedListener.class), any(UserHandle.class));
         List<String> dmas = new ArrayList<>();
         dmas.add(DEFAULT_MESSAGING_APP1);
-        when(mIRoleManager.getRoleHoldersAsUser(any(), anyInt())).thenReturn(dmas);
+        when(mRoleManager.getRoleHolders(eq(RoleManager.ROLE_SMS))).thenReturn(dmas);
 
         mProvider = new SimInfoContentProvider(mPhone);
         mProvider.setCursor(mCursor);
@@ -268,9 +252,6 @@
             mRcsProvisioningMonitor = null;
         }
 
-        if (mSession != null) {
-            mSession.finishMocking();
-        }
         if (mLooper != null) {
             mLooper.destroy();
             mLooper = null;
@@ -487,7 +468,8 @@
             Looper.prepare();
         }
         makeFakeActiveSubIds(subCount);
-        mRcsProvisioningMonitor = new RcsProvisioningMonitor(mPhone, mHandlerThread.getLooper());
+        mRcsProvisioningMonitor = new RcsProvisioningMonitor(mPhone, mHandlerThread.getLooper(),
+                mRoleManager);
         mHandler = mRcsProvisioningMonitor.getHandler();
         try {
             mLooper = new TestableLooper(mHandler.getLooper());
@@ -512,27 +494,12 @@
         when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(subIds);
     }
 
-    private void updateDefaultMessageApplication(String packageName) throws Exception {
+    private void updateDefaultMessageApplication(String packageName) {
         List<String> dmas = new ArrayList<>();
         dmas.add(packageName);
-        when(mIRoleManager.getRoleHoldersAsUser(any(), anyInt())).thenReturn(dmas);
-        mExecutor.execute(() -> {
-            try {
-                mRoleHolderChangedListener.onRoleHoldersChanged(
-                        RoleManager.ROLE_SMS, UserHandle.USER_ALL);
-            } catch (RemoteException e) {
-                logd("exception to call onRoleHoldersChanged " + e);
-            }
-        });
-    }
-
-    private void replaceService(final String serviceName,
-            final IInterface serviceInstance) throws Exception {
-        IBinder binder = mock(IBinder.class);
-        when(binder.queryLocalInterface(anyString())).thenReturn(serviceInstance);
-        Field field = ServiceManager.class.getDeclaredField("sCache");
-        field.setAccessible(true);
-        ((Map<String, IBinder>) field.get(null)).put(serviceName, binder);
+        when(mRoleManager.getRoleHolders(eq(RoleManager.ROLE_SMS))).thenReturn(dmas);
+        mExecutor.execute(() -> mRoleHolderChangedListener.onRoleHoldersChanged(
+                RoleManager.ROLE_SMS, UserHandle.ALL));
     }
 
     private void processAllMessages() {