Merge "Create a helper lib for emergency numbers."

This commit is contained in:
Fan Zhang
2020-11-19 18:53:00 +00:00
committed by Android (Google) Code Review
5 changed files with 291 additions and 0 deletions

View File

@@ -51,6 +51,7 @@ java_defaults {
"SettingsLibRadioButtonPreference",
"SettingsLibDisplayDensityUtils",
"SettingsLibUtils",
"SettingsLibEmergencyNumber",
"SettingsLibTopIntroPreference",
],
}

View File

@@ -0,0 +1,10 @@
android_library {
name: "SettingsLibEmergencyNumber",
srcs: ["src/**/*.java"],
static_libs: [
"androidx.annotation_annotation",
],
sdk_version: "system_current",
min_sdk_version: "21",
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2019 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
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.settingslib.emergencynumber">
<uses-sdk android:minSdkVersion="21" />
</manifest>

View File

@@ -0,0 +1,133 @@
/*
* 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.settingslib.emergencynumber;
import static android.telephony.emergency.EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE;
import static android.telephony.emergency.EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Util class to help manage emergency numbers
*/
public class EmergencyNumberUtils {
private static final String TAG = "EmergencyNumberUtils";
private static final String EMERGENCY_GESTURE_CALL_NUMBER = "emergency_gesture_call_number";
@VisibleForTesting
static final String FALL_BACK_NUMBER = "112";
private final Context mContext;
private final TelephonyManager mTelephonyManager;
public EmergencyNumberUtils(Context context) {
mContext = context;
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
mTelephonyManager = context.getSystemService(TelephonyManager.class);
} else {
mTelephonyManager = null;
}
}
/**
* Returns the most appropriate number for police.
*/
public String getDefaultPoliceNumber() {
if (mTelephonyManager == null) {
return FALL_BACK_NUMBER;
}
final List<EmergencyNumber> promotedPoliceNumber = getPromotedEmergencyNumbers(
EMERGENCY_SERVICE_CATEGORY_POLICE);
if (promotedPoliceNumber == null || promotedPoliceNumber.isEmpty()) {
return FALL_BACK_NUMBER;
}
return promotedPoliceNumber.get(0).getNumber();
}
/**
* Returns the number chosen by user. If user has not provided any number, use default ({@link
* #getDefaultPoliceNumber()}).
*/
public String getPoliceNumber() {
final String userProvidedNumber = Settings.Secure.getString(mContext.getContentResolver(),
EMERGENCY_GESTURE_CALL_NUMBER);
return TextUtils.isEmpty(userProvidedNumber)
? getDefaultPoliceNumber() : userProvidedNumber;
}
private List<EmergencyNumber> getPromotedEmergencyNumbers(int categories) {
Map<Integer, List<EmergencyNumber>> allLists = mTelephonyManager.getEmergencyNumberList(
categories);
if (allLists == null || allLists.isEmpty()) {
Log.w(TAG, "Unable to retrieve emergency number lists!");
return new ArrayList<>();
}
Map<Integer, List<EmergencyNumber>> promotedEmergencyNumberLists = new ArrayMap<>();
for (Map.Entry<Integer, List<EmergencyNumber>> entry : allLists.entrySet()) {
if (entry.getKey() == null || entry.getValue() == null) {
continue;
}
List<EmergencyNumber> emergencyNumberList = entry.getValue();
Log.d(TAG, "Emergency numbers for subscription id " + entry.getKey());
// The list of promoted emergency numbers which will be visible on shortcut view.
List<EmergencyNumber> promotedList = new ArrayList<>();
// A temporary list for non-prioritized emergency numbers.
List<EmergencyNumber> tempList = new ArrayList<>();
for (EmergencyNumber emergencyNumber : emergencyNumberList) {
// Emergency numbers in DATABASE are prioritized since they were well-categorized.
boolean isFromPrioritizedSource =
emergencyNumber.getEmergencyNumberSources().contains(
EMERGENCY_NUMBER_SOURCE_DATABASE);
Log.d(TAG, String.format("Number %s, isFromPrioritizedSource %b",
emergencyNumber, isFromPrioritizedSource));
if (isFromPrioritizedSource) {
promotedList.add(emergencyNumber);
} else {
tempList.add(emergencyNumber);
}
}
// Puts numbers in temp list after prioritized numbers.
promotedList.addAll(tempList);
if (!promotedList.isEmpty()) {
promotedEmergencyNumberLists.put(entry.getKey(), promotedList);
}
}
if (promotedEmergencyNumberLists.isEmpty()) {
Log.w(TAG, "No promoted emergency number found!");
}
return promotedEmergencyNumberLists.get(SubscriptionManager.getDefaultSubscriptionId());
}
}

View File

@@ -0,0 +1,124 @@
/*
* 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.settingslib.emergencynumber;
import static android.telephony.emergency.EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
import android.util.ArrayMap;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@RunWith(RobolectricTestRunner.class)
public class EmergencyNumberUtilsTest {
private static final String TELEPHONY_EMERGENCY_NUMBER = "1234";
private static final String USER_OVERRIDE_EMERGENCY_NUMBER = "5678";
@Mock
private Context mContext;
@Mock
private PackageManager mPackageManager;
@Mock
private TelephonyManager mTelephonyManager;
private EmergencyNumberUtils mUtils;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
}
@Test
public void getDefaultPoliceNumber_noTelephony_shouldReturnDefault() {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(false);
mUtils = new EmergencyNumberUtils(mContext);
assertThat(mUtils.getDefaultPoliceNumber()).isEqualTo(
EmergencyNumberUtils.FALL_BACK_NUMBER);
}
@Test
public void getDefaultPoliceNumber_hasTelephony_shouldLoadFromTelephony() {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
addEmergencyNumberToTelephony();
mUtils = new EmergencyNumberUtils(mContext);
assertThat(mUtils.getDefaultPoliceNumber()).isEqualTo(TELEPHONY_EMERGENCY_NUMBER);
}
@Test
public void getPoliceNumber_hasUserOverride_shouldLoadFromUserOverride() {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
addEmergencyNumberToTelephony();
ContentResolver resolver = RuntimeEnvironment.application.getContentResolver();
when(mContext.getContentResolver()).thenReturn(resolver);
Settings.Secure.putString(resolver, Settings.Secure.EMERGENCY_GESTURE_CALL_NUMBER,
USER_OVERRIDE_EMERGENCY_NUMBER);
mUtils = new EmergencyNumberUtils(mContext);
assertThat(mUtils.getPoliceNumber()).isEqualTo(USER_OVERRIDE_EMERGENCY_NUMBER);
}
@Test
public void getPoliceNumber_noUserOverride_shouldLoadFromTelephony() {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
addEmergencyNumberToTelephony();
mUtils = new EmergencyNumberUtils(mContext);
assertThat(mUtils.getPoliceNumber()).isEqualTo(TELEPHONY_EMERGENCY_NUMBER);
}
private void addEmergencyNumberToTelephony() {
final int subId = SubscriptionManager.getDefaultSubscriptionId();
EmergencyNumber emergencyNumber = mock(EmergencyNumber.class);
Map<Integer, List<EmergencyNumber>> numbers = new ArrayMap<>();
List<EmergencyNumber> numbersForSubId = new ArrayList<>();
numbersForSubId.add(emergencyNumber);
numbers.put(subId, numbersForSubId);
when(mTelephonyManager.getEmergencyNumberList(
EMERGENCY_SERVICE_CATEGORY_POLICE)).thenReturn(numbers);
when(emergencyNumber.getNumber()).thenReturn(TELEPHONY_EMERGENCY_NUMBER);
}
}