Cache default dialer in Telecom (part 1)
In order to avoid a flurry of recursive calls into Telecom on every
Telecom API call, cache the default dialer in the Telecom process and
only update it when either the relevant setting changes or when the
current default dialer has been uninstalled/disabled.
Part 1 of change. Adds the default dialer cache class, but does not
integrate it into the rest of Telecom.
Test: added unit tests
Change-Id: Ie81e8a052b2463bef5df4c60c443c73db880780b
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index f84a545..eccd513 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -29,6 +29,7 @@
<!-- TODO: Needed because we call ActivityManager.getCurrentUser() statically. -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.MANAGE_USERS" />
<!-- Used to access TelephonyManager APIs -->
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
index 76929e7..fa5b6f0 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -259,6 +259,12 @@
}
@Override
+ public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle handle,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ return null;
+ }
+
+ @Override
public void sendBroadcast(Intent intent) {
// TODO -- need to ensure this is captured
}
diff --git a/tests/src/com/android/server/telecom/tests/DefaultDialerCacheTest.java b/tests/src/com/android/server/telecom/tests/DefaultDialerCacheTest.java
new file mode 100644
index 0000000..8ddcb1d
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/DefaultDialerCacheTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2016 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.tests;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.server.telecom.DefaultDialerCache;
+import com.android.server.telecom.TelecomServiceImpl;
+import com.android.server.telecom.TelecomSystem;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class DefaultDialerCacheTest extends TelecomTestCase {
+
+ private static final String DIALER1 = "com.android.dialer";
+ private static final String DIALER2 = "xyz.abc.dialer";
+ private static final String DIALER3 = "aaa.bbb.ccc.ddd";
+ private static final int USER0 = 0;
+ private static final int USER1 = 1;
+ private static final int USER2 = 2;
+
+ private DefaultDialerCache mDefaultDialerCache;
+ private ContentObserver mDefaultDialerSettingObserver;
+ private BroadcastReceiver mPackageChangeReceiver;
+
+ @Mock private TelecomServiceImpl.DefaultDialerManagerAdapter mMockDefaultDialerManager;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
+
+ ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+
+ mDefaultDialerCache = new DefaultDialerCache(
+ mContext, mMockDefaultDialerManager, new TelecomSystem.SyncRoot() { });
+
+ verify(mContext).registerReceiverAsUser(
+ receiverCaptor.capture(), eq(UserHandle.ALL), any(IntentFilter.class),
+ isNull(String.class), isNull(Handler.class));
+ mPackageChangeReceiver = receiverCaptor.getValue();
+ mDefaultDialerSettingObserver = mDefaultDialerCache.getContentObserver();
+
+ when(mMockDefaultDialerManager.getDefaultDialerApplication(any(Context.class), eq(USER0)))
+ .thenReturn(DIALER1);
+ when(mMockDefaultDialerManager.getDefaultDialerApplication(any(Context.class), eq(USER1)))
+ .thenReturn(DIALER2);
+ when(mMockDefaultDialerManager.getDefaultDialerApplication(any(Context.class), eq(USER2)))
+ .thenReturn(DIALER3);
+ }
+
+ @SmallTest
+ public void testThreeUsers() {
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(), DIALER1);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER0), DIALER1);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER1), DIALER2);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER2), DIALER3);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(), DIALER1);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER0), DIALER1);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER1), DIALER2);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER2), DIALER3);
+
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER0));
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER1));
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER2));
+ }
+
+ @SmallTest
+ public void testDialer1PackageChanged() {
+ // Populate the caches first
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER0), DIALER1);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER1), DIALER2);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER2), DIALER3);
+
+ Intent packageChangeIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED,
+ Uri.fromParts("package", DIALER1, null));
+ when(mMockDefaultDialerManager.getDefaultDialerApplication(any(Context.class), eq(USER0)))
+ .thenReturn(DIALER2);
+ mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
+ verify(mMockDefaultDialerManager, times(2))
+ .getDefaultDialerApplication(any(Context.class), eq(USER0));
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER1));
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER2));
+
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER0), DIALER2);
+ }
+
+ @SmallTest
+ public void testRandomOtherPackageChanged() {
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER0), DIALER1);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER1), DIALER2);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER2), DIALER3);
+
+ Intent packageChangeIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED,
+ Uri.fromParts("package", "red.orange.blue", null));
+ mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER0));
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER1));
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER2));
+ }
+
+ @SmallTest
+ public void testPackageRemovedWithoutReplace() {
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER0), DIALER1);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER1), DIALER2);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER2), DIALER3);
+
+ Intent packageChangeIntent = new Intent(Intent.ACTION_PACKAGE_REMOVED,
+ Uri.fromParts("package", DIALER1, null));
+ packageChangeIntent.putExtra(Intent.EXTRA_REPLACING, false);
+
+ mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
+ verify(mMockDefaultDialerManager, times(2))
+ .getDefaultDialerApplication(any(Context.class), eq(USER0));
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER1));
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER2));
+ }
+
+ @SmallTest
+ public void testPackageAdded() {
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER0), DIALER1);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER1), DIALER2);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER2), DIALER3);
+
+ Intent packageChangeIntent = new Intent(Intent.ACTION_PACKAGE_ADDED,
+ Uri.fromParts("package", "ppp.qqq.zzz", null));
+
+ mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
+ verify(mMockDefaultDialerManager, times(2))
+ .getDefaultDialerApplication(any(Context.class), eq(USER0));
+ verify(mMockDefaultDialerManager, times(2))
+ .getDefaultDialerApplication(any(Context.class), eq(USER1));
+ verify(mMockDefaultDialerManager, times(2))
+ .getDefaultDialerApplication(any(Context.class), eq(USER2));
+ }
+
+ @SmallTest
+ public void testPackageRemovedWithReplace() {
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER0), DIALER1);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER1), DIALER2);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER2), DIALER3);
+
+ Intent packageChangeIntent = new Intent(Intent.ACTION_PACKAGE_REMOVED,
+ Uri.fromParts("package", DIALER1, null));
+ packageChangeIntent.putExtra(Intent.EXTRA_REPLACING, true);
+
+ mPackageChangeReceiver.onReceive(mContext, packageChangeIntent);
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER0));
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER1));
+ verify(mMockDefaultDialerManager, times(1))
+ .getDefaultDialerApplication(any(Context.class), eq(USER2));
+ }
+
+ @SmallTest
+ public void testDefaultDialerSettingChanged() {
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER0), DIALER1);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER1), DIALER2);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER2), DIALER3);
+
+ when(mMockDefaultDialerManager.getDefaultDialerApplication(any(Context.class), eq(USER0)))
+ .thenReturn(DIALER2);
+ when(mMockDefaultDialerManager.getDefaultDialerApplication(any(Context.class), eq(USER1)))
+ .thenReturn(DIALER2);
+ when(mMockDefaultDialerManager.getDefaultDialerApplication(any(Context.class), eq(USER2)))
+ .thenReturn(DIALER2);
+ mDefaultDialerSettingObserver.onChange(false);
+
+ verify(mMockDefaultDialerManager, times(2))
+ .getDefaultDialerApplication(any(Context.class), eq(USER0));
+ verify(mMockDefaultDialerManager, times(2))
+ .getDefaultDialerApplication(any(Context.class), eq(USER2));
+ verify(mMockDefaultDialerManager, times(2))
+ .getDefaultDialerApplication(any(Context.class), eq(USER2));
+
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER0), DIALER2);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER1), DIALER2);
+ assertEquals(mDefaultDialerCache.getDefaultDialerApplication(USER2), DIALER2);
+ }
+}