/*
 * 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) {
            }
        }
    }
}
