Merge "Filter self managed phone accounts out when finding emergency accts."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 45e3151..0776e9d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -56,6 +56,7 @@
     <uses-permission android:name="android.permission.READ_BLOCKED_NUMBERS"/>
     <uses-permission android:name="android.permission.WRITE_BLOCKED_NUMBERS"/>
     <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/>
+    <uses-permission android:name="com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID"/>
 
     <permission android:name="android.permission.BROADCAST_CALLLOG_INFO"
          android:label="Broadcast the call type/duration information"
diff --git a/res/xml/activity_blocked_numbers.xml b/res/xml/activity_blocked_numbers.xml
index df1a759..f884ec9 100644
--- a/res/xml/activity_blocked_numbers.xml
+++ b/res/xml/activity_blocked_numbers.xml
@@ -75,7 +75,7 @@
                     <TextView
                             android:id="@+id/add_blocked"
                             android:layout_width="wrap_content"
-                            android:layout_height="48dp"
+                            android:layout_height="wrap_content"
                             android:text="@string/block_number"
                             android:layout_marginBottom="@dimen/blocked_numbers_button_bottom_margin"
                             android:paddingTop="@dimen/blocked_numbers_button_large_padding"
diff --git a/src/com/android/server/telecom/CallDiagnosticServiceController.java b/src/com/android/server/telecom/CallDiagnosticServiceController.java
index d8ee475..7bd7288 100644
--- a/src/com/android/server/telecom/CallDiagnosticServiceController.java
+++ b/src/com/android/server/telecom/CallDiagnosticServiceController.java
@@ -60,7 +60,7 @@
      */
     public interface ContextProxy {
         List<ResolveInfo> queryIntentServicesAsUser(@NonNull Intent intent,
-                @PackageManager.ResolveInfoFlags int flags, @UserIdInt int userId);
+                int resolveInfoFlags, @UserIdInt int userId);
         boolean bindServiceAsUser(@NonNull @RequiresPermission Intent service,
                 @NonNull ServiceConnection conn, int flags, @NonNull UserHandle user);
         void unbindService(@NonNull ServiceConnection conn);
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index e4922b0..6873e42 100755
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -596,7 +596,7 @@
         IntentFilter intentFilter = new IntentFilter(
                 CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
         intentFilter.addAction(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED);
-        context.registerReceiver(mReceiver, intentFilter);
+        context.registerReceiver(mReceiver, intentFilter, Context.RECEIVER_EXPORTED);
         mGraphHandlerThreads = new LinkedList<>();
     }
 
@@ -2193,7 +2193,7 @@
      * @param callId The ID of the call to show the redirection dialog for.
      */
     private void showRedirectionDialog(@NonNull String callId, @NonNull CharSequence appName) {
-        AlertDialog confirmDialog = new AlertDialog.Builder(mContext).create();
+        AlertDialog confirmDialog = FrameworksUtils.makeAlertDialogBuilder(mContext).create();
         LayoutInflater layoutInflater = LayoutInflater.from(mContext);
         View dialogView = layoutInflater.inflate(R.layout.call_redirection_confirm_dialog, null);
 
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 21c6844..6eae3e3 100755
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -45,6 +45,8 @@
 import android.telecom.StatusHints;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
+import android.telephony.CellIdentity;
+import android.telephony.TelephonyManager;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telecom.IConnectionService;
@@ -1197,6 +1199,24 @@
         }
     }
 
+    private CellIdentity getLastKnownCellIdentity() {
+        TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
+        if (telephonyManager != null) {
+            CellIdentity lastKnownCellIdentity = telephonyManager.getLastKnownCellIdentity();
+            try {
+                mAppOpsManager.noteOp(AppOpsManager.OP_FINE_LOCATION,
+                        mContext.getPackageManager().getPackageUid(
+                                getComponentName().getPackageName(), 0),
+                        getComponentName().getPackageName());
+            } catch (PackageManager.NameNotFoundException nameNotFoundException) {
+                Log.e(this, nameNotFoundException, "could not find the package -- %s",
+                        getComponentName().getPackageName());
+            }
+            return lastKnownCellIdentity;
+        }
+        return null;
+    }
+
     /**
      * Creates a conference for a new outgoing call or attach to an existing incoming call.
      */
@@ -1316,6 +1336,11 @@
                         Log.piiHandle(call.getHandle()) + " via:" +
                                 getComponentName().getPackageName());
 
+                if (call.isEmergencyCall()) {
+                    extras.putParcelable(Connection.EXTRA_LAST_KNOWN_CELL_IDENTITY,
+                            getLastKnownCellIdentity());
+                }
+
                 ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
                         .setAccountHandle(call.getTargetPhoneAccount())
                         .setAddress(call.getHandle())
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index e5b4197..3561211 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -667,7 +667,7 @@
             }
 
             // then by hashcode
-            return account1.hashCode() - account2.hashCode();
+            return Integer.compare(account1.hashCode(), account2.hashCode());
         });
     }
 
diff --git a/src/com/android/server/telecom/FrameworksUtils.java b/src/com/android/server/telecom/FrameworksUtils.java
new file mode 100644
index 0000000..08a19f5
--- /dev/null
+++ b/src/com/android/server/telecom/FrameworksUtils.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 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.server.telecom;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.res.Configuration;
+
+/**
+ * This class provides utility functions over framework APIs
+ */
+public class FrameworksUtils {
+    /**
+     * Create a new instance of {@link AlertDialog.Builder}.
+     * @param context reference to a Context
+     * @return an instance of AlertDialog.Builder
+     */
+    public static AlertDialog.Builder makeAlertDialogBuilder(Context context) {
+        boolean isDarkTheme = (context.getResources().getConfiguration().uiMode
+                & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
+        return new AlertDialog.Builder(context, isDarkTheme
+                ? android.R.style.Theme_DeviceDefault_Dialog_Alert : 0);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index ca76456..d315127 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -1696,11 +1696,16 @@
         }
 
         PackageManager packageManager = mContext.getPackageManager();
+        Context userContext = mContext.createContextAsUser(mCallsManager.getCurrentUserHandle(),
+                0 /* flags */);
+        PackageManager userPackageManager = userContext != null ?
+                userContext.getPackageManager() : packageManager;
         for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(
                 serviceIntent,
                 PackageManager.GET_META_DATA | PackageManager.MATCH_DISABLED_COMPONENTS,
                 mCallsManager.getCurrentUserHandle().getIdentifier())) {
             ServiceInfo serviceInfo = entry.serviceInfo;
+
             if (serviceInfo != null) {
                 boolean isExternalCallsSupported = serviceInfo.metaData != null &&
                         serviceInfo.metaData.getBoolean(
@@ -1718,7 +1723,7 @@
                 }
 
                 boolean isEnabled = isServiceEnabled(foundComponentName,
-                        serviceInfo, packageManager);
+                        serviceInfo, userPackageManager);
                 boolean isRequestedType;
                 if (requestedType == IN_CALL_SERVICE_TYPE_INVALID) {
                     isRequestedType = true;
@@ -1737,6 +1742,10 @@
 
     private boolean isServiceEnabled(ComponentName componentName,
             ServiceInfo serviceInfo, PackageManager packageManager) {
+        if (packageManager == null) {
+            return serviceInfo.isEnabled();
+        }
+
         int componentEnabledState = packageManager.getComponentEnabledSetting(componentName);
 
         if (componentEnabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
diff --git a/src/com/android/server/telecom/TtyManager.java b/src/com/android/server/telecom/TtyManager.java
index 457ba36..f1b74a4 100644
--- a/src/com/android/server/telecom/TtyManager.java
+++ b/src/com/android/server/telecom/TtyManager.java
@@ -52,7 +52,7 @@
                 TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
         mContext.registerReceiver(mReceiver, intentFilter,
                 android.Manifest.permission.MODIFY_PHONE_STATE,
-                null);
+                null, Context.RECEIVER_EXPORTED);
 
         updateCurrentTtyMode();
     }
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index 8e93a75..c7671e3 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -157,12 +157,14 @@
         Set<Long> seenHiSyncIds = new LinkedHashSet<>();
         // Add the left-most active device to the seen list so that we match up with the list
         // generated in BluetoothRouteManager.
-        for (BluetoothDevice device : mBluetoothAdapter.getActiveDevices(
-                    BluetoothProfile.HEARING_AID)) {
-            if (device != null) {
-                result.add(device);
-                seenHiSyncIds.add(mHearingAidDeviceSyncIds.getOrDefault(device, -1L));
-                break;
+        if (mBluetoothAdapter != null) {
+            for (BluetoothDevice device : mBluetoothAdapter.getActiveDevices(
+                        BluetoothProfile.HEARING_AID)) {
+                if (device != null) {
+                    result.add(device);
+                    seenHiSyncIds.add(mHearingAidDeviceSyncIds.getOrDefault(device, -1L));
+                    break;
+                }
             }
         }
         synchronized (mLock) {
@@ -244,10 +246,12 @@
     }
 
     public void disconnectAudio() {
-        for (BluetoothDevice device: mBluetoothAdapter.getActiveDevices(
-                    BluetoothProfile.HEARING_AID)) {
-            if (device != null) {
-                mBluetoothAdapter.setActiveDevice(null, BluetoothAdapter.ACTIVE_DEVICE_ALL);
+        if (mBluetoothAdapter != null) {
+            for (BluetoothDevice device: mBluetoothAdapter.getActiveDevices(
+                        BluetoothProfile.HEARING_AID)) {
+                if (device != null) {
+                    mBluetoothAdapter.removeActiveDevice(BluetoothAdapter.ACTIVE_DEVICE_ALL);
+                }
             }
         }
         disconnectSco();
@@ -295,10 +299,12 @@
     }
 
     public void cacheHearingAidDevice() {
-        for (BluetoothDevice device : mBluetoothAdapter.getActiveDevices(
-                    BluetoothProfile.HEARING_AID)) {
-            if (device != null) {
-                mBluetoothHearingAidActiveDeviceCache = device;
+        if (mBluetoothAdapter != null) {
+            for (BluetoothDevice device : mBluetoothAdapter.getActiveDevices(
+                        BluetoothProfile.HEARING_AID)) {
+                if (device != null) {
+                    mBluetoothHearingAidActiveDeviceCache = device;
+                }
             }
         }
     }
diff --git a/src/com/android/server/telecom/components/ErrorDialogActivity.java b/src/com/android/server/telecom/components/ErrorDialogActivity.java
index 1bdcdf2..3618b77 100644
--- a/src/com/android/server/telecom/components/ErrorDialogActivity.java
+++ b/src/com/android/server/telecom/components/ErrorDialogActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom.components;
 
+import com.android.server.telecom.FrameworksUtils;
 import com.android.server.telecom.R;
 
 import android.app.Activity;
@@ -84,7 +85,7 @@
             }
         };
 
-        final AlertDialog errorDialog = new AlertDialog.Builder(this)
+        final AlertDialog errorDialog = FrameworksUtils.makeAlertDialogBuilder(this)
                 .setMessage(msg).setPositiveButton(android.R.string.ok, clickListener)
                         .setOnCancelListener(cancelListener).create();
 
@@ -97,7 +98,7 @@
     }
 
     private void showMissingVoicemailErrorDialog() {
-        new AlertDialog.Builder(this)
+        FrameworksUtils.makeAlertDialogBuilder(this)
                 .setTitle(R.string.no_vm_number)
                 .setMessage(R.string.no_vm_number_msg)
                 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
diff --git a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
index 1fe7c5f..b573042 100644
--- a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
+++ b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
@@ -56,6 +56,7 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.android.server.telecom.FrameworksUtils;
 import com.android.server.telecom.R;
 
 
@@ -247,7 +248,7 @@
         final EditText editText = (EditText) dialogView.findViewById(R.id.add_blocked_number);
         editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher());
         editText.addTextChangedListener(this);
-        AlertDialog dialog = new AlertDialog.Builder(this)
+        AlertDialog dialog = FrameworksUtils.makeAlertDialogBuilder(this)
                 .setView(dialogView)
                 .setPositiveButton(R.string.block_button, new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int id) {
diff --git a/src/com/android/server/telecom/settings/BlockedNumbersAdapter.java b/src/com/android/server/telecom/settings/BlockedNumbersAdapter.java
index df68f6e..333e451 100644
--- a/src/com/android/server/telecom/settings/BlockedNumbersAdapter.java
+++ b/src/com/android/server/telecom/settings/BlockedNumbersAdapter.java
@@ -29,6 +29,7 @@
 import android.widget.SimpleCursorAdapter;
 import android.widget.TextView;
 
+import com.android.server.telecom.FrameworksUtils;
 import com.android.server.telecom.R;
 
 public class BlockedNumbersAdapter extends SimpleCursorAdapter {
@@ -72,7 +73,7 @@
         Spannable messageSpannable = new SpannableString(message);
         PhoneNumberUtils.addTtsSpan(messageSpannable, startingPosition,
                 startingPosition + formattedNumber.length());
-        AlertDialog dialog = new AlertDialog.Builder(context)
+        AlertDialog dialog = FrameworksUtils.makeAlertDialogBuilder(context)
                 .setMessage(messageSpannable)
                 .setPositiveButton(R.string.unblock_button,
                         new DialogInterface.OnClickListener() {
diff --git a/src/com/android/server/telecom/settings/CallBlockDisabledActivity.java b/src/com/android/server/telecom/settings/CallBlockDisabledActivity.java
index 5f42b37..232546b 100644
--- a/src/com/android/server/telecom/settings/CallBlockDisabledActivity.java
+++ b/src/com/android/server/telecom/settings/CallBlockDisabledActivity.java
@@ -22,6 +22,7 @@
 import android.os.Bundle;
 import android.provider.BlockedNumberContract;
 
+import com.android.server.telecom.FrameworksUtils;
 import com.android.server.telecom.R;
 
 /**
@@ -50,7 +51,7 @@
             return;
         }
 
-        AlertDialog.Builder builder = new AlertDialog.Builder(this);
+        AlertDialog.Builder builder = FrameworksUtils.makeAlertDialogBuilder(this);
         mDialog = builder
                 .setTitle(R.string.phone_strings_emergency_call_made_dialog_title_txt)
                 .setMessage(R.string
diff --git a/src/com/android/server/telecom/ui/CallRedirectionTimeoutDialogActivity.java b/src/com/android/server/telecom/ui/CallRedirectionTimeoutDialogActivity.java
index 5aa80c6..b5c850e 100644
--- a/src/com/android/server/telecom/ui/CallRedirectionTimeoutDialogActivity.java
+++ b/src/com/android/server/telecom/ui/CallRedirectionTimeoutDialogActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom.ui;
 
+import com.android.server.telecom.FrameworksUtils;
 import com.android.server.telecom.R;
 
 import android.app.Activity;
@@ -45,7 +46,7 @@
         Log.i(this, "showDialog: timeout redirection with %s", redirectionAppName);
         CharSequence message = getString(
                 R.string.alert_redirect_outgoing_call_timeout, redirectionAppName);
-        final AlertDialog errorDialog = new AlertDialog.Builder(this)
+        final AlertDialog errorDialog = FrameworksUtils.makeAlertDialogBuilder(this)
                 .setMessage(message)
                 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                     @Override
diff --git a/src/com/android/server/telecom/ui/ConfirmCallDialogActivity.java b/src/com/android/server/telecom/ui/ConfirmCallDialogActivity.java
index 4735e3c..e9f99b6 100644
--- a/src/com/android/server/telecom/ui/ConfirmCallDialogActivity.java
+++ b/src/com/android/server/telecom/ui/ConfirmCallDialogActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom.ui;
 
+import com.android.server.telecom.FrameworksUtils;
 import com.android.server.telecom.R;
 import com.android.server.telecom.TelecomBroadcastIntentProcessor;
 import com.android.server.telecom.components.TelecomBroadcastReceiver;
@@ -48,7 +49,7 @@
     private void showDialog(final String callId, CharSequence ongoingAppName) {
         Log.i(this, "showDialog: confirming callId=%s, ongoing=%s", callId, ongoingAppName);
         CharSequence message = getString(R.string.alert_outgoing_call, ongoingAppName);
-        final AlertDialog errorDialog = new AlertDialog.Builder(this)
+        final AlertDialog errorDialog = FrameworksUtils.makeAlertDialogBuilder(this)
                 .setMessage(message)
                 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                     @Override
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
index 02fdecc..db26aaf 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
@@ -239,7 +239,7 @@
                 .thenReturn(Arrays.asList(device2, null));
 
         mBluetoothDeviceManager.disconnectAudio();
-        verify(mAdapter).setActiveDevice(null, BluetoothAdapter.ACTIVE_DEVICE_ALL);
+        verify(mAdapter).removeActiveDevice(BluetoothAdapter.ACTIVE_DEVICE_ALL);
         verify(mBluetoothHeadset).disconnectAudio();
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
index ebb336e..2463847 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -123,6 +123,11 @@
         }
 
         @Override
+        public Context createContextAsUser(UserHandle userHandle, int flags) {
+            return this;
+        }
+
+        @Override
         public String getPackageName() {
             return "com.android.server.telecom.tests";
         }
@@ -327,12 +332,23 @@
         }
 
         @Override
+        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, int flags) {
+            return null;
+        }
+
+        @Override
         public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
                 String broadcastPermission, Handler scheduler) {
             return null;
         }
 
         @Override
+        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
+                String broadcastPermission, Handler scheduler, int flags) {
+            return null;
+        }
+
+        @Override
         public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle handle,
                 IntentFilter filter, String broadcastPermission, Handler scheduler) {
             return null;