create a new notification channel for high prio sim alert
create a high priority notification channel for sim releated alert
in some scenario, we want users to know that they cannot completely
rely on their ability to make a phone call and data call with the
SIM and this may apply to emergency situations.
Bug: 134790138
Test: Manual test
Change-Id: Ia3c6d568d424bf501d77336e3dcb940f4c8179a4
diff --git a/res/drawable/ic_sim_card.xml b/res/drawable/ic_sim_card.xml
new file mode 100644
index 0000000..f563d23
--- /dev/null
+++ b/res/drawable/ic_sim_card.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+<path
+ android:fillColor="#757575"
+ android:pathData="M18,2h-8L4.02,8 4,20c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,4c0,-1.1 -0.9,-2 -2,-2zM13,17h-2v-2h2v2zM13,13h-2L11,8h2v5z"/>
+</vector>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4ad0d26..9d21933 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -572,6 +572,12 @@
<string name="roaming_check_price_warning">Check with your network provider for pricing.</string>
<!-- Mobile network settings screen, dialog message title when user selects the Data roaming check box -->
<string name="roaming_alert_title">Allow data roaming?</string>
+ <!-- Notification title for limited sim function during dual sim -->
+ <string name="limited_sim_function_notification_title">Limited SIM functionality</string>
+ <!-- Notification message for limited sim function during dual sim -->
+ <string name="limited_sim_function_with_phone_num_notification_message"><xliff:g id="carrier_name">%1$s</xliff:g> calls and data services may be blocked while using <xliff:g id="phone_number">%2$s</xliff:g>.</string>
+ <!-- Notification message for limited sim function during dual sim -->
+ <string name="limited_sim_function_notification_message"><xliff:g id="carrier_name">%1$s</xliff:g> calls and data services may be blocked while using another SIM. Tap to make changes.</string>
<!-- Mobile network settings screen, data usage setting check box name -->
<string name="data_usage_title">App data usage</string>
<!-- Summary about how much data has been used in a date range [CHAR LIMIT=100] -->
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index 942c1e2..3b9f996 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.READ_PHONE_STATE;
+import android.annotation.Nullable;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -62,6 +63,7 @@
import com.android.internal.telephony.util.NotificationChannelController;
import com.android.phone.settings.VoicemailSettingsActivity;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -92,6 +94,7 @@
static final int CALL_FORWARD_NOTIFICATION = 4;
static final int DATA_DISCONNECTED_ROAMING_NOTIFICATION = 5;
static final int SELECTED_OPERATOR_FAIL_NOTIFICATION = 6;
+ static final int LIMITED_SIM_FUNCTION_NOTIFICATION = 7;
// Event for network selection notification.
private static final int EVENT_PENDING_NETWORK_SELECTION_NOTIFICATION = 1;
@@ -101,6 +104,8 @@
private static final int STATE_UNKNOWN_SERVICE = -1;
+ private static final String ACTION_MOBILE_NETWORK_LIST = "android.settings.MOBILE_NETWORK_LIST";
+
/** The singleton NotificationMgr instance. */
private static NotificationMgr sInstance;
@@ -118,6 +123,9 @@
// used to track the notification of selected network unavailable, per subscription id.
private SparseArray<Boolean> mSelectedUnavailableNotify = new SparseArray<>();
+ // used to track the notification of limited sim function under dual sim, per subscription id.
+ private Set<Integer> mLimitedSimFunctionNotify = new HashSet<>();
+
// used to track whether the message waiting indicator is visible, per subscription id.
private ArrayMap<Integer, Boolean> mMwiVisible = new ArrayMap<Integer, Boolean>();
@@ -597,6 +605,88 @@
}
/**
+ * Shows the "Limited SIM functionality" warning notification, which appears when using a
+ * special carrier under dual sim. limited function applies for DSDS in general when two SIM
+ * cards share a single radio, thus the voice & data maybe impaired under certain scenarios.
+ */
+ public void showLimitedSimFunctionWarningNotification(int subId, @Nullable String carrierName) {
+ if (DBG) log("showLimitedSimFunctionWarningNotification carrier: " + carrierName
+ + " subId: " + subId);
+ if (mLimitedSimFunctionNotify.contains(subId)) {
+ // handle the case that user swipe the notification but condition triggers
+ // frequently which cause the same notification consistently displayed.
+ if (DBG) log("showLimitedSimFunctionWarningNotification, "
+ + "not display again if already displayed");
+ return;
+ }
+ // Navigate to "Network Selection Settings" which list all subscriptions.
+ PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0,
+ new Intent(ACTION_MOBILE_NETWORK_LIST), 0);
+ String line1Num = mTelephonyManager.getLine1Number(subId);
+
+ final CharSequence contentText = TextUtils.isEmpty(line1Num) ?
+ String.format(mContext.getText(
+ R.string.limited_sim_function_notification_message).toString(),
+ carrierName, line1Num) :
+ String.format(mContext.getText(
+ R.string.limited_sim_function_with_phone_num_notification_message).toString(),
+ carrierName);
+ final Notification.Builder builder = new Notification.Builder(mContext)
+ .setSmallIcon(R.drawable.ic_sim_card)
+ .setContentTitle(mContext.getText(
+ R.string.limited_sim_function_notification_title))
+ .setContentText(contentText)
+ .setOnlyAlertOnce(true)
+ .setOngoing(true)
+ .setChannel(NotificationChannelController.CHANNEL_ID_SIM_HIGH_PRIORITY)
+ .setContentIntent(contentIntent);
+ final Notification notification = new Notification.BigTextStyle(builder).bigText(
+ contentText).build();
+
+ mNotificationManager.notifyAsUser(Integer.toString(subId),
+ LIMITED_SIM_FUNCTION_NOTIFICATION,
+ notification, UserHandle.ALL);
+ mLimitedSimFunctionNotify.add(subId);
+ }
+
+ /**
+ * Dismiss the "Limited SIM functionality" warning notification for the given subId.
+ */
+ public void dismissLimitedSimFunctionWarningNotification(int subId) {
+ if (DBG) log("dismissLimitedSimFunctionWarningNotification subId: " + subId);
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ // dismiss all notifications
+ for (int id : mLimitedSimFunctionNotify) {
+ mNotificationManager.cancelAsUser(Integer.toString(id),
+ LIMITED_SIM_FUNCTION_NOTIFICATION, UserHandle.ALL);
+ }
+ mLimitedSimFunctionNotify.clear();
+ } else if (mLimitedSimFunctionNotify.contains(subId)) {
+ mNotificationManager.cancelAsUser(Integer.toString(subId),
+ LIMITED_SIM_FUNCTION_NOTIFICATION, UserHandle.ALL);
+ mLimitedSimFunctionNotify.remove(subId);
+ }
+ }
+
+ /**
+ * Dismiss the "Limited SIM functionality" warning notification for all inactive subscriptions.
+ */
+ public void dismissLimitedSimFunctionWarningNotificationForInactiveSubs() {
+ if (DBG) log("dismissLimitedSimFunctionWarningNotificationForInactiveSubs");
+ // dismiss notification for inactive subscriptions.
+ // handle the corner case that SIM change by SIM refresh doesn't clear the notification
+ // from the old SIM if both old & new SIM configured to display the notification.
+ mLimitedSimFunctionNotify.removeIf(id -> {
+ if (!mSubscriptionManager.isActiveSubId(id)) {
+ mNotificationManager.cancelAsUser(Integer.toString(id),
+ LIMITED_SIM_FUNCTION_NOTIFICATION, UserHandle.ALL);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ /**
* Display the network selection "no service" notification
* @param operator is the numeric operator number
* @param subId is the subscription ID
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 0f8f146..8d3027a 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -46,6 +46,7 @@
import android.telephony.AnomalyReporter;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
@@ -73,6 +74,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.List;
/**
* Global state for the telephony subsystem when running in the primary
@@ -649,6 +651,7 @@
// Roaming status could be overridden by carrier config, so we need to update it.
if (VDBG) Log.v(LOG_TAG, "carrier config changed.");
updateDataRoamingStatus();
+ updateLimitedSimFunctionForDualSim();
} else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
// We also need to pay attention when default data subscription changes.
if (VDBG) Log.v(LOG_TAG, "default data sub changed.");
@@ -755,6 +758,38 @@
}
}
+ private void updateLimitedSimFunctionForDualSim() {
+ if (DBG) Log.d(LOG_TAG, "updateLimitedSimFunctionForDualSim");
+ // check conditions to display limited SIM function notification under dual SIM
+ SubscriptionManager subMgr = (SubscriptionManager) getSystemService(
+ Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ List<SubscriptionInfo> subList = subMgr.getActiveSubscriptionInfoList(false);
+ if (subList != null && subList.size() > 1) {
+ CarrierConfigManager configMgr = (CarrierConfigManager)
+ getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ for (SubscriptionInfo info : subList) {
+ PersistableBundle b = configMgr.getConfigForSubId(info.getSubscriptionId());
+ if (b != null) {
+ if (b.getBoolean(CarrierConfigManager
+ .KEY_LIMITED_SIM_FUNCTION_NOTIFICATION_FOR_DSDS_BOOL)) {
+ notificationMgr.showLimitedSimFunctionWarningNotification(
+ info.getSubscriptionId(),
+ info.getDisplayName().toString());
+ } else {
+ notificationMgr.dismissLimitedSimFunctionWarningNotification(
+ info.getSubscriptionId());
+ }
+ }
+ }
+ } else {
+ // cancel notifications for all subs
+ notificationMgr.dismissLimitedSimFunctionWarningNotification(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ }
+ notificationMgr.dismissLimitedSimFunctionWarningNotificationForInactiveSubs();
+
+ }
+
public Phone getPhoneInEcm() {
return phoneInEcm;
}