summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Fabian Kozynski <kozynski@google.com> 2019-01-24 21:32:43 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2019-01-24 21:32:43 +0000
commitbcc927a19f45895ce2e8d152192934ea9eef9c8d (patch)
treeb3a0b9cb10e8549210bff5e2bf03356499f1fbf9
parent42aba33e20d14eaf6dcab8d1f0f94cde8d7175c6 (diff)
parent02941af5582d145d496066e997b41c0796f327a5 (diff)
Merge "Refactor logic out of CarrierText"
-rw-r--r--packages/SystemUI/src/com/android/keyguard/CarrierText.java407
-rw-r--r--packages/SystemUI/src/com/android/keyguard/CarrierTextController.java512
2 files changed, 536 insertions, 383 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index b7d51978fab2..8069ce4c0100 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -17,29 +17,14 @@
package com.android.keyguard;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.res.TypedArray;
-import android.net.ConnectivityManager;
-import android.net.wifi.WifiManager;
-import android.telephony.ServiceState;
-import android.telephony.SubscriptionInfo;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.method.SingleLineTransformationMethod;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
import android.widget.TextView;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.settingslib.WirelessUtils;
-
-import java.util.List;
import java.util.Locale;
-import java.util.Objects;
public class CarrierText extends TextView {
private static final boolean DEBUG = KeyguardConstants.DEBUG;
@@ -47,77 +32,30 @@ public class CarrierText extends TextView {
private static CharSequence mSeparator;
- private final boolean mIsEmergencyCallCapable;
-
- private boolean mTelephonyCapable;
-
private boolean mShowMissingSim;
private boolean mShowAirplaneMode;
+ private boolean mShouldMarquee;
- private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-
- private WifiManager mWifiManager;
-
- private boolean[] mSimErrorState = new boolean[TelephonyManager.getDefault().getPhoneCount()];
-
- private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
- @Override
- public void onRefreshCarrierInfo() {
- if (DEBUG) Log.d(TAG, "onRefreshCarrierInfo(), mTelephonyCapable: "
- + Boolean.toString(mTelephonyCapable));
- updateCarrierText();
- }
-
- public void onFinishedGoingToSleep(int why) {
- setSelected(false);
- };
-
- public void onStartedWakingUp() {
- setSelected(true);
- };
+ private CarrierTextController mCarrierTextController;
- @Override
- public void onTelephonyCapable(boolean capable) {
- if (DEBUG) Log.d(TAG, "onTelephonyCapable() mTelephonyCapable: "
- + Boolean.toString(capable));
- mTelephonyCapable = capable;
- updateCarrierText();
- }
-
- public void onSimStateChanged(int subId, int slotId, IccCardConstants.State simState) {
- if (slotId < 0) {
- Log.d(TAG, "onSimStateChanged() - slotId invalid: " + slotId
- + " mTelephonyCapable: " + Boolean.toString(mTelephonyCapable));
- return;
- }
+ private CarrierTextController.CarrierTextCallback mCarrierTextCallback =
+ new CarrierTextController.CarrierTextCallback() {
+ @Override
+ public void updateCarrierText(CharSequence carrierText, boolean simsReady) {
+ setText(carrierText);
+ }
- if (DEBUG) Log.d(TAG,"onSimStateChanged: " + getStatusForIccState(simState));
- if (getStatusForIccState(simState) == StatusMode.SimIoError) {
- mSimErrorState[slotId] = true;
- updateCarrierText();
- } else if (mSimErrorState[slotId]) {
- mSimErrorState[slotId] = false;
- updateCarrierText();
- }
- }
- };
+ @Override
+ public void startedGoingToSleep() {
+ setSelected(false);
+ }
- /**
- * The status of this lock screen. Primarily used for widgets on LockScreen.
- */
- private static enum StatusMode {
- Normal, // Normal case (sim card present, it's not locked)
- NetworkLocked, // SIM card is 'network locked'.
- SimMissing, // SIM card is missing.
- SimMissingLocked, // SIM card is missing, and device isn't provisioned; don't allow access
- SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times
- SimLocked, // SIM card is currently locked
- SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
- SimNotReady, // SIM is not ready yet. May never be on devices w/o a SIM.
- SimIoError, // SIM card is faulty
- SimUnknown // SIM card is unknown
- }
+ @Override
+ public void finishedWakingUp() {
+ setSelected(mShouldMarquee);
+ }
+ };
public CarrierText(Context context) {
this(context, null);
@@ -125,8 +63,6 @@ public class CarrierText extends TextView {
public CarrierText(Context context, AttributeSet attrs) {
super(context, attrs);
- mIsEmergencyCallCapable = context.getResources().getBoolean(
- com.android.internal.R.bool.config_voice_capable);
boolean useAllCaps;
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs, R.styleable.CarrierText, 0, 0);
@@ -138,132 +74,6 @@ public class CarrierText extends TextView {
a.recycle();
}
setTransformationMethod(new CarrierTextTransformationMethod(mContext, useAllCaps));
-
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
- }
-
- /**
- * Checks if there are faulty cards. Adds the text depending on the slot of the card
- * @param text: current carrier text based on the sim state
- * @param noSims: whether a valid sim card is inserted
- * @return text
- */
- private CharSequence updateCarrierTextWithSimIoError(CharSequence text, boolean noSims) {
- final CharSequence carrier = "";
- CharSequence carrierTextForSimIOError = getCarrierTextForSimState(
- IccCardConstants.State.CARD_IO_ERROR, carrier);
- for (int index = 0; index < mSimErrorState.length; index++) {
- if (mSimErrorState[index]) {
- // In the case when no sim cards are detected but a faulty card is inserted
- // overwrite the text and only show "Invalid card"
- if (noSims) {
- return concatenate(carrierTextForSimIOError,
- getContext().getText(com.android.internal.R.string.emergency_calls_only));
- } else if (index == 0) {
- // prepend "Invalid card" when faulty card is inserted in slot 0
- text = concatenate(carrierTextForSimIOError, text);
- } else {
- // concatenate "Invalid card" when faulty card is inserted in slot 1
- text = concatenate(text, carrierTextForSimIOError);
- }
- }
- }
- return text;
- }
-
- protected void updateCarrierText() {
- boolean allSimsMissing = true;
- boolean anySimReadyAndInService = false;
- CharSequence displayText = null;
-
- List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
- final int N = subs.size();
- if (DEBUG) Log.d(TAG, "updateCarrierText(): " + N);
- for (int i = 0; i < N; i++) {
- int subId = subs.get(i).getSubscriptionId();
- State simState = mKeyguardUpdateMonitor.getSimState(subId);
- CharSequence carrierName = subs.get(i).getCarrierName();
- CharSequence carrierTextForSimState = getCarrierTextForSimState(simState, carrierName);
- if (DEBUG) {
- Log.d(TAG, "Handling (subId=" + subId + "): " + simState + " " + carrierName);
- }
- if (carrierTextForSimState != null) {
- allSimsMissing = false;
- displayText = concatenate(displayText, carrierTextForSimState);
- }
- if (simState == IccCardConstants.State.READY) {
- ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId);
- if (ss != null && ss.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
- // hack for WFC (IWLAN) not turning off immediately once
- // Wi-Fi is disassociated or disabled
- if (ss.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
- || (mWifiManager.isWifiEnabled()
- && mWifiManager.getConnectionInfo() != null
- && mWifiManager.getConnectionInfo().getBSSID() != null)) {
- if (DEBUG) {
- Log.d(TAG, "SIM ready and in service: subId=" + subId + ", ss=" + ss);
- }
- anySimReadyAndInService = true;
- }
- }
- }
- }
- if (allSimsMissing) {
- if (N != 0) {
- // Shows "No SIM card | Emergency calls only" on devices that are voice-capable.
- // This depends on mPlmn containing the text "Emergency calls only" when the radio
- // has some connectivity. Otherwise, it should be null or empty and just show
- // "No SIM card"
- // Grab the first subscripton, because they all should contain the emergency text,
- // described above.
- displayText = makeCarrierStringOnEmergencyCapable(
- getMissingSimMessage(), subs.get(0).getCarrierName());
- } else {
- // We don't have a SubscriptionInfo to get the emergency calls only from.
- // Grab it from the old sticky broadcast if possible instead. We can use it
- // here because no subscriptions are active, so we don't have
- // to worry about MSIM clashing.
- CharSequence text =
- getContext().getText(com.android.internal.R.string.emergency_calls_only);
- Intent i = getContext().registerReceiver(null,
- new IntentFilter(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION));
- if (i != null) {
- String spn = "";
- String plmn = "";
- if (i.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
- spn = i.getStringExtra(TelephonyIntents.EXTRA_SPN);
- }
- if (i.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
- plmn = i.getStringExtra(TelephonyIntents.EXTRA_PLMN);
- }
- if (DEBUG) Log.d(TAG, "Getting plmn/spn sticky brdcst " + plmn + "/" + spn);
- if (Objects.equals(plmn, spn)) {
- text = plmn;
- } else {
- text = concatenate(plmn, spn);
- }
- }
- displayText = makeCarrierStringOnEmergencyCapable(getMissingSimMessage(), text);
- }
- }
-
- displayText = updateCarrierTextWithSimIoError(displayText, allSimsMissing);
- // APM (airplane mode) != no carrier state. There are carrier services
- // (e.g. WFC = Wi-Fi calling) which may operate in APM.
- if (!anySimReadyAndInService && WirelessUtils.isAirplaneModeOn(mContext)) {
- displayText = getAirplaneModeMessage();
- }
- setText(displayText);
- }
-
- private String getMissingSimMessage() {
- return mShowMissingSim && mTelephonyCapable
- ? getContext().getString(R.string.keyguard_missing_sim_message_short) : "";
- }
-
- private String getAirplaneModeMessage() {
- return mShowAirplaneMode
- ? getContext().getString(R.string.airplane_mode) : "";
}
@Override
@@ -271,36 +81,28 @@ public class CarrierText extends TextView {
super.onFinishInflate();
mSeparator = getResources().getString(
com.android.internal.R.string.kg_text_message_separator);
- boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
- setSelected(shouldMarquee); // Allow marquee to work.
+ mCarrierTextController = new CarrierTextController(mContext, mSeparator, mShowAirplaneMode,
+ mShowMissingSim);
+ mShouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
+ setSelected(mShouldMarquee); // Allow marquee to work.
+
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- if (ConnectivityManager.from(mContext).isNetworkSupported(
- ConnectivityManager.TYPE_MOBILE)) {
- mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
- mKeyguardUpdateMonitor.registerCallback(mCallback);
- } else {
- // Don't listen and clear out the text when the device isn't a phone.
- mKeyguardUpdateMonitor = null;
- setText("");
- }
+ mCarrierTextController.setListening(mCarrierTextCallback);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- if (mKeyguardUpdateMonitor != null) {
- mKeyguardUpdateMonitor.removeCallback(mCallback);
- }
+ mCarrierTextController.setListening(null);
}
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
-
// Only show marquee when visible
if (visibility == VISIBLE) {
setEllipsize(TextUtils.TruncateAt.MARQUEE);
@@ -309,167 +111,6 @@ public class CarrierText extends TextView {
}
}
- /**
- * Top-level function for creating carrier text. Makes text based on simState, PLMN
- * and SPN as well as device capabilities, such as being emergency call capable.
- *
- * @param simState
- * @param text
- * @param spn
- * @return Carrier text if not in missing state, null otherwise.
- */
- private CharSequence getCarrierTextForSimState(IccCardConstants.State simState,
- CharSequence text) {
- CharSequence carrierText = null;
- StatusMode status = getStatusForIccState(simState);
- switch (status) {
- case Normal:
- carrierText = text;
- break;
-
- case SimNotReady:
- // Null is reserved for denoting missing, in this case we have nothing to display.
- carrierText = ""; // nothing to display yet.
- break;
-
- case NetworkLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
- mContext.getText(R.string.keyguard_network_locked_message), text);
- break;
-
- case SimMissing:
- carrierText = null;
- break;
-
- case SimPermDisabled:
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(
- R.string.keyguard_permanent_disabled_sim_message_short),
- text);
- break;
-
- case SimMissingLocked:
- carrierText = null;
- break;
-
- case SimLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.keyguard_sim_locked_message),
- text);
- break;
-
- case SimPukLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.keyguard_sim_puk_locked_message),
- text);
- break;
- case SimIoError:
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.keyguard_sim_error_message_short),
- text);
- break;
- case SimUnknown:
- carrierText = null;
- break;
- }
-
- return carrierText;
- }
-
- /*
- * Add emergencyCallMessage to carrier string only if phone supports emergency calls.
- */
- private CharSequence makeCarrierStringOnEmergencyCapable(
- CharSequence simMessage, CharSequence emergencyCallMessage) {
- if (mIsEmergencyCallCapable) {
- return concatenate(simMessage, emergencyCallMessage);
- }
- return simMessage;
- }
-
- /**
- * Determine the current status of the lock screen given the SIM state and other stuff.
- */
- private StatusMode getStatusForIccState(IccCardConstants.State simState) {
- // Since reading the SIM may take a while, we assume it is present until told otherwise.
- if (simState == null) {
- return StatusMode.Normal;
- }
-
- final boolean missingAndNotProvisioned =
- !KeyguardUpdateMonitor.getInstance(mContext).isDeviceProvisioned()
- && (simState == IccCardConstants.State.ABSENT ||
- simState == IccCardConstants.State.PERM_DISABLED);
-
- // Assume we're NETWORK_LOCKED if not provisioned
- simState = missingAndNotProvisioned ? IccCardConstants.State.NETWORK_LOCKED : simState;
- switch (simState) {
- case ABSENT:
- return StatusMode.SimMissing;
- case NETWORK_LOCKED:
- return StatusMode.SimMissingLocked;
- case NOT_READY:
- return StatusMode.SimNotReady;
- case PIN_REQUIRED:
- return StatusMode.SimLocked;
- case PUK_REQUIRED:
- return StatusMode.SimPukLocked;
- case READY:
- return StatusMode.Normal;
- case PERM_DISABLED:
- return StatusMode.SimPermDisabled;
- case UNKNOWN:
- return StatusMode.SimUnknown;
- case CARD_IO_ERROR:
- return StatusMode.SimIoError;
- }
- return StatusMode.SimUnknown;
- }
-
- private static CharSequence concatenate(CharSequence plmn, CharSequence spn) {
- final boolean plmnValid = !TextUtils.isEmpty(plmn);
- final boolean spnValid = !TextUtils.isEmpty(spn);
- if (plmnValid && spnValid) {
- return new StringBuilder().append(plmn).append(mSeparator).append(spn).toString();
- } else if (plmnValid) {
- return plmn;
- } else if (spnValid) {
- return spn;
- } else {
- return "";
- }
- }
-
- private CharSequence getCarrierHelpTextForSimState(IccCardConstants.State simState,
- String plmn, String spn) {
- int carrierHelpTextId = 0;
- StatusMode status = getStatusForIccState(simState);
- switch (status) {
- case NetworkLocked:
- carrierHelpTextId = R.string.keyguard_instructions_when_pattern_disabled;
- break;
-
- case SimMissing:
- carrierHelpTextId = R.string.keyguard_missing_sim_instructions_long;
- break;
-
- case SimPermDisabled:
- carrierHelpTextId = R.string.keyguard_permanent_disabled_sim_instructions;
- break;
-
- case SimMissingLocked:
- carrierHelpTextId = R.string.keyguard_missing_sim_instructions;
- break;
-
- case Normal:
- case SimLocked:
- case SimPukLocked:
- break;
- }
-
- return mContext.getText(carrierHelpTextId);
- }
-
private class CarrierTextTransformationMethod extends SingleLineTransformationMethod {
private final Locale mLocale;
private final boolean mAllCaps;
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
new file mode 100644
index 000000000000..3698a6e6a776
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -0,0 +1,512 @@
+/*
+ * 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.
+ */
+
+package com.android.keyguard;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiManager;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.settingslib.WirelessUtils;
+import com.android.systemui.Dependency;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Controller that generates text including the carrier names and/or the status of all the SIM
+ * interfaces in the device. Through a callback, the updates can be retrieved either as a list or
+ * separated by a given separator {@link CharSequence}.
+ */
+public class CarrierTextController {
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
+ private static final String TAG = "CarrierTextController";
+
+ private final boolean mIsEmergencyCallCapable;
+
+ private boolean mTelephonyCapable;
+
+ private boolean mShowMissingSim;
+
+ private boolean mShowAirplaneMode;
+
+ private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
+ private WifiManager mWifiManager;
+
+ private boolean[] mSimErrorState = new boolean[TelephonyManager.getDefault().getPhoneCount()];
+ private CarrierTextCallback mCarrierTextCallback;
+ private Context mContext;
+ private CharSequence mSeparator;
+ private WakefulnessLifecycle mWakefulnessLifecycle;
+ private final WakefulnessLifecycle.Observer mWakefulnessObserver =
+ new WakefulnessLifecycle.Observer() {
+ @Override
+ public void onFinishedWakingUp() {
+ mCarrierTextCallback.finishedWakingUp();
+ }
+
+ @Override
+ public void onStartedGoingToSleep() {
+ mCarrierTextCallback.startedGoingToSleep();
+ }
+ };
+
+ private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onRefreshCarrierInfo() {
+ if (DEBUG) {
+ Log.d(TAG, "onRefreshCarrierInfo(), mTelephonyCapable: "
+ + Boolean.toString(mTelephonyCapable));
+ }
+ updateCarrierText();
+ }
+
+ @Override
+ public void onTelephonyCapable(boolean capable) {
+ if (DEBUG) {
+ Log.d(TAG, "onTelephonyCapable() mTelephonyCapable: "
+ + Boolean.toString(capable));
+ }
+ mTelephonyCapable = capable;
+ updateCarrierText();
+ }
+
+ public void onSimStateChanged(int subId, int slotId, IccCardConstants.State simState) {
+ if (slotId < 0) {
+ Log.d(TAG, "onSimStateChanged() - slotId invalid: " + slotId
+ + " mTelephonyCapable: " + Boolean.toString(mTelephonyCapable));
+ return;
+ }
+
+ if (DEBUG) Log.d(TAG, "onSimStateChanged: " + getStatusForIccState(simState));
+ if (getStatusForIccState(simState) == CarrierTextController.StatusMode.SimIoError) {
+ mSimErrorState[slotId] = true;
+ updateCarrierText();
+ } else if (mSimErrorState[slotId]) {
+ mSimErrorState[slotId] = false;
+ updateCarrierText();
+ }
+ }
+ };
+
+ /**
+ * The status of this lock screen. Primarily used for widgets on LockScreen.
+ */
+ private enum StatusMode {
+ Normal, // Normal case (sim card present, it's not locked)
+ NetworkLocked, // SIM card is 'network locked'.
+ SimMissing, // SIM card is missing.
+ SimMissingLocked, // SIM card is missing, and device isn't provisioned; don't allow access
+ SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times
+ SimLocked, // SIM card is currently locked
+ SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
+ SimNotReady, // SIM is not ready yet. May never be on devices w/o a SIM.
+ SimIoError, // SIM card is faulty
+ SimUnknown // SIM card is unknown
+ }
+
+ /**
+ * Controller that provides updates on text with carriers names or SIM status.
+ * Used by {@link CarrierText}.
+ * @param context
+ * @param separator Separator between different parts of the text
+ * @param showAirplaneMode
+ * @param showMissingSim
+ */
+ public CarrierTextController(Context context, CharSequence separator, boolean showAirplaneMode,
+ boolean showMissingSim) {
+ mContext = context;
+ mIsEmergencyCallCapable = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_voice_capable);
+
+ mShowAirplaneMode = showAirplaneMode;
+ mShowMissingSim = showMissingSim;
+
+ mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mSeparator = separator;
+ mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
+ }
+
+ /**
+ * Checks if there are faulty cards. Adds the text depending on the slot of the card
+ *
+ * @param text: current carrier text based on the sim state
+ * @param noSims: whether a valid sim card is inserted
+ * @return text
+ */
+ private CharSequence updateCarrierTextWithSimIoError(CharSequence text, boolean noSims) {
+ final CharSequence carrier = "";
+ CharSequence carrierTextForSimIOError = getCarrierTextForSimState(
+ IccCardConstants.State.CARD_IO_ERROR, carrier);
+ for (int index = 0; index < mSimErrorState.length; index++) {
+ if (mSimErrorState[index]) {
+ // In the case when no sim cards are detected but a faulty card is inserted
+ // overwrite the text and only show "Invalid card"
+ if (noSims) {
+ return concatenate(carrierTextForSimIOError,
+ getContext().getText(
+ com.android.internal.R.string.emergency_calls_only),
+ mSeparator);
+ } else if (index == 0) {
+ // prepend "Invalid card" when faulty card is inserted in slot 0
+ text = concatenate(carrierTextForSimIOError, text, mSeparator);
+ } else {
+ // concatenate "Invalid card" when faulty card is inserted in slot 1
+ text = concatenate(text, carrierTextForSimIOError, mSeparator);
+ }
+ }
+ }
+ return text;
+ }
+
+ /**
+ * Sets the listening status of this controller. If the callback is null, it is set to
+ * not listening
+ * @param callback Callback to provide text updates
+ */
+ public void setListening(CarrierTextCallback callback) {
+ if (callback != null) {
+ mCarrierTextCallback = callback;
+ if (ConnectivityManager.from(mContext).isNetworkSupported(
+ ConnectivityManager.TYPE_MOBILE)) {
+ mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+ mKeyguardUpdateMonitor.registerCallback(mCallback);
+ mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
+ } else {
+ // Don't listen and clear out the text when the device isn't a phone.
+ mKeyguardUpdateMonitor = null;
+ callback.updateCarrierText("", false);
+ }
+ } else {
+ mCarrierTextCallback = null;
+ if (mKeyguardUpdateMonitor != null) {
+ mKeyguardUpdateMonitor.removeCallback(mCallback);
+ mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
+ }
+ }
+ }
+
+ protected void updateCarrierText() {
+ boolean allSimsMissing = true;
+ boolean anySimReadyAndInService = false;
+ CharSequence displayText = null;
+
+ List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
+ final int numSubs = subs.size();
+ if (DEBUG) Log.d(TAG, "updateCarrierText(): " + numSubs);
+ for (int i = 0; i < numSubs; i++) {
+ int subId = subs.get(i).getSubscriptionId();
+ IccCardConstants.State simState = mKeyguardUpdateMonitor.getSimState(subId);
+ CharSequence carrierName = subs.get(i).getCarrierName();
+ CharSequence carrierTextForSimState = getCarrierTextForSimState(simState, carrierName);
+ if (DEBUG) {
+ Log.d(TAG, "Handling (subId=" + subId + "): " + simState + " " + carrierName);
+ }
+ if (carrierTextForSimState != null) {
+ allSimsMissing = false;
+ displayText = concatenate(displayText, carrierTextForSimState, mSeparator);
+ }
+ if (simState == IccCardConstants.State.READY) {
+ ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId);
+ if (ss != null && ss.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
+ // hack for WFC (IWLAN) not turning off immediately once
+ // Wi-Fi is disassociated or disabled
+ if (ss.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
+ || (mWifiManager.isWifiEnabled()
+ && mWifiManager.getConnectionInfo() != null
+ && mWifiManager.getConnectionInfo().getBSSID() != null)) {
+ if (DEBUG) {
+ Log.d(TAG, "SIM ready and in service: subId=" + subId + ", ss=" + ss);
+ }
+ anySimReadyAndInService = true;
+ }
+ }
+ }
+ }
+ if (allSimsMissing) {
+ if (numSubs != 0) {
+ // Shows "No SIM card | Emergency calls only" on devices that are voice-capable.
+ // This depends on mPlmn containing the text "Emergency calls only" when the radio
+ // has some connectivity. Otherwise, it should be null or empty and just show
+ // "No SIM card"
+ // Grab the first subscripton, because they all should contain the emergency text,
+ // described above.
+ displayText = makeCarrierStringOnEmergencyCapable(
+ getMissingSimMessage(), subs.get(0).getCarrierName());
+ } else {
+ // We don't have a SubscriptionInfo to get the emergency calls only from.
+ // Grab it from the old sticky broadcast if possible instead. We can use it
+ // here because no subscriptions are active, so we don't have
+ // to worry about MSIM clashing.
+ CharSequence text =
+ getContext().getText(com.android.internal.R.string.emergency_calls_only);
+ Intent i = getContext().registerReceiver(null,
+ new IntentFilter(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION));
+ if (i != null) {
+ String spn = "";
+ String plmn = "";
+ if (i.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
+ spn = i.getStringExtra(TelephonyIntents.EXTRA_SPN);
+ }
+ if (i.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
+ plmn = i.getStringExtra(TelephonyIntents.EXTRA_PLMN);
+ }
+ if (DEBUG) Log.d(TAG, "Getting plmn/spn sticky brdcst " + plmn + "/" + spn);
+ if (Objects.equals(plmn, spn)) {
+ text = plmn;
+ } else {
+ text = concatenate(plmn, spn, mSeparator);
+ }
+ }
+ displayText = makeCarrierStringOnEmergencyCapable(getMissingSimMessage(), text);
+ }
+ }
+
+ displayText = updateCarrierTextWithSimIoError(displayText, allSimsMissing);
+ // APM (airplane mode) != no carrier state. There are carrier services
+ // (e.g. WFC = Wi-Fi calling) which may operate in APM.
+ if (!anySimReadyAndInService && WirelessUtils.isAirplaneModeOn(mContext)) {
+ displayText = getAirplaneModeMessage();
+ }
+
+ if (mCarrierTextCallback != null) {
+ mCarrierTextCallback.updateCarrierText(displayText, anySimReadyAndInService);
+ mCarrierTextCallback.updateCarrierList(
+ displayText.toString().split(mSeparator.toString()), anySimReadyAndInService);
+ }
+
+ }
+
+ private Context getContext() {
+ return mContext;
+ }
+
+ private String getMissingSimMessage() {
+ return mShowMissingSim && mTelephonyCapable
+ ? getContext().getString(R.string.keyguard_missing_sim_message_short) : "";
+ }
+
+ private String getAirplaneModeMessage() {
+ return mShowAirplaneMode
+ ? getContext().getString(R.string.airplane_mode) : "";
+ }
+
+ /**
+ * Top-level function for creating carrier text. Makes text based on simState, PLMN
+ * and SPN as well as device capabilities, such as being emergency call capable.
+ *
+ * @return Carrier text if not in missing state, null otherwise.
+ */
+ private CharSequence getCarrierTextForSimState(IccCardConstants.State simState,
+ CharSequence text) {
+ CharSequence carrierText = null;
+ CarrierTextController.StatusMode status = getStatusForIccState(simState);
+ switch (status) {
+ case Normal:
+ carrierText = text;
+ break;
+
+ case SimNotReady:
+ // Null is reserved for denoting missing, in this case we have nothing to display.
+ carrierText = ""; // nothing to display yet.
+ break;
+
+ case NetworkLocked:
+ carrierText = makeCarrierStringOnEmergencyCapable(
+ mContext.getText(R.string.keyguard_network_locked_message), text);
+ break;
+
+ case SimMissing:
+ carrierText = null;
+ break;
+
+ case SimPermDisabled:
+ carrierText = makeCarrierStringOnEmergencyCapable(
+ getContext().getText(
+ R.string.keyguard_permanent_disabled_sim_message_short),
+ text);
+ break;
+
+ case SimMissingLocked:
+ carrierText = null;
+ break;
+
+ case SimLocked:
+ carrierText = makeCarrierStringOnEmergencyCapable(
+ getContext().getText(R.string.keyguard_sim_locked_message),
+ text);
+ break;
+
+ case SimPukLocked:
+ carrierText = makeCarrierStringOnEmergencyCapable(
+ getContext().getText(R.string.keyguard_sim_puk_locked_message),
+ text);
+ break;
+ case SimIoError:
+ carrierText = makeCarrierStringOnEmergencyCapable(
+ getContext().getText(R.string.keyguard_sim_error_message_short),
+ text);
+ break;
+ case SimUnknown:
+ carrierText = null;
+ break;
+ }
+
+ return carrierText;
+ }
+
+ /*
+ * Add emergencyCallMessage to carrier string only if phone supports emergency calls.
+ */
+ private CharSequence makeCarrierStringOnEmergencyCapable(
+ CharSequence simMessage, CharSequence emergencyCallMessage) {
+ if (mIsEmergencyCallCapable) {
+ return concatenate(simMessage, emergencyCallMessage, mSeparator);
+ }
+ return simMessage;
+ }
+
+ /**
+ * Determine the current status of the lock screen given the SIM state and other stuff.
+ */
+ private CarrierTextController.StatusMode getStatusForIccState(IccCardConstants.State simState) {
+ // Since reading the SIM may take a while, we assume it is present until told otherwise.
+ if (simState == null) {
+ return CarrierTextController.StatusMode.Normal;
+ }
+
+ final boolean missingAndNotProvisioned =
+ !KeyguardUpdateMonitor.getInstance(mContext).isDeviceProvisioned()
+ && (simState == IccCardConstants.State.ABSENT
+ || simState == IccCardConstants.State.PERM_DISABLED);
+
+ // Assume we're NETWORK_LOCKED if not provisioned
+ simState = missingAndNotProvisioned ? IccCardConstants.State.NETWORK_LOCKED : simState;
+ switch (simState) {
+ case ABSENT:
+ return CarrierTextController.StatusMode.SimMissing;
+ case NETWORK_LOCKED:
+ return CarrierTextController.StatusMode.SimMissingLocked;
+ case NOT_READY:
+ return CarrierTextController.StatusMode.SimNotReady;
+ case PIN_REQUIRED:
+ return CarrierTextController.StatusMode.SimLocked;
+ case PUK_REQUIRED:
+ return CarrierTextController.StatusMode.SimPukLocked;
+ case READY:
+ return CarrierTextController.StatusMode.Normal;
+ case PERM_DISABLED:
+ return CarrierTextController.StatusMode.SimPermDisabled;
+ case UNKNOWN:
+ return CarrierTextController.StatusMode.SimUnknown;
+ case CARD_IO_ERROR:
+ return CarrierTextController.StatusMode.SimIoError;
+ }
+ return CarrierTextController.StatusMode.SimUnknown;
+ }
+
+ private static CharSequence concatenate(CharSequence plmn, CharSequence spn,
+ CharSequence separator) {
+ final boolean plmnValid = !TextUtils.isEmpty(plmn);
+ final boolean spnValid = !TextUtils.isEmpty(spn);
+ if (plmnValid && spnValid) {
+ return new StringBuilder().append(plmn).append(separator).append(spn).toString();
+ } else if (plmnValid) {
+ return plmn;
+ } else if (spnValid) {
+ return spn;
+ } else {
+ return "";
+ }
+ }
+
+ private static List<CharSequence> append(List<CharSequence> list, CharSequence string) {
+ if (!TextUtils.isEmpty(string)) {
+ list.add(string);
+ }
+ return list;
+ }
+
+ private CharSequence getCarrierHelpTextForSimState(IccCardConstants.State simState,
+ String plmn, String spn) {
+ int carrierHelpTextId = 0;
+ CarrierTextController.StatusMode status = getStatusForIccState(simState);
+ switch (status) {
+ case NetworkLocked:
+ carrierHelpTextId = R.string.keyguard_instructions_when_pattern_disabled;
+ break;
+
+ case SimMissing:
+ carrierHelpTextId = R.string.keyguard_missing_sim_instructions_long;
+ break;
+
+ case SimPermDisabled:
+ carrierHelpTextId = R.string.keyguard_permanent_disabled_sim_instructions;
+ break;
+
+ case SimMissingLocked:
+ carrierHelpTextId = R.string.keyguard_missing_sim_instructions;
+ break;
+
+ case Normal:
+ case SimLocked:
+ case SimPukLocked:
+ break;
+ }
+
+ return mContext.getText(carrierHelpTextId);
+ }
+
+ /**
+ * Callback to communicate to Views
+ */
+ public interface CarrierTextCallback {
+ /**
+ * Provides an updated list of carrier names
+ * @param listOfCarriers
+ * @param simsReady Whether at least one SIM is ready and with service
+ */
+ default void updateCarrierList(CharSequence[] listOfCarriers, boolean simsReady) {};
+
+ /**
+ * Provides an updated full carrier text
+ * @param carrierText
+ * @param simsReady Whether at least one SIM is ready and with service
+ */
+ default void updateCarrierText(CharSequence carrierText, boolean simsReady) {};
+
+ /**
+ * Notifies the View that the device is going to sleep
+ */
+ default void startedGoingToSleep() {};
+
+ /**
+ * Notifies the View that the device finished waking up
+ */
+ default void finishedWakingUp() {};
+ }
+}