Loading packages/SettingsLib/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ java_defaults { "SettingsLibRadioButtonPreference", "SettingsLibDisplayDensityUtils", "SettingsLibUtils", "SettingsLibEmergencyNumber", "SettingsLibTopIntroPreference", ], } Loading packages/SettingsLib/EmergencyNumber/Android.bp 0 → 100644 +10 −0 Original line number Diff line number Diff line android_library { name: "SettingsLibEmergencyNumber", srcs: ["src/**/*.java"], static_libs: [ "androidx.annotation_annotation", ], sdk_version: "system_current", min_sdk_version: "21", } packages/SettingsLib/EmergencyNumber/AndroidManifest.xml 0 → 100644 +23 −0 Original line number Diff line number Diff line <?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> packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java 0 → 100644 +133 −0 Original line number Diff line number Diff line /* * 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()); } } packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java 0 → 100644 +124 −0 Original line number Diff line number Diff line /* * 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); } } Loading
packages/SettingsLib/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ java_defaults { "SettingsLibRadioButtonPreference", "SettingsLibDisplayDensityUtils", "SettingsLibUtils", "SettingsLibEmergencyNumber", "SettingsLibTopIntroPreference", ], } Loading
packages/SettingsLib/EmergencyNumber/Android.bp 0 → 100644 +10 −0 Original line number Diff line number Diff line android_library { name: "SettingsLibEmergencyNumber", srcs: ["src/**/*.java"], static_libs: [ "androidx.annotation_annotation", ], sdk_version: "system_current", min_sdk_version: "21", }
packages/SettingsLib/EmergencyNumber/AndroidManifest.xml 0 → 100644 +23 −0 Original line number Diff line number Diff line <?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>
packages/SettingsLib/EmergencyNumber/src/com/android/settingslib/emergencynumber/EmergencyNumberUtils.java 0 → 100644 +133 −0 Original line number Diff line number Diff line /* * 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()); } }
packages/SettingsLib/tests/robotests/src/com/android/settingslib/emergencynumber/EmergencyNumberUtilsTest.java 0 → 100644 +124 −0 Original line number Diff line number Diff line /* * 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); } }