upload android base code part8

This commit is contained in:
August 2018-08-08 20:10:12 +08:00
parent 841ae54672
commit 5425409085
57075 changed files with 9846578 additions and 0 deletions

View file

@ -0,0 +1,41 @@
#
# Copyright (C) 2009 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.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_PACKAGE_NAME := TeleServiceTests
LOCAL_CERTIFICATE := platform
LOCAL_MODULE_TAGS := tests
LOCAL_JAVA_LIBRARIES := telephony-common android-support-test
LOCAL_INSTRUMENTATION_FOR := TeleService
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
mockito-target-minus-junit4 \
espresso-core \
truth-prebuilt \
legacy-android-test
LOCAL_COMPATIBILITY_SUITE := device-tests
include $(BUILD_PACKAGE)

View file

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.phone.tests">
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.PERFORM_CDMA_PROVISIONING" />
<application android:label="@string/app_name">
<uses-library android:name="android.test.runner" />
<!-- Miscellaneous phone app-related test activities -->
<!-- Test activity that mimics the behavior of 3rd party apps
firing off CALL and DIAL intents. -->
<!-- To run:
adb shell am start -n com.android.phone.tests/.CallDialTest
-->
<activity android:name="CallDialTest"
android:label="@string/callDialTestLabel">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service android:name="SendInstantTextTestService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE" >
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
</intent-filter>
</service>
<receiver android:name="com.android.services.telephony.activation.ResponseReceiver" />
</application>
<!--
To run all tests:
adb shell am instrument -w
com.android.phone.tests/android.support.test.runner.AndroidJUnitRunner
To run a single class test:
adb shell am instrument -e class com.android.phone.unit.FooUnitTest
-w com.android.phone.tests/android.support.test.runner.AndroidJUnitRunner
-->
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.phone"
android:label="Phone application tests." />
</manifest>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 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.
-->
<configuration description="Run Phone application tests.">
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
<option name="test-file-name" value="TeleServiceTests.apk" />
</target_preparer>
<option name="test-suite-tag" value="apct" />
<option name="test-tag" value="TeleServiceTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.phone.tests" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
</test>
</configuration>

View file

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<!-- Ultra-simple test activity for testing CALL and DIAL intents. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center_vertical|center_horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="64dip"
>
<TextView android:id="@+id/label1"
android:text="@string/callDialTestLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dip"
android:textAppearance="?android:attr/textAppearanceLarge"
/>
<View android:layout_width="1dip"
android:layout_height="1dip"
android:layout_weight="1" />
<!-- Phone number (or potentially a SIP address) to be used -->
<EditText android:id="@+id/number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="32dip"
android:paddingRight="32dip"
android:paddingTop="32dip"
android:paddingBottom="32dip"
android:textAppearance="?android:attr/textAppearanceLarge" />
<View android:layout_width="1dip"
android:layout_height="1dip"
android:layout_weight="2" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<Button android:id="@+id/callButton"
android:text="@string/callCommand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:paddingLeft="32dip"
android:paddingRight="32dip"
android:textAppearance="?android:attr/textAppearanceLarge"
/>
<Button android:id="@+id/dialButton"
android:text="@string/dialCommand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:paddingLeft="32dip"
android:paddingRight="32dip"
android:textAppearance="?android:attr/textAppearanceLarge"
/>
</LinearLayout>
<View android:layout_width="1dip"
android:layout_height="1dip"
android:layout_weight="2" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<Button android:id="@+id/itelephonyCallButton"
android:text="@string/itelephonyCallCommand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:paddingLeft="32dip"
android:paddingRight="32dip"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<Button android:id="@+id/itelephonyDialButton"
android:text="@string/itelephonyDialCommand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:paddingLeft="32dip"
android:paddingRight="32dip"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
</LinearLayout>
<View android:layout_width="1dip"
android:layout_height="1dip"
android:layout_weight="4" />
</LinearLayout>

View file

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<!-- Ultra-simple test activity for triggering an OTASP call. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center_vertical|center_horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="64dip"
>
<TextView android:id="@+id/label1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dip"
android:textAppearance="?android:attr/textAppearanceLarge"
/>
<View android:layout_width="1dip"
android:layout_height="1dip"
android:layout_weight="1" />
<ProgressBar android:id="@+id/progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="240dip"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="invisible" />
<TextView android:id="@+id/result1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:visibility="invisible" />
<View android:layout_width="1dip"
android:layout_height="1dip"
android:layout_weight="1" />
<Button android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:layout_marginBottom="10dip"
android:paddingLeft="32dip"
android:paddingRight="32dip"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<View android:layout_width="1dip"
android:layout_height="1dip"
android:layout_weight="1" />
</LinearLayout>

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2009 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.
-->
<resources>
<!-- Application label -->
<string name="app_name">PhoneAppTests</string>
<!-- Strings for the CallDialTest activity -->
<string name="callDialTestLabel">CALL/DIAL test</string>
<string name="callCommand">CALL</string>
<string name="dialCommand">DIAL</string>
<string name="itelephonyCallCommand">ITelephony.call()</string>
<string name="itelephonyDialCommand">ITelephony.dial()</string>
<string name="instant_text_back_content">message: %s, Uri: %s, </string>
</resources>

View file

@ -0,0 +1,80 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.support.test.InstrumentationRegistry;
import android.util.Log;
import org.mockito.MockitoAnnotations;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Helper class to load Mockito Resources into a test.
*/
public class TelephonyTestBase {
protected Context mContext;
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getTargetContext();
MockitoAnnotations.initMocks(this);
// Set up the looper if it does not exist on the test thread.
if (Looper.myLooper() == null) {
Looper.prepare();
}
}
public void tearDown() throws Exception {
}
protected final void waitForHandlerAction(Handler h, long timeoutMillis) {
final CountDownLatch lock = new CountDownLatch(1);
h.post(lock::countDown);
while (lock.getCount() > 0) {
try {
lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// do nothing
}
}
}
protected final void waitForHandlerActionDelayed(Handler h, long timeoutMillis, long delayMs) {
final CountDownLatch lock = new CountDownLatch(1);
h.postDelayed(lock::countDown, delayMs);
while (lock.getCount() > 0) {
try {
lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// do nothing
}
}
}
protected void waitForMs(long ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
Log.e("TelephonyTestBase", "InterruptedException while waiting: " + e);
}
}
}

View file

@ -0,0 +1,76 @@
/*
* Copyright (C) 2009 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.
*/
// Need to be in this package to access package methods.
package com.android.phone;
import android.content.Context;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import com.android.internal.telephony.CallerInfo;
import com.android.phone.PhoneUtils;
import static com.android.internal.telephony.PhoneConstants.PRESENTATION_ALLOWED;
import static com.android.internal.telephony.PhoneConstants.PRESENTATION_PAYPHONE;
import static com.android.internal.telephony.PhoneConstants.PRESENTATION_RESTRICTED;
import static com.android.internal.telephony.PhoneConstants.PRESENTATION_UNKNOWN;
// Test suite for the Caller Name Presentation (CNAP) handling.
// See AndroidManifest.xml how to run these tests.
public class CnapTest extends AndroidTestCase {
private static final String TAG = "CnapTest";
private Context mContext;
private CallerInfo mCallerInfo;
// TODO: This string should be loaded from the phone package and
// not hardcoded.
private String mUnknown = "Unknown";
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getContext();
mCallerInfo = new CallerInfo();
}
// Checks the cnap 'ABSENT NUMBER' is mapped to the unknown presentation.
@SmallTest
public void testAbsentNumberIsMappedToUnknown() throws Exception {
String num = modifyForSpecialCnapCases("ABSENT NUMBER", PRESENTATION_ALLOWED);
assertIsUnknown(num);
}
// HELPERS
/**
* Checks the number and CallerInfo structure indicate the number
* is unknown.
*/
private void assertIsUnknown(String number) {
assertEquals(mUnknown, number);
assertEquals(PRESENTATION_UNKNOWN, mCallerInfo.numberPresentation);
// TODO: cnapName and name presentation should be set to
// unknown. At least I cannot see why it shouldn't be the case
// assertEquals(mUnknown, mCallerInfo.cnapName);
// assertEquals(PRESENTATION_UNKNOWN, mCallerInfo.namePresentation);
}
/**
* Shorthand for PhoneUtils.modifyForSpecialCnapCases(mContext, mCallerInfo, ...)
*/
private String modifyForSpecialCnapCases(String number, int presentation) {
return PhoneUtils.modifyForSpecialCnapCases(
mContext, mCallerInfo, number, presentation);
}
}

View file

@ -0,0 +1,139 @@
/*
* Copyright (C) 2017 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.phone;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ProviderInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.os.UserManager;
import android.provider.SearchIndexablesContract;
import android.provider.Settings;
import android.support.test.runner.AndroidJUnit4;
import android.telephony.euicc.EuiccManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
/** Unit tests for {@link PhoneSearchIndexablesProvider}. */
@RunWith(AndroidJUnit4.class)
public final class PhoneSearchIndexablesProviderTest {
private PhoneSearchIndexablesTestProvider mProvider;
@Mock private ApplicationInfo mApplicationInfo;
@Mock private Context mContext;
@Mock private Resources mResources;
@Mock private UserManager mUserManager;
@Mock private EuiccManager mEuiccManager;
@Mock private ContentResolver mCr;
private class PhoneSearchIndexablesTestProvider extends PhoneSearchIndexablesProvider {
private boolean mIsEuiccSettingsHidden = false;
private boolean mIsEnhanced4gLteHidden = false;
@Override boolean isEuiccSettingsHidden() {
return mIsEuiccSettingsHidden;
}
@Override boolean isEnhanced4gLteHidden() {
return mIsEnhanced4gLteHidden;
}
public void setIsEuiccSettingsHidden(boolean isEuiccSettingsHidden) {
mIsEuiccSettingsHidden = isEuiccSettingsHidden;
}
public void setIsEnhanced4gLteHidden(boolean isEnhanced4gLteHidden) {
mIsEnhanced4gLteHidden = isEnhanced4gLteHidden;
}
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mResources.getString(com.android.phone.R.string.carrier_settings_euicc))
.thenReturn("");
when(mResources.getString(com.android.phone.R.string.keywords_carrier_settings_euicc))
.thenReturn("");
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
when(mContext.getSystemService(Context.EUICC_SERVICE)).thenReturn(mEuiccManager);
when(mContext.getResources()).thenReturn(mResources);
when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
when(mContext.getPackageName()).thenReturn("PhoneSearchIndexablesProviderTest");
when(mContext.getContentResolver()).thenReturn(mCr);
when(mCr.getPackageName()).thenReturn("com.android.phone");
final ProviderInfo providerInfo = new ProviderInfo();
providerInfo.authority = Settings.AUTHORITY;
providerInfo.exported = true;
providerInfo.grantUriPermissions = true;
providerInfo.readPermission = android.Manifest.permission.READ_SEARCH_INDEXABLES;
mProvider = new PhoneSearchIndexablesTestProvider();
mProvider.attachInfo(mContext, providerInfo);
}
@Test
public void testQueryRawData() {
when(mUserManager.isAdminUser()).thenReturn(true);
when(mEuiccManager.isEnabled()).thenReturn(true);
Settings.Global.putInt(mCr, Settings.Global.EUICC_PROVISIONED, 1);
Settings.Global.getInt(mCr, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
Cursor cursor = mProvider.queryRawData(SearchIndexablesContract.INDEXABLES_RAW_COLUMNS);
assertThat(cursor.getColumnNames()).isEqualTo(
SearchIndexablesContract.INDEXABLES_RAW_COLUMNS);
assertThat(cursor.getCount()).isEqualTo(1);
cursor.moveToNext();
assertThat(cursor.getString(SearchIndexablesContract.COLUMN_INDEX_RAW_KEY))
.isEqualTo("esim_list_profile");
}
@Test
public void testQueryNonIndexableKeys() {
mProvider.setIsEnhanced4gLteHidden(false /* isEnhanced4gLteHidden */);
mProvider.setIsEuiccSettingsHidden(false /* isEuiccSettingsHiden */);
when(mUserManager.isAdminUser()).thenReturn(false);
Cursor cursor1 = mProvider.queryNonIndexableKeys(
SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
assertThat(cursor1.getColumnNames()).isEqualTo(
SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
assertThat(cursor1.getCount()).isEqualTo(11);
when(mUserManager.isAdminUser()).thenReturn(true);
Cursor cursor2 = mProvider
.queryNonIndexableKeys(SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
assertThat(cursor2.getCount()).isEqualTo(1);
mProvider.setIsEuiccSettingsHidden(true /* isEuiccSettingsHidden */);
Cursor cursor3 = mProvider
.queryNonIndexableKeys(SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
assertThat(cursor3.getCount()).isEqualTo(2);
mProvider.setIsEnhanced4gLteHidden(true /* isEnhanced4gLteHidden */);
Cursor cursor4 = mProvider
.queryNonIndexableKeys(SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
assertThat(cursor4.getCount()).isEqualTo(3);
}
}

View file

@ -0,0 +1,128 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.phone;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.provider.Settings.Global;
import android.provider.Settings.SettingNotFoundException;
import android.support.test.espresso.matcher.PreferenceMatchers;
import android.support.test.rule.ActivityTestRule;
import android.support.test.filters.FlakyTest;
import com.google.common.truth.Truth;
import junit.framework.AssertionFailedError;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import static android.support.test.espresso.Espresso.onData;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
import static android.support.test.espresso.matcher.ViewMatchers.isChecked;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static com.google.common.truth.Truth.assertThat;
/**
* Espresso tests to check some properties of the dialog that appears when a user
* tries to turn on data roaming.
*/
public class RoamingDialogFragmentTest {
@Rule
public ActivityTestRule<MobileNetworkSettings> mRule =
new ActivityTestRule<>(MobileNetworkSettings.class);
private Activity mActivity;
/**
* Make sure roaming is off before we start a test since this checks the dialog that only
* shows up when we try to turn it on.
*/
@Before
public void disableRoaming() {
mActivity = mRule.getActivity();
// turn off data roaming if it is on
try {
onData(PreferenceMatchers.withTitle(R.string.roaming))
.check(matches(hasDescendant(isChecked())))
.perform(click());
} catch (AssertionFailedError e) {
// don't click the switch if it is already off.
}
}
@FlakyTest
@Test
public void dataRoamingDialogPersistsOnRotation() {
// click on the data roaming preference to trigger warning dialog
onData(PreferenceMatchers.withTitle(R.string.roaming)).perform(click());
// request both orientations to ensure at least one rotation occurs
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// verify the title of the dialog is visible
onView(withText(R.string.roaming_alert_title)).check(matches(isDisplayed()));
}
@FlakyTest
@Test
public void dataRoamingEnabledWhenPositiveButtonClicked() throws SettingNotFoundException {
// click on the data roaming preference to trigger warning dialog
onData(PreferenceMatchers.withTitle(R.string.roaming)).perform(click());
// click to confirm we want to turn on data roaming
onView(withId(android.R.id.button1)).perform(click());
// verify that the the setting has actually been changed
assertThat(Global.getInt(mActivity.getApplicationContext().getContentResolver(),
Global.DATA_ROAMING)).isEqualTo(1);
}
@FlakyTest
@Test
public void dialogDismissedOnNegativeButtonClicked() {
// click on the data roaming preference to trigger warning dialog
onData(PreferenceMatchers.withTitle(R.string.roaming)).perform(click());
// click to cancel turning on data roaming
onView(withId(android.R.id.button2)).perform(click());
// verify the title of the dialog is gone
onView(withText(R.string.roaming_alert_title)).check(doesNotExist());
}
@FlakyTest
@Test
public void dataRoamingStaysDisabledWhenDialogCanceled() throws SettingNotFoundException {
// click on the data roaming preference to trigger warning dialog
onData(PreferenceMatchers.withTitle(R.string.roaming)).perform(click());
// click to cancel turning on data roaming
onView(withId(android.R.id.button2)).perform(click());
// verify that the the setting has not been changed
assertThat(Global.getInt(mActivity.getApplicationContext().getContentResolver(),
Global.DATA_ROAMING)).isEqualTo(0);
}
}

View file

@ -0,0 +1,125 @@
/*
* Copyright (C) 2017 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.phone.euicc;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.telephony.euicc.EuiccManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class EuiccUiDispatcherActivityTest {
private static final Intent MANAGE_INTENT =
new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS);
private static final Intent PROVISION_INTENT =
new Intent(EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION);
private static final ActivityInfo ACTIVITY_INFO = new ActivityInfo();
static {
ACTIVITY_INFO.packageName = "test.package";
ACTIVITY_INFO.name = "TestClass";
}
@Mock private Context mMockContext;
@Mock private EuiccManager mMockEuiccManager;
private boolean mIsProvisioned = true;
private ActivityInfo mActivityInfo = ACTIVITY_INFO;
private Intent mIntent = MANAGE_INTENT;
private EuiccUiDispatcherActivity mActivity;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mMockEuiccManager.isEnabled()).thenReturn(true);
when(mMockContext.getSystemService(Context.EUICC_SERVICE)).thenReturn(mMockEuiccManager);
InstrumentationRegistry.getInstrumentation().runOnMainSync(
new Runnable() {
@Override
public void run() {
mActivity = new TestEuiccUiDispatcherActivity();
}
}
);
}
@Test
public void testResolveEuiccUiIntent_disabled() {
when(mMockEuiccManager.isEnabled()).thenReturn(false);
assertNull(mActivity.resolveEuiccUiIntent());
}
@Test
public void testResolveEuiccUiIntent_unsupportedAction() {
mIntent = new Intent("fake.action");
assertNull(mActivity.resolveEuiccUiIntent());
}
@Test
public void testResolveEuiccUiIntent_alreadyProvisioned() {
mIntent = PROVISION_INTENT;
assertNull(mActivity.resolveEuiccUiIntent());
}
@Test
public void testResolveEuiccUiIntent_noImplementation() {
mActivityInfo = null;
assertNull(mActivity.resolveEuiccUiIntent());
}
@Test
public void testResolveEuiccUiIntent_validManage() {
assertNotNull(mActivity.resolveEuiccUiIntent());
}
@Test
public void testResolveEuiccUiIntent_validProvision() {
mIsProvisioned = false;
assertNotNull(mActivity.resolveEuiccUiIntent());
}
class TestEuiccUiDispatcherActivity extends EuiccUiDispatcherActivity {
public TestEuiccUiDispatcherActivity() {
attachBaseContext(mMockContext);
}
@Override
public Intent getIntent() {
return mIntent;
}
@Override
boolean isDeviceProvisioned() {
return mIsProvisioned;
}
@Override
ActivityInfo findBestActivity(Intent euiccUiIntent) {
return mActivityInfo;
}
}
}

View file

@ -0,0 +1,189 @@
/*
* Copyright (C) 2010 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.phone.tests;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telecom.PhoneAccount;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.telephony.ITelephony;
/**
* Test activity that mimics the behavior of 3rd party apps firing off
* CALL and DIAL intents.
*/
public class CallDialTest extends Activity implements View.OnClickListener {
private static final String LOG_TAG = "CallDialTest";
// UI elements
private TextView mLabel;
private EditText mNumber;
@Override
protected void onCreate(Bundle savedInstanceState) {
Intent intent = getIntent();
log("onCreate: intent = " + intent);
// Construct our basic UI:
super.onCreate(savedInstanceState);
setContentView(R.layout.call_dial_test);
mLabel = (TextView) findViewById(R.id.label1);
mNumber = (EditText) findViewById(R.id.number);
mNumber.setText("6505551234"); // Preload it with something useful
((Button) findViewById(R.id.callButton)).setOnClickListener(this);
((Button) findViewById(R.id.dialButton)).setOnClickListener(this);
((Button) findViewById(R.id.itelephonyCallButton)).setOnClickListener(this);
((Button) findViewById(R.id.itelephonyDialButton)).setOnClickListener(this);
}
@Override
protected void onResume() {
log("onResume()...");
super.onResume();
}
@Override
protected void onPause() {
log("onPause()...");
super.onPause();
}
// View.OnClickListener implementation
@Override
public void onClick(View view) {
int id = view.getId();
log("onClick(View " + view + ", id " + id + ")...");
switch (id) {
case R.id.callButton:
log("onClick: CALL...");
fireIntent(Intent.ACTION_CALL);
break;
case R.id.dialButton:
log("onClick: DIAL...");
fireIntent(Intent.ACTION_DIAL);
break;
case R.id.itelephonyCallButton:
log("onClick: ITelephony.call()...");
doITelephonyCall();
break;
case R.id.itelephonyDialButton:
log("onClick: ITelephony.dial()...");
doITelephonyDial();
break;
default:
Log.wtf(LOG_TAG, "onClick: unexpected View: " + view);
break;
}
}
private void fireIntent(String action) {
log("fireIntent(action = '" + action + "')...");
// Get a phone number or SIP address from the EditText widget
String number = mNumber.getText().toString();
log("==> number: '" + number + "'");
// Based on the number, fire off a CALL or DIAL intent:
// - if it's a fully qualified URI (with scheme), use it directly
// - if it looks like a SIP address, prepend sip:
// - if it's just a number, prepend tel: automatically
// - if it's blank, fire off a blank CALL or DIAL intent
Uri uri = null;
if (!TextUtils.isEmpty(number)) {
if (number.contains(":")) {
uri = Uri.parse(number);
} else if (PhoneNumberUtils.isUriNumber(number)) {
uri = Uri.fromParts(PhoneAccount.SCHEME_SIP, number, null);
} else {
uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null);
}
}
log("==> uri: " + uri);
Intent intent = new Intent(action, uri);
log("==> intent: " + intent);
try {
startActivity(intent);
Toast.makeText(this, "Starting activity...", Toast.LENGTH_SHORT).show();
} catch (ActivityNotFoundException e) {
Log.w(LOG_TAG, "testCall: ActivityNotFoundException for intent: " + intent);
Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.w(LOG_TAG, "testCall: Unexpected exception from startActivity(): " + e);
Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
}
}
private void doITelephonyCall() {
log("doITelephonyCall()...");
// Get a phone number from the EditText widget
String number = mNumber.getText().toString();
log("==> number: '" + number + "'");
try {
ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
log("- phone: " + phone);
log("- calling call()...");
phone.call(getPackageName(), number);
log(" Done.");
} catch (RemoteException ex) {
Log.w(LOG_TAG, "RemoteException!", ex);
}
}
private void doITelephonyDial() {
log("doITelephonyDial()...");
// Get a phone number from the EditText widget
String number = mNumber.getText().toString();
log("==> number: '" + number + "'");
try {
ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
log("- phone: " + phone);
log("- calling dial()...");
phone.dial(number);
log(" Done.");
} catch (RemoteException ex) {
Log.w(LOG_TAG, "RemoteException!", ex);
}
}
private void log(String msg) {
Log.i(LOG_TAG, msg);
}
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 2017 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.phone.tests;
import android.support.test.runner.AndroidJUnit4;
import android.telephony.PhoneNumberUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Locale;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
/**
* Tests Related to CallForwardInfoTest
*/
@RunWith(AndroidJUnit4.class)
public class CallForwardInfoTest {
@Test
public void testCallForwardNumberResponses() {
// Test numbers in correct formats
assertNotNull(PhoneNumberUtils.formatNumber("+12345678900", Locale.US.getCountry()));
assertNotNull(PhoneNumberUtils.formatNumber("123-456-7890", Locale.US.getCountry()));
assertNotNull(PhoneNumberUtils.formatNumber("#123", Locale.US.getCountry()));
assertNotNull(PhoneNumberUtils.formatNumber("*12", Locale.US.getCountry()));
// Test invalid numbers
assertNull(PhoneNumberUtils.formatNumber("a", Locale.US.getCountry()));
assertNull(PhoneNumberUtils.formatNumber("a1", Locale.US.getCountry()));
}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (C) 2012 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.phone.tests;
import android.app.IntentService;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
/**
* Service which receives instant text responses from in-call UI and shows the message using
* {@link Toast}.
*/
public class SendInstantTextTestService extends IntentService {
private static final String TAG = SendInstantTextTestService.class.getSimpleName();
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
showMessageWithToast((Intent) msg.obj);
}
};
public SendInstantTextTestService() {
super("send_instant_text_test_service");
}
@Override
protected void onHandleIntent(Intent intent) {
String action = intent.getAction();
Uri uri = intent.getData();
String message = intent.getStringExtra(Intent.EXTRA_TEXT);
Log.i(TAG, "Received instant response message. action=" + action
+ ", uri=" + uri + ", message=\"" + message + "\"");
// Phone app uses Toast to show confirmation, which overlaps with this message.
// Let's delay showing this one for 5sec.
mHandler.sendMessageDelayed(Message.obtain(mHandler, 0, intent), 5 * 1000);
}
private void showMessageWithToast(Intent intent) {
Uri uri = intent.getData();
String message = intent.getStringExtra(Intent.EXTRA_TEXT);
String toastText = getString(R.string.instant_text_back_content, message, uri.toString());
Toast.makeText(this, toastText, Toast.LENGTH_LONG).show();
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (C) 2017 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.services.telephony;
import android.net.Uri;
import android.support.test.runner.AndroidJUnit4;
import android.telecom.Conference;
import android.telecom.ConferenceParticipant;
import org.junit.Test;
import org.junit.runner.RunWith;
import static com.android.services.telephony.ConferenceParticipantConnection.getParticipantAddress;
import static org.junit.Assert.assertEquals;
/**
* Tests proper parsing of conference event package participant addresses.
*/
@RunWith(AndroidJUnit4.class)
public class ConferenceParticipantConnectionTest {
@Test
public void testParticipantParseSimpleTel() {
assertUrisEqual(Uri.parse("tel:+16505551212"),
getParticipantAddress(Uri.parse("tel:6505551212"), "US"));
}
@Test
public void testParticipantParseTelExtended() {
assertUrisEqual(Uri.parse("tel:+16505551212"),
getParticipantAddress(Uri.parse("tel:6505551212;phone-context=blah"), "US"));
}
@Test
public void testParticipantParseSip() {
assertUrisEqual(Uri.parse("tel:+16505551212"),
getParticipantAddress(Uri.parse("sip:16505551212;phone-context=blah.com@host.com"),
"US"));
}
@Test
public void testParticipantParseSip2() {
assertUrisEqual(Uri.parse("tel:+12125551212"),
getParticipantAddress(Uri.parse("sip:+1-212-555-1212@something.com;user=phone"),
"US"));
}
@Test
public void testParticipantParseTelJp() {
assertUrisEqual(Uri.parse("tel:+819066570660"),
getParticipantAddress(Uri.parse(
"tel:09066570660;phone-context=ims.mnc020.mcc440.3gppnetwork.org"),
"JP"));
}
@Test
public void testParticipantParseSipJp() {
assertUrisEqual(Uri.parse("tel:+819066571180"),
getParticipantAddress(Uri.parse(
"sip:+819066571180@ims.mnc020.mcc440.3gppnetwork.org;user=phone"),
"JP"));
}
private void assertUrisEqual(Uri expected, Uri actual) {
assertEquals(expected.getScheme(), actual.getScheme());
assertEquals(expected.getSchemeSpecificPart(), actual.getSchemeSpecificPart());
}
}

View file

@ -0,0 +1,237 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.services.telephony;
import android.os.AsyncResult;
import android.os.Handler;
import android.telephony.ServiceState;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.filters.FlakyTest;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.TelephonyTestBase;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.ServiceStateTracker;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.when;
/**
* Tests the EmergencyCallStateListener, which listens to one Phone and waits until its service
* state changes to accepting emergency calls or in service. If it can not find a tower to camp onto
* for emergency calls, then it will fail after a timeout period.
*/
@RunWith(AndroidJUnit4.class)
public class EmergencyCallStateListenerTest extends TelephonyTestBase {
private static final long TIMEOUT_MS = 100;
@Mock Phone mMockPhone;
@Mock ServiceStateTracker mMockServiceStateTracker;
@Mock EmergencyCallStateListener.Callback mCallback;
EmergencyCallStateListener mListener;
@Before
public void setUp() throws Exception {
super.setUp();
mListener = new EmergencyCallStateListener();
}
@After
public void tearDown() throws Exception {
mListener.getHandler().removeCallbacksAndMessages(null);
super.tearDown();
}
/**
* Ensure that we successfully register for the ServiceState changed messages in Telephony.
*/
@Test
@SmallTest
public void testRegisterForCallback() {
mListener.waitForRadioOn(mMockPhone, mCallback);
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
verify(mMockPhone).unregisterForServiceStateChanged(any(Handler.class));
verify(mMockPhone).registerForServiceStateChanged(any(Handler.class),
eq(EmergencyCallStateListener.MSG_SERVICE_STATE_CHANGED), isNull());
}
/**
* Prerequisites:
* - Phone is IN_SERVICE
* - Radio is on
*
* Test: Send SERVICE_STATE_CHANGED message
*
* Result: callback's onComplete is called with the isRadioReady=true
*/
@Test
@SmallTest
public void testPhoneChangeState_InService() {
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_IN_SERVICE);
when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
when(mMockPhone.getServiceStateTracker()).thenReturn(mMockServiceStateTracker);
when(mMockServiceStateTracker.isRadioOn()).thenReturn(true);
mListener.waitForRadioOn(mMockPhone, mCallback);
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
mListener.getHandler().obtainMessage(EmergencyCallStateListener.MSG_SERVICE_STATE_CHANGED,
new AsyncResult(null, state, null)).sendToTarget();
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
verify(mCallback).onComplete(eq(mListener), eq(true));
}
/**
* Prerequisites:
* - Phone is OUT_OF_SERVICE (emergency calls only)
* - Radio is on
*
* Test: Send SERVICE_STATE_CHANGED message
*
* Result: callback's onComplete is called with the isRadioReady=true
*/
@Test
@SmallTest
public void testPhoneChangeState_EmergencyCalls() {
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_OUT_OF_SERVICE);
state.setEmergencyOnly(true);
when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
when(mMockPhone.getServiceState()).thenReturn(state);
when(mMockPhone.getServiceStateTracker()).thenReturn(mMockServiceStateTracker);
when(mMockServiceStateTracker.isRadioOn()).thenReturn(true);
mListener.waitForRadioOn(mMockPhone, mCallback);
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
mListener.getHandler().obtainMessage(EmergencyCallStateListener.MSG_SERVICE_STATE_CHANGED,
new AsyncResult(null, state, null)).sendToTarget();
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
verify(mCallback).onComplete(eq(mListener), eq(true));
}
/**
* Prerequisites:
* - Phone is OUT_OF_SERVICE
* - Radio is on
*
* Test: Send SERVICE_STATE_CHANGED message
*
* Result: callback's onComplete is called with the isRadioReady=true. Even though the radio is
* not reporting emergency calls only, we still send onComplete so that the radio can trigger
* the emergency call.
*/
@Test
@SmallTest
public void testPhoneChangeState_OutOfService() {
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_OUT_OF_SERVICE);
when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
when(mMockPhone.getServiceState()).thenReturn(state);
when(mMockPhone.getServiceStateTracker()).thenReturn(mMockServiceStateTracker);
when(mMockServiceStateTracker.isRadioOn()).thenReturn(true);
mListener.waitForRadioOn(mMockPhone, mCallback);
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
// Still expect an answer because we will be sending the onComplete message as soon as the
// radio is confirmed to be on, whether or not it is out of service or not.
mListener.getHandler().obtainMessage(EmergencyCallStateListener.MSG_SERVICE_STATE_CHANGED,
new AsyncResult(null, state, null)).sendToTarget();
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
verify(mCallback).onComplete(eq(mListener), eq(true));
}
/**
* Prerequisites:
* - Phone is OUT_OF_SERVICE (emergency calls only)
* - Radio is on
*
* Test: Wait for retry timer to complete (don't send ServiceState changed message)
*
* Result: callback's onComplete is called with the isRadioReady=true.
*/
@Test
@FlakyTest
@SmallTest
public void testTimeout_EmergencyCalls() {
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_OUT_OF_SERVICE);
state.setEmergencyOnly(true);
when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
when(mMockPhone.getServiceState()).thenReturn(state);
when(mMockPhone.getServiceStateTracker()).thenReturn(mMockServiceStateTracker);
when(mMockServiceStateTracker.isRadioOn()).thenReturn(true);
mListener.setTimeBetweenRetriesMillis(100);
// Wait for the timer to expire and check state manually in onRetryTimeout
mListener.waitForRadioOn(mMockPhone, mCallback);
waitForHandlerActionDelayed(mListener.getHandler(), TIMEOUT_MS, 500);
verify(mCallback).onComplete(eq(mListener), eq(true));
}
/**
* Prerequisites:
* - Phone is OUT_OF_SERVICE
* - Radio is off
*
* Test: Wait for retry timer to complete, no ServiceState changed messages received.
*
* Result:
* - callback's onComplete is called with the isRadioReady=false.
* - setRadioPower was send twice (tried to turn on the radio)
*/
@Test
@FlakyTest
@SmallTest
public void testTimeout_RetryFailure() {
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_POWER_OFF);
when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
when(mMockPhone.getServiceState()).thenReturn(state);
when(mMockPhone.getServiceStateTracker()).thenReturn(mMockServiceStateTracker);
when(mMockServiceStateTracker.isRadioOn()).thenReturn(false);
mListener.setTimeBetweenRetriesMillis(50);
mListener.setMaxNumRetries(2);
// Wait for the timer to expire and check state manually in onRetryTimeout
mListener.waitForRadioOn(mMockPhone, mCallback);
waitForHandlerActionDelayed(mListener.getHandler(), TIMEOUT_MS, 500);
verify(mCallback).onComplete(eq(mListener), eq(false));
verify(mMockPhone, times(2)).setRadioPower(eq(true));
}
}

View file

@ -0,0 +1,134 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.services.telephony;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.times;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import android.os.Looper;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.internal.telephony.PhoneConstants;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
/**
* Tests the functionality in ImsConferenceController.java
*/
public class ImsConferenceControllerTest {
@Mock
private TelephonyConnectionServiceProxy mMockTelephonyConnectionServiceProxy;
private TelecomAccountRegistry mTelecomAccountRegistry;
private MockTelephonyConnection mMockTelephonyConnectionA;
private MockTelephonyConnection mMockTelephonyConnectionB;
private ImsConferenceController mControllerTest;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
if (Looper.myLooper() == null) {
Looper.prepare();
}
mTelecomAccountRegistry = TelecomAccountRegistry.getInstance(null);
mMockTelephonyConnectionA = new MockTelephonyConnection();
mMockTelephonyConnectionB = new MockTelephonyConnection();
mControllerTest = new ImsConferenceController(mTelecomAccountRegistry,
mMockTelephonyConnectionServiceProxy);
}
/**
* Behavior: add telephony connections B and A to conference controller,
* set status for connections, remove one call
* Assumption: after performing the behaviors, the status of Connection A is STATE_ACTIVE;
* the status of Connection B is STATE_HOLDING
* Expected: Connection A and Connection B are conferenceable with each other;
* Connection B is not conferenceable with Connection A after A is removed;
* addConference for ImsConference is not called
*/
@Test
@SmallTest
public void testConferenceable() {
mControllerTest.add(mMockTelephonyConnectionB);
mControllerTest.add(mMockTelephonyConnectionA);
mMockTelephonyConnectionA.setActive();
mMockTelephonyConnectionB.setOnHold();
assertTrue(mMockTelephonyConnectionA.getConferenceables()
.contains(mMockTelephonyConnectionB));
assertTrue(mMockTelephonyConnectionB.getConferenceables()
.contains(mMockTelephonyConnectionA));
// verify addConference method is never called
verify(mMockTelephonyConnectionServiceProxy, never())
.addConference(any(ImsConference.class));
// call A removed
mControllerTest.remove(mMockTelephonyConnectionA);
assertFalse(mMockTelephonyConnectionB.getConferenceables()
.contains(mMockTelephonyConnectionA));
}
/**
* Behavior: add telephony connection B and A to conference controller,
* set status for merged connections
* Assumption: after performing the behaviors, the status of Connection A is STATE_ACTIVE;
* the status of Connection B is STATE_HOLDING;
* getPhoneType() in the original connection of the telephony connection
* is PhoneConstants.PHONE_TYPE_IMS
* Expected: addConference for ImsConference is called twice
*/
@Test
@SmallTest
public void testMergeMultiPartyCalls() {
when(mMockTelephonyConnectionA.mMockRadioConnection.getPhoneType())
.thenReturn(PhoneConstants.PHONE_TYPE_IMS);
when(mMockTelephonyConnectionB.mMockRadioConnection.getPhoneType())
.thenReturn(PhoneConstants.PHONE_TYPE_IMS);
when(mMockTelephonyConnectionA.mMockRadioConnection.isMultiparty()).thenReturn(true);
when(mMockTelephonyConnectionB.mMockRadioConnection.isMultiparty()).thenReturn(true);
mControllerTest.add(mMockTelephonyConnectionB);
mControllerTest.add(mMockTelephonyConnectionA);
mMockTelephonyConnectionA.setActive();
mMockTelephonyConnectionB.setOnHold();
verify(mMockTelephonyConnectionServiceProxy, times(2))
.addConference(any(ImsConference.class));
}
}

View file

@ -0,0 +1,72 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.services.telephony;
import static org.mockito.Mockito.when;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.Phone;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
/**
* Mock Telephony Connection used in TelephonyConferenceController.java for testing purpose
*/
public class MockTelephonyConnection extends TelephonyConnection {
@Mock
com.android.internal.telephony.Connection mMockRadioConnection;
@Mock
Call mMockCall;
@Mock
Phone mMockPhone;
@Override
public com.android.internal.telephony.Connection getOriginalConnection() {
return mMockRadioConnection;
}
public MockTelephonyConnection() {
super(null, null, false);
MockitoAnnotations.initMocks(this);
// Set up mMockRadioConnection and mMockPhone to contain an active call
when(mMockRadioConnection.getState()).thenReturn(Call.State.ACTIVE);
when(mMockRadioConnection.getCall()).thenReturn(mMockCall);
when(mMockPhone.getRingingCall()).thenReturn(mMockCall);
when(mMockCall.getState()).thenReturn(Call.State.ACTIVE);
}
@Override
public boolean isConferenceSupported() {
return true;
}
@Override
public Phone getPhone() {
return mMockPhone;
}
public TelephonyConnection cloneConnection() {
return this;
}
}

View file

@ -0,0 +1,176 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.services.telephony;
import android.os.Looper;
import android.telecom.Conference;
import android.telecom.Connection;
import android.test.suitebuilder.annotation.SmallTest;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.ArgumentCaptor;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.any;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import java.util.ArrayList;
import java.util.Collection;
/**
* Tests the functionality in TelephonyConferenceController.java
* Assumption: these tests are based on setting status manually
*/
public class TelephonyConferenceControllerTest {
@Mock
private TelephonyConnectionServiceProxy mMockTelephonyConnectionServiceProxy;
@Mock
private Conference.Listener mMockListener;
private MockTelephonyConnection mMockTelephonyConnectionA;
private MockTelephonyConnection mMockTelephonyConnectionB;
private TelephonyConferenceController mControllerTest;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
if (Looper.myLooper() == null) {
Looper.prepare();
}
mMockTelephonyConnectionA = new MockTelephonyConnection();
mMockTelephonyConnectionB = new MockTelephonyConnection();
mControllerTest = new TelephonyConferenceController(mMockTelephonyConnectionServiceProxy);
}
/**
* Behavior: add telephony connections B and A to conference controller,
* set status for connections and calls, remove one call
* Assumption: after performing the behaviours, the status of Connection A is STATE_ACTIVE;
* the status of Connection B is STATE_HOLDING;
* the call in the original connection is Call.State.ACTIVE;
* isMultiparty of the call is false;
* isConferenceSupported of the connection is True
* Expected: Connection A and Connection B are conferenceable with each other
*/
@Test
@SmallTest
public void testConferenceable() {
when(mMockTelephonyConnectionA.mMockRadioConnection.getCall()
.isMultiparty()).thenReturn(false);
when(mMockTelephonyConnectionB.mMockRadioConnection.getCall()
.isMultiparty()).thenReturn(false);
// add telephony connection B
mControllerTest.add(mMockTelephonyConnectionB);
// add telephony connection A
mControllerTest.add(mMockTelephonyConnectionA);
mMockTelephonyConnectionA.setActive();
mMockTelephonyConnectionB.setOnHold();
assertTrue(mMockTelephonyConnectionA.getConferenceables()
.contains(mMockTelephonyConnectionB));
assertTrue(mMockTelephonyConnectionB.getConferenceables()
.contains(mMockTelephonyConnectionA));
// verify addConference method is never called
verify(mMockTelephonyConnectionServiceProxy, never())
.addConference(any(TelephonyConference.class));
// call A removed
mControllerTest.remove(mMockTelephonyConnectionA);
assertFalse(mMockTelephonyConnectionB.getConferenceables()
.contains(mMockTelephonyConnectionA));
}
/**
* Behavior: add telephony connection B and A to conference controller,
* set status for connections and merged calls, remove one call
* Assumption: after performing the behaviours, the status of Connection A is STATE_ACTIVE;
* the status of Connection B is STATE_HOLDING;
* the call in the original connection is Call.State.ACTIVE;
* isMultiparty of the call is True;
* isConferenceSupported of the connection is True
* Expected: Connection A and Connection B are conferenceable with each other
* addConference is called
*/
@Test
@SmallTest
public void testMergeMultiPartyCalls() {
// set isMultiparty() true to create the same senario of merge behaviour
when(mMockTelephonyConnectionA.mMockRadioConnection.getCall()
.isMultiparty()).thenReturn(true);
when(mMockTelephonyConnectionB.mMockRadioConnection.getCall()
.isMultiparty()).thenReturn(true);
// Add connections into connection Service
Collection<Connection> allConnections = new ArrayList<Connection>();
allConnections.add(mMockTelephonyConnectionA);
allConnections.add(mMockTelephonyConnectionB);
when(mMockTelephonyConnectionServiceProxy.getAllConnections())
.thenReturn(allConnections);
// add telephony connection B
mControllerTest.add(mMockTelephonyConnectionB);
// add telephony connection A
mControllerTest.add(mMockTelephonyConnectionA);
mMockTelephonyConnectionA.setActive();
mMockTelephonyConnectionB.setOnHold();
assertTrue(mMockTelephonyConnectionA.getConferenceables()
.contains(mMockTelephonyConnectionB));
assertTrue(mMockTelephonyConnectionB.getConferenceables()
.contains(mMockTelephonyConnectionA));
// capture the argument in the addConference method, and verify it is called
ArgumentCaptor<TelephonyConference> argumentCaptor = ArgumentCaptor.
forClass(TelephonyConference.class);
verify(mMockTelephonyConnectionServiceProxy).addConference(argumentCaptor.capture());
// add a listener to the added conference
argumentCaptor.getValue().addListener(mMockListener);
verify(mMockListener, never()).onDestroyed(any(Conference.class));
// call A removed
mControllerTest.remove(mMockTelephonyConnectionA);
assertFalse(mMockTelephonyConnectionB.getConferenceables()
.contains(mMockTelephonyConnectionA));
//onDestroy should be called during the destroy
verify(mMockListener).onDestroyed(any(Conference.class));
}
}

View file

@ -0,0 +1,527 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.services.telephony;
import android.telephony.RadioAccessFamily;
import android.telephony.ServiceState;
import android.support.test.runner.AndroidJUnit4;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.TelephonyTestBase;
import com.android.internal.telephony.Phone;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import static junit.framework.Assert.assertEquals;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Unit tests for TelephonyConnectionService.
*/
@RunWith(AndroidJUnit4.class)
public class TelephonyConnectionServiceTest extends TelephonyTestBase {
private static final int SLOT_0_PHONE_ID = 0;
private static final int SLOT_1_PHONE_ID = 1;
@Mock TelephonyConnectionService.TelephonyManagerProxy mTelephonyManagerProxy;
@Mock TelephonyConnectionService.SubscriptionManagerProxy mSubscriptionManagerProxy;
@Mock TelephonyConnectionService.PhoneFactoryProxy mPhoneFactoryProxy;
TelephonyConnectionService mTestConnectionService;
@Before
public void setUp() throws Exception {
super.setUp();
mTestConnectionService = new TelephonyConnectionService();
mTestConnectionService.setPhoneFactoryProxy(mPhoneFactoryProxy);
mTestConnectionService.setTelephonyManagerProxy(mTelephonyManagerProxy);
mTestConnectionService.setSubscriptionManagerProxy(mSubscriptionManagerProxy);
}
@After
public void tearDown() throws Exception {
mTestConnectionService = null;
super.tearDown();
}
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Users default Voice SIM choice is IN_SERVICE
*
* Result: getFirstPhoneForEmergencyCall returns the default Voice SIM choice.
*/
@Test
@SmallTest
public void testDefaultVoiceSimInService() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
true /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot0Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Slot 0 is OUT_OF_SERVICE, Slot 1 is OUT_OF_SERVICE (emergency calls only)
*
* Result: getFirstPhoneForEmergencyCall returns the slot 1 phone
*/
@Test
@SmallTest
public void testSlot1EmergencyOnly() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
true /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot1Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Slot 0 is OUT_OF_SERVICE, Slot 1 is IN_SERVICE
*
* Result: getFirstPhoneForEmergencyCall returns the slot 1 phone
*/
@Test
@SmallTest
public void testSlot1InService() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_IN_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot1Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Slot 0 is PUK locked, Slot 1 is ready
* - Slot 0 is LTE capable, Slot 1 is GSM capable
*
* Result: getFirstPhoneForEmergencyCall returns the slot 1 phone. Although Slot 0 is more
* capable, it is locked, so use the other slot.
*/
@Test
@SmallTest
public void testSlot0PukLocked() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
// Set Slot 0 to be PUK locked
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
// Make Slot 0 higher capability
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot1Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Slot 0 is PIN locked, Slot 1 is ready
* - Slot 0 is LTE capable, Slot 1 is GSM capable
*
* Result: getFirstPhoneForEmergencyCall returns the slot 1 phone. Although Slot 0 is more
* capable, it is locked, so use the other slot.
*/
@Test
@SmallTest
public void testSlot0PinLocked() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
// Set Slot 0 to be PUK locked
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PIN_REQUIRED);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
// Make Slot 0 higher capability
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot1Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Slot 1 is PUK locked, Slot 0 is ready
* - Slot 1 is LTE capable, Slot 0 is GSM capable
*
* Result: getFirstPhoneForEmergencyCall returns the slot 0 phone. Although Slot 1 is more
* capable, it is locked, so use the other slot.
*/
@Test
@SmallTest
public void testSlot1PukLocked() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
// Set Slot 1 to be PUK locked
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED);
// Make Slot 1 higher capability
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot0Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Slot 1 is PIN locked, Slot 0 is ready
* - Slot 1 is LTE capable, Slot 0 is GSM capable
*
* Result: getFirstPhoneForEmergencyCall returns the slot 0 phone. Although Slot 1 is more
* capable, it is locked, so use the other slot.
*/
@Test
@SmallTest
public void testSlot1PinLocked() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
// Set Slot 1 to be PUK locked
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PIN_REQUIRED);
// Make Slot 1 higher capability
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot0Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Slot 1 is LTE capable, Slot 0 is GSM capable
*
* Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is more capable
*/
@Test
@SmallTest
public void testSlot1HigherCapablity() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
// Make Slot 1 higher capability
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot1Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Slot 1 is GSM/LTE capable, Slot 0 is GSM capable
*
* Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it has more
* capabilities.
*/
@Test
@SmallTest
public void testSlot1MoreCapabilities() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
// Make Slot 1 more capable
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
setPhoneRadioAccessFamily(slot1Phone,
RadioAccessFamily.RAF_GSM | RadioAccessFamily.RAF_LTE);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot1Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Both SIMs PUK Locked
* - Slot 0 is LTE capable, Slot 1 is GSM capable
*
* Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is more capable,
* ignoring that both SIMs are PUK locked.
*/
@Test
@SmallTest
public void testSlot0MoreCapableBothPukLocked() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_PUK_REQUIRED);
// Make Slot 0 higher capability
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_GSM);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot0Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
* - Both SIMs have the same capability
*
* Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is the first slot.
*/
@Test
@SmallTest
public void testEqualCapabilityTwoSimsInserted() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
// Make Capability the same
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
// Two SIMs inserted
setSlotHasIccCard(SLOT_0_PHONE_ID, true /*isInserted*/);
setSlotHasIccCard(SLOT_1_PHONE_ID, true /*isInserted*/);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot0Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, only slot 0 inserted
* - Both SIMs have the same capability
*
* Result: getFirstPhoneForEmergencyCall returns the slot 0 phone because it is the only one
* with a SIM inserted
*/
@Test
@SmallTest
public void testEqualCapabilitySim0Inserted() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
// Make Capability the same
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
// Slot 0 has SIM inserted.
setSlotHasIccCard(SLOT_0_PHONE_ID, true /*isInserted*/);
setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot0Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, only slot 1 inserted
* - Both SIMs have the same capability
*
* Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is the only one
* with a SIM inserted
*/
@Test
@SmallTest
public void testEqualCapabilitySim1Inserted() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
// Make Capability the same
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
// Slot 1 has SIM inserted.
setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/);
setSlotHasIccCard(SLOT_1_PHONE_ID, true /*isInserted*/);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot1Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, no SIMs inserted
* - SIM 1 has the higher capability
*
* Result: getFirstPhoneForEmergencyCall returns the slot 1 phone, since it is a higher
* capability
*/
@Test
@SmallTest
public void testSim1HigherCapabilityNoSimsInserted() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
// Make Capability the same
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
// No SIMs inserted
setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/);
setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot1Phone, resultPhone);
}
/**
* Prerequisites:
* - MSIM Device, no SIMs inserted
* - Both SIMs have the same capability (Unknown)
*
* Result: getFirstPhoneForEmergencyCall returns the slot 0 phone, since it is the first slot.
*/
@Test
@SmallTest
public void testEqualCapabilityNoSimsInserted() {
Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
false /*isEmergencyOnly*/);
setDefaultPhone(slot0Phone);
setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
// Make Capability the same
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_UNKNOWN);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_UNKNOWN);
// No SIMs inserted
setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/);
setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
assertEquals(slot0Phone, resultPhone);
}
private Phone makeTestPhone(int phoneId, int serviceState, boolean isEmergencyOnly) {
Phone phone = mock(Phone.class);
ServiceState testServiceState = new ServiceState();
testServiceState.setState(serviceState);
testServiceState.setEmergencyOnly(isEmergencyOnly);
when(phone.getServiceState()).thenReturn(testServiceState);
when(phone.getPhoneId()).thenReturn(phoneId);
return phone;
}
// Setup 2 SIM device
private void setupDeviceConfig(Phone slot0Phone, Phone slot1Phone, int defaultVoicePhoneId) {
when(mTelephonyManagerProxy.getPhoneCount()).thenReturn(2);
when(mSubscriptionManagerProxy.getDefaultVoicePhoneId()).thenReturn(defaultVoicePhoneId);
when(mPhoneFactoryProxy.getPhone(eq(SLOT_0_PHONE_ID))).thenReturn(slot0Phone);
when(mPhoneFactoryProxy.getPhone(eq(SLOT_1_PHONE_ID))).thenReturn(slot1Phone);
}
private void setPhoneRadioAccessFamily(Phone phone, int radioAccessFamily) {
when(phone.getRadioAccessFamily()).thenReturn(radioAccessFamily);
}
private void setPhoneSlotState(int slotId, int slotState) {
when(mSubscriptionManagerProxy.getSimStateForSlotIdx(slotId)).thenReturn(slotState);
}
private void setSlotHasIccCard(int slotId, boolean isInserted) {
when(mTelephonyManagerProxy.hasIccCard(slotId)).thenReturn(isInserted);
}
private void setDefaultPhone(Phone phone) {
when(mPhoneFactoryProxy.getDefaultPhone()).thenReturn(phone);
}
}