blob: ec863840571296fb580c777bf64e470677e5e42c [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;
Santos Cordone18902f2016-03-22 17:16:04 -070029import android.net.ConnectivityManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070030import android.net.Uri;
31import android.os.AsyncResult;
Junda Liu605148f2015-04-28 15:23:40 -070032import android.os.Bundle;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070033import android.os.Handler;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070034import android.os.Message;
Jonathan Basseric31f1f32015-05-12 10:13:03 -070035import android.os.PersistableBundle;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070036import android.os.PowerManager;
Brad Ebinger3fa43462016-04-12 16:06:48 -070037import android.os.ServiceManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070038import android.os.SystemClock;
39import android.os.SystemProperties;
Brad Ebinger3fa43462016-04-12 16:06:48 -070040import android.os.SystemService;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070041import android.os.UpdateLock;
Brad Ebinger3fa43462016-04-12 16:06:48 -070042import android.os.UserManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070043import android.preference.PreferenceManager;
Sanket Padawe4c699232016-02-09 11:07:22 -080044import android.provider.Settings;
Junda Liu12f7d802015-05-01 12:06:44 -070045import android.telephony.CarrierConfigManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070046import android.telephony.ServiceState;
Andrew Lee385019f2014-11-24 14:19:50 -080047import android.telephony.SubscriptionManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070048import android.util.Log;
Santos Cordone18902f2016-03-22 17:16:04 -070049import android.widget.Toast;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070050
51import com.android.internal.telephony.Call;
52import com.android.internal.telephony.CallManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070053import com.android.internal.telephony.IccCardConstants;
54import com.android.internal.telephony.MmiCode;
55import com.android.internal.telephony.Phone;
56import com.android.internal.telephony.PhoneConstants;
57import com.android.internal.telephony.PhoneFactory;
58import com.android.internal.telephony.TelephonyCapabilities;
59import com.android.internal.telephony.TelephonyIntents;
Santos Cordon352ff652014-05-30 01:41:45 -070060import com.android.phone.common.CallLogAsync;
Andrew Leefb7f92e2015-02-26 16:23:32 -080061import com.android.phone.settings.SettingsConstants;
Brad Ebinger3fa43462016-04-12 16:06:48 -070062import com.android.server.sip.SipService;
Santos Cordon76aaf482015-04-08 10:58:27 -070063import com.android.services.telephony.activation.SimActivationManager;
Brad Ebinger3fa43462016-04-12 16:06:48 -070064import com.android.services.telephony.sip.SipUtil;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070065
66/**
67 * Global state for the telephony subsystem when running in the primary
68 * phone process.
69 */
Sailesh Nepalbf900542014-07-15 16:18:32 -070070public class PhoneGlobals extends ContextWrapper {
Andrew Lee83383e42014-10-31 12:42:28 -070071 public static final String LOG_TAG = "PhoneApp";
Santos Cordon7d4ddf62013-07-10 11:58:08 -070072
73 /**
74 * Phone app-wide debug level:
75 * 0 - no debug logging
76 * 1 - normal debug logging if ro.debuggable is set (which is true in
77 * "eng" and "userdebug" builds but not "user" builds)
78 * 2 - ultra-verbose debug logging
79 *
80 * Most individual classes in the phone app have a local DBG constant,
81 * typically set to
82 * (PhoneApp.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1)
83 * or else
84 * (PhoneApp.DBG_LEVEL >= 2)
85 * depending on the desired verbosity.
86 *
87 * ***** DO NOT SUBMIT WITH DBG_LEVEL > 0 *************
88 */
Andrew Lee88b51e22014-10-29 15:48:51 -070089 public static final int DBG_LEVEL = 0;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070090
91 private static final boolean DBG =
92 (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
93 private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2);
94
95 // Message codes; see mHandler below.
96 private static final int EVENT_SIM_NETWORK_LOCKED = 3;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070097 private static final int EVENT_SIM_STATE_CHANGED = 8;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070098 private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10;
99 private static final int EVENT_DATA_ROAMING_OK = 11;
100 private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12;
Brad Ebinger3fa43462016-04-12 16:06:48 -0700101 private static final int EVENT_RESTART_SIP = 13;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700102
103 // The MMI codes are also used by the InCallScreen.
104 public static final int MMI_INITIATE = 51;
105 public static final int MMI_COMPLETE = 52;
106 public static final int MMI_CANCEL = 53;
107 // Don't use message codes larger than 99 here; those are reserved for
108 // the individual Activities of the Phone UI.
109
Santos Cordone18902f2016-03-22 17:16:04 -0700110 public static final int AIRPLANE_ON = 1;
111 public static final int AIRPLANE_OFF = 0;
112
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700113 /**
114 * Allowable values for the wake lock code.
115 * SLEEP means the device can be put to sleep.
116 * PARTIAL means wake the processor, but we display can be kept off.
117 * FULL means wake both the processor and the display.
118 */
119 public enum WakeState {
120 SLEEP,
121 PARTIAL,
122 FULL
123 }
124
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700125 private static PhoneGlobals sMe;
126
127 // A few important fields we expose to the rest of the package
128 // directly (rather than thru set/get methods) for efficiency.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700129 CallController callController;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700130 CallManager mCM;
Santos Cordon63a84242013-07-23 13:32:52 -0700131 CallNotifier notifier;
132 CallerInfoCache callerInfoCache;
Santos Cordon63a84242013-07-23 13:32:52 -0700133 NotificationMgr notificationMgr;
Andrew Lee9431b832015-03-09 18:46:45 -0700134 public PhoneInterfaceManager phoneMgr;
Santos Cordon76aaf482015-04-08 10:58:27 -0700135 public SimActivationManager simActivationManager;
Jonathan Basseri6465afd2015-02-25 13:05:57 -0800136 CarrierConfigLoader configLoader;
Santos Cordon63a84242013-07-23 13:32:52 -0700137
Santos Cordon69a69192013-08-22 14:25:42 -0700138 private CallGatewayManager callGatewayManager;
Santos Cordon63a84242013-07-23 13:32:52 -0700139
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700140 static boolean sVoiceCapable = true;
141
Santos Cordonc593d002015-06-03 15:41:15 -0700142 // TODO: Remove, no longer used.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700143 CdmaPhoneCallState cdmaPhoneCallState;
144
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700145 // The currently-active PUK entry activity and progress dialog.
146 // Normally, these are the Emergency Dialer and the subsequent
147 // progress dialog. null if there is are no such objects in
148 // the foreground.
149 private Activity mPUKEntryActivity;
150 private ProgressDialog mPUKEntryProgressDialog;
151
Yorke Lee4d2db1c2014-11-06 11:37:09 -0800152 private boolean mDataDisconnectedDueToRoaming = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700153
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700154 private WakeState mWakeState = WakeState.SLEEP;
155
156 private PowerManager mPowerManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700157 private PowerManager.WakeLock mWakeLock;
158 private PowerManager.WakeLock mPartialWakeLock;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700159 private KeyguardManager mKeyguardManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700160
161 private UpdateLock mUpdateLock;
162
163 // Broadcast receiver for various intent broadcasts (see onCreate())
164 private final BroadcastReceiver mReceiver = new PhoneAppBroadcastReceiver();
165
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700166 /**
167 * The singleton OtaUtils instance used for OTASP calls.
168 *
169 * The OtaUtils instance is created lazily the first time we need to
170 * make an OTASP call, regardless of whether it's an interactive or
171 * non-interactive OTASP call.
172 */
173 public OtaUtils otaUtils;
174
175 // Following are the CDMA OTA information Objects used during OTA Call.
176 // cdmaOtaProvisionData object store static OTA information that needs
177 // to be maintained even during Slider open/close scenarios.
178 // cdmaOtaConfigData object stores configuration info to control visiblity
179 // of each OTA Screens.
180 // cdmaOtaScreenState object store OTA Screen State information.
181 public OtaUtils.CdmaOtaProvisionData cdmaOtaProvisionData;
182 public OtaUtils.CdmaOtaConfigData cdmaOtaConfigData;
183 public OtaUtils.CdmaOtaScreenState cdmaOtaScreenState;
184 public OtaUtils.CdmaOtaInCallScreenUiState cdmaOtaInCallScreenUiState;
185
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700186 Handler mHandler = new Handler() {
187 @Override
188 public void handleMessage(Message msg) {
189 PhoneConstants.State phoneState;
190 switch (msg.what) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700191 // TODO: This event should be handled by the lock screen, just
192 // like the "SIM missing" and "Sim locked" cases (bug 1804111).
193 case EVENT_SIM_NETWORK_LOCKED:
Jonathan Basseri9504c6b2015-06-04 14:23:32 -0700194 if (getCarrierConfig().getBoolean(
195 CarrierConfigManager.KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL)) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700196 // Some products don't have the concept of a "SIM network lock"
197 Log.i(LOG_TAG, "Ignoring EVENT_SIM_NETWORK_LOCKED event; "
198 + "not showing 'SIM network unlock' PIN entry screen");
199 } else {
200 // Normal case: show the "SIM network unlock" PIN entry screen.
201 // The user won't be able to do anything else until
202 // they enter a valid SIM network PIN.
203 Log.i(LOG_TAG, "show sim depersonal panel");
Tyler Gunn52a37072015-08-24 14:23:19 -0700204 IccNetworkDepersonalizationPanel.showDialog();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700205 }
206 break;
207
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700208 case EVENT_DATA_ROAMING_DISCONNECTED:
209 notificationMgr.showDataDisconnectedRoaming();
210 break;
211
212 case EVENT_DATA_ROAMING_OK:
213 notificationMgr.hideDataDisconnectedRoaming();
214 break;
215
216 case MMI_COMPLETE:
217 onMMIComplete((AsyncResult) msg.obj);
218 break;
219
220 case MMI_CANCEL:
Stuart Scottdcf40a92014-12-09 10:45:01 -0800221 PhoneUtils.cancelMmiCode(mCM.getFgPhone());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700222 break;
223
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700224 case EVENT_SIM_STATE_CHANGED:
225 // Marks the event where the SIM goes into ready state.
226 // Right now, this is only used for the PUK-unlocking
227 // process.
228 if (msg.obj.equals(IccCardConstants.INTENT_VALUE_ICC_READY)) {
229 // when the right event is triggered and there
230 // are UI objects in the foreground, we close
231 // them to display the lock panel.
232 if (mPUKEntryActivity != null) {
233 mPUKEntryActivity.finish();
234 mPUKEntryActivity = null;
235 }
236 if (mPUKEntryProgressDialog != null) {
237 mPUKEntryProgressDialog.dismiss();
238 mPUKEntryProgressDialog = null;
239 }
240 }
241 break;
242
243 case EVENT_UNSOL_CDMA_INFO_RECORD:
244 //TODO: handle message here;
245 break;
Brad Ebinger3fa43462016-04-12 16:06:48 -0700246 case EVENT_RESTART_SIP:
247 // This should only run if the Phone process crashed and was restarted. We do
248 // not want this running if the device is still in the FBE encrypted state.
249 // This is the same procedure that is triggered in the SipBroadcastReceiver
250 // upon BOOT_COMPLETED.
251 UserManager userManager = UserManager.get(sMe);
252 if (userManager != null && userManager.isUserUnlocked()) {
253 SipUtil.startSipService();
254 }
255 break;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700256 }
257 }
258 };
259
260 public PhoneGlobals(Context context) {
261 super(context);
262 sMe = this;
263 }
264
265 public void onCreate() {
266 if (VDBG) Log.v(LOG_TAG, "onCreate()...");
267
268 ContentResolver resolver = getContentResolver();
269
270 // Cache the "voice capable" flag.
271 // This flag currently comes from a resource (which is
272 // overrideable on a per-product basis):
273 sVoiceCapable =
274 getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);
275 // ...but this might eventually become a PackageManager "system
276 // feature" instead, in which case we'd do something like:
277 // sVoiceCapable =
278 // getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS);
279
Stuart Scottdcf40a92014-12-09 10:45:01 -0800280 if (mCM == null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700281 // Initialize the telephony framework
282 PhoneFactory.makeDefaultPhones(this);
283
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700284 // Start TelephonyDebugService After the default phone is created.
285 Intent intent = new Intent(this, TelephonyDebugService.class);
286 startService(intent);
287
288 mCM = CallManager.getInstance();
Stuart Scottdcf40a92014-12-09 10:45:01 -0800289 for (Phone phone : PhoneFactory.getPhones()) {
290 mCM.registerPhone(phone);
Stuart Scottdcf40a92014-12-09 10:45:01 -0800291 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700292
293 // Create the NotificationMgr singleton, which is used to display
294 // status bar icons and control other status bar behavior.
295 notificationMgr = NotificationMgr.init(this);
296
Brad Ebinger3fa43462016-04-12 16:06:48 -0700297 // If PhoneGlobals has crashed and is being restarted, then restart.
298 mHandler.sendEmptyMessage(EVENT_RESTART_SIP);
299
Anthony Lee03ebdfc2015-07-27 08:12:02 -0700300 // Create an instance of CdmaPhoneCallState and initialize it to IDLE
301 cdmaPhoneCallState = new CdmaPhoneCallState();
302 cdmaPhoneCallState.CdmaPhoneCallStateInit();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700303
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700304 // before registering for phone state changes
305 mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
306 mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG);
307 // lock used to keep the processor awake, when we don't care for the display.
308 mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
309 | PowerManager.ON_AFTER_RELEASE, LOG_TAG);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700310
311 mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
312
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700313 // Get UpdateLock to suppress system-update related events (e.g. dialog show-up)
314 // during phone calls.
315 mUpdateLock = new UpdateLock("phone");
316
317 if (DBG) Log.d(LOG_TAG, "onCreate: mUpdateLock: " + mUpdateLock);
318
319 CallLogger callLogger = new CallLogger(this, new CallLogAsync());
320
Jay Shrauner21a75342013-11-25 16:14:43 -0800321 callGatewayManager = CallGatewayManager.getInstance();
Santos Cordon69a69192013-08-22 14:25:42 -0700322
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700323 // Create the CallController singleton, which is the interface
324 // to the telephony layer for user-initiated telephony functionality
325 // (like making outgoing calls.)
Santos Cordon69a69192013-08-22 14:25:42 -0700326 callController = CallController.init(this, callLogger, callGatewayManager);
327
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700328 // Create the CallerInfoCache singleton, which remembers custom ring tone and
329 // send-to-voicemail settings.
330 //
331 // The asynchronous caching will start just after this call.
332 callerInfoCache = CallerInfoCache.init(this);
333
Stuart Scottdcf40a92014-12-09 10:45:01 -0800334 phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());
Santos Cordon406c0342013-08-28 00:07:47 -0700335
Jonathan Basseri6465afd2015-02-25 13:05:57 -0800336 configLoader = CarrierConfigLoader.init(this);
337
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700338 // Create the CallNotifer singleton, which handles
339 // asynchronous events from the telephony layer (like
340 // launching the incoming-call UI when an incoming call comes
341 // in.)
Brad Ebingera9c6b6d2016-01-07 17:24:16 -0800342 notifier = CallNotifier.init(this);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700343
Stuart Scottdcf40a92014-12-09 10:45:01 -0800344 PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700345
346 // register for MMI/USSD
347 mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);
348
349 // register connection tracking to PhoneUtils
350 PhoneUtils.initializeConnectionHandler(mCM);
351
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700352 // Register for misc other intent broadcasts.
353 IntentFilter intentFilter =
354 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700355 intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700356 intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
357 intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
358 intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
359 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700360 registerReceiver(mReceiver, intentFilter);
361
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700362 //set the default values for the preferences in the phone.
363 PreferenceManager.setDefaultValues(this, R.xml.network_setting, false);
364
365 PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false);
366
367 // Make sure the audio mode (along with some
368 // audio-mode-related state of our own) is initialized
369 // correctly, given the current state of the phone.
370 PhoneUtils.setAudioMode(mCM);
371 }
372
Santos Cordon52bc81b2014-10-07 19:55:12 -0700373 cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData();
374 cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData();
375 cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState();
376 cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700377
Santos Cordon76aaf482015-04-08 10:58:27 -0700378 simActivationManager = new SimActivationManager();
379
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700380 // XXX pre-load the SimProvider so that it's ready
381 resolver.getType(Uri.parse("content://icc/adn"));
382
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700383 // TODO: Register for Cdma Information Records
384 // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null);
385
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700386 // Read HAC settings and configure audio hardware
387 if (getResources().getBoolean(R.bool.hac_enabled)) {
Stuart Scottdcf40a92014-12-09 10:45:01 -0800388 int hac = android.provider.Settings.System.getInt(
389 getContentResolver(),
390 android.provider.Settings.System.HEARING_AID,
391 0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700392 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
Andrew Leefb7f92e2015-02-26 16:23:32 -0800393 audioManager.setParameter(SettingsConstants.HAC_KEY,
394 hac == SettingsConstants.HAC_ENABLED
395 ? SettingsConstants.HAC_VAL_ON : SettingsConstants.HAC_VAL_OFF);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700396 }
Santos Cordonff506f52013-11-21 19:13:19 -0800397 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700398
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700399 /**
400 * Returns the singleton instance of the PhoneApp.
401 */
Sailesh Nepal1eaf22b2014-02-22 17:00:49 -0800402 public static PhoneGlobals getInstance() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700403 if (sMe == null) {
404 throw new IllegalStateException("No PhoneGlobals here!");
405 }
406 return sMe;
407 }
408
409 /**
410 * Returns the singleton instance of the PhoneApp if running as the
411 * primary user, otherwise null.
412 */
413 static PhoneGlobals getInstanceIfPrimary() {
414 return sMe;
415 }
416
417 /**
Stuart Scottdcf40a92014-12-09 10:45:01 -0800418 * Returns the default phone.
419 *
Andrew Lee385019f2014-11-24 14:19:50 -0800420 * WARNING: This method should be used carefully, now that there may be multiple phones.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700421 */
Andrew Lee83383e42014-10-31 12:42:28 -0700422 public static Phone getPhone() {
Stuart Scottdcf40a92014-12-09 10:45:01 -0800423 return PhoneFactory.getDefaultPhone();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700424 }
425
Andrew Lee2fcb6c32014-12-04 14:52:35 -0800426 public static Phone getPhone(int subId) {
427 return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
Andrew Lee385019f2014-11-24 14:19:50 -0800428 }
429
Santos Cordonde10b752013-09-19 04:11:33 -0700430 /* package */ CallManager getCallManager() {
431 return mCM;
432 }
433
Chris Manton4e9fa912015-06-19 11:26:57 -0700434 public PersistableBundle getCarrierConfig() {
Shishir Agrawald3480e02016-01-25 13:05:49 -0800435 return getCarrierConfigForSubId(SubscriptionManager.getDefaultSubscriptionId());
Jonathan Basseri89b0ab42015-05-01 10:52:40 -0700436 }
437
Chris Manton4e9fa912015-06-19 11:26:57 -0700438 public PersistableBundle getCarrierConfigForSubId(int subId) {
Jonathan Basseri89b0ab42015-05-01 10:52:40 -0700439 return configLoader.getConfigForSubId(subId);
Junda Liu605148f2015-04-28 15:23:40 -0700440 }
441
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700442 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700443 * Handles OTASP-related events from the telephony layer.
444 *
445 * While an OTASP call is active, the CallNotifier forwards
446 * OTASP-related telephony events to this method.
447 */
448 void handleOtaspEvent(Message msg) {
449 if (DBG) Log.d(LOG_TAG, "handleOtaspEvent(message " + msg + ")...");
450
451 if (otaUtils == null) {
452 // We shouldn't be getting OTASP events without ever
453 // having started the OTASP call in the first place!
454 Log.w(LOG_TAG, "handleOtaEvents: got an event but otaUtils is null! "
455 + "message = " + msg);
456 return;
457 }
458
459 otaUtils.onOtaProvisionStatusChanged((AsyncResult) msg.obj);
460 }
461
462 /**
463 * Similarly, handle the disconnect event of an OTASP call
464 * by forwarding it to the OtaUtils instance.
465 */
466 /* package */ void handleOtaspDisconnect() {
467 if (DBG) Log.d(LOG_TAG, "handleOtaspDisconnect()...");
468
469 if (otaUtils == null) {
470 // We shouldn't be getting OTASP events without ever
471 // having started the OTASP call in the first place!
472 Log.w(LOG_TAG, "handleOtaspDisconnect: otaUtils is null!");
473 return;
474 }
475
476 otaUtils.onOtaspDisconnect();
477 }
478
479 /**
480 * Sets the activity responsible for un-PUK-blocking the device
481 * so that we may close it when we receive a positive result.
482 * mPUKEntryActivity is also used to indicate to the device that
483 * we are trying to un-PUK-lock the phone. In other words, iff
484 * it is NOT null, then we are trying to unlock and waiting for
485 * the SIM to move to READY state.
486 *
487 * @param activity is the activity to close when PUK has
488 * finished unlocking. Can be set to null to indicate the unlock
489 * or SIM READYing process is over.
490 */
491 void setPukEntryActivity(Activity activity) {
492 mPUKEntryActivity = activity;
493 }
494
495 Activity getPUKEntryActivity() {
496 return mPUKEntryActivity;
497 }
498
499 /**
500 * Sets the dialog responsible for notifying the user of un-PUK-
501 * blocking - SIM READYing progress, so that we may dismiss it
502 * when we receive a positive result.
503 *
504 * @param dialog indicates the progress dialog informing the user
505 * of the state of the device. Dismissed upon completion of
506 * READYing process
507 */
508 void setPukEntryProgressDialog(ProgressDialog dialog) {
509 mPUKEntryProgressDialog = dialog;
510 }
511
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700512 /**
513 * Controls whether or not the screen is allowed to sleep.
514 *
515 * Once sleep is allowed (WakeState is SLEEP), it will rely on the
516 * settings for the poke lock to determine when to timeout and let
517 * the device sleep {@link PhoneGlobals#setScreenTimeout}.
518 *
519 * @param ws tells the device to how to wake.
520 */
521 /* package */ void requestWakeState(WakeState ws) {
522 if (VDBG) Log.d(LOG_TAG, "requestWakeState(" + ws + ")...");
523 synchronized (this) {
524 if (mWakeState != ws) {
525 switch (ws) {
526 case PARTIAL:
527 // acquire the processor wake lock, and release the FULL
528 // lock if it is being held.
529 mPartialWakeLock.acquire();
530 if (mWakeLock.isHeld()) {
531 mWakeLock.release();
532 }
533 break;
534 case FULL:
535 // acquire the full wake lock, and release the PARTIAL
536 // lock if it is being held.
537 mWakeLock.acquire();
538 if (mPartialWakeLock.isHeld()) {
539 mPartialWakeLock.release();
540 }
541 break;
542 case SLEEP:
543 default:
544 // release both the PARTIAL and FULL locks.
545 if (mWakeLock.isHeld()) {
546 mWakeLock.release();
547 }
548 if (mPartialWakeLock.isHeld()) {
549 mPartialWakeLock.release();
550 }
551 break;
552 }
553 mWakeState = ws;
554 }
555 }
556 }
557
558 /**
559 * If we are not currently keeping the screen on, then poke the power
560 * manager to wake up the screen for the user activity timeout duration.
561 */
562 /* package */ void wakeUpScreen() {
563 synchronized (this) {
564 if (mWakeState == WakeState.SLEEP) {
565 if (DBG) Log.d(LOG_TAG, "pulse screen lock");
Dianne Hackborn148769b2015-07-13 17:55:47 -0700566 mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.phone:WAKE");
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700567 }
568 }
569 }
570
571 /**
572 * Sets the wake state and screen timeout based on the current state
573 * of the phone, and the current state of the in-call UI.
574 *
575 * This method is a "UI Policy" wrapper around
576 * {@link PhoneGlobals#requestWakeState} and {@link PhoneGlobals#setScreenTimeout}.
577 *
578 * It's safe to call this method regardless of the state of the Phone
579 * (e.g. whether or not it's idle), and regardless of the state of the
580 * Phone UI (e.g. whether or not the InCallScreen is active.)
581 */
582 /* package */ void updateWakeState() {
583 PhoneConstants.State state = mCM.getState();
584
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700585 // True if the speakerphone is in use. (If so, we *always* use
586 // the default timeout. Since the user is obviously not holding
587 // the phone up to his/her face, we don't need to worry about
588 // false touches, and thus don't need to turn the screen off so
589 // aggressively.)
590 // Note that we need to make a fresh call to this method any
591 // time the speaker state changes. (That happens in
592 // PhoneUtils.turnOnSpeaker().)
593 boolean isSpeakerInUse = (state == PhoneConstants.State.OFFHOOK) && PhoneUtils.isSpeakerOn(this);
594
595 // TODO (bug 1440854): The screen timeout *might* also need to
596 // depend on the bluetooth state, but this isn't as clear-cut as
597 // the speaker state (since while using BT it's common for the
598 // user to put the phone straight into a pocket, in which case the
599 // timeout should probably still be short.)
600
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700601 // Decide whether to force the screen on or not.
602 //
603 // Force the screen to be on if the phone is ringing or dialing,
604 // or if we're displaying the "Call ended" UI for a connection in
605 // the "disconnected" state.
606 // However, if the phone is disconnected while the user is in the
607 // middle of selecting a quick response message, we should not force
608 // the screen to be on.
609 //
610 boolean isRinging = (state == PhoneConstants.State.RINGING);
Stuart Scottdcf40a92014-12-09 10:45:01 -0800611 boolean isDialing = (mCM.getFgPhone().getForegroundCall().getState() == Call.State.DIALING);
Jay Shrauner6fe8fd62013-09-16 19:39:30 -0700612 boolean keepScreenOn = isRinging || isDialing;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700613 // keepScreenOn == true means we'll hold a full wake lock:
614 requestWakeState(keepScreenOn ? WakeState.FULL : WakeState.SLEEP);
615 }
616
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700617 KeyguardManager getKeyguardManager() {
618 return mKeyguardManager;
619 }
620
621 private void onMMIComplete(AsyncResult r) {
622 if (VDBG) Log.d(LOG_TAG, "onMMIComplete()...");
623 MmiCode mmiCode = (MmiCode) r.result;
Stuart Scottdcf40a92014-12-09 10:45:01 -0800624 PhoneUtils.displayMMIComplete(mmiCode.getPhone(), getInstance(), mmiCode, null, null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700625 }
626
Stuart Scottdcf40a92014-12-09 10:45:01 -0800627 private void initForNewRadioTechnology(int phoneId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700628 if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology...");
629
Stuart Scottdcf40a92014-12-09 10:45:01 -0800630 final Phone phone = PhoneFactory.getPhone(phoneId);
Santos Cordonc593d002015-06-03 15:41:15 -0700631 if (phone == null || !TelephonyCapabilities.supportsOtasp(phone)) {
632 // Clean up OTA for non-CDMA since it is only valid for CDMA.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700633 clearOtaState();
634 }
635
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700636 notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700637 }
638
Santos Cordone18902f2016-03-22 17:16:04 -0700639 private void handleAirplaneModeChange(int newMode) {
640 if (newMode == AIRPLANE_ON) {
641 // If we are trying to turn off the radio, make sure there are no active
642 // emergency calls. If there are, switch airplane mode back to off.
643 if (PhoneUtils.isInEmergencyCall(mCM)) {
644 // Switch airplane mode back to off.
645 ConnectivityManager.from(this).setAirplaneMode(false);
646 Toast.makeText(this, R.string.radio_off_during_emergency_call, Toast.LENGTH_LONG)
647 .show();
648 Log.i(LOG_TAG, "Ignoring airplane mode: emergency call. Turning airplane off");
649 } else {
650 Log.i(LOG_TAG, "Turning radio off - airplane");
651 PhoneUtils.setRadioPower(false);
652 }
653 } else {
654 Log.i(LOG_TAG, "Turning radio on - airplane");
655 PhoneUtils.setRadioPower(true);
656 }
657 }
658
Santos Cordon593ab382013-08-06 21:58:23 -0700659 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700660 * Receiver for misc intent broadcasts the Phone app cares about.
661 */
662 private class PhoneAppBroadcastReceiver extends BroadcastReceiver {
663 @Override
664 public void onReceive(Context context, Intent intent) {
665 String action = intent.getAction();
666 if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
Santos Cordone18902f2016-03-22 17:16:04 -0700667 int airplaneMode = Settings.Global.getInt(getContentResolver(),
668 Settings.Global.AIRPLANE_MODE_ON, AIRPLANE_OFF);
669 // Treat any non-OFF values as ON.
670 if (airplaneMode != AIRPLANE_OFF) {
671 airplaneMode = AIRPLANE_ON;
672 }
673 handleAirplaneModeChange(airplaneMode);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700674 } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
Stuart Scottdcf40a92014-12-09 10:45:01 -0800675 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
676 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
677 int phoneId = SubscriptionManager.getPhoneId(subId);
678 String state = intent.getStringExtra(PhoneConstants.STATE_KEY);
679 if (VDBG) {
680 Log.d(LOG_TAG, "mReceiver: ACTION_ANY_DATA_CONNECTION_STATE_CHANGED");
681 Log.d(LOG_TAG, "- state: " + state);
682 Log.d(LOG_TAG, "- reason: "
683 + intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY));
684 Log.d(LOG_TAG, "- subId: " + subId);
685 Log.d(LOG_TAG, "- phoneId: " + phoneId);
686 }
687 Phone phone = SubscriptionManager.isValidPhoneId(phoneId) ?
688 PhoneFactory.getPhone(phoneId) : PhoneFactory.getDefaultPhone();
Santos Cordonc593d002015-06-03 15:41:15 -0700689
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700690 // The "data disconnected due to roaming" notification is shown
691 // if (a) you have the "data roaming" feature turned off, and
692 // (b) you just lost data connectivity because you're roaming.
693 boolean disconnectedDueToRoaming =
694 !phone.getDataRoamingEnabled()
Stuart Scottdcf40a92014-12-09 10:45:01 -0800695 && PhoneConstants.DataState.DISCONNECTED.equals(state)
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700696 && Phone.REASON_ROAMING_ON.equals(
697 intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY));
Yorke Lee4d2db1c2014-11-06 11:37:09 -0800698 if (mDataDisconnectedDueToRoaming != disconnectedDueToRoaming) {
699 mDataDisconnectedDueToRoaming = disconnectedDueToRoaming;
700 mHandler.sendEmptyMessage(disconnectedDueToRoaming
701 ? EVENT_DATA_ROAMING_DISCONNECTED : EVENT_DATA_ROAMING_OK);
702 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700703 } else if ((action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) &&
704 (mPUKEntryActivity != null)) {
705 // if an attempt to un-PUK-lock the device was made, while we're
706 // receiving this state change notification, notify the handler.
707 // NOTE: This is ONLY triggered if an attempt to un-PUK-lock has
708 // been attempted.
709 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SIM_STATE_CHANGED,
710 intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)));
711 } else if (action.equals(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED)) {
712 String newPhone = intent.getStringExtra(PhoneConstants.PHONE_NAME_KEY);
Stuart Scottdcf40a92014-12-09 10:45:01 -0800713 int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY,
714 SubscriptionManager.INVALID_PHONE_INDEX);
715 Log.d(LOG_TAG, "Radio technology switched. Now " + newPhone + " (" + phoneId
716 + ") is active.");
717 initForNewRadioTechnology(phoneId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700718 } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) {
719 handleServiceStateChanged(intent);
720 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
Stuart Scottdcf40a92014-12-09 10:45:01 -0800721 if (TelephonyCapabilities.supportsEcm(mCM.getFgPhone())) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700722 Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp.");
723 // Start Emergency Callback Mode service
724 if (intent.getBooleanExtra("phoneinECMState", false)) {
725 context.startService(new Intent(context,
726 EmergencyCallbackModeService.class));
727 }
728 } else {
729 // It doesn't make sense to get ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
730 // on a device that doesn't support ECM in the first place.
731 Log.e(LOG_TAG, "Got ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, "
Stuart Scottdcf40a92014-12-09 10:45:01 -0800732 + "but ECM isn't supported for phone: "
733 + mCM.getFgPhone().getPhoneName());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700734 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700735 }
736 }
737 }
738
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700739 private void handleServiceStateChanged(Intent intent) {
740 /**
741 * This used to handle updating EriTextWidgetProvider this routine
742 * and and listening for ACTION_SERVICE_STATE_CHANGED intents could
743 * be removed. But leaving just in case it might be needed in the near
744 * future.
745 */
746
747 // If service just returned, start sending out the queued messages
Santos Cordonc593d002015-06-03 15:41:15 -0700748 Bundle extras = intent.getExtras();
749 if (extras != null) {
750 ServiceState ss = ServiceState.newFromBundle(extras);
751 if (ss != null) {
752 int state = ss.getState();
753 notificationMgr.updateNetworkSelection(state);
754 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700755 }
756 }
757
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700758 // it is safe to call clearOtaState() even if the InCallScreen isn't active
759 public void clearOtaState() {
760 if (DBG) Log.d(LOG_TAG, "- clearOtaState ...");
Jay Shrauner6fe8fd62013-09-16 19:39:30 -0700761 if (otaUtils != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700762 otaUtils.cleanOtaScreen(true);
763 if (DBG) Log.d(LOG_TAG, " - clearOtaState clears OTA screen");
764 }
765 }
766
767 // it is safe to call dismissOtaDialogs() even if the InCallScreen isn't active
768 public void dismissOtaDialogs() {
769 if (DBG) Log.d(LOG_TAG, "- dismissOtaDialogs ...");
Jay Shrauner6fe8fd62013-09-16 19:39:30 -0700770 if (otaUtils != null) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700771 otaUtils.dismissAllOtaDialogs();
772 if (DBG) Log.d(LOG_TAG, " - dismissOtaDialogs clears OTA dialogs");
773 }
774 }
775
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700776 /**
Tyler Gunn9c1071f2014-12-09 10:07:54 -0800777 * Triggers a refresh of the message waiting (voicemail) indicator.
778 *
779 * @param subId the subscription id we should refresh the notification for.
780 */
781 public void refreshMwiIndicator(int subId) {
782 notificationMgr.refreshMwi(subId);
783 }
784
785 /**
Nancy Chenbb49d412015-07-23 13:54:16 -0700786 * Dismisses the message waiting (voicemail) indicator.
787 *
788 * @param subId the subscription id we should dismiss the notification for.
789 */
790 public void clearMwiIndicator(int subId) {
791 notificationMgr.updateMwi(subId, false);
792 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700793}