blob: c2ec7195bba686aba34b64c18016f630e0eeab46 [file] [log] [blame]
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001/*
2 * Copyright (C) 2006 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.phone;
18
19import android.app.Activity;
20import android.app.KeyguardManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070021import android.app.ProgressDialog;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070022import android.content.BroadcastReceiver;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070023import android.content.ContentResolver;
24import android.content.Context;
25import android.content.ContextWrapper;
26import android.content.Intent;
27import android.content.IntentFilter;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070028import android.media.AudioManager;
29import android.net.Uri;
30import android.os.AsyncResult;
Junda Liu605148f2015-04-28 15:23:40 -070031import android.os.Bundle;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070032import android.os.Handler;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070033import android.os.Message;
Jonathan Basseric31f1f32015-05-12 10:13:03 -070034import android.os.PersistableBundle;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070035import android.os.PowerManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070036import android.os.SystemClock;
37import android.os.SystemProperties;
38import android.os.UpdateLock;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070039import android.preference.PreferenceManager;
Sanket Padawe4c699232016-02-09 11:07:22 -080040import android.provider.Settings;
Junda Liu12f7d802015-05-01 12:06:44 -070041import android.telephony.CarrierConfigManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070042import android.telephony.ServiceState;
Andrew Lee385019f2014-11-24 14:19:50 -080043import android.telephony.SubscriptionManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070044import android.util.Log;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070045
46import com.android.internal.telephony.Call;
47import com.android.internal.telephony.CallManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070048import com.android.internal.telephony.IccCardConstants;
49import com.android.internal.telephony.MmiCode;
50import com.android.internal.telephony.Phone;
51import com.android.internal.telephony.PhoneConstants;
52import com.android.internal.telephony.PhoneFactory;
53import com.android.internal.telephony.TelephonyCapabilities;
54import com.android.internal.telephony.TelephonyIntents;
Santos Cordon352ff652014-05-30 01:41:45 -070055import com.android.phone.common.CallLogAsync;
Andrew Leefb7f92e2015-02-26 16:23:32 -080056import com.android.phone.settings.SettingsConstants;
Santos Cordon76aaf482015-04-08 10:58:27 -070057import com.android.services.telephony.activation.SimActivationManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070058
59/**
60 * Global state for the telephony subsystem when running in the primary
61 * phone process.
62 */
Sailesh Nepalbf900542014-07-15 16:18:32 -070063public class PhoneGlobals extends ContextWrapper {
Andrew Lee83383e42014-10-31 12:42:28 -070064 public static final String LOG_TAG = "PhoneApp";
Santos Cordon7d4ddf62013-07-10 11:58:08 -070065
66 /**
67 * Phone app-wide debug level:
68 * 0 - no debug logging
69 * 1 - normal debug logging if ro.debuggable is set (which is true in
70 * "eng" and "userdebug" builds but not "user" builds)
71 * 2 - ultra-verbose debug logging
72 *
73 * Most individual classes in the phone app have a local DBG constant,
74 * typically set to
75 * (PhoneApp.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1)
76 * or else
77 * (PhoneApp.DBG_LEVEL >= 2)
78 * depending on the desired verbosity.
79 *
80 * ***** DO NOT SUBMIT WITH DBG_LEVEL > 0 *************
81 */
Andrew Lee88b51e22014-10-29 15:48:51 -070082 public static final int DBG_LEVEL = 0;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070083
84 private static final boolean DBG =
85 (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
86 private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2);
87
88 // Message codes; see mHandler below.
89 private static final int EVENT_SIM_NETWORK_LOCKED = 3;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070090 private static final int EVENT_SIM_STATE_CHANGED = 8;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070091 private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10;
92 private static final int EVENT_DATA_ROAMING_OK = 11;
93 private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070094
95 // The MMI codes are also used by the InCallScreen.
96 public static final int MMI_INITIATE = 51;
97 public static final int MMI_COMPLETE = 52;
98 public static final int MMI_CANCEL = 53;
99 // Don't use message codes larger than 99 here; those are reserved for
100 // the individual Activities of the Phone UI.
101
102 /**
103 * Allowable values for the wake lock code.
104 * SLEEP means the device can be put to sleep.
105 * PARTIAL means wake the processor, but we display can be kept off.
106 * FULL means wake both the processor and the display.
107 */
108 public enum WakeState {
109 SLEEP,
110 PARTIAL,
111 FULL
112 }
113
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700114 private static PhoneGlobals sMe;
115
116 // A few important fields we expose to the rest of the package
117 // directly (rather than thru set/get methods) for efficiency.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700118 CallController callController;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700119 CallManager mCM;
Santos Cordon63a84242013-07-23 13:32:52 -0700120 CallNotifier notifier;
121 CallerInfoCache callerInfoCache;
Santos Cordon63a84242013-07-23 13:32:52 -0700122 NotificationMgr notificationMgr;
Andrew Lee9431b832015-03-09 18:46:45 -0700123 public PhoneInterfaceManager phoneMgr;
Santos Cordon76aaf482015-04-08 10:58:27 -0700124 public SimActivationManager simActivationManager;
Jonathan Basseri6465afd2015-02-25 13:05:57 -0800125 CarrierConfigLoader configLoader;
Santos Cordon63a84242013-07-23 13:32:52 -0700126
Santos Cordon69a69192013-08-22 14:25:42 -0700127 private CallGatewayManager callGatewayManager;
Santos Cordon63a84242013-07-23 13:32:52 -0700128
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700129 static boolean sVoiceCapable = true;
130
Santos Cordonc593d002015-06-03 15:41:15 -0700131 // TODO: Remove, no longer used.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700132 CdmaPhoneCallState cdmaPhoneCallState;
133
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700134 // The currently-active PUK entry activity and progress dialog.
135 // Normally, these are the Emergency Dialer and the subsequent
136 // progress dialog. null if there is are no such objects in
137 // the foreground.
138 private Activity mPUKEntryActivity;
139 private ProgressDialog mPUKEntryProgressDialog;
140
Yorke Lee4d2db1c2014-11-06 11:37:09 -0800141 private boolean mDataDisconnectedDueToRoaming = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700142
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700143 private WakeState mWakeState = WakeState.SLEEP;
144
145 private PowerManager mPowerManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700146 private PowerManager.WakeLock mWakeLock;
147 private PowerManager.WakeLock mPartialWakeLock;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700148 private KeyguardManager mKeyguardManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700149
150 private UpdateLock mUpdateLock;
151
152 // Broadcast receiver for various intent broadcasts (see onCreate())
153 private final BroadcastReceiver mReceiver = new PhoneAppBroadcastReceiver();
154
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700155 /**
156 * The singleton OtaUtils instance used for OTASP calls.
157 *
158 * The OtaUtils instance is created lazily the first time we need to
159 * make an OTASP call, regardless of whether it's an interactive or
160 * non-interactive OTASP call.
161 */
162 public OtaUtils otaUtils;
163
164 // Following are the CDMA OTA information Objects used during OTA Call.
165 // cdmaOtaProvisionData object store static OTA information that needs
166 // to be maintained even during Slider open/close scenarios.
167 // cdmaOtaConfigData object stores configuration info to control visiblity
168 // of each OTA Screens.
169 // cdmaOtaScreenState object store OTA Screen State information.
170 public OtaUtils.CdmaOtaProvisionData cdmaOtaProvisionData;
171 public OtaUtils.CdmaOtaConfigData cdmaOtaConfigData;
172 public OtaUtils.CdmaOtaScreenState cdmaOtaScreenState;
173 public OtaUtils.CdmaOtaInCallScreenUiState cdmaOtaInCallScreenUiState;
174
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700175 Handler mHandler = new Handler() {
176 @Override
177 public void handleMessage(Message msg) {
178 PhoneConstants.State phoneState;
179 switch (msg.what) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700180 // TODO: This event should be handled by the lock screen, just
181 // like the "SIM missing" and "Sim locked" cases (bug 1804111).
182 case EVENT_SIM_NETWORK_LOCKED:
Jonathan Basseri9504c6b2015-06-04 14:23:32 -0700183 if (getCarrierConfig().getBoolean(
184 CarrierConfigManager.KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL)) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700185 // Some products don't have the concept of a "SIM network lock"
186 Log.i(LOG_TAG, "Ignoring EVENT_SIM_NETWORK_LOCKED event; "
187 + "not showing 'SIM network unlock' PIN entry screen");
188 } else {
189 // Normal case: show the "SIM network unlock" PIN entry screen.
190 // The user won't be able to do anything else until
191 // they enter a valid SIM network PIN.
192 Log.i(LOG_TAG, "show sim depersonal panel");
Tyler Gunn52a37072015-08-24 14:23:19 -0700193 IccNetworkDepersonalizationPanel.showDialog();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700194 }
195 break;
196
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700197 case EVENT_DATA_ROAMING_DISCONNECTED:
198 notificationMgr.showDataDisconnectedRoaming();
199 break;
200
201 case EVENT_DATA_ROAMING_OK:
202 notificationMgr.hideDataDisconnectedRoaming();
203 break;
204
205 case MMI_COMPLETE:
206 onMMIComplete((AsyncResult) msg.obj);
207 break;
208
209 case MMI_CANCEL:
Stuart Scottdcf40a92014-12-09 10:45:01 -0800210 PhoneUtils.cancelMmiCode(mCM.getFgPhone());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700211 break;
212
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700213 case EVENT_SIM_STATE_CHANGED:
214 // Marks the event where the SIM goes into ready state.
215 // Right now, this is only used for the PUK-unlocking
216 // process.
217 if (msg.obj.equals(IccCardConstants.INTENT_VALUE_ICC_READY)) {
218 // when the right event is triggered and there
219 // are UI objects in the foreground, we close
220 // them to display the lock panel.
221 if (mPUKEntryActivity != null) {
222 mPUKEntryActivity.finish();
223 mPUKEntryActivity = null;
224 }
225 if (mPUKEntryProgressDialog != null) {
226 mPUKEntryProgressDialog.dismiss();
227 mPUKEntryProgressDialog = null;
228 }
229 }
230 break;
231
232 case EVENT_UNSOL_CDMA_INFO_RECORD:
233 //TODO: handle message here;
234 break;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700235 }
236 }
237 };
238
239 public PhoneGlobals(Context context) {
240 super(context);
241 sMe = this;
242 }
243
244 public void onCreate() {
245 if (VDBG) Log.v(LOG_TAG, "onCreate()...");
246
247 ContentResolver resolver = getContentResolver();
248
249 // Cache the "voice capable" flag.
250 // This flag currently comes from a resource (which is
251 // overrideable on a per-product basis):
252 sVoiceCapable =
253 getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);
254 // ...but this might eventually become a PackageManager "system
255 // feature" instead, in which case we'd do something like:
256 // sVoiceCapable =
257 // getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS);
258
Stuart Scottdcf40a92014-12-09 10:45:01 -0800259 if (mCM == null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700260 // Initialize the telephony framework
261 PhoneFactory.makeDefaultPhones(this);
262
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700263 // Start TelephonyDebugService After the default phone is created.
264 Intent intent = new Intent(this, TelephonyDebugService.class);
265 startService(intent);
266
267 mCM = CallManager.getInstance();
Stuart Scottdcf40a92014-12-09 10:45:01 -0800268 for (Phone phone : PhoneFactory.getPhones()) {
269 mCM.registerPhone(phone);
Stuart Scottdcf40a92014-12-09 10:45:01 -0800270 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700271
272 // Create the NotificationMgr singleton, which is used to display
273 // status bar icons and control other status bar behavior.
274 notificationMgr = NotificationMgr.init(this);
275
Anthony Lee03ebdfc2015-07-27 08:12:02 -0700276 // Create an instance of CdmaPhoneCallState and initialize it to IDLE
277 cdmaPhoneCallState = new CdmaPhoneCallState();
278 cdmaPhoneCallState.CdmaPhoneCallStateInit();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700279
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700280 // before registering for phone state changes
281 mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
282 mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG);
283 // lock used to keep the processor awake, when we don't care for the display.
284 mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
285 | PowerManager.ON_AFTER_RELEASE, LOG_TAG);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700286
287 mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
288
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700289 // Get UpdateLock to suppress system-update related events (e.g. dialog show-up)
290 // during phone calls.
291 mUpdateLock = new UpdateLock("phone");
292
293 if (DBG) Log.d(LOG_TAG, "onCreate: mUpdateLock: " + mUpdateLock);
294
295 CallLogger callLogger = new CallLogger(this, new CallLogAsync());
296
Jay Shrauner21a75342013-11-25 16:14:43 -0800297 callGatewayManager = CallGatewayManager.getInstance();
Santos Cordon69a69192013-08-22 14:25:42 -0700298
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700299 // Create the CallController singleton, which is the interface
300 // to the telephony layer for user-initiated telephony functionality
301 // (like making outgoing calls.)
Santos Cordon69a69192013-08-22 14:25:42 -0700302 callController = CallController.init(this, callLogger, callGatewayManager);
303
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700304 // Create the CallerInfoCache singleton, which remembers custom ring tone and
305 // send-to-voicemail settings.
306 //
307 // The asynchronous caching will start just after this call.
308 callerInfoCache = CallerInfoCache.init(this);
309
Stuart Scottdcf40a92014-12-09 10:45:01 -0800310 phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());
Santos Cordon406c0342013-08-28 00:07:47 -0700311
Jonathan Basseri6465afd2015-02-25 13:05:57 -0800312 configLoader = CarrierConfigLoader.init(this);
313
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700314 // Create the CallNotifer singleton, which handles
315 // asynchronous events from the telephony layer (like
316 // launching the incoming-call UI when an incoming call comes
317 // in.)
Brad Ebingera9c6b6d2016-01-07 17:24:16 -0800318 notifier = CallNotifier.init(this);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700319
Stuart Scottdcf40a92014-12-09 10:45:01 -0800320 PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700321
322 // register for MMI/USSD
323 mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);
324
325 // register connection tracking to PhoneUtils
326 PhoneUtils.initializeConnectionHandler(mCM);
327
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700328 // Register for misc other intent broadcasts.
329 IntentFilter intentFilter =
330 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700331 intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700332 intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
333 intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
334 intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
335 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700336 registerReceiver(mReceiver, intentFilter);
337
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700338 //set the default values for the preferences in the phone.
339 PreferenceManager.setDefaultValues(this, R.xml.network_setting, false);
340
341 PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false);
342
343 // Make sure the audio mode (along with some
344 // audio-mode-related state of our own) is initialized
345 // correctly, given the current state of the phone.
346 PhoneUtils.setAudioMode(mCM);
347 }
348
Santos Cordon52bc81b2014-10-07 19:55:12 -0700349 cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData();
350 cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData();
351 cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState();
352 cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700353
Santos Cordon76aaf482015-04-08 10:58:27 -0700354 simActivationManager = new SimActivationManager();
355
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700356 // XXX pre-load the SimProvider so that it's ready
357 resolver.getType(Uri.parse("content://icc/adn"));
358
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700359 // TODO: Register for Cdma Information Records
360 // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null);
361
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700362 // Read HAC settings and configure audio hardware
363 if (getResources().getBoolean(R.bool.hac_enabled)) {
Stuart Scottdcf40a92014-12-09 10:45:01 -0800364 int hac = android.provider.Settings.System.getInt(
365 getContentResolver(),
366 android.provider.Settings.System.HEARING_AID,
367 0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700368 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
Andrew Leefb7f92e2015-02-26 16:23:32 -0800369 audioManager.setParameter(SettingsConstants.HAC_KEY,
370 hac == SettingsConstants.HAC_ENABLED
371 ? SettingsConstants.HAC_VAL_ON : SettingsConstants.HAC_VAL_OFF);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700372 }
Santos Cordonff506f52013-11-21 19:13:19 -0800373 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700374
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700375 /**
376 * Returns the singleton instance of the PhoneApp.
377 */
Sailesh Nepal1eaf22b2014-02-22 17:00:49 -0800378 public static PhoneGlobals getInstance() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700379 if (sMe == null) {
380 throw new IllegalStateException("No PhoneGlobals here!");
381 }
382 return sMe;
383 }
384
385 /**
386 * Returns the singleton instance of the PhoneApp if running as the
387 * primary user, otherwise null.
388 */
389 static PhoneGlobals getInstanceIfPrimary() {
390 return sMe;
391 }
392
393 /**
Stuart Scottdcf40a92014-12-09 10:45:01 -0800394 * Returns the default phone.
395 *
Andrew Lee385019f2014-11-24 14:19:50 -0800396 * WARNING: This method should be used carefully, now that there may be multiple phones.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700397 */
Andrew Lee83383e42014-10-31 12:42:28 -0700398 public static Phone getPhone() {
Stuart Scottdcf40a92014-12-09 10:45:01 -0800399 return PhoneFactory.getDefaultPhone();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700400 }
401
Andrew Lee2fcb6c32014-12-04 14:52:35 -0800402 public static Phone getPhone(int subId) {
403 return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
Andrew Lee385019f2014-11-24 14:19:50 -0800404 }
405
Santos Cordonde10b752013-09-19 04:11:33 -0700406 /* package */ CallManager getCallManager() {
407 return mCM;
408 }
409
Chris Manton4e9fa912015-06-19 11:26:57 -0700410 public PersistableBundle getCarrierConfig() {
Shishir Agrawald3480e02016-01-25 13:05:49 -0800411 return getCarrierConfigForSubId(SubscriptionManager.getDefaultSubscriptionId());
Jonathan Basseri89b0ab42015-05-01 10:52:40 -0700412 }
413
Chris Manton4e9fa912015-06-19 11:26:57 -0700414 public PersistableBundle getCarrierConfigForSubId(int subId) {
Jonathan Basseri89b0ab42015-05-01 10:52:40 -0700415 return configLoader.getConfigForSubId(subId);
Junda Liu605148f2015-04-28 15:23:40 -0700416 }
417
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700418 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700419 * Handles OTASP-related events from the telephony layer.
420 *
421 * While an OTASP call is active, the CallNotifier forwards
422 * OTASP-related telephony events to this method.
423 */
424 void handleOtaspEvent(Message msg) {
425 if (DBG) Log.d(LOG_TAG, "handleOtaspEvent(message " + msg + ")...");
426
427 if (otaUtils == null) {
428 // We shouldn't be getting OTASP events without ever
429 // having started the OTASP call in the first place!
430 Log.w(LOG_TAG, "handleOtaEvents: got an event but otaUtils is null! "
431 + "message = " + msg);
432 return;
433 }
434
435 otaUtils.onOtaProvisionStatusChanged((AsyncResult) msg.obj);
436 }
437
438 /**
439 * Similarly, handle the disconnect event of an OTASP call
440 * by forwarding it to the OtaUtils instance.
441 */
442 /* package */ void handleOtaspDisconnect() {
443 if (DBG) Log.d(LOG_TAG, "handleOtaspDisconnect()...");
444
445 if (otaUtils == null) {
446 // We shouldn't be getting OTASP events without ever
447 // having started the OTASP call in the first place!
448 Log.w(LOG_TAG, "handleOtaspDisconnect: otaUtils is null!");
449 return;
450 }
451
452 otaUtils.onOtaspDisconnect();
453 }
454
455 /**
456 * Sets the activity responsible for un-PUK-blocking the device
457 * so that we may close it when we receive a positive result.
458 * mPUKEntryActivity is also used to indicate to the device that
459 * we are trying to un-PUK-lock the phone. In other words, iff
460 * it is NOT null, then we are trying to unlock and waiting for
461 * the SIM to move to READY state.
462 *
463 * @param activity is the activity to close when PUK has
464 * finished unlocking. Can be set to null to indicate the unlock
465 * or SIM READYing process is over.
466 */
467 void setPukEntryActivity(Activity activity) {
468 mPUKEntryActivity = activity;
469 }
470
471 Activity getPUKEntryActivity() {
472 return mPUKEntryActivity;
473 }
474
475 /**
476 * Sets the dialog responsible for notifying the user of un-PUK-
477 * blocking - SIM READYing progress, so that we may dismiss it
478 * when we receive a positive result.
479 *
480 * @param dialog indicates the progress dialog informing the user
481 * of the state of the device. Dismissed upon completion of
482 * READYing process
483 */
484 void setPukEntryProgressDialog(ProgressDialog dialog) {
485 mPUKEntryProgressDialog = dialog;
486 }
487
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700488 /**
489 * Controls whether or not the screen is allowed to sleep.
490 *
491 * Once sleep is allowed (WakeState is SLEEP), it will rely on the
492 * settings for the poke lock to determine when to timeout and let
493 * the device sleep {@link PhoneGlobals#setScreenTimeout}.
494 *
495 * @param ws tells the device to how to wake.
496 */
497 /* package */ void requestWakeState(WakeState ws) {
498 if (VDBG) Log.d(LOG_TAG, "requestWakeState(" + ws + ")...");
499 synchronized (this) {
500 if (mWakeState != ws) {
501 switch (ws) {
502 case PARTIAL:
503 // acquire the processor wake lock, and release the FULL
504 // lock if it is being held.
505 mPartialWakeLock.acquire();
506 if (mWakeLock.isHeld()) {
507 mWakeLock.release();
508 }
509 break;
510 case FULL:
511 // acquire the full wake lock, and release the PARTIAL
512 // lock if it is being held.
513 mWakeLock.acquire();
514 if (mPartialWakeLock.isHeld()) {
515 mPartialWakeLock.release();
516 }
517 break;
518 case SLEEP:
519 default:
520 // release both the PARTIAL and FULL locks.
521 if (mWakeLock.isHeld()) {
522 mWakeLock.release();
523 }
524 if (mPartialWakeLock.isHeld()) {
525 mPartialWakeLock.release();
526 }
527 break;
528 }
529 mWakeState = ws;
530 }
531 }
532 }
533
534 /**
535 * If we are not currently keeping the screen on, then poke the power
536 * manager to wake up the screen for the user activity timeout duration.
537 */
538 /* package */ void wakeUpScreen() {
539 synchronized (this) {
540 if (mWakeState == WakeState.SLEEP) {
541 if (DBG) Log.d(LOG_TAG, "pulse screen lock");
Dianne Hackborn148769b2015-07-13 17:55:47 -0700542 mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.phone:WAKE");
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700543 }
544 }
545 }
546
547 /**
548 * Sets the wake state and screen timeout based on the current state
549 * of the phone, and the current state of the in-call UI.
550 *
551 * This method is a "UI Policy" wrapper around
552 * {@link PhoneGlobals#requestWakeState} and {@link PhoneGlobals#setScreenTimeout}.
553 *
554 * It's safe to call this method regardless of the state of the Phone
555 * (e.g. whether or not it's idle), and regardless of the state of the
556 * Phone UI (e.g. whether or not the InCallScreen is active.)
557 */
558 /* package */ void updateWakeState() {
559 PhoneConstants.State state = mCM.getState();
560
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700561 // True if the speakerphone is in use. (If so, we *always* use
562 // the default timeout. Since the user is obviously not holding
563 // the phone up to his/her face, we don't need to worry about
564 // false touches, and thus don't need to turn the screen off so
565 // aggressively.)
566 // Note that we need to make a fresh call to this method any
567 // time the speaker state changes. (That happens in
568 // PhoneUtils.turnOnSpeaker().)
569 boolean isSpeakerInUse = (state == PhoneConstants.State.OFFHOOK) && PhoneUtils.isSpeakerOn(this);
570
571 // TODO (bug 1440854): The screen timeout *might* also need to
572 // depend on the bluetooth state, but this isn't as clear-cut as
573 // the speaker state (since while using BT it's common for the
574 // user to put the phone straight into a pocket, in which case the
575 // timeout should probably still be short.)
576
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700577 // Decide whether to force the screen on or not.
578 //
579 // Force the screen to be on if the phone is ringing or dialing,
580 // or if we're displaying the "Call ended" UI for a connection in
581 // the "disconnected" state.
582 // However, if the phone is disconnected while the user is in the
583 // middle of selecting a quick response message, we should not force
584 // the screen to be on.
585 //
586 boolean isRinging = (state == PhoneConstants.State.RINGING);
Stuart Scottdcf40a92014-12-09 10:45:01 -0800587 boolean isDialing = (mCM.getFgPhone().getForegroundCall().getState() == Call.State.DIALING);
Jay Shrauner6fe8fd62013-09-16 19:39:30 -0700588 boolean keepScreenOn = isRinging || isDialing;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700589 // keepScreenOn == true means we'll hold a full wake lock:
590 requestWakeState(keepScreenOn ? WakeState.FULL : WakeState.SLEEP);
591 }
592
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700593 KeyguardManager getKeyguardManager() {
594 return mKeyguardManager;
595 }
596
597 private void onMMIComplete(AsyncResult r) {
598 if (VDBG) Log.d(LOG_TAG, "onMMIComplete()...");
599 MmiCode mmiCode = (MmiCode) r.result;
Stuart Scottdcf40a92014-12-09 10:45:01 -0800600 PhoneUtils.displayMMIComplete(mmiCode.getPhone(), getInstance(), mmiCode, null, null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700601 }
602
Stuart Scottdcf40a92014-12-09 10:45:01 -0800603 private void initForNewRadioTechnology(int phoneId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700604 if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology...");
605
Stuart Scottdcf40a92014-12-09 10:45:01 -0800606 final Phone phone = PhoneFactory.getPhone(phoneId);
Santos Cordonc593d002015-06-03 15:41:15 -0700607 if (phone == null || !TelephonyCapabilities.supportsOtasp(phone)) {
608 // Clean up OTA for non-CDMA since it is only valid for CDMA.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700609 clearOtaState();
610 }
611
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700612 notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700613 }
614
Santos Cordon593ab382013-08-06 21:58:23 -0700615 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700616 * Receiver for misc intent broadcasts the Phone app cares about.
617 */
618 private class PhoneAppBroadcastReceiver extends BroadcastReceiver {
619 @Override
620 public void onReceive(Context context, Intent intent) {
621 String action = intent.getAction();
622 if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
Sanket Padawe4c699232016-02-09 11:07:22 -0800623 boolean enabled = Settings.Global.getInt(getContentResolver(),
624 Settings.Global.AIRPLANE_MODE_ON, 0) == 0;
Stuart Scottdcf40a92014-12-09 10:45:01 -0800625 PhoneUtils.setRadioPower(enabled);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700626 } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
Stuart Scottdcf40a92014-12-09 10:45:01 -0800627 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
628 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
629 int phoneId = SubscriptionManager.getPhoneId(subId);
630 String state = intent.getStringExtra(PhoneConstants.STATE_KEY);
631 if (VDBG) {
632 Log.d(LOG_TAG, "mReceiver: ACTION_ANY_DATA_CONNECTION_STATE_CHANGED");
633 Log.d(LOG_TAG, "- state: " + state);
634 Log.d(LOG_TAG, "- reason: "
635 + intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY));
636 Log.d(LOG_TAG, "- subId: " + subId);
637 Log.d(LOG_TAG, "- phoneId: " + phoneId);
638 }
639 Phone phone = SubscriptionManager.isValidPhoneId(phoneId) ?
640 PhoneFactory.getPhone(phoneId) : PhoneFactory.getDefaultPhone();
Santos Cordonc593d002015-06-03 15:41:15 -0700641
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700642 // The "data disconnected due to roaming" notification is shown
643 // if (a) you have the "data roaming" feature turned off, and
644 // (b) you just lost data connectivity because you're roaming.
645 boolean disconnectedDueToRoaming =
646 !phone.getDataRoamingEnabled()
Stuart Scottdcf40a92014-12-09 10:45:01 -0800647 && PhoneConstants.DataState.DISCONNECTED.equals(state)
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700648 && Phone.REASON_ROAMING_ON.equals(
649 intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY));
Yorke Lee4d2db1c2014-11-06 11:37:09 -0800650 if (mDataDisconnectedDueToRoaming != disconnectedDueToRoaming) {
651 mDataDisconnectedDueToRoaming = disconnectedDueToRoaming;
652 mHandler.sendEmptyMessage(disconnectedDueToRoaming
653 ? EVENT_DATA_ROAMING_DISCONNECTED : EVENT_DATA_ROAMING_OK);
654 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700655 } else if ((action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) &&
656 (mPUKEntryActivity != null)) {
657 // if an attempt to un-PUK-lock the device was made, while we're
658 // receiving this state change notification, notify the handler.
659 // NOTE: This is ONLY triggered if an attempt to un-PUK-lock has
660 // been attempted.
661 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SIM_STATE_CHANGED,
662 intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)));
663 } else if (action.equals(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED)) {
664 String newPhone = intent.getStringExtra(PhoneConstants.PHONE_NAME_KEY);
Stuart Scottdcf40a92014-12-09 10:45:01 -0800665 int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY,
666 SubscriptionManager.INVALID_PHONE_INDEX);
667 Log.d(LOG_TAG, "Radio technology switched. Now " + newPhone + " (" + phoneId
668 + ") is active.");
669 initForNewRadioTechnology(phoneId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700670 } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) {
671 handleServiceStateChanged(intent);
672 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
Stuart Scottdcf40a92014-12-09 10:45:01 -0800673 if (TelephonyCapabilities.supportsEcm(mCM.getFgPhone())) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700674 Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp.");
675 // Start Emergency Callback Mode service
676 if (intent.getBooleanExtra("phoneinECMState", false)) {
677 context.startService(new Intent(context,
678 EmergencyCallbackModeService.class));
679 }
680 } else {
681 // It doesn't make sense to get ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
682 // on a device that doesn't support ECM in the first place.
683 Log.e(LOG_TAG, "Got ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, "
Stuart Scottdcf40a92014-12-09 10:45:01 -0800684 + "but ECM isn't supported for phone: "
685 + mCM.getFgPhone().getPhoneName());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700686 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700687 }
688 }
689 }
690
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700691 private void handleServiceStateChanged(Intent intent) {
692 /**
693 * This used to handle updating EriTextWidgetProvider this routine
694 * and and listening for ACTION_SERVICE_STATE_CHANGED intents could
695 * be removed. But leaving just in case it might be needed in the near
696 * future.
697 */
698
699 // If service just returned, start sending out the queued messages
Santos Cordonc593d002015-06-03 15:41:15 -0700700 Bundle extras = intent.getExtras();
701 if (extras != null) {
702 ServiceState ss = ServiceState.newFromBundle(extras);
703 if (ss != null) {
704 int state = ss.getState();
705 notificationMgr.updateNetworkSelection(state);
706 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700707 }
708 }
709
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700710 // it is safe to call clearOtaState() even if the InCallScreen isn't active
711 public void clearOtaState() {
712 if (DBG) Log.d(LOG_TAG, "- clearOtaState ...");
Jay Shrauner6fe8fd62013-09-16 19:39:30 -0700713 if (otaUtils != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700714 otaUtils.cleanOtaScreen(true);
715 if (DBG) Log.d(LOG_TAG, " - clearOtaState clears OTA screen");
716 }
717 }
718
719 // it is safe to call dismissOtaDialogs() even if the InCallScreen isn't active
720 public void dismissOtaDialogs() {
721 if (DBG) Log.d(LOG_TAG, "- dismissOtaDialogs ...");
Jay Shrauner6fe8fd62013-09-16 19:39:30 -0700722 if (otaUtils != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700723 otaUtils.dismissAllOtaDialogs();
724 if (DBG) Log.d(LOG_TAG, " - dismissOtaDialogs clears OTA dialogs");
725 }
726 }
727
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700728 /**
Tyler Gunn9c1071f2014-12-09 10:07:54 -0800729 * Triggers a refresh of the message waiting (voicemail) indicator.
730 *
731 * @param subId the subscription id we should refresh the notification for.
732 */
733 public void refreshMwiIndicator(int subId) {
734 notificationMgr.refreshMwi(subId);
735 }
736
737 /**
Nancy Chenbb49d412015-07-23 13:54:16 -0700738 * Dismisses the message waiting (voicemail) indicator.
739 *
740 * @param subId the subscription id we should dismiss the notification for.
741 */
742 public void clearMwiIndicator(int subId) {
743 notificationMgr.updateMwi(subId, false);
744 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700745}