blob: cfd31d398dd4e9a835ede12bc5642e07a229c248 [file] [log] [blame]
/*
* 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 android.telephony.cts;
import android.app.Instrumentation;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.provider.Telephony.Sms;
import android.provider.Telephony.Sms.Intents;
import android.support.annotation.Nullable;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
import android.telephony.VisualVoicemailSms;
import android.telephony.VisualVoicemailSmsFilterSettings;
import android.test.InstrumentationTestCase;
import android.text.TextUtils;
import android.util.Log;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class VisualVoicemailServiceTest extends InstrumentationTestCase {
private static final String TAG = "VvmServiceTest";
private static final String COMMAND_SET_DEFAULT_DIALER = "telecom set-default-dialer ";
private static final String COMMAND_GET_DEFAULT_DIALER = "telecom get-default-dialer";
private static final String PACKAGE = "android.telephony.cts";
private static final long EVENT_RECEIVED_TIMEOUT_MILLIS = 60_000;
private static final long EVENT_NOT_RECEIVED_TIMEOUT_MILLIS = 1_000;
private Context mContext;
private TelephonyManager mTelephonyManager;
private String mPreviousDefaultDialer;
private PhoneAccountHandle mPhoneAccountHandle;
private String mPhoneNumber;
private SmsBroadcastReceiver mSmsReceiver;
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getContext();
if (hasTelephony(mContext)) {
mPreviousDefaultDialer = getDefaultDialer(getInstrumentation());
setDefaultDialer(getInstrumentation(), PACKAGE);
TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
mPhoneAccountHandle = telecomManager
.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
mPhoneNumber = telecomManager.getLine1Number(mPhoneAccountHandle);
mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
.createForPhoneAccountHandle(mPhoneAccountHandle);
}
PackageManager packageManager = mContext.getPackageManager();
packageManager.setComponentEnabledSetting(
new ComponentName(mContext, MockVisualVoicemailService.class),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
packageManager.setComponentEnabledSetting(
new ComponentName(mContext, PermissionlessVisualVoicemailService.class),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
}
@Override
protected void tearDown() throws Exception {
if (hasTelephony(mContext)) {
if (!TextUtils.isEmpty(mPreviousDefaultDialer)) {
setDefaultDialer(getInstrumentation(), mPreviousDefaultDialer);
}
if (mSmsReceiver != null) {
mContext.unregisterReceiver(mSmsReceiver);
}
}
super.tearDown();
}
public void testPermissionlessService_ignored() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
PackageManager packageManager = mContext.getPackageManager();
packageManager.setComponentEnabledSetting(
new ComponentName(mContext, MockVisualVoicemailService.class),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
packageManager.setComponentEnabledSetting(
new ComponentName(mContext, PermissionlessVisualVoicemailService.class),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
String clientPrefix = "//CTSVVM";
String text = "//CTSVVM:STATUS:st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1";
mTelephonyManager.setVisualVoicemailSmsFilterSettings(
new VisualVoicemailSmsFilterSettings.Builder()
.setClientPrefix(clientPrefix)
.build());
try {
mTelephonyManager
.sendVisualVoicemailSms(mPhoneNumber, 0, text, null);
fail("SecurityException expected");
} catch (SecurityException e) {
// Expected
}
CompletableFuture<VisualVoicemailSms> future = new CompletableFuture<>();
PermissionlessVisualVoicemailService.setSmsFuture(future);
setupSmsReceiver(text);
SmsManager.getDefault().sendTextMessage(mPhoneNumber, null, text, null, null);
mSmsReceiver.assertReceived(EVENT_RECEIVED_TIMEOUT_MILLIS);
try {
future.get(EVENT_NOT_RECEIVED_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
throw new RuntimeException("Unexpected visual voicemail SMS received");
} catch (TimeoutException e) {
// expected
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
}
public void testFilter() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
VisualVoicemailSms result = getSmsFromText("//CTSVVM",
"//CTSVVM:STATUS:st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1");
assertEquals("STATUS", result.getPrefix());
assertEquals("R", result.getFields().getString("st"));
assertEquals("0", result.getFields().getString("rc"));
assertEquals("1", result.getFields().getString("srv"));
assertEquals("1", result.getFields().getString("dn"));
assertEquals("1", result.getFields().getString("ipt"));
assertEquals("0", result.getFields().getString("spt"));
assertEquals("eg@example.com", result.getFields().getString("u"));
assertEquals("1", result.getFields().getString("pw"));
}
public void testFilter_data() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
if (!hasDataSms()) {
Log.d(TAG, "skipping test that requires data SMS feature");
return;
}
VisualVoicemailSmsFilterSettings settings = new VisualVoicemailSmsFilterSettings.Builder()
.setClientPrefix("//CTSVVM")
.build();
VisualVoicemailSms result = getSmsFromData(settings, (short) 1000,
"//CTSVVM:STATUS:st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1", true);
assertEquals("STATUS", result.getPrefix());
assertEquals("R", result.getFields().getString("st"));
assertEquals("0", result.getFields().getString("rc"));
assertEquals("1", result.getFields().getString("srv"));
assertEquals("1", result.getFields().getString("dn"));
assertEquals("1", result.getFields().getString("ipt"));
assertEquals("0", result.getFields().getString("spt"));
assertEquals("eg@example.com", result.getFields().getString("u"));
assertEquals("1", result.getFields().getString("pw"));
}
public void testFilter_TrailingSemiColon() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
VisualVoicemailSms result = getSmsFromText("//CTSVVM",
"//CTSVVM:STATUS:st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1;");
assertEquals("STATUS", result.getPrefix());
assertEquals("R", result.getFields().getString("st"));
assertEquals("0", result.getFields().getString("rc"));
assertEquals("1", result.getFields().getString("srv"));
assertEquals("1", result.getFields().getString("dn"));
assertEquals("1", result.getFields().getString("ipt"));
assertEquals("0", result.getFields().getString("spt"));
assertEquals("eg@example.com", result.getFields().getString("u"));
assertEquals("1", result.getFields().getString("pw"));
}
public void testFilter_EmptyPrefix() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
VisualVoicemailSms result = getSmsFromText("//CTSVVM",
"//CTSVVM::st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1");
assertEquals("", result.getPrefix());
assertEquals("R", result.getFields().getString("st"));
assertEquals("0", result.getFields().getString("rc"));
assertEquals("1", result.getFields().getString("srv"));
assertEquals("1", result.getFields().getString("dn"));
assertEquals("1", result.getFields().getString("ipt"));
assertEquals("0", result.getFields().getString("spt"));
assertEquals("eg@example.com", result.getFields().getString("u"));
assertEquals("1", result.getFields().getString("pw"));
}
public void testFilter_EmptyField() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
VisualVoicemailSms result = getSmsFromText("//CTSVVM",
"//CTSVVM:STATUS:");
assertTrue(result.getFields().isEmpty());
}
public void testFilterFail_NotVvm() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
assertVisualVoicemailSmsNotReceived("//CTSVVM",
"helloworld");
}
public void testFilterFail_PrefixMismatch() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
assertVisualVoicemailSmsNotReceived("//CTSVVM",
"//FOOVVM:STATUS:st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1");
}
public void testFilterFail_MissingFirstColon() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
assertVisualVoicemailSmsNotReceived("//CTSVVM",
"//CTSVVMSTATUS:st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1");
}
public void testFilterFail_MissingSecondColon() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
assertVisualVoicemailSmsNotReceived("//CTSVVM",
"//CTSVVM:STATUSst=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1");
}
public void testFilterFail_MessageEndAfterClientPrefix() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
assertVisualVoicemailSmsNotReceived("//CTSVVM",
"//CTSVVM:");
}
public void testFilterFail_MessageEndAfterPrefix() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
assertVisualVoicemailSmsNotReceived("//CTSVVM",
"//CTSVVM:STATUS");
}
public void testFilterFail_InvalidKeyValuePair() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
assertVisualVoicemailSmsNotReceived("//CTSVVM",
"//CTSVVM:STATUS:key");
}
public void testFilterFail_InvalidMissingKey() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
assertVisualVoicemailSmsNotReceived("//CTSVVM",
"//CTSVVM:STATUS:=value");
}
public void testFilter_MissingValue() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
VisualVoicemailSms result = getSmsFromText("//CTSVVM",
"//CTSVVM:STATUS:key=");
assertEquals("STATUS", result.getPrefix());
assertEquals("", result.getFields().getString("key"));
}
public void testFilter_originatingNumber_match_filtered() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
VisualVoicemailSmsFilterSettings settings = new VisualVoicemailSmsFilterSettings.Builder()
.setClientPrefix("//CTSVVM")
.setOriginatingNumbers(Arrays.asList(mPhoneNumber))
.build();
getSmsFromText(settings, "//CTSVVM:SYNC:key=value", true);
}
public void testFilter_originatingNumber_mismatch_notFiltered() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
VisualVoicemailSmsFilterSettings settings = new VisualVoicemailSmsFilterSettings.Builder()
.setClientPrefix("//CTSVVM")
.setOriginatingNumbers(Arrays.asList("1"))
.build();
getSmsFromText(settings, "//CTSVVM:SYNC:key=value", false);
}
public void testFilter_port_match() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
if (!hasDataSms()) {
Log.d(TAG, "skipping test that requires data SMS feature");
return;
}
VisualVoicemailSmsFilterSettings settings = new VisualVoicemailSmsFilterSettings.Builder()
.setClientPrefix("//CTSVVM")
.setDestinationPort(1000)
.build();
getSmsFromData(settings, (short) 1000,
"//CTSVVM:STATUS:st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1", true);
}
public void testFilter_port_mismatch() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
if (!hasDataSms()) {
Log.d(TAG, "skipping test that requires data SMS feature");
return;
}
VisualVoicemailSmsFilterSettings settings = new VisualVoicemailSmsFilterSettings.Builder()
.setClientPrefix("//CTSVVM")
.setDestinationPort(1001)
.build();
getSmsFromData(settings, (short) 1000,
"//CTSVVM:STATUS:st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1", false);
}
public void testFilter_port_anydata() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
if (!hasDataSms()) {
Log.d(TAG, "skipping test that requires data SMS feature");
return;
}
VisualVoicemailSmsFilterSettings settings = new VisualVoicemailSmsFilterSettings.Builder()
.setClientPrefix("//CTSVVM")
.setDestinationPort(VisualVoicemailSmsFilterSettings.DESTINATION_PORT_DATA_SMS)
.build();
getSmsFromData(settings, (short) 1000,
"//CTSVVM:STATUS:st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1", true);
}
/**
* Text SMS should not be filtered with DESTINATION_PORT_DATA_SMS
*/
public void testFilter_port_anydata_notData() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
if (!hasDataSms()) {
Log.d(TAG, "skipping test that requires data SMS feature");
return;
}
VisualVoicemailSmsFilterSettings settings = new VisualVoicemailSmsFilterSettings.Builder()
.setClientPrefix("//CTSVVM")
.setDestinationPort(VisualVoicemailSmsFilterSettings.DESTINATION_PORT_DATA_SMS)
.build();
getSmsFromText(settings,
"//CTSVVM:STATUS:st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1", false);
}
public void testGetVisualVoicemailPackageName_isSelf() {
if (!hasTelephony(mContext)) {
Log.d(TAG, "skipping test that requires telephony feature");
return;
}
assertEquals(PACKAGE, mTelephonyManager.getVisualVoicemailPackageName());
}
private VisualVoicemailSms getSmsFromText(String clientPrefix, String text) {
return getSmsFromText(clientPrefix, text, true);
}
@Nullable
private VisualVoicemailSms getSmsFromText(String clientPrefix, String text,
boolean expectVvmSms) {
return getSmsFromText(
new VisualVoicemailSmsFilterSettings.Builder()
.setClientPrefix(clientPrefix)
.build(),
text,
expectVvmSms);
}
private void assertVisualVoicemailSmsNotReceived(String clientPrefix, String text) {
getSmsFromText(clientPrefix, text, false);
}
/**
* Setup the SMS filter with only the {@code clientPrefix}, and sends {@code text} to the
* device. The SMS sent should not be written to the SMS provider. <p> If {@code expectVvmSms}
* is {@code true}, the SMS should be be caught by the SMS filter. The user should not receive
* the text, and the parsed result will be returned.* <p> If {@code expectVvmSms} is {@code
* false}, the SMS should pass through the SMS filter. The user should receive the text, and
* {@code null} be returned.
*/
@Nullable
private VisualVoicemailSms getSmsFromText(VisualVoicemailSmsFilterSettings settings,
String text,
boolean expectVvmSms) {
mTelephonyManager.setVisualVoicemailSmsFilterSettings(settings);
CompletableFuture<VisualVoicemailSms> future = new CompletableFuture<>();
MockVisualVoicemailService.setSmsFuture(future);
setupSmsReceiver(text);
try (SentSmsObserver observer = new SentSmsObserver(mContext, text)) {
mTelephonyManager
.sendVisualVoicemailSms(mPhoneNumber,0, text, null);
if (expectVvmSms) {
VisualVoicemailSms sms;
try {
sms = future.get(EVENT_RECEIVED_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
throw new RuntimeException(e);
}
mSmsReceiver.assertNotReceived(EVENT_NOT_RECEIVED_TIMEOUT_MILLIS);
observer.assertNotChanged();
return sms;
} else {
mSmsReceiver.assertReceived(EVENT_RECEIVED_TIMEOUT_MILLIS);
try {
future.get(EVENT_NOT_RECEIVED_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
throw new RuntimeException("Unexpected visual voicemail SMS received");
} catch (TimeoutException e) {
// expected
return null;
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
@Nullable
private VisualVoicemailSms getSmsFromData(VisualVoicemailSmsFilterSettings settings, short port,
String text, boolean expectVvmSms) {
mTelephonyManager.setVisualVoicemailSmsFilterSettings(settings);
CompletableFuture<VisualVoicemailSms> future = new CompletableFuture<>();
MockVisualVoicemailService.setSmsFuture(future);
setupSmsReceiver(text);
mTelephonyManager.sendVisualVoicemailSms(mPhoneNumber, port, text, null);
if (expectVvmSms) {
VisualVoicemailSms sms;
try {
sms = future.get(EVENT_RECEIVED_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
throw new RuntimeException(e);
}
mSmsReceiver.assertNotReceived(EVENT_NOT_RECEIVED_TIMEOUT_MILLIS);
return sms;
} else {
mSmsReceiver.assertReceived(EVENT_RECEIVED_TIMEOUT_MILLIS);
try {
future.get(EVENT_NOT_RECEIVED_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
throw new RuntimeException("Unexpected visual voicemail SMS received");
} catch (TimeoutException e) {
// expected
return null;
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
}
}
private void setupSmsReceiver(String text) {
mSmsReceiver = new SmsBroadcastReceiver(text);
mContext.registerReceiver(mSmsReceiver, new IntentFilter(Intents.SMS_RECEIVED_ACTION));
IntentFilter dataFilter = new IntentFilter(Intents.DATA_SMS_RECEIVED_ACTION);
dataFilter.addDataScheme("sms");
mContext.registerReceiver(mSmsReceiver, dataFilter);
}
private static class SmsBroadcastReceiver extends BroadcastReceiver {
private final String mText;
private CompletableFuture<Boolean> mFuture = new CompletableFuture<>();
public SmsBroadcastReceiver(String text) {
mText = text;
}
@Override
public void onReceive(Context context, Intent intent) {
SmsMessage[] messages = Sms.Intents.getMessagesFromIntent(intent);
StringBuilder messageBody = new StringBuilder();
CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
for (SmsMessage message : messages) {
if (message.getMessageBody() != null) {
messageBody.append(message.getMessageBody());
} else if (message.getUserData() != null) {
ByteBuffer byteBuffer = ByteBuffer.wrap(message.getUserData());
try {
messageBody.append(decoder.decode(byteBuffer).toString());
} catch (CharacterCodingException e) {
return;
}
}
}
if (!TextUtils.equals(mText, messageBody.toString())) {
return;
}
mFuture.complete(true);
}
public void assertReceived(long timeoutMillis) {
try {
mFuture.get(timeoutMillis, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
throw new RuntimeException(e);
}
}
public void assertNotReceived(long timeoutMillis) {
try {
mFuture.get(timeoutMillis, TimeUnit.MILLISECONDS);
throw new RuntimeException("Unexpected SMS received");
} catch (TimeoutException e) {
// expected
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}
private static class SentSmsObserver extends ContentObserver implements AutoCloseable {
private final Context mContext;
private final String mText;
public CompletableFuture<Boolean> mFuture = new CompletableFuture<>();
public SentSmsObserver(Context context, String text) {
super(new Handler(Looper.getMainLooper()));
mContext = context;
mText = text;
mContext.getContentResolver().registerContentObserver(Sms.CONTENT_URI, true, this);
}
public void assertNotChanged() {
try {
mFuture.get(EVENT_NOT_RECEIVED_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
fail("Visual voicemail SMS should not be added into the sent SMS");
} catch (TimeoutException e) {
// expected
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
}
@Override
public void onChange(boolean selfChange, Uri uri) {
try (Cursor cursor = mContext.getContentResolver()
.query(uri, new String[] {Sms.TYPE, Sms.BODY}, null, null, null)) {
if (cursor == null){
return;
}
if (!cursor.moveToFirst()){
return;
}
if (cursor.getInt(0) == Sms.MESSAGE_TYPE_SENT && TextUtils
.equals(cursor.getString(1), mText)) {
mFuture.complete(true);
}
} catch (SQLiteException e) {
}
}
@Override
public void close() {
mContext.getContentResolver().unregisterContentObserver(this);
}
}
private static boolean hasTelephony(Context context) {
final PackageManager packageManager = context.getPackageManager();
return packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) &&
packageManager.hasSystemFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
}
private boolean hasDataSms() {
if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
return false;
}
String mccmnc = mTelephonyManager.getSimOperator();
return !CarrierCapability.UNSUPPORT_DATA_SMS_MESSAGES.contains(mccmnc);
}
private static String setDefaultDialer(Instrumentation instrumentation, String packageName)
throws Exception {
return executeShellCommand(instrumentation, COMMAND_SET_DEFAULT_DIALER + packageName);
}
private static String getDefaultDialer(Instrumentation instrumentation) throws Exception {
return executeShellCommand(instrumentation, COMMAND_GET_DEFAULT_DIALER);
}
/**
* Executes the given shell command and returns the output in a string. Note that even if we
* don't care about the output, we have to read the stream completely to make the command
* execute.
*/
private static String executeShellCommand(Instrumentation instrumentation,
String command) throws Exception {
final ParcelFileDescriptor parcelFileDescriptor =
instrumentation.getUiAutomation().executeShellCommand(command);
BufferedReader bufferedReader = null;
try (InputStream in = new FileInputStream(parcelFileDescriptor.getFileDescriptor())) {
bufferedReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
String string = null;
StringBuilder out = new StringBuilder();
while ((string = bufferedReader.readLine()) != null) {
out.append(string);
}
return out.toString();
} finally {
if (bufferedReader != null) {
closeQuietly(bufferedReader);
}
closeQuietly(parcelFileDescriptor);
}
}
private static void closeQuietly(AutoCloseable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (RuntimeException rethrown) {
throw rethrown;
} catch (Exception ignored) {
}
}
}
}