Merge "annotation part 2"
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index c5b4875..18ff034 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -194,7 +194,7 @@
 
                 case EVENT_SYSTEM_UNLOCKED:
                 {
-                    for (int i = 0; i < TelephonyManager.from(mContext).getPhoneCount(); ++i) {
+                    for (int i = 0; i < TelephonyManager.from(mContext).getMaxPhoneCount(); ++i) {
                         // When user unlock device, we should only try to send broadcast again if we
                         // have sent it before unlock. This will avoid we try to load carrier config
                         // when SIM is still loading when unlock happens.
@@ -211,7 +211,7 @@
                     // Only update if there are cached config removed to avoid updating config for
                     // unrelated packages.
                     if (clearCachedConfigForPackage(carrierPackageName)) {
-                        int numPhones = TelephonyManager.from(mContext).getPhoneCount();
+                        int numPhones = TelephonyManager.from(mContext).getMaxPhoneCount();
                         for (int i = 0; i < numPhones; ++i) {
                             updateConfigForPhoneId(i);
                         }
@@ -523,7 +523,7 @@
         pkgFilter.addDataScheme("package");
         context.registerReceiver(mPackageReceiver, pkgFilter);
 
-        int numPhones = TelephonyManager.from(context).getPhoneCount();
+        int numPhones = TelephonyManager.from(context).getMaxPhoneCount();
         mConfigFromDefaultApp = new PersistableBundle[numPhones];
         mConfigFromCarrierApp = new PersistableBundle[numPhones];
         mOverrideConfigs = new PersistableBundle[numPhones];
@@ -566,6 +566,13 @@
             configPackagename = mPlatformCarrierConfigPackage;
             configToSend = mConfigFromDefaultApp[phoneId];
         }
+
+        // mOverrideConfigs is for testing. And it will override current configs.
+        PersistableBundle config = mOverrideConfigs[phoneId];
+        if (config != null) {
+            configToSend.putAll(config);
+        }
+
         mSubscriptionInfoUpdater.updateSubscriptionByCarrierConfigAndNotifyComplete(
                 phoneId, configPackagename, configToSend,
                 mHandler.obtainMessage(EVENT_SUBSCRIPTION_INFO_UPDATED, phoneId, -1));
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 2a654a3..a847d66 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -1950,7 +1950,15 @@
     }
 
     @Override
-    public String getNetworkCountryIsoForPhone(int phoneId) {
+    public String getNetworkCountryIsoForPhone(int phoneId, String callingPackage) {
+        if (!TextUtils.isEmpty(callingPackage)) {
+            final int subId = mSubscriptionController.getSubIdUsingPhoneId(phoneId);
+            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                    mApp, subId, callingPackage, "getNetworkCountryIsoForPhone")) {
+                return "";
+            }
+        }
+
         // Reporting the correct network country is ambiguous when IWLAN could conflict with
         // registered cell info, so return a NULL country instead.
         final long identity = Binder.clearCallingIdentity();
diff --git a/src/com/android/services/telephony/EmergencyTonePlayer.java b/src/com/android/services/telephony/EmergencyTonePlayer.java
index 8e26349..431f8d7 100644
--- a/src/com/android/services/telephony/EmergencyTonePlayer.java
+++ b/src/com/android/services/telephony/EmergencyTonePlayer.java
@@ -23,7 +23,6 @@
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.ToneGenerator;
-import android.os.SystemVibrator;
 import android.os.Vibrator;
 import android.provider.Settings;
 
@@ -49,11 +48,9 @@
                 .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
                 .build();
 
-    // We don't rely on getSystemService(Context.VIBRATOR_SERVICE) to make sure that this vibrator
-    // object will be isolated from others.
-    private final Vibrator mVibrator = new SystemVibrator();
     private final Context mContext;
     private final AudioManager mAudioManager;
+    private final Vibrator mVibrator;
 
     private ToneGenerator mToneGenerator;
     private int mSavedInCallVolume;
@@ -62,6 +59,7 @@
     EmergencyTonePlayer(Context context) {
         mContext = context;
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
     }
 
     public void start() {
diff --git a/src/com/android/services/telephony/RadioOnHelper.java b/src/com/android/services/telephony/RadioOnHelper.java
index 288c72c..85f94ab 100644
--- a/src/com/android/services/telephony/RadioOnHelper.java
+++ b/src/com/android/services/telephony/RadioOnHelper.java
@@ -53,7 +53,7 @@
             return;
         }
         mListeners = new ArrayList<>(2);
-        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+        for (int i = 0; i < TelephonyManager.getDefault().getMaxPhoneCount(); i++) {
             mListeners.add(new RadioOnStateListener());
         }
     }
@@ -76,7 +76,7 @@
         mCallback = callback;
         mInProgressListeners.clear();
         mIsRadioOnCallingEnabled = false;
-        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+        for (int i = 0; i < TelephonyManager.getDefault().getMaxPhoneCount(); i++) {
             Phone phone = PhoneFactory.getPhone(i);
             if (phone == null) {
                 continue;
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index c8562c7..0e5a612 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -25,6 +25,9 @@
 import android.content.IntentFilter;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
 import android.provider.Settings;
 import android.telecom.Conference;
 import android.telecom.Connection;
@@ -176,6 +179,8 @@
     // destroyed.
     @VisibleForTesting
     public Pair<WeakReference<TelephonyConnection>, Queue<Phone>> mEmergencyRetryCache;
+    private Handler mDdsSwitchHandler;
+    private HandlerThread mHandlerThread;
 
     /**
      * Keeps track of the status of a SIM slot.
@@ -329,11 +334,17 @@
         IntentFilter intentFilter = new IntentFilter(
                 TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
         registerReceiver(mTtyBroadcastReceiver, intentFilter);
+
+        mHandlerThread = new HandlerThread("DdsSwitchHandlerThread");
+        mHandlerThread.start();
+        Looper looper = mHandlerThread.getLooper();
+        mDdsSwitchHandler = new Handler(looper);
     }
 
     @Override
     public boolean onUnbind(Intent intent) {
         unregisterReceiver(mTtyBroadcastReceiver);
+        mHandlerThread.quitSafely();
         return super.onUnbind(intent);
     }
 
@@ -523,14 +534,14 @@
             } else {
                 final Connection resultConnection = getTelephonyConnection(request, numberToDial,
                         true, handle, phone);
-                CompletableFuture<Boolean> phoneFuture = delayDialForDdsSwitch(phone);
-                phoneFuture.whenComplete((result, error) -> {
-                    if (error != null) {
-                        Log.w(this, "onCreateOutgoingConn - delayDialForDdsSwitch exception= "
-                                + error.getMessage());
+                mDdsSwitchHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        boolean result = delayDialForDdsSwitch(phone);
+                        Log.i(this,
+                                "onCreateOutgoingConn - delayDialForDdsSwitch result = " + result);
+                        placeOutgoingConnection(request, resultConnection, phone);
                     }
-                    Log.i(this, "onCreateOutgoingConn - delayDialForDdsSwitch result = " + result);
-                    placeOutgoingConnection(request, resultConnection, phone);
                 });
                 return resultConnection;
             }
@@ -604,14 +615,14 @@
                 adjustAndPlaceOutgoingConnection(phone, originalConnection, request, numberToDial,
                         handle, originalPhoneType, false);
             } else {
-                delayDialForDdsSwitch(phone).whenComplete((result, error) -> {
-                    if (error != null) {
-                        Log.w(this, "handleOnComplete - delayDialForDdsSwitch exception= "
-                                + error.getMessage());
+                mDdsSwitchHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        boolean result = delayDialForDdsSwitch(phone);
+                        Log.i(this, "handleOnComplete - delayDialForDdsSwitch result = " + result);
+                        adjustAndPlaceOutgoingConnection(phone, originalConnection, request,
+                                numberToDial, handle, originalPhoneType, true);
                     }
-                    Log.i(this, "handleOnComplete - delayDialForDdsSwitch result = " + result);
-                    adjustAndPlaceOutgoingConnection(phone, originalConnection, request,
-                            numberToDial, handle, originalPhoneType, true);
                 });
             }
 
@@ -1380,13 +1391,22 @@
         return chosenPhone;
     }
 
-    private CompletableFuture<Boolean> delayDialForDdsSwitch(Phone phone) {
+    /**
+     * If needed, block until the the default data is is switched for outgoing emergency call, or
+     * timeout expires.
+     */
+    private boolean delayDialForDdsSwitch(Phone phone) {
         if (phone == null) {
-            return CompletableFuture.completedFuture(Boolean.TRUE);
+            return true;
         }
-        return possiblyOverrideDefaultDataForEmergencyCall(phone)
-                .completeOnTimeout(false, DEFAULT_DATA_SWITCH_TIMEOUT_MS,
-                        TimeUnit.MILLISECONDS);
+        try {
+            return possiblyOverrideDefaultDataForEmergencyCall(phone).get(
+                    DEFAULT_DATA_SWITCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        } catch (Exception e) {
+            Log.w(this, "onCreateOutgoingConn - delayDialForDdsSwitch exception= "
+                    + e.getMessage());
+            return false;
+        }
     }
 
     /**