summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2021-10-07 23:50:24 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2021-10-07 23:50:24 +0000
commit4dffc62f2b5462ddcd01051c9b479e8e91055376 (patch)
tree80afdab2635af0425aca44dc2df05dd652ebcaa7 /tests
parent66273f82ba3a6097a4189d453df35aac4b1407b5 (diff)
parenta920c1b1ca4e2a7d34ea0a08fb06b7cca0a3e8fd (diff)
downloadplatform_packages_services_Telecomm-master.tar.gz
platform_packages_services_Telecomm-master.tar.bz2
platform_packages_services_Telecomm-master.zip
Merge "Merge Android 12"HEADmaster
Diffstat (limited to 'tests')
-rw-r--r--tests/AndroidManifest.xml8
-rw-r--r--tests/src/com/android/server/telecom/tests/AnalyticsTests.java3
-rw-r--r--tests/src/com/android/server/telecom/tests/BasicCallTests.java6
-rw-r--r--tests/src/com/android/server/telecom/tests/BlockedNumbersUtilTests.java60
-rw-r--r--tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java42
-rw-r--r--tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java32
-rw-r--r--tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java38
-rw-r--r--tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java46
-rw-r--r--tests/src/com/android/server/telecom/tests/CallLogManagerTest.java62
-rw-r--r--tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java4
-rw-r--r--tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java56
-rw-r--r--tests/src/com/android/server/telecom/tests/CallsManagerTest.java117
-rw-r--r--tests/src/com/android/server/telecom/tests/CarModeTrackerTest.java111
-rw-r--r--tests/src/com/android/server/telecom/tests/ComponentContextFixture.java62
-rwxr-xr-xtests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java5
-rw-r--r--tests/src/com/android/server/telecom/tests/InCallControllerTests.java252
-rw-r--r--tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java56
-rw-r--r--tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java2
-rw-r--r--tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java10
-rw-r--r--tests/src/com/android/server/telecom/tests/RingerTest.java10
-rw-r--r--tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java81
-rw-r--r--tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java41
22 files changed, 963 insertions, 141 deletions
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 22f5348da..e8c69d419 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -26,6 +26,7 @@
<!-- TODO: Needed because we call BluetoothAdapter.getDefaultAdapter() statically, and
BluetoothAdapter is a final class. -->
<uses-permission android:name="android.permission.BLUETOOTH" />
+ <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<!-- TODO: Needed because we call ActivityManager.getCurrentUser() statically. -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
@@ -36,6 +37,13 @@
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <!-- Used to access Projection State APIs -->
+ <uses-permission android:name="android.permission.READ_PROJECTION_STATE"/>
+
+ <!-- Used to access PlatformCompat APIs -->
+ <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+ <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
+
<application android:label="@string/app_name"
android:debuggable="true">
<uses-library android:name="android.test.runner" />
diff --git a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
index a4cc521d4..2a304a43d 100644
--- a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
+++ b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
@@ -30,6 +30,7 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.content.ContentResolver;
import android.content.Context;
import android.os.Build;
import android.telecom.CallAudioState;
@@ -185,6 +186,8 @@ public class AnalyticsTests extends TelecomSystemTest {
@MediumTest
@Test
public void testAnalyticsTwoCalls() throws Exception {
+ when(mTimeoutsAdapter.getCallScreeningTimeoutMillis(any(ContentResolver.class)))
+ .thenReturn((long) TEST_TIMEOUT);
IdPair testCall1 = startAndMakeActiveIncomingCall(
"650-555-1212",
mPhoneAccountA0.getAccountHandle(),
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index a8e1c00b4..a3b8654f5 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -63,6 +63,7 @@ import com.google.common.base.Predicate;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -473,6 +474,7 @@ public class BasicCallTests extends TelecomSystemTest {
@LargeTest
@Test
@FlakyTest
+ @Ignore("b/189904580")
public void testIncomingCallFromBlockedNumberIsRejected() throws Exception {
String phoneNumber = "650-555-1212";
blockNumber(phoneNumber);
@@ -492,6 +494,7 @@ public class BasicCallTests extends TelecomSystemTest {
waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(),
TEST_TIMEOUT);
+
assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size());
for (CallerInfoAsyncQueryFactoryFixture.Request request :
mCallerInfoAsyncQueryFactoryFixture.mRequests) {
@@ -827,8 +830,7 @@ public class BasicCallTests extends TelecomSystemTest {
private void blockNumberWithAnswer(String phoneNumber, Answer answer) throws Exception {
when(getBlockedNumberProvider().call(
- anyString(),
- nullable(String.class),
+ any(),
anyString(),
eq(BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER),
eq(phoneNumber),
diff --git a/tests/src/com/android/server/telecom/tests/BlockedNumbersUtilTests.java b/tests/src/com/android/server/telecom/tests/BlockedNumbersUtilTests.java
new file mode 100644
index 000000000..56cb73570
--- /dev/null
+++ b/tests/src/com/android/server/telecom/tests/BlockedNumbersUtilTests.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 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 static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.verify;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.os.UserHandle;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.server.telecom.settings.BlockedNumbersUtil;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class BlockedNumbersUtilTests extends TelecomTestCase {
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @SmallTest
+ @Test
+ public void testPostNotification() {
+ BlockedNumbersUtil.updateEmergencyCallNotification(mContext, true);
+ NotificationManager mgr = mComponentContextFixture.getNotificationManager();
+ verify(mgr).notifyAsUser(isNull(), anyInt(), any(Notification.class),
+ any(UserHandle.class));
+ }
+
+ @SmallTest
+ @Test
+ public void testDismissNotification() {
+ BlockedNumbersUtil.updateEmergencyCallNotification(mContext, false);
+ NotificationManager mgr = mComponentContextFixture.getNotificationManager();
+ verify(mgr).cancelAsUser(isNull(), anyInt(), any(UserHandle.class));
+ }
+}
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
index bfa7a75bb..02fdecc3c 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
@@ -26,8 +26,6 @@ import android.content.Intent;
import android.os.Parcel;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.server.telecom.BluetoothAdapterProxy;
-import com.android.server.telecom.BluetoothHeadsetProxy;
import com.android.server.telecom.bluetooth.BluetoothDeviceManager;
import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import com.android.server.telecom.bluetooth.BluetoothStateReceiver;
@@ -54,8 +52,8 @@ import java.util.Arrays;
@RunWith(JUnit4.class)
public class BluetoothDeviceManagerTest extends TelecomTestCase {
@Mock BluetoothRouteManager mRouteManager;
- @Mock BluetoothHeadsetProxy mHeadsetProxy;
- @Mock BluetoothAdapterProxy mAdapterProxy;
+ @Mock BluetoothHeadset mBluetoothHeadset;
+ @Mock BluetoothAdapter mAdapter;
@Mock BluetoothHearingAid mBluetoothHearingAid;
BluetoothDeviceManager mBluetoothDeviceManager;
@@ -82,18 +80,18 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
when(mBluetoothHearingAid.getHiSyncId(device4)).thenReturn(100L);
mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
- mBluetoothDeviceManager = new BluetoothDeviceManager(mContext, mAdapterProxy);
+ mBluetoothDeviceManager = new BluetoothDeviceManager(mContext, mAdapter);
mBluetoothDeviceManager.setBluetoothRouteManager(mRouteManager);
ArgumentCaptor<BluetoothProfile.ServiceListener> serviceCaptor =
ArgumentCaptor.forClass(BluetoothProfile.ServiceListener.class);
- verify(mAdapterProxy).getProfileProxy(eq(mContext),
+ verify(mAdapter).getProfileProxy(eq(mContext),
serviceCaptor.capture(), eq(BluetoothProfile.HEADSET));
serviceListenerUnderTest = serviceCaptor.getValue();
receiverUnderTest = new BluetoothStateReceiver(mBluetoothDeviceManager, mRouteManager);
- mBluetoothDeviceManager.setHeadsetServiceForTesting(mHeadsetProxy);
+ mBluetoothDeviceManager.setHeadsetServiceForTesting(mBluetoothHeadset);
mBluetoothDeviceManager.setHearingAidServiceForTesting(mBluetoothHearingAid);
}
@@ -127,7 +125,7 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
assertEquals(0, mBluetoothDeviceManager.getNumConnectedDevices());
}
-
+
@SmallTest
@Test
public void testMultiDeviceConnectAndDisconnect() {
@@ -173,7 +171,7 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
verify(mRouteManager).onDeviceLost(device1.getAddress());
verify(mRouteManager).onDeviceLost(device3.getAddress());
verify(mRouteManager, never()).onDeviceLost(device2.getAddress());
- assertNull(mBluetoothDeviceManager.getHeadsetService());
+ assertNull(mBluetoothDeviceManager.getBluetoothHeadset());
assertEquals(1, mBluetoothDeviceManager.getNumConnectedDevices());
}
@@ -192,7 +190,7 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
verify(mRouteManager).onDeviceLost(device2.getAddress());
verify(mRouteManager, never()).onDeviceLost(device1.getAddress());
verify(mRouteManager, never()).onDeviceLost(device3.getAddress());
- assertNull(mBluetoothDeviceManager.getHearingAidService());
+ assertNull(mBluetoothDeviceManager.getBluetoothHearingAid());
assertEquals(2, mBluetoothDeviceManager.getNumConnectedDevices());
}
@@ -216,12 +214,14 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
public void testConnectDisconnectAudioHeadset() {
receiverUnderTest.onReceive(mContext,
buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device1, false));
- when(mAdapterProxy.setActiveDevice(nullable(BluetoothDevice.class), eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
+ when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
+ eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
mBluetoothDeviceManager.connectAudio(device1.getAddress());
- verify(mAdapterProxy).setActiveDevice(device1, BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL);
- verify(mAdapterProxy, never()).setActiveDevice(nullable(BluetoothDevice.class), eq(BluetoothAdapter.ACTIVE_DEVICE_ALL));
+ verify(mAdapter).setActiveDevice(device1, BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL);
+ verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class),
+ eq(BluetoothAdapter.ACTIVE_DEVICE_ALL));
mBluetoothDeviceManager.disconnectAudio();
- verify(mHeadsetProxy).disconnectAudio();
+ verify(mBluetoothHeadset).disconnectAudio();
}
@SmallTest
@@ -230,15 +230,17 @@ public class BluetoothDeviceManagerTest extends TelecomTestCase {
receiverUnderTest.onReceive(mContext,
buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device2, true));
mBluetoothDeviceManager.connectAudio(device2.getAddress());
- verify(mAdapterProxy).setActiveDevice(device2, BluetoothAdapter.ACTIVE_DEVICE_ALL);
- verify(mHeadsetProxy, never()).connectAudio();
- verify(mAdapterProxy, never()).setActiveDevice(nullable(BluetoothDevice.class), eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL));
+ verify(mAdapter).setActiveDevice(device2, BluetoothAdapter.ACTIVE_DEVICE_ALL);
+ verify(mBluetoothHeadset, never()).connectAudio();
+ verify(mAdapter, never()).setActiveDevice(nullable(BluetoothDevice.class),
+ eq(BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL));
- when(mBluetoothHearingAid.getActiveDevices()).thenReturn(Arrays.asList(device2, null));
+ when(mAdapter.getActiveDevices(eq(BluetoothProfile.HEARING_AID)))
+ .thenReturn(Arrays.asList(device2, null));
mBluetoothDeviceManager.disconnectAudio();
- verify(mAdapterProxy).setActiveDevice(null, BluetoothAdapter.ACTIVE_DEVICE_ALL);
- verify(mHeadsetProxy).disconnectAudio();
+ verify(mAdapter).setActiveDevice(null, BluetoothAdapter.ACTIVE_DEVICE_ALL);
+ verify(mBluetoothHeadset).disconnectAudio();
}
private Intent buildConnectionActionIntent(int state, BluetoothDevice device,
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
index b20ecfb22..28f69668e 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteManagerTest.java
@@ -16,16 +16,17 @@
package com.android.server.telecom.tests;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothProfile;
import android.content.ContentResolver;
import android.os.Parcel;
import android.telecom.Log;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.internal.os.SomeArgs;
-import com.android.server.telecom.BluetoothHeadsetProxy;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;
import com.android.server.telecom.bluetooth.BluetoothDeviceManager;
@@ -60,8 +61,9 @@ public class BluetoothRouteManagerTest extends TelecomTestCase {
static final BluetoothDevice DEVICE3 = makeBluetoothDevice("00:00:00:00:00:03");
static final BluetoothDevice HEARING_AID_DEVICE = makeBluetoothDevice("00:00:00:00:00:04");
+ @Mock private BluetoothAdapter mBluetoothAdapter;
@Mock private BluetoothDeviceManager mDeviceManager;
- @Mock private BluetoothHeadsetProxy mHeadsetProxy;
+ @Mock private BluetoothHeadset mBluetoothHeadset;
@Mock private BluetoothHearingAid mBluetoothHearingAid;
@Mock private Timeouts.Adapter mTimeoutsAdapter;
@Mock private BluetoothRouteManager.BluetoothStateListener mListener;
@@ -86,7 +88,7 @@ public class BluetoothRouteManagerTest extends TelecomTestCase {
setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, null, null, null);
when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
nullable(ContentResolver.class))).thenReturn(0L);
- when(mHeadsetProxy.connectAudio()).thenReturn(false);
+ when(mBluetoothHeadset.connectAudio()).thenReturn(false);
executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, DEVICE1.getAddress());
// Wait 3 times: for the first connection attempt, the retry attempt,
// the second retry, and once more to make sure there are only three attempts.
@@ -125,7 +127,7 @@ public class BluetoothRouteManagerTest extends TelecomTestCase {
BluetoothRouteManager sm = setupStateMachine(
BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX, DEVICE1);
setupConnectedDevices(new BluetoothDevice[]{DEVICE1}, null, DEVICE1, null);
- when(mHeadsetProxy.getAudioState(DEVICE1))
+ when(mBluetoothHeadset.getAudioState(DEVICE1))
.thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
executeRoutingAction(sm, BluetoothRouteManager.BT_AUDIO_LOST, DEVICE1.getAddress());
@@ -143,7 +145,7 @@ public class BluetoothRouteManagerTest extends TelecomTestCase {
setupConnectedDevices(new BluetoothDevice[]{DEVICE1, DEVICE2}, null, null, null);
when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
nullable(ContentResolver.class))).thenReturn(0L);
- when(mHeadsetProxy.connectAudio()).thenReturn(false);
+ when(mBluetoothHeadset.connectAudio()).thenReturn(false);
executeRoutingAction(sm, BluetoothRouteManager.CONNECT_HFP, DEVICE2.getAddress());
// Wait 3 times: the first connection attempt is accounted for in executeRoutingAction,
// so wait twice for the retry attempt, again to make sure there are only three attempts,
@@ -185,14 +187,15 @@ public class BluetoothRouteManagerTest extends TelecomTestCase {
.collect(Collectors.toList());
when(mDeviceManager.getConnectedDevices()).thenReturn(allDevices);
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(Arrays.asList(hfpDevices));
- when(mHeadsetProxy.getActiveDevice()).thenReturn(hfpActiveDevice);
- when(mHeadsetProxy.getAudioState(hfpActiveDevice))
+ when(mBluetoothHeadset.getConnectedDevices()).thenReturn(Arrays.asList(hfpDevices));
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEADSET)))
+ .thenReturn(Arrays.asList(hfpActiveDevice));
+ when(mBluetoothHeadset.getAudioState(hfpActiveDevice))
.thenReturn(BluetoothHeadset.STATE_AUDIO_CONNECTED);
when(mBluetoothHearingAid.getConnectedDevices())
.thenReturn(Arrays.asList(hearingAidDevices));
- when(mBluetoothHearingAid.getActiveDevices())
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEARING_AID)))
.thenReturn(Arrays.asList(hearingAidActiveDevice, null));
}
@@ -215,11 +218,12 @@ public class BluetoothRouteManagerTest extends TelecomTestCase {
}
private void resetMocks() {
- reset(mDeviceManager, mListener, mHeadsetProxy, mTimeoutsAdapter);
- when(mDeviceManager.getHeadsetService()).thenReturn(mHeadsetProxy);
- when(mDeviceManager.getHearingAidService()).thenReturn(mBluetoothHearingAid);
- when(mHeadsetProxy.connectAudio()).thenReturn(true);
- when(mHeadsetProxy.setActiveDevice(nullable(BluetoothDevice.class))).thenReturn(true);
+ reset(mDeviceManager, mListener, mBluetoothHeadset, mTimeoutsAdapter);
+ when(mDeviceManager.getBluetoothHeadset()).thenReturn(mBluetoothHeadset);
+ when(mDeviceManager.getBluetoothHearingAid()).thenReturn(mBluetoothHearingAid);
+ when(mDeviceManager.getBluetoothAdapter()).thenReturn(mBluetoothAdapter);
+ when(mBluetoothHeadset.connectAudio()).thenReturn(true);
+ when(mBluetoothHeadset.setActiveDevice(nullable(BluetoothDevice.class))).thenReturn(true);
when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
nullable(ContentResolver.class))).thenReturn(100000L);
when(mTimeoutsAdapter.getBluetoothPendingTimeoutMillis(
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
index b36d74bf1..d96b68746 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothRouteTransitionTests.java
@@ -16,15 +16,16 @@
package com.android.server.telecom.tests;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothProfile;
import android.content.ContentResolver;
import android.telecom.Log;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.internal.os.SomeArgs;
-import com.android.server.telecom.BluetoothHeadsetProxy;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;
import com.android.server.telecom.bluetooth.BluetoothDeviceManager;
@@ -76,7 +77,7 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
private BluetoothDevice expectedConnectionDevice;
private String expectedFinalStateName;
private BluetoothDevice[] connectedDevices;
- // the active device as returned by BluetoothHeadset#getActiveDevice
+ // the active device as returned by BluetoothAdapter#getActiveDevices
private BluetoothDevice activeDevice = null;
private List<BluetoothDevice> hearingAidBtDevices = Collections.emptyList();
@@ -183,7 +184,7 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
public BluetoothDevice expectedConnectionDevice; // Expected device to connect to.
public String expectedFinalStateName; // Expected name of the final state.
public BluetoothDevice[] connectedDevices; // array of connected devices
- // the active device as returned by BluetoothHeadset#getActiveDevice
+ // the active device as returned by BluetoothAdapter#getActiveDevices
private BluetoothDevice activeDevice = null;
private List<BluetoothDevice> hearingAidBtDevices;
@@ -236,7 +237,8 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
private final BluetoothRouteTestParameters mParams;
@Mock private BluetoothDeviceManager mDeviceManager;
- @Mock private BluetoothHeadsetProxy mHeadsetProxy;
+ @Mock private BluetoothAdapter mBluetoothAdapter;
+ @Mock private BluetoothHeadset mBluetoothHeadset;
@Mock private BluetoothHearingAid mBluetoothHearingAid;
@Mock private Timeouts.Adapter mTimeoutsAdapter;
@Mock private BluetoothRouteManager.BluetoothStateListener mListener;
@@ -245,6 +247,7 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
@Before
public void setUp() throws Exception {
super.setUp();
+ when(mDeviceManager.getBluetoothAdapter()).thenReturn(mBluetoothAdapter);
}
@Override
@@ -272,7 +275,8 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
SomeArgs args = SomeArgs.obtain();
args.arg1 = Log.createSubsession();
args.arg2 = mParams.initialDevice.getAddress();
- when(mHeadsetProxy.getActiveDevice()).thenReturn(null);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEADSET)))
+ .thenReturn(Arrays.asList((BluetoothDevice) null));
sm.sendMessage(BluetoothRouteManager.BT_AUDIO_LOST, args);
return true;
}).when(mDeviceManager).disconnectAudio();
@@ -287,9 +291,11 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
sm.onActiveDeviceChanged(null,
mParams.hearingAidBtDevices.contains(mParams.messageDevice));
if (mParams.hearingAidBtDevices.contains(mParams.messageDevice)) {
- when(mBluetoothHearingAid.getActiveDevices()).thenReturn(Arrays.asList(null, null));
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEARING_AID)))
+ .thenReturn(Arrays.asList(null, null));
} else {
- when(mHeadsetProxy.getActiveDevice()).thenReturn(null);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEADSET)))
+ .thenReturn(Arrays.asList((BluetoothDevice) null));
}
sm.onDeviceLost(mParams.messageDevice.getAddress());
} else {
@@ -344,13 +350,15 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
BluetoothDevice audioOnDevice, BluetoothDevice activeDevice) {
when(mDeviceManager.getNumConnectedDevices()).thenReturn(devices.length);
when(mDeviceManager.getConnectedDevices()).thenReturn(Arrays.asList(devices));
- when(mHeadsetProxy.getConnectedDevices()).thenReturn(Arrays.asList(devices));
- when(mHeadsetProxy.getActiveDevice()).thenReturn(activeDevice);
- when(mHeadsetProxy.getAudioState(nullable(BluetoothDevice.class)))
+ when(mBluetoothHeadset.getConnectedDevices()).thenReturn(Arrays.asList(devices));
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEADSET)))
+ .thenReturn(Arrays.asList(activeDevice));
+ when(mBluetoothHeadset.getAudioState(nullable(BluetoothDevice.class)))
.thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
if (audioOnDevice != null) {
- when(mHeadsetProxy.getActiveDevice()).thenReturn(audioOnDevice);
- when(mHeadsetProxy.getAudioState(audioOnDevice))
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.HEADSET)))
+ .thenReturn(Arrays.asList(audioOnDevice));
+ when(mBluetoothHeadset.getAudioState(audioOnDevice))
.thenReturn(BluetoothHeadset.STATE_AUDIO_CONNECTED);
}
}
@@ -358,8 +366,8 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
private BluetoothRouteManager setupStateMachine(String initialState,
BluetoothDevice initialDevice) {
resetMocks();
- when(mDeviceManager.getHeadsetService()).thenReturn(mHeadsetProxy);
- when(mDeviceManager.getHearingAidService()).thenReturn(mBluetoothHearingAid);
+ when(mDeviceManager.getBluetoothHeadset()).thenReturn(mBluetoothHeadset);
+ when(mDeviceManager.getBluetoothHearingAid()).thenReturn(mBluetoothHearingAid);
when(mDeviceManager.connectAudio(nullable(String.class))).thenReturn(true);
when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis(
nullable(ContentResolver.class))).thenReturn(100000L);
@@ -375,7 +383,7 @@ public class BluetoothRouteTransitionTests extends TelecomTestCase {
}
private void resetMocks() {
- clearInvocations(mDeviceManager, mListener, mHeadsetProxy, mTimeoutsAdapter);
+ clearInvocations(mDeviceManager, mListener, mBluetoothHeadset, mTimeoutsAdapter);
}
@Parameterized.Parameters(name = "{0}")
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index 976a4dae8..91ec7f35f 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -17,7 +17,10 @@
package com.android.server.telecom.tests;
import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.IAudioService;
import android.os.HandlerThread;
@@ -151,6 +154,49 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase {
@MediumTest
@Test
+ public void testStreamRingMuteChange() {
+ CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
+ mContext,
+ mockCallsManager,
+ mockBluetoothRouteManager,
+ mockWiredHeadsetManager,
+ mockStatusBarNotifier,
+ mAudioServiceFactory,
+ CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED,
+ mThreadHandler.getLooper());
+ stateMachine.setCallAudioManager(mockCallAudioManager);
+ CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_SPEAKER,
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER);
+ stateMachine.initialize(initState);
+
+ // Make sure we register a receiver for the STREAM_MUTE_CHANGED_ACTION so we can see if the
+ // ring stream unmutes.
+ ArgumentCaptor<BroadcastReceiver> brCaptor = ArgumentCaptor.forClass(
+ BroadcastReceiver.class);
+ ArgumentCaptor<IntentFilter> filterCaptor = ArgumentCaptor.forClass(IntentFilter.class);
+ verify(mContext, times(3)).registerReceiver(brCaptor.capture(), filterCaptor.capture());
+ boolean foundValid = false;
+ for (int ix = 0; ix < brCaptor.getAllValues().size(); ix++) {
+ BroadcastReceiver receiver = brCaptor.getAllValues().get(ix);
+ IntentFilter filter = filterCaptor.getAllValues().get(ix);
+ if (!filter.hasAction(AudioManager.STREAM_MUTE_CHANGED_ACTION)) {
+ continue;
+ }
+
+ // Fake out a call to the broadcast receiver and make sure we call into audio manager
+ // to trigger re-evaluation of ringing.
+ Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
+ intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, false);
+ intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, AudioManager.STREAM_RING);
+ receiver.onReceive(mContext, intent);
+ verify(mockCallAudioManager).onRingerModeChange();
+ foundValid = true;
+ }
+ assertTrue(foundValid);
+ }
+
+ @MediumTest
+ @Test
public void testSpeakerPersistence() {
CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
mContext,
diff --git a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
index dfc32588b..b9f5667ab 100644
--- a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
@@ -18,6 +18,7 @@ package com.android.server.telecom.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -40,7 +41,9 @@ import android.content.res.Resources;
import android.location.Country;
import android.location.CountryDetector;
import android.location.CountryListener;
+import android.location.Location;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.SystemClock;
@@ -52,6 +55,7 @@ import android.telecom.Connection;
import android.telecom.DisconnectCause;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
@@ -172,7 +176,7 @@ public class CallLogManagerTest extends TelecomTestCase {
when(userManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true);
when(userManager.hasUserRestriction(any(String.class), any(UserHandle.class)))
.thenReturn(false);
- when(userManager.getUsers(any(Boolean.class)))
+ when(userManager.getAliveUsers())
.thenReturn(Arrays.asList(userInfo, otherUserInfo, managedProfileUserInfo));
when(userManager.getUserInfo(eq(CURRENT_USER_ID))).thenReturn(userInfo);
when(userManager.getUserInfo(eq(OTHER_USER_ID))).thenReturn(otherUserInfo);
@@ -819,6 +823,54 @@ public class CallLogManagerTest extends TelecomTestCase {
@SmallTest
@Test
+ public void testCallComposerElements() {
+ Call fakeCall = makeFakeCall(
+ DisconnectCause.LOCAL, // disconnectCauseCode
+ false, // isConference
+ true, // isIncoming
+ 1L, // creationTimeMillis
+ 1000L, // ageMillis
+ TEL_PHONEHANDLE, // callHandle
+ mDefaultAccountHandle, // phoneAccountHandle
+ NO_VIDEO_STATE, // callVideoState
+ POST_DIAL_STRING, // postDialDigits
+ VIA_NUMBER_STRING, // viaNumber
+ UserHandle.of(CURRENT_USER_ID)
+ );
+ String subject = "segmentation fault";
+ // =)
+ double lat = 40.649723;
+ double lon = -80.082090;
+ Location location = new Location("");
+ location.setLatitude(lat);
+ location.setLongitude(lon);
+
+ Uri fakeProviderUri = Uri.parse("content://nothing_to_see_here/12345");
+
+ Bundle extras = new Bundle();
+ extras.putInt(TelecomManager.EXTRA_PRIORITY, TelecomManager.PRIORITY_URGENT);
+ extras.putString(TelecomManager.EXTRA_CALL_SUBJECT, subject);
+ extras.putParcelable(TelecomManager.EXTRA_LOCATION, location);
+ extras.putParcelable(TelecomManager.EXTRA_PICTURE_URI, fakeProviderUri);
+ when(fakeCall.getIntentExtras()).thenReturn(extras);
+
+ mCallLogManager.onCallStateChanged(fakeCall, CallState.ACTIVE,
+ CallState.DISCONNECTED);
+ ContentValues locationValues = verifyLocationInsertionWithCapture(CURRENT_USER_ID);
+ assertEquals(lat, locationValues.getAsDouble(CallLog.Locations.LATITUDE), 0);
+ assertEquals(lon, locationValues.getAsDouble(CallLog.Locations.LONGITUDE), 0);
+
+ ContentValues callLogValues = verifyInsertionWithCapture(CURRENT_USER_ID);
+ assertEquals(subject, callLogValues.getAsString(Calls.SUBJECT));
+ assertEquals(fakeProviderUri.toString(),
+ callLogValues.getAsString(Calls.COMPOSER_PHOTO_URI));
+ assertEquals(TelecomManager.PRIORITY_URGENT,
+ (int) callLogValues.getAsInteger(Calls.PRIORITY));
+ assertNotNull(callLogValues.getAsString(Calls.LOCATION));
+ }
+
+ @SmallTest
+ @Test
public void testDoNotLogConferenceWithNoChildren() {
Call fakeCall = makeFakeCall(
DisconnectCause.LOCAL, // disconnectCauseCode
@@ -976,6 +1028,14 @@ public class CallLogManagerTest extends TelecomTestCase {
return captor.getValue();
}
+ private ContentValues verifyLocationInsertionWithCapture(int userId) {
+ Uri uri = ContentProvider.maybeAddUserId(CallLog.Locations.CONTENT_URI, userId);
+ ArgumentCaptor<ContentValues> captor = ArgumentCaptor.forClass(ContentValues.class);
+ verify(mContentProvider, timeout(TEST_TIMEOUT_MILLIS).times(1)).insert(
+ eq(uri), captor.capture());
+ return captor.getValue();
+ }
+
private Call makeFakeCall(int disconnectCauseCode, boolean isConference, boolean isIncoming,
long creationTimeMillis, long ageMillis, Uri callHandle,
PhoneAccountHandle phoneAccountHandle, int callVideoState,
diff --git a/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java b/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java
index ff16880cc..0a896a8ce 100644
--- a/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java
@@ -65,8 +65,6 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import java.util.ArrayList;
-
@RunWith(JUnit4.class)
public class CallRedirectionProcessorTest extends TelecomTestCase {
@Mock private Context mContext;
@@ -151,7 +149,7 @@ public class CallRedirectionProcessorTest extends TelecomTestCase {
}
private void setIsInCarMode(boolean isInCarMode) {
- when(mSystemStateHelper.isCarMode()).thenReturn(isInCarMode);
+ when(mSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(isInCarMode);
}
private void enableUserDefinedCallRedirectionService() {
diff --git a/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java b/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
index c7b3a7eb5..68caf6776 100644
--- a/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallScreeningServiceFilterTest.java
@@ -93,6 +93,16 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
.setShouldShowNotification(true)
.build();
+ private static final CallFilteringResult PASS_RESULT_WITH_NAME =
+ new CallFilteringResult.Builder()
+ .setShouldAllowCall(true)
+ .setShouldReject(false)
+ .setShouldAddToCallLog(true)
+ .setShouldShowNotification(true)
+ .setCallScreeningAppName(APP_NAME)
+ .setCallScreeningComponentName(COMPONENT_NAME.flattenToString())
+ .build();
+
@Override
@Before
public void setUp() throws Exception {
@@ -235,8 +245,14 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
- csAdapter.allowCall(CALL_ID);
- assertEquals(PASS_RESULT,
+ CallScreeningService.CallResponse allowCallResponse =
+ new CallScreeningService.CallResponse.Builder()
+ .setDisallowCall(false)
+ .setRejectCall(false)
+ .setSilenceCall(false)
+ .build();
+ csAdapter.onScreeningResponse(CALL_ID, COMPONENT_NAME, allowCallResponse.toParcelable());
+ assertEquals(PASS_RESULT_WITH_NAME,
resultFuture.toCompletableFuture().get(
CallScreeningServiceFilter.CALL_SCREENING_FILTER_TIMEOUT,
TimeUnit.MILLISECONDS));
@@ -264,12 +280,16 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
ServiceConnection serviceConnection = verifyBindingIntent();
serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
+ CallScreeningService.CallResponse disallowCallResponse =
+ new CallScreeningService.CallResponse.Builder()
+ .setDisallowCall(true)
+ .setRejectCall(true)
+ .setSkipCallLog(false)
+ .setSkipNotification(false)
+ .build();
ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
- csAdapter.disallowCall(CALL_ID,
- true, // shouldReject
- true, //shouldAddToCallLog
- true, // shouldShowNotification
- COMPONENT_NAME);
+ csAdapter.onScreeningResponse(CALL_ID, COMPONENT_NAME, disallowCallResponse.toParcelable());
+
assertEquals(expectedResult,
resultFuture.toCompletableFuture().get(
CallScreeningServiceFilter.CALL_SCREENING_FILTER_TIMEOUT,
@@ -286,6 +306,8 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
.setShouldSilence(true)
.setShouldAddToCallLog(true)
.setShouldShowNotification(true)
+ .setCallScreeningAppName(APP_NAME)
+ .setCallScreeningComponentName(COMPONENT_NAME.flattenToString())
.build();
CallScreeningServiceFilter filter = new CallScreeningServiceFilter(mCall, PKG_NAME,
CallScreeningServiceFilter.PACKAGE_TYPE_CARRIER, mContext, mCallsManager,
@@ -296,7 +318,13 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
- csAdapter.silenceCall(CALL_ID);
+ CallScreeningService.CallResponse silenceCallResponse =
+ new CallScreeningService.CallResponse.Builder()
+ .setDisallowCall(false)
+ .setRejectCall(false)
+ .setSilenceCall(true)
+ .build();
+ csAdapter.onScreeningResponse(CALL_ID, COMPONENT_NAME, silenceCallResponse.toParcelable());
assertEquals(expectedResult,
resultFuture.toCompletableFuture().get(
CallScreeningServiceFilter.CALL_SCREENING_FILTER_TIMEOUT,
@@ -314,6 +342,7 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
.setShouldSilence(false)
.setShouldScreenViaAudio(true)
.setCallScreeningAppName(APP_NAME)
+ .setCallScreeningComponentName(COMPONENT_NAME.flattenToString())
.build();
CallScreeningServiceFilter filter = new CallScreeningServiceFilter(mCall, PKG_NAME,
CallScreeningServiceFilter.PACKAGE_TYPE_DEFAULT_DIALER, mContext, mCallsManager,
@@ -323,8 +352,17 @@ public class CallScreeningServiceFilterTest extends TelecomTestCase {
ServiceConnection serviceConnection = verifyBindingIntent();
serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
+
+ CallScreeningService.CallResponse additionalScreeningResponse =
+ new CallScreeningService.CallResponse.Builder()
+ .setDisallowCall(false)
+ .setRejectCall(false)
+ .setSilenceCall(false)
+ .setShouldScreenCallViaAudioProcessing(true)
+ .build();
ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
- csAdapter.screenCallFurther(CALL_ID);
+ csAdapter.onScreeningResponse(CALL_ID, COMPONENT_NAME,
+ additionalScreeningResponse.toParcelable());
assertEquals(expectedResult,
resultFuture.toCompletableFuture().get(
CallScreeningServiceFilter.CALL_SCREENING_FILTER_TIMEOUT,
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index 08f353668..da7293330 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -21,6 +21,7 @@ import static junit.framework.TestCase.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -36,11 +37,14 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -52,6 +56,8 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.telecom.CallerInfo;
import android.telecom.Connection;
+import android.telecom.DisconnectCause;
+import android.telecom.Log;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
@@ -75,6 +81,7 @@ import com.android.server.telecom.CallsManagerListenerBase;
import com.android.server.telecom.ClockProxy;
import com.android.server.telecom.ConnectionServiceFocusManager;
import com.android.server.telecom.ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory;
+import com.android.server.telecom.ConnectionServiceWrapper;
import com.android.server.telecom.DefaultDialerCache;
import com.android.server.telecom.EmergencyCallHelper;
import com.android.server.telecom.HeadsetMediaButton;
@@ -228,6 +235,8 @@ public class CallsManagerTest extends TelecomTestCase {
doNothing().when(mRoleManagerAdapter).setCurrentUserHandle(any());
when(mDisconnectedCallNotifierFactory.create(any(Context.class),any(CallsManager.class)))
.thenReturn(mDisconnectedCallNotifier);
+ when(mTimeoutsAdapter.getCallDiagnosticServiceTimeoutMillis(any(ContentResolver.class)))
+ .thenReturn(2000L);
mCallsManager = new CallsManager(
mComponentContextFixture.getTestDouble().getApplicationContext(),
mLock,
@@ -1106,6 +1115,46 @@ public class CallsManagerTest extends TelecomTestCase {
assertFalse(mCallsManager.isInEmergencyCall());
}
+
+ @SmallTest
+ @Test
+ public void testBlockNonEmergencyCallDuringEmergencyCall() throws Exception {
+ // Setup a call which the network identified as an emergency call.
+ Call ongoingCall = addSpyCall();
+ ongoingCall.setConnectionProperties(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL);
+ assertTrue(mCallsManager.isInEmergencyCall());
+
+ Call newCall = addSpyCall(CallState.NEW);
+ ConnectionServiceWrapper service = mock(ConnectionServiceWrapper.class);
+ doReturn(SIM_2_HANDLE.getComponentName()).when(service).getComponentName();
+
+ // Ensure contact info lookup succeeds
+ doAnswer(invocation -> {
+ Uri handle = invocation.getArgument(0);
+ CallerInfo info = new CallerInfo();
+ CompletableFuture<Pair<Uri, CallerInfo>> callerInfoFuture = new CompletableFuture<>();
+ callerInfoFuture.complete(new Pair<>(handle, info));
+ return callerInfoFuture;
+ }).when(mCallerInfoLookupHelper).startLookup(any(Uri.class));
+
+ // Ensure we have candidate phone account handle info.
+ when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
+ SIM_1_HANDLE);
+ when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
+ any(), anyInt(), anyInt())).thenReturn(
+ new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
+ mCallsManager.addConnectionServiceRepositoryCache(SIM_2_HANDLE.getComponentName(),
+ SIM_2_HANDLE.getUserHandle(), service);
+
+ CompletableFuture<Call> callFuture = mCallsManager.startOutgoingCall(
+ newCall.getHandle(), newCall.getTargetPhoneAccount(), new Bundle(),
+ UserHandle.CURRENT, new Intent(), "com.test.stuff");
+
+ verify(service, timeout(TEST_TIMEOUT)).createConnectionFailed(any());
+ Call result = callFuture.get(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertNull(result);
+ }
+
@SmallTest
@Test
public void testHasEmergencyCallIncomingCallPermitted() {
@@ -1204,6 +1253,21 @@ public class CallsManagerTest extends TelecomTestCase {
verify(ringingCall).reject(anyBoolean(), any(), any());
}
+ @SmallTest
+ @Test
+ public void testMakeRoomForOutgoingCallConnecting() {
+ Call ongoingCall = addSpyCall(SIM_2_HANDLE, CallState.CONNECTING);
+
+ Call newCall = createCall(SIM_1_HANDLE, CallState.NEW);
+ when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any()))
+ .thenReturn(false);
+ newCall.setHandle(Uri.fromParts("tel", "5551213", null),
+ TelecomManager.PRESENTATION_ALLOWED);
+
+ assertTrue(mCallsManager.makeRoomForOutgoingCall(newCall));
+ verify(ongoingCall).disconnect(anyLong(), anyString());
+ }
+
/**
* Verifies that changes to a {@link PhoneAccount}'s
* {@link PhoneAccount#CAPABILITY_VIDEO_CALLING} capability will be reflected on a call.
@@ -1508,6 +1572,59 @@ public class CallsManagerTest extends TelecomTestCase {
eq(CallState.ACTIVE));
}
+ /**
+ * Verifies where a call diagnostic service is NOT in use that we don't try to relay to the
+ * CallDiagnosticService and that we get a synchronous disconnect.
+ * @throws Exception
+ */
+ @MediumTest
+ @Test
+ public void testDisconnectCallSynchronous() throws Exception {
+ Call callSpy = addSpyCall();
+ callSpy.setIsSimCall(true);
+ when(mCallDiagnosticServiceController.isConnected()).thenReturn(false);
+ mCallsManager.markCallAsDisconnected(callSpy, new DisconnectCause(DisconnectCause.ERROR));
+
+ verify(mCallDiagnosticServiceController, never()).onCallDisconnected(any(Call.class),
+ any(DisconnectCause.class));
+ verify(callSpy).setDisconnectCause(any(DisconnectCause.class));
+ }
+
+ @MediumTest
+ @Test
+ public void testDisconnectCallAsynchronous() throws Exception {
+ Call callSpy = addSpyCall();
+ callSpy.setIsSimCall(true);
+ when(mCallDiagnosticServiceController.isConnected()).thenReturn(true);
+ when(mCallDiagnosticServiceController.onCallDisconnected(any(Call.class),
+ any(DisconnectCause.class))).thenReturn(true);
+ mCallsManager.markCallAsDisconnected(callSpy, new DisconnectCause(DisconnectCause.ERROR));
+
+ verify(mCallDiagnosticServiceController).onCallDisconnected(any(Call.class),
+ any(DisconnectCause.class));
+ verify(callSpy, never()).setDisconnectCause(any(DisconnectCause.class));
+ }
+
+ /**
+ * Verifies that if call state goes from DIALING to DISCONNECTED, and a call diagnostic service
+ * IS in use, it would call onCallDisconnected of the CallDiagnosticService
+ * @throws Exception
+ */
+ @MediumTest
+ @Test
+ public void testDisconnectDialingCall() throws Exception {
+ Call callSpy = addSpyCall(CallState.DIALING);
+ callSpy.setIsSimCall(true);
+ when(mCallDiagnosticServiceController.isConnected()).thenReturn(true);
+ when(mCallDiagnosticServiceController.onCallDisconnected(any(Call.class),
+ any(DisconnectCause.class))).thenReturn(true);
+ mCallsManager.markCallAsDisconnected(callSpy, new DisconnectCause(DisconnectCause.ERROR));
+
+ verify(mCallDiagnosticServiceController).onCallDisconnected(any(Call.class),
+ any(DisconnectCause.class));
+ verify(callSpy, never()).setDisconnectCause(any(DisconnectCause.class));
+ }
+
private Call addSpyCall() {
return addSpyCall(SIM_2_HANDLE, CallState.ACTIVE);
}
diff --git a/tests/src/com/android/server/telecom/tests/CarModeTrackerTest.java b/tests/src/com/android/server/telecom/tests/CarModeTrackerTest.java
index dbfcdb12a..4ad46ae52 100644
--- a/tests/src/com/android/server/telecom/tests/CarModeTrackerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CarModeTrackerTest.java
@@ -21,9 +21,6 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.TestCase.assertNull;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.when;
-
import android.app.UiModeManager;
import com.android.server.telecom.CarModeTracker;
@@ -33,7 +30,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-import org.mockito.Mock;
@RunWith(JUnit4.class)
public class CarModeTrackerTest extends TelecomTestCase {
@@ -110,7 +106,7 @@ public class CarModeTrackerTest extends TelecomTestCase {
@Test
public void testForceExitCarMode() {
testEnterCarModeBasic();
- mCarModeTracker.forceExitCarMode(CAR_MODE_APP1_PACKAGE_NAME);
+ mCarModeTracker.forceRemove(CAR_MODE_APP1_PACKAGE_NAME);
assertFalse(mCarModeTracker.isInCarMode());
assertNull(mCarModeTracker.getCurrentCarModePackage());
}
@@ -226,4 +222,109 @@ public class CarModeTrackerTest extends TelecomTestCase {
CAR_MODE_APP3_PACKAGE_NAME);
assertNull(mCarModeTracker.getCurrentCarModePackage());
}
+
+ /**
+ * Verifies that setting automotive projection by itself works.
+ */
+ @Test
+ public void testSetAutomotiveProjectionBasic() {
+ mCarModeTracker.handleSetAutomotiveProjection(CAR_MODE_APP1_PACKAGE_NAME);
+ assertEquals(CAR_MODE_APP1_PACKAGE_NAME, mCarModeTracker.getCurrentCarModePackage());
+ // We should be tracking our car mode app.
+ assertEquals(1, mCarModeTracker.getCarModeApps().size());
+ assertTrue(mCarModeTracker.isInCarMode());
+ }
+
+ /**
+ * Verifies that if we set automotive projection more than once with the same package, nothing
+ * changes.
+ */
+ @Test
+ public void testSetAutomotiveProjectionMultipleTimes() {
+ mCarModeTracker.handleSetAutomotiveProjection(CAR_MODE_APP1_PACKAGE_NAME);
+ mCarModeTracker.handleSetAutomotiveProjection(CAR_MODE_APP1_PACKAGE_NAME);
+ // Should still only have one app.
+ assertEquals(1, mCarModeTracker.getCarModeApps().size());
+ assertTrue(mCarModeTracker.isInCarMode());
+ // It should be the same one.
+ assertEquals(CAR_MODE_APP1_PACKAGE_NAME, mCarModeTracker.getCurrentCarModePackage());
+ }
+
+ /**
+ * Verifies that if we set automotive projection more than once, the new package overrides.
+ */
+ @Test
+ public void testSetAutomotiveProjectionMultipleTimesDifferentPackages() {
+ mCarModeTracker.handleSetAutomotiveProjection(CAR_MODE_APP1_PACKAGE_NAME);
+ mCarModeTracker.handleSetAutomotiveProjection(CAR_MODE_APP2_PACKAGE_NAME);
+ // Should still only have one app.
+ assertEquals(1, mCarModeTracker.getCarModeApps().size());
+ assertTrue(mCarModeTracker.isInCarMode());
+ // It should be the newer one.
+ assertEquals(CAR_MODE_APP2_PACKAGE_NAME, mCarModeTracker.getCurrentCarModePackage());
+ }
+
+ /**
+ * Verifies that releasing automotive projection works as expected.
+ */
+ @Test
+ public void testReleaseAutomotiveProjectionBasic() {
+ // Releasing before something's set shouldn't break anything.
+ mCarModeTracker.handleReleaseAutomotiveProjection();
+ assertEquals(0, mCarModeTracker.getCarModeApps().size());
+ assertFalse(mCarModeTracker.isInCarMode());
+
+ mCarModeTracker.handleSetAutomotiveProjection(CAR_MODE_APP1_PACKAGE_NAME);
+ mCarModeTracker.handleReleaseAutomotiveProjection();
+ // Should be gone now.
+ assertEquals(0, mCarModeTracker.getCarModeApps().size());
+ assertFalse(mCarModeTracker.isInCarMode());
+ }
+
+ /**
+ * Verifies that setting automotive projection overrides but doesn't overwrite car mode apps.
+ */
+ @Test
+ public void testAutomotiveProjectionOverridesCarMode() {
+ mCarModeTracker.handleEnterCarMode(50, CAR_MODE_APP1_PACKAGE_NAME);
+ mCarModeTracker.handleSetAutomotiveProjection(CAR_MODE_APP4_PACKAGE_NAME);
+
+ // Should have two apps now, the car mode and the automotive projection one.
+ assertEquals(2, mCarModeTracker.getCarModeApps().size());
+ assertTrue(mCarModeTracker.isInCarMode());
+
+ // Automotive projection takes priority.
+ assertEquals(CAR_MODE_APP4_PACKAGE_NAME, mCarModeTracker.getCurrentCarModePackage());
+
+ // If we add another car mode app, automotive projection still has priority.
+ mCarModeTracker.handleEnterCarMode(Integer.MAX_VALUE, CAR_MODE_APP2_PACKAGE_NAME);
+ assertEquals(3, mCarModeTracker.getCarModeApps().size());
+ assertTrue(mCarModeTracker.isInCarMode());
+ assertEquals(CAR_MODE_APP4_PACKAGE_NAME, mCarModeTracker.getCurrentCarModePackage());
+
+ // If we release automotive projection, we go back to the prioritized list of plain car
+ // mode apps.
+ mCarModeTracker.handleReleaseAutomotiveProjection();
+ assertEquals(2, mCarModeTracker.getCarModeApps().size());
+ assertTrue(mCarModeTracker.isInCarMode());
+ assertEquals(CAR_MODE_APP2_PACKAGE_NAME, mCarModeTracker.getCurrentCarModePackage());
+
+ // Make sure we didn't mess with the first app that was added.
+ mCarModeTracker.handleExitCarMode(Integer.MAX_VALUE, CAR_MODE_APP2_PACKAGE_NAME);
+ assertEquals(1, mCarModeTracker.getCarModeApps().size());
+ assertTrue(mCarModeTracker.isInCarMode());
+ assertEquals(CAR_MODE_APP1_PACKAGE_NAME, mCarModeTracker.getCurrentCarModePackage());
+ }
+
+ /**
+ * Verifies that releasing automotive projection doesn't interfere with plain car mode apps.
+ */
+ @Test
+ public void testReleaseAutomotiveProjectionNoopForCarModeApps() {
+ mCarModeTracker.handleEnterCarMode(50, CAR_MODE_APP1_PACKAGE_NAME);
+ mCarModeTracker.handleReleaseAutomotiveProjection();
+ assertEquals(1, mCarModeTracker.getCarModeApps().size());
+ assertTrue(mCarModeTracker.isInCarMode());
+ assertEquals(CAR_MODE_APP1_PACKAGE_NAME, mCarModeTracker.getCurrentCarModePackage());
+ }
}
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
index ae8d943e2..ebb336e12 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -30,7 +30,10 @@ import android.Manifest;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.app.StatusBarManager;
+import android.app.UiModeManager;
import android.app.role.RoleManager;
+import android.content.AttributionSource;
+import android.content.AttributionSourceState;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -47,6 +50,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.hardware.SensorPrivacyManager;
import android.location.Country;
import android.location.CountryDetector;
import android.media.AudioManager;
@@ -55,8 +59,11 @@ import android.os.Handler;
import android.os.IInterface;
import android.os.PersistableBundle;
import android.os.PowerWhitelistManager;
+import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.VibratorManager;
+import android.permission.PermissionCheckerManager;
import android.telecom.CallAudioState;
import android.telecom.ConnectionService;
import android.telecom.Log;
@@ -68,6 +75,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyRegistryManager;
import android.test.mock.MockContext;
+import android.util.DisplayMetrics;
import java.io.File;
import java.io.IOException;
@@ -79,7 +87,9 @@ import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Executor;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.matches;
+import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
@@ -206,6 +216,14 @@ public class ComponentContextFixture implements TestFixture<Context> {
return mRoleManager;
case Context.TELEPHONY_REGISTRY_SERVICE:
return mTelephonyRegistryManager;
+ case Context.UI_MODE_SERVICE:
+ return mUiModeManager;
+ case Context.VIBRATOR_MANAGER_SERVICE:
+ return mVibratorManager;
+ case Context.PERMISSION_CHECKER_SERVICE:
+ return mPermissionCheckerManager;
+ case Context.SENSOR_PRIVACY_SERVICE:
+ return mSensorPrivacyManager;
default:
return null;
}
@@ -227,6 +245,14 @@ public class ComponentContextFixture implements TestFixture<Context> {
return Context.TELEPHONY_SUBSCRIPTION_SERVICE;
} else if (svcClass == TelephonyRegistryManager.class) {
return Context.TELEPHONY_REGISTRY_SERVICE;
+ } else if (svcClass == UiModeManager.class) {
+ return Context.UI_MODE_SERVICE;
+ } else if (svcClass == VibratorManager.class) {
+ return Context.VIBRATOR_MANAGER_SERVICE;
+ } else if (svcClass == PermissionCheckerManager.class) {
+ return Context.PERMISSION_CHECKER_SERVICE;
+ } else if (svcClass == SensorPrivacyManager.class) {
+ return Context.SENSOR_PRIVACY_SERVICE;
}
throw new UnsupportedOperationException();
}
@@ -252,6 +278,11 @@ public class ComponentContextFixture implements TestFixture<Context> {
}
@Override
+ public AttributionSource getAttributionSource() {
+ return mAttributionSource;
+ }
+
+ @Override
public ContentResolver getContentResolver() {
return new ContentResolver(mApplicationContextSpy) {
@Override
@@ -444,6 +475,10 @@ public class ComponentContextFixture implements TestFixture<Context> {
}
}
+ private static final String PACKAGE_NAME = "com.android.server.telecom.tests";
+ private final AttributionSource mAttributionSource =
+ new AttributionSource.Builder(Process.myUid()).setPackageName(PACKAGE_NAME).build();
+
private final Multimap<String, ComponentName> mComponentNamesByAction =
ArrayListMultimap.create();
private final Map<ComponentName, IInterface> mServiceByComponentName = new HashMap<>();
@@ -474,6 +509,7 @@ public class ComponentContextFixture implements TestFixture<Context> {
private final Resources.Theme mResourcesTheme = mock(Resources.Theme.class);
private final Resources mResources = mock(Resources.class);
private final Context mApplicationContextSpy = spy(mApplicationContext);
+ private final DisplayMetrics mDisplayMetrics = mock(DisplayMetrics.class);
private final PackageManager mPackageManager = mock(PackageManager.class);
private final Executor mMainExecutor = mock(Executor.class);
private final AudioManager mAudioManager = spy(new FakeAudioManager(mContext));
@@ -491,7 +527,12 @@ public class ComponentContextFixture implements TestFixture<Context> {
private final RoleManager mRoleManager = mock(RoleManager.class);
private final TelephonyRegistryManager mTelephonyRegistryManager =
mock(TelephonyRegistryManager.class);
+ private final VibratorManager mVibratorManager = mock(VibratorManager.class);
+ private final UiModeManager mUiModeManager = mock(UiModeManager.class);
+ private final PermissionCheckerManager mPermissionCheckerManager =
+ mock(PermissionCheckerManager.class);
private final PermissionInfo mPermissionInfo = mock(PermissionInfo.class);
+ private final SensorPrivacyManager mSensorPrivacyManager = mock(SensorPrivacyManager.class);
private TelecomManager mTelecomManager = mock(TelecomManager.class);
@@ -500,6 +541,9 @@ public class ComponentContextFixture implements TestFixture<Context> {
when(mResources.getConfiguration()).thenReturn(mResourceConfiguration);
when(mResources.getString(anyInt())).thenReturn("");
when(mResources.getStringArray(anyInt())).thenReturn(new String[0]);
+ when(mResources.newTheme()).thenReturn(mResourcesTheme);
+ when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
+ mDisplayMetrics.density = 3.125f;
mResourceConfiguration.setLocale(Locale.TAIWAN);
// TODO: Move into actual tests
@@ -542,9 +586,10 @@ public class ComponentContextFixture implements TestFixture<Context> {
}).when(mPackageManager).queryBroadcastReceiversAsUser((Intent) any(), anyInt(), anyInt());
// By default, tests use non-ui apps instead of 3rd party companion apps.
- when(mPackageManager.checkPermission(
- matches(Manifest.permission.CALL_COMPANION_APP), anyString()))
- .thenReturn(PackageManager.PERMISSION_DENIED);
+ when(mPermissionCheckerManager.checkPermission(
+ matches(Manifest.permission.CALL_COMPANION_APP), any(AttributionSourceState.class),
+ nullable(String.class), anyBoolean(), anyBoolean(), anyBoolean(), anyInt()))
+ .thenReturn(PermissionCheckerManager.PERMISSION_HARD_DENIED);
try {
when(mPackageManager.getPermissionInfo(anyString(), anyInt())).thenReturn(
@@ -553,6 +598,7 @@ public class ComponentContextFixture implements TestFixture<Context> {
}
when(mPermissionInfo.isAppOp()).thenReturn(true);
+ when(mVibratorManager.getVibratorIds()).thenReturn(new int[0]);
// Used in CreateConnectionProcessor to rank emergency numbers by viability.
// For the test, make them all equal to INVALID so that the preferred PhoneAccount will be
@@ -620,11 +666,15 @@ public class ComponentContextFixture implements TestFixture<Context> {
serviceInfo.name = componentName.getClassName();
mServiceInfoByComponentName.put(componentName, serviceInfo);
- // Used in InCallController to check permissions for CONTROL_INCALL_EXPERIENCE
+ // Used in InCallController to check permissions for CONTROL_INCALL_fvEXPERIENCE
when(mPackageManager.getPackagesForUid(eq(uid))).thenReturn(new String[] {
componentName.getPackageName() });
when(mPackageManager.checkPermission(eq(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
eq(componentName.getPackageName()))).thenReturn(PackageManager.PERMISSION_GRANTED);
+ when(mPermissionCheckerManager.checkPermission(
+ eq(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
+ any(AttributionSourceState.class), anyString(), anyBoolean(), anyBoolean(),
+ anyBoolean(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
}
public void addIntentReceiver(String action, ComponentName name) {
@@ -667,6 +717,10 @@ public class ComponentContextFixture implements TestFixture<Context> {
return mTelephonyManager;
}
+ public NotificationManager getNotificationManager() {
+ return mNotificationManager;
+ }
+
private void addService(String action, ComponentName name, IInterface service) {
mComponentNamesByAction.put(action, name);
mServiceByComponentName.put(name, service);
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 5b4e80031..6e6646f7a 100755
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -34,6 +34,7 @@ import android.os.IInterface;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.telecom.CallAudioState;
+import android.telecom.CallScreeningService;
import android.telecom.Conference;
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
@@ -437,6 +438,10 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
@Override
public void handoverComplete(String callId, Session.Info sessionInfo) {}
+
+ @Override
+ public void onCallFilteringCompleted(String callId,
+ Connection.CallFilteringCompletionInfo completionInfo, Session.Info sessionInfo) { }
}
FakeConnectionServiceDelegate mConnectionServiceDelegate;
diff --git a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
index 0b926fe92..f66187835 100644
--- a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
+++ b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
@@ -18,13 +18,16 @@ package com.android.server.telecom.tests;
import static com.android.server.telecom.InCallController.IN_CALL_SERVICE_NOTIFICATION_ID;
import static com.android.server.telecom.InCallController.NOTIFICATION_TAG;
+import static com.android.server.telecom.tests.TelecomSystemTest.TEST_TIMEOUT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
@@ -41,14 +44,19 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.UiModeManager;
+import android.content.AttributionSource;
+import android.content.AttributionSourceState;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.PermissionChecker;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -61,7 +69,9 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.os.Process;
import android.os.UserHandle;
+import android.permission.PermissionCheckerManager;
import android.telecom.CallAudioState;
import android.telecom.InCallService;
import android.telecom.ParcelableCall;
@@ -72,10 +82,10 @@ import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.telecom.IInCallAdapter;
import com.android.internal.telecom.IInCallService;
import com.android.server.telecom.Analytics;
-import com.android.server.telecom.BluetoothHeadsetProxy;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.CarModeTracker;
@@ -96,23 +106,27 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
import org.mockito.invocation.InvocationOnMock;
+import org.mockito.quality.Strictness;
import org.mockito.stubbing.Answer;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.CompletableFuture;
@RunWith(JUnit4.class)
public class InCallControllerTests extends TelecomTestCase {
@Mock CallsManager mMockCallsManager;
@Mock PhoneAccountRegistrar mMockPhoneAccountRegistrar;
- @Mock BluetoothHeadsetProxy mMockBluetoothHeadset;
@Mock SystemStateHelper mMockSystemStateHelper;
@Mock PackageManager mMockPackageManager;
+ @Mock PermissionCheckerManager mMockPermissionCheckerManager;
@Mock Call mMockCall;
@Mock Resources mMockResources;
@Mock AppOpsManager mMockAppOpsManager;
@@ -178,8 +192,12 @@ public class InCallControllerTests extends TelecomTestCase {
when(mMockCallsManager.getRoleManagerAdapter()).thenReturn(mMockRoleManagerAdapter);
when(mMockContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
.thenReturn(mNotificationManager);
+ when(mMockContext.getSystemService(eq(PermissionCheckerManager.class)))
+ .thenReturn(mMockPermissionCheckerManager);
when(mMockPackageManager.getPermissionInfo(anyString(), anyInt())).thenReturn(
mMockPermissionInfo);
+ when(mMockContext.getAttributionSource()).thenReturn(new AttributionSource(Process.myUid(),
+ "com.android.server.telecom.tests", null));
mInCallController = new InCallController(mMockContext, mLock, mMockCallsManager,
mMockSystemStateHelper, mDefaultDialerCache, mTimeoutsAdapter,
mEmergencyCallHelper, mCarModeTracker, mClockProxy);
@@ -210,21 +228,37 @@ public class InCallControllerTests extends TelecomTestCase {
}
return null;
}).when(mMockPackageManager).getPackagesForUid(anyInt());
- when(mMockPackageManager.checkPermission(
+
+ when(mMockPermissionCheckerManager.checkPermission(
matches(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
- matches(COMPANION_PKG))).thenReturn(PackageManager.PERMISSION_DENIED);
- when(mMockPackageManager.checkPermission(
+ matchesAttributionSourcePackage(COMPANION_PKG), nullable(String.class),
+ anyBoolean(), anyBoolean(), anyBoolean(), anyInt()))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+
+ when(mMockPermissionCheckerManager.checkPermission(
matches(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
- matches(CAR_PKG))).thenReturn(PackageManager.PERMISSION_GRANTED);
- when(mMockPackageManager.checkPermission(
+ matchesAttributionSourcePackage(CAR_PKG), nullable(String.class),
+ anyBoolean(), anyBoolean(), anyBoolean(), anyInt()))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+
+ when(mMockPermissionCheckerManager.checkPermission(
matches(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
- matches(CAR2_PKG))).thenReturn(PackageManager.PERMISSION_GRANTED);
- when(mMockPackageManager.checkPermission(
+ matchesAttributionSourcePackage(CAR2_PKG), nullable(String.class),
+ anyBoolean(), anyBoolean(), anyBoolean(), anyInt()))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+
+ when(mMockPermissionCheckerManager.checkPermission(
matches(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
- matches(NONUI_PKG))).thenReturn(PackageManager.PERMISSION_GRANTED);
- when(mMockPackageManager.checkPermission(
+ matchesAttributionSourcePackage(NONUI_PKG), nullable(String.class),
+ anyBoolean(), anyBoolean(), anyBoolean(), anyInt()))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+
+ when(mMockPermissionCheckerManager.checkPermission(
matches(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
- matches(APPOP_NONUI_PKG))).thenReturn(PackageManager.PERMISSION_DENIED);
+ matchesAttributionSourcePackage(APPOP_NONUI_PKG), nullable(String.class),
+ anyBoolean(), anyBoolean(), anyBoolean(), anyInt()))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+
when(mMockCallsManager.getAudioState()).thenReturn(new CallAudioState(false, 0, 0));
}
@@ -243,14 +277,53 @@ public class InCallControllerTests extends TelecomTestCase {
when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
- when(mMockSystemStateHelper.isCarMode()).thenReturn(true);
+ when(mMockSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(true);
+
+ mSystemStateListener.onCarModeChanged(666, CAR_PKG, true);
+ verify(mCarModeTracker).handleEnterCarMode(666, CAR_PKG);
+ assertTrue(mCarModeTracker.isInCarMode());
+
+ mSystemStateListener.onPackageUninstalled(CAR_PKG);
+ verify(mCarModeTracker).forceRemove(CAR_PKG);
+ assertFalse(mCarModeTracker.isInCarMode());
+ }
+
+ /**
+ * Ensure that if we remove a random unrelated app we don't exit car mode.
+ */
+ @SmallTest
+ @Test
+ public void testRandomAppRemovalInCarMode() {
+ setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
+ when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+
+ when(mMockSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(true);
mSystemStateListener.onCarModeChanged(666, CAR_PKG, true);
verify(mCarModeTracker).handleEnterCarMode(666, CAR_PKG);
assertTrue(mCarModeTracker.isInCarMode());
+ mSystemStateListener.onPackageUninstalled("com.foo.test");
+ verify(mCarModeTracker, never()).forceRemove(CAR_PKG);
+ assertTrue(mCarModeTracker.isInCarMode());
+ }
+
+ @SmallTest
+ @Test
+ public void testAutomotiveProjectionAppRemoval() {
+ setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
+ when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+
+ when(mMockSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(true);
+
+ mSystemStateListener.onAutomotiveProjectionStateSet(CAR_PKG);
+ verify(mCarModeTracker).handleSetAutomotiveProjection(CAR_PKG);
+ assertTrue(mCarModeTracker.isInCarMode());
+
mSystemStateListener.onPackageUninstalled(CAR_PKG);
- verify(mCarModeTracker).forceExitCarMode(CAR_PKG);
+ verify(mCarModeTracker).forceRemove(CAR_PKG);
assertFalse(mCarModeTracker.isInCarMode());
}
@@ -439,7 +512,7 @@ public class InCallControllerTests extends TelecomTestCase {
// Pretend that the call has gone away.
when(mMockCallsManager.getCalls()).thenReturn(Collections.emptyList());
mInCallController.onCallRemoved(mMockCall);
- waitForHandlerAction(new Handler(Looper.getMainLooper()), TelecomSystemTest.TEST_TIMEOUT);
+ waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
verify(mMockPackageManager).revokeRuntimePermission(eq(SYS_PKG),
eq(Manifest.permission.ACCESS_FINE_LOCATION), eq(mUserHandle));
@@ -786,7 +859,7 @@ public class InCallControllerTests extends TelecomTestCase {
setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
// Enable car mode
- when(mMockSystemStateHelper.isCarMode()).thenReturn(true);
+ when(mMockSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(true);
mInCallController.handleCarModeChange(UiModeManager.DEFAULT_PRIORITY, CAR_PKG, true);
// Now bind; we should only bind to one app.
@@ -816,7 +889,7 @@ public class InCallControllerTests extends TelecomTestCase {
matches(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
matches(CAR_PKG))).thenReturn(PackageManager.PERMISSION_DENIED);
// Enable car mode
- when(mMockSystemStateHelper.isCarMode()).thenReturn(true);
+ when(mMockSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(true);
// Register the fact that the invalid app entered car mode.
mInCallController.handleCarModeChange(UiModeManager.DEFAULT_PRIORITY, CAR_PKG, true);
@@ -841,39 +914,45 @@ public class InCallControllerTests extends TelecomTestCase {
@MediumTest
@Test
public void testBindToService_ThirdPartyApp() throws Exception {
- setupMocks(false /* isExternalCall */);
- setupMockPackageManager(false /* default */, false /* nonui */, true /* appop_nonui */,
- true /* system */, false /* external calls */, false /* self mgd in default */,
- false /* self mgd in car*/);
-
- // Enable Third Party Companion App
- when(mMockPackageManager.getPermissionInfo(anyString(), anyInt())).thenReturn(
- mMockPermissionInfo);
- when(mMockPermissionInfo.isAppOp()).thenReturn(true);
- when(mMockAppOpsManager.unsafeCheckOpRawNoThrow(matches(
- AppOpsManager.OPSTR_MANAGE_ONGOING_CALLS), eq(APPOP_NONUI_UID),
- matches(APPOP_NONUI_PKG))).thenReturn(AppOpsManager.MODE_ALLOWED);
-
- // Now bind; we should bind to the system dialer and app op non ui app.
- mInCallController.bindToServices(mMockCall);
-
- // Bind InCallServices
- ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
- verify(mMockContext, times(2)).bindServiceAsUser(
- bindIntentCaptor.capture(),
- any(ServiceConnection.class),
- eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
- | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS),
- eq(UserHandle.CURRENT));
-
- // Verify bind
- assertEquals(2, bindIntentCaptor.getAllValues().size());
-
- // Should have first bound to the system dialer.
- verifyBinding(bindIntentCaptor, 0, SYS_PKG, SYS_CLASS);
-
- // Should have next bound to the third party app op non ui app.
- verifyBinding(bindIntentCaptor, 1, APPOP_NONUI_PKG, APPOP_NONUI_CLASS);
+ final MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
+ .strictness(Strictness.WARN)
+ .spyStatic(PermissionChecker.class)
+ .startMocking();
+ try {
+ setupMocks(false /* isExternalCall */);
+ setupMockPackageManager(false /* default */, false /* nonui */, true /* appop_nonui */,
+ true /* system */, false /* external calls */, false /* self mgd in default */,
+ false /* self mgd in car*/);
+
+ // Enable Third Party Companion App
+ ExtendedMockito.doReturn(PermissionChecker.PERMISSION_GRANTED).when(() ->
+ PermissionChecker.checkPermissionForDataDeliveryFromDataSource(
+ any(Context.class), eq(Manifest.permission.MANAGE_ONGOING_CALLS),
+ anyInt(), any(AttributionSource.class), nullable(String.class)));
+
+ // Now bind; we should bind to the system dialer and app op non ui app.
+ mInCallController.bindToServices(mMockCall);
+
+ // Bind InCallServices
+ ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext, times(2)).bindServiceAsUser(
+ bindIntentCaptor.capture(),
+ any(ServiceConnection.class),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
+ | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS),
+ eq(UserHandle.CURRENT));
+
+ // Verify bind
+ assertEquals(2, bindIntentCaptor.getAllValues().size());
+
+ // Should have first bound to the system dialer.
+ verifyBinding(bindIntentCaptor, 0, SYS_PKG, SYS_CLASS);
+
+ // Should have next bound to the third party app op non ui app.
+ verifyBinding(bindIntentCaptor, 1, APPOP_NONUI_PKG, APPOP_NONUI_CLASS);
+ } finally {
+ mockitoSession.finishMocking();
+ }
}
/**
@@ -951,6 +1030,31 @@ public class InCallControllerTests extends TelecomTestCase {
*/
@MediumTest
@Test
+ public void testRandomAppRemovalWhenNotInCarMode() throws Exception {
+ setupMocks(true /* isExternalCall */);
+ setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
+ // Bind to default dialer.
+ mInCallController.bindToServices(mMockCall);
+
+ // Uninstall an unrelated app.
+ mSystemStateListener.onPackageUninstalled("com.joe.stuff");
+
+ // Bind InCallServices, just once; we should not re-bind to the same app.
+ ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext).bindServiceAsUser(
+ bindIntentCaptor.capture(),
+ any(ServiceConnection.class),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
+ | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS),
+ eq(UserHandle.CURRENT));
+ }
+
+ /**
+ * Ensures that the {@link InCallController} will bind to a higher priority car mode service
+ * when one becomes available.
+ */
+ @MediumTest
+ @Test
public void testCarmodeRebindHigherPriority() throws Exception {
setupMocks(true /* isExternalCall */);
setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
@@ -958,7 +1062,7 @@ public class InCallControllerTests extends TelecomTestCase {
mInCallController.bindToServices(mMockCall);
// Enable car mode and enter car mode at default priority.
- when(mMockSystemStateHelper.isCarMode()).thenReturn(true);
+ when(mMockSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(true);
mInCallController.handleCarModeChange(UiModeManager.DEFAULT_PRIORITY, CAR_PKG, true);
// And change to the second car mode app.
@@ -1105,7 +1209,7 @@ public class InCallControllerTests extends TelecomTestCase {
// Now switch to car mode.
// Enable car mode and enter car mode at default priority.
- when(mMockSystemStateHelper.isCarMode()).thenReturn(true);
+ when(mMockSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(true);
mInCallController.handleCarModeChange(UiModeManager.DEFAULT_PRIORITY, CAR_PKG, true);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -1145,7 +1249,7 @@ public class InCallControllerTests extends TelecomTestCase {
// Now switch to car mode.
// Enable car mode and enter car mode at default priority.
- when(mMockSystemStateHelper.isCarMode()).thenReturn(true);
+ when(mMockSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(true);
mInCallController.handleCarModeChange(UiModeManager.DEFAULT_PRIORITY, CAR_PKG, true);
// We currently will bind to the car-mode InCallService even if there are no calls available
@@ -1379,6 +1483,28 @@ public class InCallControllerTests extends TelecomTestCase {
}
}).when(mMockPackageManager).queryIntentServicesAsUser(
any(Intent.class), anyInt(), eq(CURRENT_USER_ID));
+
+ if (useDefaultDialer) {
+ when(mMockPackageManager
+ .getComponentEnabledSetting(new ComponentName(DEF_PKG, DEF_CLASS)))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+ }
+
+ when(mMockPackageManager
+ .getComponentEnabledSetting(new ComponentName(SYS_PKG, SYS_CLASS)))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+
+ when(mMockPackageManager
+ .getComponentEnabledSetting(new ComponentName(CAR_PKG, CAR_CLASS)))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+
+ when(mMockPackageManager
+ .getComponentEnabledSetting(new ComponentName(COMPANION_PKG, COMPANION_CLASS)))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+
+ when(mMockPackageManager
+ .getComponentEnabledSetting(new ComponentName(CAR2_PKG, CAR2_CLASS)))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
}
private void setupMockPackageManagerLocationPermission(final String pkg,
@@ -1388,4 +1514,24 @@ public class InCallControllerTests extends TelecomTestCase {
? PackageManager.PERMISSION_GRANTED
: PackageManager.PERMISSION_DENIED);
}
+
+ private static AttributionSourceState matchesAttributionSourcePackage(
+ @Nullable String packageName) {
+ return argThat(new PackageNameArgumentMatcher(packageName));
+ }
+
+ private static class PackageNameArgumentMatcher implements
+ ArgumentMatcher<AttributionSourceState> {
+ @Nullable
+ private final String mPackgeName;
+
+ PackageNameArgumentMatcher(@Nullable String packageName) {
+ mPackgeName = packageName;
+ }
+
+ @Override
+ public boolean matches(@NonNull AttributionSourceState attributionSource) {
+ return Objects.equals(mPackgeName, attributionSource.packageName);
+ }
+ }
}
diff --git a/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java b/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java
index db44dcd4b..2b05430c5 100644
--- a/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/MissedCallNotifierImplTest.java
@@ -29,6 +29,8 @@ import android.content.Context;
import android.content.IContentProvider;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
@@ -65,11 +67,13 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -79,6 +83,7 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -132,6 +137,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase {
}
}
+ private static final long TIMEOUT_DELAY = 5000;
private static final Uri TEL_CALL_HANDLE = Uri.parse("tel:+11915552620");
private static final Uri SIP_CALL_HANDLE = Uri.parse("sip:testaddress@testdomain.com");
private static final String CALLER_NAME = "Fake Name";
@@ -139,6 +145,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase {
private static final String MISSED_CALLS_TITLE = "Missed Calls";
private static final String MISSED_CALLS_MSG = "%s missed calls";
private static final String USER_CALL_ACTIVITY_LABEL = "Phone";
+ private static final String DEFAULT_DIALER_PACKAGE = "com.android.server.telecom.test";
private static final int REQUEST_ID = 0;
private static final long CALL_TIMESTAMP;
@@ -213,6 +220,49 @@ public class MissedCallNotifierImplTest extends TelecomTestCase {
cancelNotificationTestInternal(SECONARY_USER);
}
+ @SmallTest
+ @Test
+ public void testDefaultDialerClear() {
+ MissedCallNotifier missedCallNotifier = setupMissedCallNotificationThroughDefaultDialer();
+ missedCallNotifier.clearMissedCalls(PRIMARY_USER);
+
+ ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).sendBroadcastAsUser(intentArgumentCaptor.capture(), any(),
+ anyString(), any());
+ Intent sentIntent = intentArgumentCaptor.getValue();
+ assertEquals(0, sentIntent.getIntExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, -1));
+ }
+
+ @SmallTest
+ @Test
+ public void testDefaultDialerIncrement() {
+ MissedCallNotifier missedCallNotifier = setupMissedCallNotificationThroughDefaultDialer();
+ PhoneAccount phoneAccount = makePhoneAccount(PRIMARY_USER, NO_CAPABILITY);
+ MissedCallNotifier.CallInfo fakeCall = makeFakeCallInfo(TEL_CALL_HANDLE, CALLER_NAME,
+ CALL_TIMESTAMP, phoneAccount.getAccountHandle());
+
+ missedCallNotifier.showMissedCallNotification(fakeCall);
+ ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).sendBroadcastAsUser(intentArgumentCaptor.capture(), any(),
+ anyString(), any());
+
+ Intent sentIntent = intentArgumentCaptor.getValue();
+ assertEquals(1, sentIntent.getIntExtra(TelecomManager.EXTRA_NOTIFICATION_COUNT, -1));
+ }
+
+ private MissedCallNotifier setupMissedCallNotificationThroughDefaultDialer() {
+ mComponentContextFixture.addIntentReceiver(
+ TelecomManager.ACTION_SHOW_MISSED_CALLS_NOTIFICATION, COMPONENT_NAME);
+ when(mDefaultDialerCache.getDefaultDialerApplication(anyInt())).thenReturn(
+ DEFAULT_DIALER_PACKAGE);
+
+ Notification.Builder builder1 = makeNotificationBuilder("builder1");
+ Notification.Builder builder2 = makeNotificationBuilder("builder2");
+ MissedCallNotifierImpl.NotificationBuilderFactory fakeBuilderFactory =
+ makeNotificationBuilderFactory(builder1, builder1, builder2, builder2);
+ return makeMissedCallNotifier(fakeBuilderFactory, PRIMARY_USER);
+ }
+
private void cancelNotificationTestInternal(UserHandle userHandle) {
Notification.Builder builder1 = makeNotificationBuilder("builder1");
Notification.Builder builder2 = makeNotificationBuilder("builder2");
@@ -458,7 +508,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase {
CallLog.Calls.PRESENTATION_ALLOWED, CALL_TIMESTAMP)
.build();
- when(cp.query(anyString(), nullable(String.class), eq(queryUri), nullable(String[].class),
+ when(cp.query(any(), eq(queryUri), nullable(String[].class),
nullable(Bundle.class), nullable(ICancellationSignal.class)))
.thenReturn(mockMissedCallsCursor);
@@ -528,7 +578,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase {
PRIMARY_USER.getIdentifier());
IContentProvider cp = getContentProviderForUser(PRIMARY_USER.getIdentifier());
- when(cp.query(anyString(), nullable(String.class), eq(queryUri), nullable(String[].class),
+ when(cp.query(any(), eq(queryUri), nullable(String[].class),
nullable(Bundle.class), nullable(ICancellationSignal.class)))
.thenReturn(mockMissedCallsCursor);
@@ -611,7 +661,7 @@ public class MissedCallNotifierImplTest extends TelecomTestCase {
assertNotNull("Not expecting null options bundle", bundleCaptor.getValue());
BroadcastOptions options = new BroadcastOptions(bundleCaptor.getValue());
assertTrue("App must have a temporary exemption set.",
- options.getTemporaryAppWhitelistDuration() > 0);
+ options.getTemporaryAppAllowlistDuration() > 0);
// A notification should never be posted by Telecom
verify(mNotificationManager, never()).notifyAsUser(nullable(String.class), anyInt(),
diff --git a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
index a5b78b7c3..e6c6bacf4 100644
--- a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
+++ b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
@@ -110,7 +110,7 @@ public class NewOutgoingCallIntentBroadcasterTest extends TelecomTestCase {
when(mPhoneAccountRegistrar.getPhoneAccountUnchecked(
any(PhoneAccountHandle.class))).thenReturn(mPhoneAccount);
when(mPhoneAccount.isSelfManaged()).thenReturn(true);
- when(mSystemStateHelper.isCarMode()).thenReturn(false);
+ when(mSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(false);
}
@Override
diff --git a/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java b/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java
index 6c941fe4d..a50328386 100644
--- a/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java
+++ b/tests/src/com/android/server/telecom/tests/ParcelableCallUtilsTest.java
@@ -1,13 +1,12 @@
package com.android.server.telecom.tests;
-import static com.android.server.telecom.TelecomSystem.*;
+import static com.android.server.telecom.TelecomSystem.SyncRoot;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
@@ -17,6 +16,7 @@ import android.os.SystemClock;
import android.telecom.Connection;
import android.telecom.ParcelableCall;
import android.telecom.PhoneAccountHandle;
+import android.telephony.ims.ImsCallProfile;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.telecom.Call;
@@ -26,7 +26,6 @@ import com.android.server.telecom.ClockProxy;
import com.android.server.telecom.ParcelableCallUtils;
import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.PhoneNumberUtilsAdapter;
-import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.ui.ToastFactory;
import org.junit.After;
@@ -98,6 +97,7 @@ public class ParcelableCallUtilsTest extends TelecomTestCase {
Bundle parceledExtras = call.getExtras();
assertFalse(parceledExtras.containsKey(Connection.EXTRA_SIP_INVITE));
+ assertTrue(parceledExtras.containsKey(ImsCallProfile.EXTRA_IS_BUSINESS_CALL));
assertFalse(parceledExtras.containsKey("SomeExtra"));
assertTrue(parceledExtras.containsKey(Connection.EXTRA_CALL_SUBJECT));
}
@@ -115,6 +115,7 @@ public class ParcelableCallUtilsTest extends TelecomTestCase {
Bundle parceledExtras = call.getExtras();
assertTrue(parceledExtras.containsKey(Connection.EXTRA_SIP_INVITE));
+ assertTrue(parceledExtras.containsKey(ImsCallProfile.EXTRA_IS_BUSINESS_CALL));
assertTrue(parceledExtras.containsKey("SomeExtra"));
assertTrue(parceledExtras.containsKey(Connection.EXTRA_CALL_SUBJECT));
}
@@ -128,6 +129,7 @@ public class ParcelableCallUtilsTest extends TelecomTestCase {
Bundle parceledExtras = call.getExtras();
assertTrue(parceledExtras.containsKey(Connection.EXTRA_SIP_INVITE));
+ assertTrue(parceledExtras.containsKey(ImsCallProfile.EXTRA_IS_BUSINESS_CALL));
assertFalse(parceledExtras.containsKey("SomeExtra"));
assertFalse(parceledExtras.containsKey(Connection.EXTRA_CALL_SUBJECT));
}
@@ -141,6 +143,7 @@ public class ParcelableCallUtilsTest extends TelecomTestCase {
Bundle parceledExtras = call.getExtras();
assertFalse(parceledExtras.containsKey(Connection.EXTRA_SIP_INVITE));
+ assertFalse(parceledExtras.containsKey(ImsCallProfile.EXTRA_IS_BUSINESS_CALL));
assertFalse(parceledExtras.containsKey("SomeExtra"));
assertFalse(parceledExtras.containsKey(Connection.EXTRA_CALL_SUBJECT));
}
@@ -192,6 +195,7 @@ public class ParcelableCallUtilsTest extends TelecomTestCase {
extras.putString(Connection.EXTRA_SIP_INVITE, "scary data");
extras.putString("SomeExtra", "Extra Extra");
extras.putString(Connection.EXTRA_CALL_SUBJECT, "Blah");
+ extras.putBoolean(ImsCallProfile.EXTRA_IS_BUSINESS_CALL, true);
return extras;
}
}
diff --git a/tests/src/com/android/server/telecom/tests/RingerTest.java b/tests/src/com/android/server/telecom/tests/RingerTest.java
index 38f63d2d2..0e93481cb 100644
--- a/tests/src/com/android/server/telecom/tests/RingerTest.java
+++ b/tests/src/com/android/server/telecom/tests/RingerTest.java
@@ -79,6 +79,16 @@ public class RingerTest extends TelecomTestCase {
}
@Override
+ public VibrationEffect resolve(int defaultAmplitude) {
+ return this;
+ }
+
+ @Override
+ public VibrationEffect scale(float scaleFactor) {
+ return this;
+ }
+
+ @Override
public void validate() {
// not needed
}
diff --git a/tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java b/tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java
index 7113148da..dc7d1fd8a 100644
--- a/tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java
+++ b/tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java
@@ -61,6 +61,7 @@ import org.mockito.MockitoAnnotations;
import org.mockito.internal.util.reflection.FieldSetter;
import java.util.List;
+import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -93,6 +94,8 @@ public class SystemStateHelperTest extends TelecomTestCase {
when(mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)).thenReturn(mGravitySensor);
when(mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)).thenReturn(mProxSensor);
+ doReturn(mUiModeManager).when(mContext).getSystemService(UiModeManager.class);
+
mComponentContextFixture.putFloatResource(
R.dimen.device_on_ear_xy_gravity_threshold, 5.5f);
mComponentContextFixture.putFloatResource(
@@ -119,17 +122,53 @@ public class SystemStateHelperTest extends TelecomTestCase {
@SmallTest
@Test
public void testQuerySystemForCarMode_True() {
- when(mContext.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(mUiModeManager);
when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_CAR);
- assertTrue(new SystemStateHelper(mContext, mLock).isCarMode());
+ assertTrue(new SystemStateHelper(mContext, mLock).isCarModeOrProjectionActive());
}
@SmallTest
@Test
public void testQuerySystemForCarMode_False() {
- when(mContext.getSystemService(Context.UI_MODE_SERVICE)).thenReturn(mUiModeManager);
when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_NORMAL);
- assertFalse(new SystemStateHelper(mContext, mLock).isCarMode());
+ assertFalse(new SystemStateHelper(mContext, mLock).isCarModeOrProjectionActive());
+ }
+
+ @SmallTest
+ @Test
+ public void testQuerySystemForAutomotiveProjection_True() {
+ when(mUiModeManager.getActiveProjectionTypes())
+ .thenReturn(UiModeManager.PROJECTION_TYPE_AUTOMOTIVE);
+ assertTrue(new SystemStateHelper(mContext, mLock).isCarModeOrProjectionActive());
+
+ when(mUiModeManager.getActiveProjectionTypes())
+ .thenReturn(UiModeManager.PROJECTION_TYPE_ALL);
+ assertTrue(new SystemStateHelper(mContext, mLock).isCarModeOrProjectionActive());
+ }
+
+ @SmallTest
+ @Test
+ public void testQuerySystemForAutomotiveProjection_False() {
+ when(mUiModeManager.getActiveProjectionTypes())
+ .thenReturn(UiModeManager.PROJECTION_TYPE_NONE);
+ assertFalse(new SystemStateHelper(mContext, mLock).isCarModeOrProjectionActive());
+ }
+
+ @SmallTest
+ @Test
+ public void testQuerySystemForAutomotiveProjectionAndCarMode_True() {
+ when(mUiModeManager.getCurrentModeType()).thenReturn(Configuration.UI_MODE_TYPE_CAR);
+ when(mUiModeManager.getActiveProjectionTypes())
+ .thenReturn(UiModeManager.PROJECTION_TYPE_AUTOMOTIVE);
+ assertTrue(new SystemStateHelper(mContext, mLock).isCarModeOrProjectionActive());
+ }
+
+ @SmallTest
+ @Test
+ public void testQuerySystemForAutomotiveProjectionOrCarMode_nullService() {
+ when(mContext.getSystemService(UiModeManager.class))
+ .thenReturn(mUiModeManager) // Without this, class construction will throw NPE.
+ .thenReturn(null);
+ assertFalse(new SystemStateHelper(mContext, mLock).isCarModeOrProjectionActive());
}
@SmallTest
@@ -206,6 +245,40 @@ public class SystemStateHelperTest extends TelecomTestCase {
@SmallTest
@Test
+ public void testOnSetReleaseAutomotiveProjection() {
+ SystemStateHelper systemStateHelper = new SystemStateHelper(mContext, mLock);
+ // We don't care what listener is registered, that's an implementation detail, but we need
+ // to call methods on whatever it is.
+ ArgumentCaptor<UiModeManager.OnProjectionStateChangedListener> listenerCaptor =
+ ArgumentCaptor.forClass(UiModeManager.OnProjectionStateChangedListener.class);
+ verify(mUiModeManager).addOnProjectionStateChangedListener(
+ eq(UiModeManager.PROJECTION_TYPE_AUTOMOTIVE), any(), listenerCaptor.capture());
+ systemStateHelper.addListener(mSystemStateListener);
+
+ String packageName1 = "Sufjan Stevens";
+ String packageName2 = "The Ascension";
+
+ // Should pay attention to automotive projection, though.
+ listenerCaptor.getValue().onProjectionStateChanged(
+ UiModeManager.PROJECTION_TYPE_AUTOMOTIVE, Set.of(packageName2));
+ verify(mSystemStateListener).onAutomotiveProjectionStateSet(packageName2);
+
+ // Without any automotive projection, it should see it as released.
+ listenerCaptor.getValue().onProjectionStateChanged(
+ UiModeManager.PROJECTION_TYPE_NONE, Set.of());
+ verify(mSystemStateListener).onAutomotiveProjectionStateReleased();
+
+ // Try the whole thing again, with different values.
+ listenerCaptor.getValue().onProjectionStateChanged(
+ UiModeManager.PROJECTION_TYPE_AUTOMOTIVE, Set.of(packageName1));
+ verify(mSystemStateListener).onAutomotiveProjectionStateSet(packageName1);
+ listenerCaptor.getValue().onProjectionStateChanged(
+ UiModeManager.PROJECTION_TYPE_AUTOMOTIVE, Set.of());
+ verify(mSystemStateListener, times(2)).onAutomotiveProjectionStateReleased();
+ }
+
+ @SmallTest
+ @Test
public void testDeviceOnEarCorrectlyDetected() {
doAnswer(invocation -> {
SensorEventListener listener = invocation.getArgument(0);
diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
index 0dfe29a08..3cec50b78 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -460,10 +460,10 @@ public class TelecomServiceImplTest extends TelecomTestCase {
@Test
public void testGetPhoneAccount() throws RemoteException {
makeAccountsVisibleToAllUsers(TEL_PA_HANDLE_16, SIP_PA_HANDLE_17);
- assertEquals(TEL_PA_HANDLE_16, mTSIBinder.getPhoneAccount(TEL_PA_HANDLE_16)
- .getAccountHandle());
- assertEquals(SIP_PA_HANDLE_17, mTSIBinder.getPhoneAccount(SIP_PA_HANDLE_17)
- .getAccountHandle());
+ assertEquals(TEL_PA_HANDLE_16, mTSIBinder.getPhoneAccount(TEL_PA_HANDLE_16,
+ mContext.getPackageName()).getAccountHandle());
+ assertEquals(SIP_PA_HANDLE_17, mTSIBinder.getPhoneAccount(SIP_PA_HANDLE_17,
+ mContext.getPackageName()).getAccountHandle());
}
@SmallTest
@@ -1202,6 +1202,39 @@ public class TelecomServiceImplTest extends TelecomTestCase {
}
/**
+ * Ensure self-managed calls cannot be ended using {@link TelecomManager#endCall()}.
+ * @throws Exception
+ */
+ @SmallTest
+ @Test
+ public void testCannotEndSelfManagedCall() throws Exception {
+ Call call = mock(Call.class);
+ when(call.isSelfManaged()).thenReturn(true);
+ when(call.getState()).thenReturn(CallState.ACTIVE);
+ when(mFakeCallsManager.getFirstCallWithState(any()))
+ .thenReturn(call);
+ assertFalse(mTSIBinder.endCall(TEST_PACKAGE));
+ verify(mFakeCallsManager, never()).disconnectCall(eq(call));
+ }
+
+ /**
+ * Ensure self-managed calls cannot be answered using {@link TelecomManager#acceptRingingCall()}
+ * or {@link TelecomManager#acceptRingingCall(int)}.
+ * @throws Exception
+ */
+ @SmallTest
+ @Test
+ public void testCannotAnswerSelfManagedCall() throws Exception {
+ Call call = mock(Call.class);
+ when(call.isSelfManaged()).thenReturn(true);
+ when(call.getState()).thenReturn(CallState.ACTIVE);
+ when(mFakeCallsManager.getFirstCallWithState(any()))
+ .thenReturn(call);
+ mTSIBinder.acceptRingingCall(TEST_PACKAGE);
+ verify(mFakeCallsManager, never()).answerCall(eq(call), anyInt());
+ }
+
+ /**
* Register phone accounts for the supplied PhoneAccountHandles to make them
* visible to all users (via the isVisibleToCaller method in TelecomServiceImpl.
* @param handles the handles for which phone accounts should be created for.