blob: baaa3fdb16baecde855410c964635479f8d37e52 [file] [log] [blame]
Fabian Kozynski02941af2019-01-17 17:57:37 -05001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.keyguard;
18
19import android.content.Context;
20import android.content.Intent;
21import android.content.IntentFilter;
22import android.net.ConnectivityManager;
23import android.net.wifi.WifiManager;
Fabian Kozynskibf6fef32019-02-04 09:21:38 -050024import android.os.Handler;
Fabian Kozynski02941af2019-01-17 17:57:37 -050025import android.telephony.ServiceState;
26import android.telephony.SubscriptionInfo;
27import android.telephony.TelephonyManager;
28import android.text.TextUtils;
29import android.util.Log;
30
Fabian Kozynskibf6fef32019-02-04 09:21:38 -050031import androidx.annotation.VisibleForTesting;
32
Fabian Kozynski02941af2019-01-17 17:57:37 -050033import com.android.internal.telephony.IccCardConstants;
34import com.android.internal.telephony.TelephonyIntents;
35import com.android.settingslib.WirelessUtils;
36import com.android.systemui.Dependency;
37import com.android.systemui.keyguard.WakefulnessLifecycle;
38
39import java.util.List;
40import java.util.Objects;
41
42/**
43 * Controller that generates text including the carrier names and/or the status of all the SIM
44 * interfaces in the device. Through a callback, the updates can be retrieved either as a list or
45 * separated by a given separator {@link CharSequence}.
46 */
47public class CarrierTextController {
48 private static final boolean DEBUG = KeyguardConstants.DEBUG;
49 private static final String TAG = "CarrierTextController";
50
51 private final boolean mIsEmergencyCallCapable;
Fabian Kozynski02941af2019-01-17 17:57:37 -050052 private boolean mTelephonyCapable;
Fabian Kozynski02941af2019-01-17 17:57:37 -050053 private boolean mShowMissingSim;
Fabian Kozynski02941af2019-01-17 17:57:37 -050054 private boolean mShowAirplaneMode;
Fabian Kozynskib176f422019-02-05 09:36:59 -050055 @VisibleForTesting
56 protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
Fabian Kozynski02941af2019-01-17 17:57:37 -050057 private WifiManager mWifiManager;
Fabian Kozynskib176f422019-02-05 09:36:59 -050058 private boolean[] mSimErrorState;
59 private final int mSimSlotsNumber;
Fabian Kozynski02941af2019-01-17 17:57:37 -050060 private CarrierTextCallback mCarrierTextCallback;
61 private Context mContext;
62 private CharSequence mSeparator;
63 private WakefulnessLifecycle mWakefulnessLifecycle;
64 private final WakefulnessLifecycle.Observer mWakefulnessObserver =
65 new WakefulnessLifecycle.Observer() {
66 @Override
67 public void onFinishedWakingUp() {
68 mCarrierTextCallback.finishedWakingUp();
69 }
70
71 @Override
72 public void onStartedGoingToSleep() {
73 mCarrierTextCallback.startedGoingToSleep();
74 }
75 };
76
Fabian Kozynskib176f422019-02-05 09:36:59 -050077 @VisibleForTesting
78 protected final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
Fabian Kozynski02941af2019-01-17 17:57:37 -050079 @Override
80 public void onRefreshCarrierInfo() {
81 if (DEBUG) {
82 Log.d(TAG, "onRefreshCarrierInfo(), mTelephonyCapable: "
83 + Boolean.toString(mTelephonyCapable));
84 }
85 updateCarrierText();
86 }
87
88 @Override
89 public void onTelephonyCapable(boolean capable) {
90 if (DEBUG) {
91 Log.d(TAG, "onTelephonyCapable() mTelephonyCapable: "
92 + Boolean.toString(capable));
93 }
94 mTelephonyCapable = capable;
95 updateCarrierText();
96 }
97
98 public void onSimStateChanged(int subId, int slotId, IccCardConstants.State simState) {
Fabian Kozynskib176f422019-02-05 09:36:59 -050099 if (slotId < 0 || slotId >= mSimSlotsNumber) {
Fabian Kozynski02941af2019-01-17 17:57:37 -0500100 Log.d(TAG, "onSimStateChanged() - slotId invalid: " + slotId
101 + " mTelephonyCapable: " + Boolean.toString(mTelephonyCapable));
102 return;
103 }
104
105 if (DEBUG) Log.d(TAG, "onSimStateChanged: " + getStatusForIccState(simState));
106 if (getStatusForIccState(simState) == CarrierTextController.StatusMode.SimIoError) {
107 mSimErrorState[slotId] = true;
108 updateCarrierText();
109 } else if (mSimErrorState[slotId]) {
110 mSimErrorState[slotId] = false;
111 updateCarrierText();
112 }
113 }
114 };
115
116 /**
117 * The status of this lock screen. Primarily used for widgets on LockScreen.
118 */
119 private enum StatusMode {
120 Normal, // Normal case (sim card present, it's not locked)
121 NetworkLocked, // SIM card is 'network locked'.
122 SimMissing, // SIM card is missing.
123 SimMissingLocked, // SIM card is missing, and device isn't provisioned; don't allow access
124 SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times
125 SimLocked, // SIM card is currently locked
126 SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
127 SimNotReady, // SIM is not ready yet. May never be on devices w/o a SIM.
128 SimIoError, // SIM card is faulty
129 SimUnknown // SIM card is unknown
130 }
131
132 /**
133 * Controller that provides updates on text with carriers names or SIM status.
134 * Used by {@link CarrierText}.
Fabian Kozynski1823f112019-01-18 11:43:29 -0500135 *
Fabian Kozynski02941af2019-01-17 17:57:37 -0500136 * @param separator Separator between different parts of the text
Fabian Kozynski02941af2019-01-17 17:57:37 -0500137 */
138 public CarrierTextController(Context context, CharSequence separator, boolean showAirplaneMode,
139 boolean showMissingSim) {
140 mContext = context;
141 mIsEmergencyCallCapable = context.getResources().getBoolean(
142 com.android.internal.R.bool.config_voice_capable);
143
144 mShowAirplaneMode = showAirplaneMode;
145 mShowMissingSim = showMissingSim;
146
147 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
148 mSeparator = separator;
149 mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
Fabian Kozynskib176f422019-02-05 09:36:59 -0500150 mSimSlotsNumber = ((TelephonyManager) context.getSystemService(
151 Context.TELEPHONY_SERVICE)).getPhoneCount();
152 mSimErrorState = new boolean[mSimSlotsNumber];
Fabian Kozynski02941af2019-01-17 17:57:37 -0500153 }
154
155 /**
156 * Checks if there are faulty cards. Adds the text depending on the slot of the card
157 *
158 * @param text: current carrier text based on the sim state
Fabian Kozynskib176f422019-02-05 09:36:59 -0500159 * @param carrierNames names order by subscription order
160 * @param subOrderBySlot array containing the sub index for each slot ID
Fabian Kozynski02941af2019-01-17 17:57:37 -0500161 * @param noSims: whether a valid sim card is inserted
162 * @return text
163 */
Fabian Kozynskib176f422019-02-05 09:36:59 -0500164 private CharSequence updateCarrierTextWithSimIoError(CharSequence text,
165 CharSequence[] carrierNames, int[] subOrderBySlot, boolean noSims) {
Fabian Kozynski02941af2019-01-17 17:57:37 -0500166 final CharSequence carrier = "";
167 CharSequence carrierTextForSimIOError = getCarrierTextForSimState(
168 IccCardConstants.State.CARD_IO_ERROR, carrier);
Fabian Kozynskib176f422019-02-05 09:36:59 -0500169 // mSimErrorState has the state of each sim indexed by slotID.
Fabian Kozynski02941af2019-01-17 17:57:37 -0500170 for (int index = 0; index < mSimErrorState.length; index++) {
Fabian Kozynskib176f422019-02-05 09:36:59 -0500171 if (!mSimErrorState[index]) {
172 continue;
Fabian Kozynski02941af2019-01-17 17:57:37 -0500173 }
Fabian Kozynskib176f422019-02-05 09:36:59 -0500174 // In the case when no sim cards are detected but a faulty card is inserted
175 // overwrite the text and only show "Invalid card"
176 if (noSims) {
177 return concatenate(carrierTextForSimIOError,
178 getContext().getText(
179 com.android.internal.R.string.emergency_calls_only),
180 mSeparator);
181 } else if (subOrderBySlot[index] != -1) {
182 int subIndex = subOrderBySlot[index];
183 // prepend "Invalid card" when faulty card is inserted in slot 0 or 1
184 carrierNames[subIndex] = concatenate(carrierTextForSimIOError,
185 carrierNames[subIndex],
186 mSeparator);
187 } else {
188 // concatenate "Invalid card" when faulty card is inserted in other slot
189 text = concatenate(text, carrierTextForSimIOError, mSeparator);
190 }
191
Fabian Kozynski02941af2019-01-17 17:57:37 -0500192 }
193 return text;
194 }
195
196 /**
197 * Sets the listening status of this controller. If the callback is null, it is set to
198 * not listening
Fabian Kozynski1823f112019-01-18 11:43:29 -0500199 *
Fabian Kozynski02941af2019-01-17 17:57:37 -0500200 * @param callback Callback to provide text updates
201 */
202 public void setListening(CarrierTextCallback callback) {
203 if (callback != null) {
204 mCarrierTextCallback = callback;
205 if (ConnectivityManager.from(mContext).isNetworkSupported(
206 ConnectivityManager.TYPE_MOBILE)) {
207 mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
208 mKeyguardUpdateMonitor.registerCallback(mCallback);
209 mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
210 } else {
211 // Don't listen and clear out the text when the device isn't a phone.
212 mKeyguardUpdateMonitor = null;
Fabian Kozynski1823f112019-01-18 11:43:29 -0500213 callback.updateCarrierInfo(new CarrierTextCallbackInfo("", null, false, null));
Fabian Kozynski02941af2019-01-17 17:57:37 -0500214 }
215 } else {
216 mCarrierTextCallback = null;
217 if (mKeyguardUpdateMonitor != null) {
218 mKeyguardUpdateMonitor.removeCallback(mCallback);
219 mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
220 }
221 }
222 }
223
224 protected void updateCarrierText() {
225 boolean allSimsMissing = true;
226 boolean anySimReadyAndInService = false;
227 CharSequence displayText = null;
228
229 List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
230 final int numSubs = subs.size();
Fabian Kozynski1823f112019-01-18 11:43:29 -0500231 final int[] subsIds = new int[numSubs];
Fabian Kozynskib176f422019-02-05 09:36:59 -0500232 // This array will contain in position i, the index of subscription in slot ID i.
233 // -1 if no subscription in that slot
234 final int[] subOrderBySlot = new int[mSimSlotsNumber];
235 for (int i = 0; i < mSimSlotsNumber; i++) {
236 subOrderBySlot[i] = -1;
237 }
238 final CharSequence[] carrierNames = new CharSequence[numSubs];
Fabian Kozynski02941af2019-01-17 17:57:37 -0500239 if (DEBUG) Log.d(TAG, "updateCarrierText(): " + numSubs);
Fabian Kozynskib176f422019-02-05 09:36:59 -0500240
Fabian Kozynski02941af2019-01-17 17:57:37 -0500241 for (int i = 0; i < numSubs; i++) {
242 int subId = subs.get(i).getSubscriptionId();
Fabian Kozynskib176f422019-02-05 09:36:59 -0500243 carrierNames[i] = "";
Fabian Kozynski1823f112019-01-18 11:43:29 -0500244 subsIds[i] = subId;
Fabian Kozynskib176f422019-02-05 09:36:59 -0500245 subOrderBySlot[subs.get(i).getSimSlotIndex()] = i;
Fabian Kozynski02941af2019-01-17 17:57:37 -0500246 IccCardConstants.State simState = mKeyguardUpdateMonitor.getSimState(subId);
247 CharSequence carrierName = subs.get(i).getCarrierName();
248 CharSequence carrierTextForSimState = getCarrierTextForSimState(simState, carrierName);
249 if (DEBUG) {
250 Log.d(TAG, "Handling (subId=" + subId + "): " + simState + " " + carrierName);
251 }
252 if (carrierTextForSimState != null) {
253 allSimsMissing = false;
Fabian Kozynskib176f422019-02-05 09:36:59 -0500254 carrierNames[i] = carrierTextForSimState;
Fabian Kozynski02941af2019-01-17 17:57:37 -0500255 }
256 if (simState == IccCardConstants.State.READY) {
257 ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId);
258 if (ss != null && ss.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
259 // hack for WFC (IWLAN) not turning off immediately once
260 // Wi-Fi is disassociated or disabled
261 if (ss.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
262 || (mWifiManager.isWifiEnabled()
263 && mWifiManager.getConnectionInfo() != null
264 && mWifiManager.getConnectionInfo().getBSSID() != null)) {
265 if (DEBUG) {
266 Log.d(TAG, "SIM ready and in service: subId=" + subId + ", ss=" + ss);
267 }
268 anySimReadyAndInService = true;
269 }
270 }
271 }
272 }
273 if (allSimsMissing) {
274 if (numSubs != 0) {
275 // Shows "No SIM card | Emergency calls only" on devices that are voice-capable.
276 // This depends on mPlmn containing the text "Emergency calls only" when the radio
277 // has some connectivity. Otherwise, it should be null or empty and just show
278 // "No SIM card"
279 // Grab the first subscripton, because they all should contain the emergency text,
280 // described above.
281 displayText = makeCarrierStringOnEmergencyCapable(
282 getMissingSimMessage(), subs.get(0).getCarrierName());
283 } else {
284 // We don't have a SubscriptionInfo to get the emergency calls only from.
285 // Grab it from the old sticky broadcast if possible instead. We can use it
286 // here because no subscriptions are active, so we don't have
287 // to worry about MSIM clashing.
288 CharSequence text =
289 getContext().getText(com.android.internal.R.string.emergency_calls_only);
290 Intent i = getContext().registerReceiver(null,
291 new IntentFilter(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION));
292 if (i != null) {
293 String spn = "";
294 String plmn = "";
295 if (i.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
296 spn = i.getStringExtra(TelephonyIntents.EXTRA_SPN);
297 }
298 if (i.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
299 plmn = i.getStringExtra(TelephonyIntents.EXTRA_PLMN);
300 }
301 if (DEBUG) Log.d(TAG, "Getting plmn/spn sticky brdcst " + plmn + "/" + spn);
302 if (Objects.equals(plmn, spn)) {
303 text = plmn;
304 } else {
305 text = concatenate(plmn, spn, mSeparator);
306 }
307 }
308 displayText = makeCarrierStringOnEmergencyCapable(getMissingSimMessage(), text);
309 }
310 }
311
Fabian Kozynskib176f422019-02-05 09:36:59 -0500312 displayText = updateCarrierTextWithSimIoError(displayText, carrierNames, subOrderBySlot,
313 allSimsMissing);
Fabian Kozynskib38edbb2019-04-12 12:20:13 -0400314 boolean airplaneMode = false;
Fabian Kozynski02941af2019-01-17 17:57:37 -0500315 // APM (airplane mode) != no carrier state. There are carrier services
316 // (e.g. WFC = Wi-Fi calling) which may operate in APM.
317 if (!anySimReadyAndInService && WirelessUtils.isAirplaneModeOn(mContext)) {
318 displayText = getAirplaneModeMessage();
Fabian Kozynskib38edbb2019-04-12 12:20:13 -0400319 airplaneMode = true;
Fabian Kozynski02941af2019-01-17 17:57:37 -0500320 }
321
Fabian Kozynskib38edbb2019-04-12 12:20:13 -0400322 if (TextUtils.isEmpty(displayText) && !airplaneMode) {
Fabian Kozynskib176f422019-02-05 09:36:59 -0500323 displayText = TextUtils.join(mSeparator, carrierNames);
324 }
Fabian Kozynskibf6fef32019-02-04 09:21:38 -0500325 final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
326 displayText,
Fabian Kozynskib176f422019-02-05 09:36:59 -0500327 carrierNames,
328 !allSimsMissing,
Fabian Kozynskib38edbb2019-04-12 12:20:13 -0400329 subsIds,
330 airplaneMode);
Fabian Kozynskib176f422019-02-05 09:36:59 -0500331 postToCallback(info);
332 }
333
334 @VisibleForTesting
335 protected void postToCallback(CarrierTextCallbackInfo info) {
336 Handler handler = Dependency.get(Dependency.MAIN_HANDLER);
Fabian Kozynski48343c32019-02-07 10:28:50 -0500337 final CarrierTextCallback callback = mCarrierTextCallback;
338 if (callback != null) {
339 handler.post(() -> callback.updateCarrierInfo(info));
Fabian Kozynski02941af2019-01-17 17:57:37 -0500340 }
Fabian Kozynski02941af2019-01-17 17:57:37 -0500341 }
342
343 private Context getContext() {
344 return mContext;
345 }
346
347 private String getMissingSimMessage() {
348 return mShowMissingSim && mTelephonyCapable
349 ? getContext().getString(R.string.keyguard_missing_sim_message_short) : "";
350 }
351
352 private String getAirplaneModeMessage() {
353 return mShowAirplaneMode
354 ? getContext().getString(R.string.airplane_mode) : "";
355 }
356
357 /**
358 * Top-level function for creating carrier text. Makes text based on simState, PLMN
359 * and SPN as well as device capabilities, such as being emergency call capable.
360 *
361 * @return Carrier text if not in missing state, null otherwise.
362 */
363 private CharSequence getCarrierTextForSimState(IccCardConstants.State simState,
364 CharSequence text) {
365 CharSequence carrierText = null;
366 CarrierTextController.StatusMode status = getStatusForIccState(simState);
367 switch (status) {
368 case Normal:
369 carrierText = text;
370 break;
371
372 case SimNotReady:
373 // Null is reserved for denoting missing, in this case we have nothing to display.
374 carrierText = ""; // nothing to display yet.
375 break;
376
377 case NetworkLocked:
378 carrierText = makeCarrierStringOnEmergencyCapable(
379 mContext.getText(R.string.keyguard_network_locked_message), text);
380 break;
381
382 case SimMissing:
383 carrierText = null;
384 break;
385
386 case SimPermDisabled:
387 carrierText = makeCarrierStringOnEmergencyCapable(
388 getContext().getText(
389 R.string.keyguard_permanent_disabled_sim_message_short),
390 text);
391 break;
392
393 case SimMissingLocked:
394 carrierText = null;
395 break;
396
397 case SimLocked:
398 carrierText = makeCarrierStringOnEmergencyCapable(
399 getContext().getText(R.string.keyguard_sim_locked_message),
400 text);
401 break;
402
403 case SimPukLocked:
404 carrierText = makeCarrierStringOnEmergencyCapable(
405 getContext().getText(R.string.keyguard_sim_puk_locked_message),
406 text);
407 break;
408 case SimIoError:
409 carrierText = makeCarrierStringOnEmergencyCapable(
410 getContext().getText(R.string.keyguard_sim_error_message_short),
411 text);
412 break;
413 case SimUnknown:
414 carrierText = null;
415 break;
416 }
417
418 return carrierText;
419 }
420
421 /*
422 * Add emergencyCallMessage to carrier string only if phone supports emergency calls.
423 */
424 private CharSequence makeCarrierStringOnEmergencyCapable(
425 CharSequence simMessage, CharSequence emergencyCallMessage) {
426 if (mIsEmergencyCallCapable) {
427 return concatenate(simMessage, emergencyCallMessage, mSeparator);
428 }
429 return simMessage;
430 }
431
432 /**
433 * Determine the current status of the lock screen given the SIM state and other stuff.
434 */
435 private CarrierTextController.StatusMode getStatusForIccState(IccCardConstants.State simState) {
436 // Since reading the SIM may take a while, we assume it is present until told otherwise.
437 if (simState == null) {
438 return CarrierTextController.StatusMode.Normal;
439 }
440
441 final boolean missingAndNotProvisioned =
442 !KeyguardUpdateMonitor.getInstance(mContext).isDeviceProvisioned()
443 && (simState == IccCardConstants.State.ABSENT
444 || simState == IccCardConstants.State.PERM_DISABLED);
445
446 // Assume we're NETWORK_LOCKED if not provisioned
447 simState = missingAndNotProvisioned ? IccCardConstants.State.NETWORK_LOCKED : simState;
448 switch (simState) {
449 case ABSENT:
450 return CarrierTextController.StatusMode.SimMissing;
451 case NETWORK_LOCKED:
452 return CarrierTextController.StatusMode.SimMissingLocked;
453 case NOT_READY:
454 return CarrierTextController.StatusMode.SimNotReady;
455 case PIN_REQUIRED:
456 return CarrierTextController.StatusMode.SimLocked;
457 case PUK_REQUIRED:
458 return CarrierTextController.StatusMode.SimPukLocked;
459 case READY:
460 return CarrierTextController.StatusMode.Normal;
461 case PERM_DISABLED:
462 return CarrierTextController.StatusMode.SimPermDisabled;
463 case UNKNOWN:
464 return CarrierTextController.StatusMode.SimUnknown;
465 case CARD_IO_ERROR:
466 return CarrierTextController.StatusMode.SimIoError;
467 }
468 return CarrierTextController.StatusMode.SimUnknown;
469 }
470
471 private static CharSequence concatenate(CharSequence plmn, CharSequence spn,
472 CharSequence separator) {
473 final boolean plmnValid = !TextUtils.isEmpty(plmn);
474 final boolean spnValid = !TextUtils.isEmpty(spn);
475 if (plmnValid && spnValid) {
476 return new StringBuilder().append(plmn).append(separator).append(spn).toString();
477 } else if (plmnValid) {
478 return plmn;
479 } else if (spnValid) {
480 return spn;
481 } else {
482 return "";
483 }
484 }
485
486 private static List<CharSequence> append(List<CharSequence> list, CharSequence string) {
487 if (!TextUtils.isEmpty(string)) {
488 list.add(string);
489 }
490 return list;
491 }
492
493 private CharSequence getCarrierHelpTextForSimState(IccCardConstants.State simState,
494 String plmn, String spn) {
495 int carrierHelpTextId = 0;
496 CarrierTextController.StatusMode status = getStatusForIccState(simState);
497 switch (status) {
498 case NetworkLocked:
499 carrierHelpTextId = R.string.keyguard_instructions_when_pattern_disabled;
500 break;
501
502 case SimMissing:
503 carrierHelpTextId = R.string.keyguard_missing_sim_instructions_long;
504 break;
505
506 case SimPermDisabled:
507 carrierHelpTextId = R.string.keyguard_permanent_disabled_sim_instructions;
508 break;
509
510 case SimMissingLocked:
511 carrierHelpTextId = R.string.keyguard_missing_sim_instructions;
512 break;
513
514 case Normal:
515 case SimLocked:
516 case SimPukLocked:
517 break;
518 }
519
520 return mContext.getText(carrierHelpTextId);
521 }
522
523 /**
Fabian Kozynski1823f112019-01-18 11:43:29 -0500524 * Data structure for passing information to CarrierTextController subscribers
525 */
526 public static final class CarrierTextCallbackInfo {
527 public final CharSequence carrierText;
528 public final CharSequence[] listOfCarriers;
529 public final boolean anySimReady;
530 public final int[] subscriptionIds;
Fabian Kozynskib38edbb2019-04-12 12:20:13 -0400531 public boolean airplaneMode;
Fabian Kozynski1823f112019-01-18 11:43:29 -0500532
Fabian Kozynskibf6fef32019-02-04 09:21:38 -0500533 @VisibleForTesting
534 public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers,
Fabian Kozynski1823f112019-01-18 11:43:29 -0500535 boolean anySimReady, int[] subscriptionIds) {
Fabian Kozynskib38edbb2019-04-12 12:20:13 -0400536 this(carrierText, listOfCarriers, anySimReady, subscriptionIds, false);
537 }
538
539 @VisibleForTesting
540 public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers,
541 boolean anySimReady, int[] subscriptionIds, boolean airplaneMode) {
Fabian Kozynski1823f112019-01-18 11:43:29 -0500542 this.carrierText = carrierText;
543 this.listOfCarriers = listOfCarriers;
544 this.anySimReady = anySimReady;
545 this.subscriptionIds = subscriptionIds;
Fabian Kozynskib38edbb2019-04-12 12:20:13 -0400546 this.airplaneMode = airplaneMode;
Fabian Kozynski1823f112019-01-18 11:43:29 -0500547 }
548 }
549
550 /**
Fabian Kozynski02941af2019-01-17 17:57:37 -0500551 * Callback to communicate to Views
552 */
553 public interface CarrierTextCallback {
554 /**
Fabian Kozynski1823f112019-01-18 11:43:29 -0500555 * Provides updated carrier information.
Fabian Kozynski02941af2019-01-17 17:57:37 -0500556 */
Fabian Kozynski1823f112019-01-18 11:43:29 -0500557 default void updateCarrierInfo(CarrierTextCallbackInfo info) {};
Fabian Kozynski02941af2019-01-17 17:57:37 -0500558
559 /**
560 * Notifies the View that the device is going to sleep
561 */
562 default void startedGoingToSleep() {};
563
564 /**
565 * Notifies the View that the device finished waking up
566 */
567 default void finishedWakingUp() {};
568 }
569}