Merge "Import translations. DO NOT MERGE" into rvc-dev
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 9c3649f..fee5ecc 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -120,7 +120,6 @@
 
 import com.android.ims.ImsManager;
 import com.android.ims.internal.IImsServiceFeatureCallback;
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.CallForwardInfo;
 import com.android.internal.telephony.CallManager;
 import com.android.internal.telephony.CallStateException;
@@ -1650,8 +1649,7 @@
     }
 
     /** Private constructor; @see init() */
-    @VisibleForTesting
-    /* package */ PhoneInterfaceManager(PhoneGlobals app) {
+    private PhoneInterfaceManager(PhoneGlobals app) {
         mApp = app;
         mCM = PhoneGlobals.getInstance().mCM;
         mImsResolver = PhoneGlobals.getInstance().getImsResolver();
@@ -7453,15 +7451,10 @@
 
     @Override
     public List<UiccCardInfo> getUiccCardsInfo(String callingPackage) {
-        try {
-            PackageManager pm = mApp.getPackageManager();
-            if (Binder.getCallingUid() != pm.getPackageUid(callingPackage, 0)) {
-                throw new SecurityException("Calling package " + callingPackage + " does not match "
-                        + "calling UID");
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            throw new SecurityException("Invalid calling package. e=" + e);
-        }
+        // Verify that tha callingPackage belongs to the calling UID
+        mApp.getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
+
         boolean hasReadPermission = false;
         try {
             enforceReadPrivilegedPermission("getUiccCardsInfo");
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 79feb10..3b8f4fd 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -32,6 +32,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.PersistableBundle;
 import android.os.UserHandle;
@@ -57,6 +58,7 @@
 import android.text.TextUtils;
 
 import com.android.ims.ImsManager;
+import com.android.internal.telephony.ExponentialBackoff;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.SubscriptionController;
@@ -84,6 +86,26 @@
     private final static int DEFAULT_SIM_ICON =  R.drawable.ic_multi_sim;
     private final static String GROUP_PREFIX = "group_";
 
+    private static final int REGISTER_START_DELAY_MS = 1 * 1000; // 1 second
+    private static final int REGISTER_MAXIMUM_DELAY_MS = 60 * 1000; // 1 minute
+
+    /**
+     * Indicates the {@link SubscriptionManager.OnSubscriptionsChangedListener} has not yet been
+     * registered.
+     */
+    private static final int LISTENER_STATE_UNREGISTERED = 0;
+
+    /**
+     * Indicates the first {@link SubscriptionManager.OnSubscriptionsChangedListener} registration
+     * attempt failed and we are performing backoff registration.
+     */
+    private static final int LISTENER_STATE_PERFORMING_BACKOFF = 2;
+
+    /**
+     * Indicates the {@link SubscriptionManager.OnSubscriptionsChangedListener} has been registered.
+     */
+    private static final int LISTENER_STATE_REGISTERED = 3;
+
     final class AccountEntry implements PstnPhoneCapabilitiesNotifier.Listener {
         private final Phone mPhone;
         private PhoneAccount mAccount;
@@ -951,18 +973,46 @@
             new OnSubscriptionsChangedListener() {
         @Override
         public void onSubscriptionsChanged() {
-            // Any time the SubscriptionInfo changes...rerun the setup
-            Log.i(this, "onSubscriptionsChanged - update accounts");
+            if (mSubscriptionListenerState != LISTENER_STATE_REGISTERED) {
+                mRegisterSubscriptionListenerBackoff.stop();
+                mHandlerThread.quitSafely();
+            }
+            mSubscriptionListenerState = LISTENER_STATE_REGISTERED;
+
+            // Any time the SubscriptionInfo changes rerun the setup
+            Log.i(this, "TelecomAccountRegistry: onSubscriptionsChanged - update accounts");
             tearDownAccounts();
             setupAccounts();
         }
+
+        @Override
+        public void onAddListenerFailed() {
+            // Woe!  Failed to add the listener!
+            Log.w(this, "TelecomAccountRegistry: onAddListenerFailed - failed to register "
+                    + "OnSubscriptionsChangedListener");
+
+            // Even though registering the listener failed, we will still try to setup the phone
+            // accounts now; the phone instances should already be present and ready, so even if
+            // telephony registry is poking along we can still try to setup the phone account.
+            tearDownAccounts();
+            setupAccounts();
+
+            if (mSubscriptionListenerState == LISTENER_STATE_UNREGISTERED) {
+                // Initial registration attempt failed; start exponential backoff.
+                mSubscriptionListenerState = LISTENER_STATE_PERFORMING_BACKOFF;
+                mRegisterSubscriptionListenerBackoff.start();
+            } else {
+                // We're already doing exponential backoff and a registration failed.
+                mRegisterSubscriptionListenerBackoff.notifyFailed();
+            }
+        }
     };
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
-                Log.i(this, "User changed, re-registering phone accounts.");
+                Log.i(this, "TelecomAccountRegistry: User changed, re-registering phone accounts.");
 
                 UserHandle currentUser = intent.getParcelableExtra(Intent.EXTRA_USER);
                 mIsPrimaryUser = currentUser == null ? true : currentUser.isSystem();
@@ -1025,20 +1075,42 @@
     private final SubscriptionManager mSubscriptionManager;
     private List<AccountEntry> mAccounts = new LinkedList<AccountEntry>();
     private final Object mAccountsLock = new Object();
+    private int mSubscriptionListenerState = LISTENER_STATE_UNREGISTERED;
     private int mServiceState = ServiceState.STATE_POWER_OFF;
     private int mActiveDataSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     private boolean mIsPrimaryUser = true;
+    private ExponentialBackoff mRegisterSubscriptionListenerBackoff;
+    private final HandlerThread mHandlerThread = new HandlerThread("TelecomAccountRegistry");
 
     // TODO: Remove back-pointer from app singleton to Service, since this is not a preferred
     // pattern; redesign. This was added to fix a late release bug.
     private TelephonyConnectionService mTelephonyConnectionService;
 
+    // Used to register subscription changed listener when initial attempts fail.
+    private Runnable mRegisterOnSubscriptionsChangedListenerRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (mSubscriptionListenerState != LISTENER_STATE_REGISTERED) {
+                Log.i(this, "TelecomAccountRegistry: performing delayed register.");
+                SubscriptionManager.from(mContext).addOnSubscriptionsChangedListener(
+                        mOnSubscriptionsChangedListener);
+            }
+        }
+    };
+
     TelecomAccountRegistry(Context context) {
         mContext = context;
         mTelecomManager = context.getSystemService(TelecomManager.class);
         mImsManager = context.getSystemService(android.telephony.ims.ImsManager.class);
         mTelephonyManager = TelephonyManager.from(context);
         mSubscriptionManager = SubscriptionManager.from(context);
+        mHandlerThread.start();
+        mRegisterSubscriptionListenerBackoff = new ExponentialBackoff(
+                REGISTER_START_DELAY_MS,
+                REGISTER_MAXIMUM_DELAY_MS,
+                2, /* multiplier */
+                mHandlerThread.getLooper(),
+                mRegisterOnSubscriptionsChangedListenerRunnable);
     }
 
     /**
@@ -1254,6 +1326,7 @@
 
         // Register for SubscriptionInfo list changes which is guaranteed
         // to invoke onSubscriptionsChanged the first time.
+        Log.i(this, "TelecomAccountRegistry: setupOnBoot - register subscription listener");
         SubscriptionManager.from(mContext).addOnSubscriptionsChangedListener(
                 mOnSubscriptionsChangedListener);
 
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index fd9de4f..f3be020 100755
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -1387,6 +1387,8 @@
         if (PhoneNumberUtils.isEmergencyNumber(mOriginalConnection.getAddress())) {
             mTreatAsEmergencyCall = true;
         }
+        // Propagate VERSTAT for IMS calls.
+        setCallerNumberVerificationStatus(mOriginalConnection.getNumberVerificationStatus());
 
         if (isImsConnection()) {
             mWasImsConnection = true;
diff --git a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
deleted file mode 100644
index 9f8de9e..0000000
--- a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2020 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 junit.framework.TestCase.fail;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.util.Log;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.TelephonyTestBase;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-
-@RunWith(AndroidJUnit4.class)
-public class PhoneInterfaceManagerTest extends TelephonyTestBase {
-
-    private static final String PRIVILEGED_PACKAGE_NAME = "test.package.name";
-
-    private static final String TAG = "PhoneInterfaceManagerTest";
-
-    private PhoneInterfaceManager mPhoneInterfaceManager;
-    private PhoneGlobals mMockPhoneGlobals;
-
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-        mMockPhoneGlobals = mock(PhoneGlobals.class);
-        //PhoneGlobals phoneGlobals = new PhoneGlobals(mContext);
-        mPhoneInterfaceManager = new PhoneInterfaceManager(mMockPhoneGlobals);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    @Test
-    public void testGetUiccCardsInfoSecurity() {
-        // Set up mocks so that the supplied package UID does not equal the calling UID
-        PackageManager mockPackageManager = mock(PackageManager.class);
-        try {
-            doReturn(Binder.getCallingUid() + 1).when(mockPackageManager)
-                    .getPackageUid(eq(PRIVILEGED_PACKAGE_NAME), anyInt());
-        } catch (Exception e) {
-            Log.d(TAG, "testGetUiccCardsInfoSecurity unable to setup mocks");
-            fail();
-        }
-        doReturn(mockPackageManager).when(mContext).getPackageManager();
-        doReturn(mockPackageManager).when(mMockPhoneGlobals).getPackageManager();
-        try {
-            mPhoneInterfaceManager.getUiccCardsInfo(PRIVILEGED_PACKAGE_NAME);
-            fail();
-        } catch (SecurityException e) {
-            Log.d(TAG, "testGetUiccCardsInfoSecurity e = " + e);
-        }
-    }
-}
diff --git a/tests/src/com/android/services/telephony/RadioOnStateListenerTest.java b/tests/src/com/android/services/telephony/RadioOnStateListenerTest.java
index 25df848..d55a2fa 100644
--- a/tests/src/com/android/services/telephony/RadioOnStateListenerTest.java
+++ b/tests/src/com/android/services/telephony/RadioOnStateListenerTest.java
@@ -69,6 +69,8 @@
     @Override
     @After
     public void tearDown() throws Exception {
+        mListener.setTimeBetweenRetriesMillis(5000);
+        mListener.setMaxNumRetries(5);
         mListener.getHandler().removeCallbacksAndMessages(null);
         // Wait for the queue to clear...
         waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS /*ms timeout*/);