1 /*
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 
17 package com.android.phone;
18 
19 import android.app.Activity;
20 import android.app.KeyguardManager;
21 import android.app.PendingIntent;
22 import android.app.ProgressDialog;
23 import android.app.TaskStackBuilder;
24 import android.bluetooth.BluetoothAdapter;
25 import android.bluetooth.IBluetoothHeadsetPhone;
26 import android.content.BroadcastReceiver;
27 import android.content.ComponentName;
28 import android.content.ContentResolver;
29 import android.content.Context;
30 import android.content.ContextWrapper;
31 import android.content.Intent;
32 import android.content.IntentFilter;
33 import android.content.ServiceConnection;
34 import android.media.AudioManager;
35 import android.net.Uri;
36 import android.os.AsyncResult;
37 import android.os.Handler;
38 import android.os.IBinder;
39 import android.os.IPowerManager;
40 import android.os.Message;
41 import android.os.PowerManager;
42 import android.os.RemoteException;
43 import android.os.ServiceManager;
44 import android.os.SystemClock;
45 import android.os.SystemProperties;
46 import android.os.UpdateLock;
47 import android.os.UserHandle;
48 import android.preference.PreferenceManager;
49 import android.provider.Settings.System;
50 import android.telephony.ServiceState;
51 import android.telephony.SubscriptionInfo;
52 import android.telephony.SubscriptionManager;
53 import android.util.Log;
54 
55 import com.android.internal.telephony.Call;
56 import com.android.internal.telephony.CallManager;
57 import com.android.internal.telephony.IccCard;
58 import com.android.internal.telephony.IccCardConstants;
59 import com.android.internal.telephony.MmiCode;
60 import com.android.internal.telephony.Phone;
61 import com.android.internal.telephony.PhoneConstants;
62 import com.android.internal.telephony.PhoneFactory;
63 import com.android.internal.telephony.SubscriptionController;
64 import com.android.internal.telephony.TelephonyCapabilities;
65 import com.android.internal.telephony.TelephonyIntents;
66 import com.android.phone.common.CallLogAsync;
67 import com.android.server.sip.SipService;
68 
69 import java.util.ArrayList;
70 import java.util.List;
71 
72 /**
73  * Global state for the telephony subsystem when running in the primary
74  * phone process.
75  */
76 public class PhoneGlobals extends ContextWrapper {
77     public static final String LOG_TAG = "PhoneApp";
78 
79     /**
80      * Phone app-wide debug level:
81      *   0 - no debug logging
82      *   1 - normal debug logging if ro.debuggable is set (which is true in
83      *       "eng" and "userdebug" builds but not "user" builds)
84      *   2 - ultra-verbose debug logging
85      *
86      * Most individual classes in the phone app have a local DBG constant,
87      * typically set to
88      *   (PhoneApp.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1)
89      * or else
90      *   (PhoneApp.DBG_LEVEL >= 2)
91      * depending on the desired verbosity.
92      *
93      * ***** DO NOT SUBMIT WITH DBG_LEVEL > 0 *************
94      */
95     public static final int DBG_LEVEL = 0;
96 
97     private static final boolean DBG =
98             (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
99     private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2);
100 
101     // Message codes; see mHandler below.
102     private static final int EVENT_SIM_NETWORK_LOCKED = 3;
103     private static final int EVENT_SIM_STATE_CHANGED = 8;
104     private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10;
105     private static final int EVENT_DATA_ROAMING_OK = 11;
106     private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12;
107     private static final int EVENT_DOCK_STATE_CHANGED = 13;
108     private static final int EVENT_START_SIP_SERVICE = 14;
109 
110     // The MMI codes are also used by the InCallScreen.
111     public static final int MMI_INITIATE = 51;
112     public static final int MMI_COMPLETE = 52;
113     public static final int MMI_CANCEL = 53;
114     // Don't use message codes larger than 99 here; those are reserved for
115     // the individual Activities of the Phone UI.
116 
117     /**
118      * Allowable values for the wake lock code.
119      *   SLEEP means the device can be put to sleep.
120      *   PARTIAL means wake the processor, but we display can be kept off.
121      *   FULL means wake both the processor and the display.
122      */
123     public enum WakeState {
124         SLEEP,
125         PARTIAL,
126         FULL
127     }
128 
129     /**
130      * Intent Action used for hanging up the current call from Notification bar. This will
131      * choose first ringing call, first active call, or first background call (typically in
132      * HOLDING state).
133      */
134     public static final String ACTION_HANG_UP_ONGOING_CALL =
135             "com.android.phone.ACTION_HANG_UP_ONGOING_CALL";
136 
137     private static PhoneGlobals sMe;
138 
139     // A few important fields we expose to the rest of the package
140     // directly (rather than thru set/get methods) for efficiency.
141     CallController callController;
142     CallManager mCM;
143     CallNotifier notifier;
144     CallerInfoCache callerInfoCache;
145     NotificationMgr notificationMgr;
146     PhoneInterfaceManager phoneMgr;
147 
148     private BluetoothManager bluetoothManager;
149     private CallGatewayManager callGatewayManager;
150     private CallStateMonitor callStateMonitor;
151 
152     static int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
153     static boolean sVoiceCapable = true;
154 
155     // Internal PhoneApp Call state tracker
156     CdmaPhoneCallState cdmaPhoneCallState;
157 
158     // The currently-active PUK entry activity and progress dialog.
159     // Normally, these are the Emergency Dialer and the subsequent
160     // progress dialog.  null if there is are no such objects in
161     // the foreground.
162     private Activity mPUKEntryActivity;
163     private ProgressDialog mPUKEntryProgressDialog;
164 
165     private boolean mIsSimPinEnabled;
166     private String mCachedSimPin;
167 
168     // True if we are beginning a call, but the phone state has not changed yet
169     private boolean mBeginningCall;
170     private boolean mDataDisconnectedDueToRoaming = false;
171 
172     // Last phone state seen by updatePhoneState()
173     private PhoneConstants.State mLastPhoneState = PhoneConstants.State.IDLE;
174 
175     private WakeState mWakeState = WakeState.SLEEP;
176 
177     private PowerManager mPowerManager;
178     private IPowerManager mPowerManagerService;
179     private PowerManager.WakeLock mWakeLock;
180     private PowerManager.WakeLock mPartialWakeLock;
181     private KeyguardManager mKeyguardManager;
182 
183     private UpdateLock mUpdateLock;
184 
185     // Broadcast receiver for various intent broadcasts (see onCreate())
186     private final BroadcastReceiver mReceiver = new PhoneAppBroadcastReceiver();
187 
188     /** boolean indicating restoring mute state on InCallScreen.onResume() */
189     private boolean mShouldRestoreMuteOnInCallResume;
190 
191     /**
192      * The singleton OtaUtils instance used for OTASP calls.
193      *
194      * The OtaUtils instance is created lazily the first time we need to
195      * make an OTASP call, regardless of whether it's an interactive or
196      * non-interactive OTASP call.
197      */
198     public OtaUtils otaUtils;
199 
200     // Following are the CDMA OTA information Objects used during OTA Call.
201     // cdmaOtaProvisionData object store static OTA information that needs
202     // to be maintained even during Slider open/close scenarios.
203     // cdmaOtaConfigData object stores configuration info to control visiblity
204     // of each OTA Screens.
205     // cdmaOtaScreenState object store OTA Screen State information.
206     public OtaUtils.CdmaOtaProvisionData cdmaOtaProvisionData;
207     public OtaUtils.CdmaOtaConfigData cdmaOtaConfigData;
208     public OtaUtils.CdmaOtaScreenState cdmaOtaScreenState;
209     public OtaUtils.CdmaOtaInCallScreenUiState cdmaOtaInCallScreenUiState;
210 
211     /**
212      * Set the restore mute state flag. Used when we are setting the mute state
213      * OUTSIDE of user interaction {@link PhoneUtils#startNewCall(Phone)}
214      */
setRestoreMuteOnInCallResume(boolean mode)215     /*package*/void setRestoreMuteOnInCallResume (boolean mode) {
216         mShouldRestoreMuteOnInCallResume = mode;
217     }
218 
219     Handler mHandler = new Handler() {
220         @Override
221         public void handleMessage(Message msg) {
222             PhoneConstants.State phoneState;
223             switch (msg.what) {
224                 // Starts the SIP service. It's a no-op if SIP API is not supported
225                 // on the deivce.
226                 // TODO: Having the phone process host the SIP service is only
227                 // temporary. Will move it to a persistent communication process
228                 // later.
229                 case EVENT_START_SIP_SERVICE:
230                     SipService.start(getApplicationContext());
231                     break;
232 
233                 // TODO: This event should be handled by the lock screen, just
234                 // like the "SIM missing" and "Sim locked" cases (bug 1804111).
235                 case EVENT_SIM_NETWORK_LOCKED:
236                     if (getResources().getBoolean(R.bool.ignore_sim_network_locked_events)) {
237                         // Some products don't have the concept of a "SIM network lock"
238                         Log.i(LOG_TAG, "Ignoring EVENT_SIM_NETWORK_LOCKED event; "
239                               + "not showing 'SIM network unlock' PIN entry screen");
240                     } else {
241                         // Normal case: show the "SIM network unlock" PIN entry screen.
242                         // The user won't be able to do anything else until
243                         // they enter a valid SIM network PIN.
244                         Log.i(LOG_TAG, "show sim depersonal panel");
245                         IccNetworkDepersonalizationPanel ndpPanel =
246                                 new IccNetworkDepersonalizationPanel(PhoneGlobals.getInstance());
247                         ndpPanel.show();
248                     }
249                     break;
250 
251                 case EVENT_DATA_ROAMING_DISCONNECTED:
252                     notificationMgr.showDataDisconnectedRoaming();
253                     break;
254 
255                 case EVENT_DATA_ROAMING_OK:
256                     notificationMgr.hideDataDisconnectedRoaming();
257                     break;
258 
259                 case MMI_COMPLETE:
260                     onMMIComplete((AsyncResult) msg.obj);
261                     break;
262 
263                 case MMI_CANCEL:
264                     PhoneUtils.cancelMmiCode(mCM.getFgPhone());
265                     break;
266 
267                 case EVENT_SIM_STATE_CHANGED:
268                     // Marks the event where the SIM goes into ready state.
269                     // Right now, this is only used for the PUK-unlocking
270                     // process.
271                     if (msg.obj.equals(IccCardConstants.INTENT_VALUE_ICC_READY)) {
272                         // when the right event is triggered and there
273                         // are UI objects in the foreground, we close
274                         // them to display the lock panel.
275                         if (mPUKEntryActivity != null) {
276                             mPUKEntryActivity.finish();
277                             mPUKEntryActivity = null;
278                         }
279                         if (mPUKEntryProgressDialog != null) {
280                             mPUKEntryProgressDialog.dismiss();
281                             mPUKEntryProgressDialog = null;
282                         }
283                     }
284                     break;
285 
286                 case EVENT_UNSOL_CDMA_INFO_RECORD:
287                     //TODO: handle message here;
288                     break;
289 
290                 case EVENT_DOCK_STATE_CHANGED:
291                     // If the phone is docked/undocked during a call, and no wired or BT headset
292                     // is connected: turn on/off the speaker accordingly.
293                     boolean inDockMode = false;
294                     if (mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
295                         inDockMode = true;
296                     }
297                     if (VDBG) Log.d(LOG_TAG, "received EVENT_DOCK_STATE_CHANGED. Phone inDock = "
298                             + inDockMode);
299 
300                     phoneState = mCM.getState();
301                     if (phoneState == PhoneConstants.State.OFFHOOK &&
302                             !bluetoothManager.isBluetoothHeadsetAudioOn()) {
303                         PhoneUtils.turnOnSpeaker(getApplicationContext(), inDockMode, true);
304                     }
305                     break;
306             }
307         }
308     };
309 
PhoneGlobals(Context context)310     public PhoneGlobals(Context context) {
311         super(context);
312         sMe = this;
313     }
314 
onCreate()315     public void onCreate() {
316         if (VDBG) Log.v(LOG_TAG, "onCreate()...");
317 
318         ContentResolver resolver = getContentResolver();
319 
320         // Cache the "voice capable" flag.
321         // This flag currently comes from a resource (which is
322         // overrideable on a per-product basis):
323         sVoiceCapable =
324                 getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);
325         // ...but this might eventually become a PackageManager "system
326         // feature" instead, in which case we'd do something like:
327         // sVoiceCapable =
328         //   getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS);
329 
330         if (mCM == null) {
331             // Initialize the telephony framework
332             PhoneFactory.makeDefaultPhones(this);
333 
334             // Start TelephonyDebugService After the default phone is created.
335             Intent intent = new Intent(this, TelephonyDebugService.class);
336             startService(intent);
337 
338             mCM = CallManager.getInstance();
339             boolean hasCdmaPhoneType = false;
340             for (Phone phone : PhoneFactory.getPhones()) {
341                 mCM.registerPhone(phone);
342                 if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
343                     hasCdmaPhoneType = true;
344                 }
345             }
346 
347             // Create the NotificationMgr singleton, which is used to display
348             // status bar icons and control other status bar behavior.
349             notificationMgr = NotificationMgr.init(this);
350 
351             mHandler.sendEmptyMessage(EVENT_START_SIP_SERVICE);
352 
353             if (hasCdmaPhoneType) {
354                 // Create an instance of CdmaPhoneCallState and initialize it to IDLE
355                 cdmaPhoneCallState = new CdmaPhoneCallState();
356                 cdmaPhoneCallState.CdmaPhoneCallStateInit();
357             }
358 
359             // before registering for phone state changes
360             mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
361             mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG);
362             // lock used to keep the processor awake, when we don't care for the display.
363             mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
364                     | PowerManager.ON_AFTER_RELEASE, LOG_TAG);
365 
366             mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
367 
368             // get a handle to the service so that we can use it later when we
369             // want to set the poke lock.
370             mPowerManagerService = IPowerManager.Stub.asInterface(
371                     ServiceManager.getService("power"));
372 
373             // Get UpdateLock to suppress system-update related events (e.g. dialog show-up)
374             // during phone calls.
375             mUpdateLock = new UpdateLock("phone");
376 
377             if (DBG) Log.d(LOG_TAG, "onCreate: mUpdateLock: " + mUpdateLock);
378 
379             CallLogger callLogger = new CallLogger(this, new CallLogAsync());
380 
381             callGatewayManager = CallGatewayManager.getInstance();
382 
383             // Create the CallController singleton, which is the interface
384             // to the telephony layer for user-initiated telephony functionality
385             // (like making outgoing calls.)
386             callController = CallController.init(this, callLogger, callGatewayManager);
387 
388             // Create the CallerInfoCache singleton, which remembers custom ring tone and
389             // send-to-voicemail settings.
390             //
391             // The asynchronous caching will start just after this call.
392             callerInfoCache = CallerInfoCache.init(this);
393 
394             // Monitors call activity from the telephony layer
395             callStateMonitor = new CallStateMonitor(mCM);
396 
397             // Bluetooth manager
398             bluetoothManager = new BluetoothManager();
399 
400             phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());
401 
402             // Create the CallNotifer singleton, which handles
403             // asynchronous events from the telephony layer (like
404             // launching the incoming-call UI when an incoming call comes
405             // in.)
406             notifier = CallNotifier.init(this, callLogger, callStateMonitor, bluetoothManager);
407 
408             PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED);
409 
410             // register for MMI/USSD
411             mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);
412 
413             // register connection tracking to PhoneUtils
414             PhoneUtils.initializeConnectionHandler(mCM);
415 
416             // Register for misc other intent broadcasts.
417             IntentFilter intentFilter =
418                     new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
419             intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
420             intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
421             intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
422             intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
423             intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
424             intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
425             registerReceiver(mReceiver, intentFilter);
426 
427             //set the default values for the preferences in the phone.
428             PreferenceManager.setDefaultValues(this, R.xml.network_setting, false);
429 
430             PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false);
431 
432             // Make sure the audio mode (along with some
433             // audio-mode-related state of our own) is initialized
434             // correctly, given the current state of the phone.
435             PhoneUtils.setAudioMode(mCM);
436         }
437 
438         cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData();
439         cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData();
440         cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState();
441         cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState();
442 
443         // XXX pre-load the SimProvider so that it's ready
444         resolver.getType(Uri.parse("content://icc/adn"));
445 
446         // start with the default value to set the mute state.
447         mShouldRestoreMuteOnInCallResume = false;
448 
449         // TODO: Register for Cdma Information Records
450         // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null);
451 
452         // Read HAC settings and configure audio hardware
453         if (getResources().getBoolean(R.bool.hac_enabled)) {
454             int hac = android.provider.Settings.System.getInt(
455                     getContentResolver(),
456                     android.provider.Settings.System.HEARING_AID,
457                     0);
458             AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
459             audioManager.setParameter(CallFeaturesSetting.HAC_KEY, hac != 0 ?
460                                       CallFeaturesSetting.HAC_VAL_ON :
461                                       CallFeaturesSetting.HAC_VAL_OFF);
462         }
463     }
464 
465     /**
466      * Returns the singleton instance of the PhoneApp.
467      */
getInstance()468     public static PhoneGlobals getInstance() {
469         if (sMe == null) {
470             throw new IllegalStateException("No PhoneGlobals here!");
471         }
472         return sMe;
473     }
474 
475     /**
476      * Returns the singleton instance of the PhoneApp if running as the
477      * primary user, otherwise null.
478      */
getInstanceIfPrimary()479     static PhoneGlobals getInstanceIfPrimary() {
480         return sMe;
481     }
482 
483     /**
484      * Returns the default phone.
485      *
486      * WARNING: This method should be used carefully, now that there may be multiple phones.
487      */
getPhone()488     public static Phone getPhone() {
489         return PhoneFactory.getDefaultPhone();
490     }
491 
getPhone(int subId)492     public static Phone getPhone(int subId) {
493         return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
494     }
495 
getBluetoothManager()496     /* package */ BluetoothManager getBluetoothManager() {
497         return bluetoothManager;
498     }
499 
getCallManager()500     /* package */ CallManager getCallManager() {
501         return mCM;
502     }
503 
504     /**
505      * Returns PendingIntent for hanging up ongoing phone call. This will typically be used from
506      * Notification context.
507      */
createHangUpOngoingCallPendingIntent(Context context)508     /* package */ static PendingIntent createHangUpOngoingCallPendingIntent(Context context) {
509         Intent intent = new Intent(PhoneGlobals.ACTION_HANG_UP_ONGOING_CALL, null,
510                 context, NotificationBroadcastReceiver.class);
511         return PendingIntent.getBroadcast(context, 0, intent, 0);
512     }
513 
isSimPinEnabled()514     boolean isSimPinEnabled() {
515         return mIsSimPinEnabled;
516     }
517 
authenticateAgainstCachedSimPin(String pin)518     boolean authenticateAgainstCachedSimPin(String pin) {
519         return (mCachedSimPin != null && mCachedSimPin.equals(pin));
520     }
521 
setCachedSimPin(String pin)522     void setCachedSimPin(String pin) {
523         mCachedSimPin = pin;
524     }
525 
526     /**
527      * Handles OTASP-related events from the telephony layer.
528      *
529      * While an OTASP call is active, the CallNotifier forwards
530      * OTASP-related telephony events to this method.
531      */
handleOtaspEvent(Message msg)532     void handleOtaspEvent(Message msg) {
533         if (DBG) Log.d(LOG_TAG, "handleOtaspEvent(message " + msg + ")...");
534 
535         if (otaUtils == null) {
536             // We shouldn't be getting OTASP events without ever
537             // having started the OTASP call in the first place!
538             Log.w(LOG_TAG, "handleOtaEvents: got an event but otaUtils is null! "
539                   + "message = " + msg);
540             return;
541         }
542 
543         otaUtils.onOtaProvisionStatusChanged((AsyncResult) msg.obj);
544     }
545 
546     /**
547      * Similarly, handle the disconnect event of an OTASP call
548      * by forwarding it to the OtaUtils instance.
549      */
handleOtaspDisconnect()550     /* package */ void handleOtaspDisconnect() {
551         if (DBG) Log.d(LOG_TAG, "handleOtaspDisconnect()...");
552 
553         if (otaUtils == null) {
554             // We shouldn't be getting OTASP events without ever
555             // having started the OTASP call in the first place!
556             Log.w(LOG_TAG, "handleOtaspDisconnect: otaUtils is null!");
557             return;
558         }
559 
560         otaUtils.onOtaspDisconnect();
561     }
562 
563     /**
564      * Sets the activity responsible for un-PUK-blocking the device
565      * so that we may close it when we receive a positive result.
566      * mPUKEntryActivity is also used to indicate to the device that
567      * we are trying to un-PUK-lock the phone. In other words, iff
568      * it is NOT null, then we are trying to unlock and waiting for
569      * the SIM to move to READY state.
570      *
571      * @param activity is the activity to close when PUK has
572      * finished unlocking. Can be set to null to indicate the unlock
573      * or SIM READYing process is over.
574      */
setPukEntryActivity(Activity activity)575     void setPukEntryActivity(Activity activity) {
576         mPUKEntryActivity = activity;
577     }
578 
getPUKEntryActivity()579     Activity getPUKEntryActivity() {
580         return mPUKEntryActivity;
581     }
582 
583     /**
584      * Sets the dialog responsible for notifying the user of un-PUK-
585      * blocking - SIM READYing progress, so that we may dismiss it
586      * when we receive a positive result.
587      *
588      * @param dialog indicates the progress dialog informing the user
589      * of the state of the device.  Dismissed upon completion of
590      * READYing process
591      */
setPukEntryProgressDialog(ProgressDialog dialog)592     void setPukEntryProgressDialog(ProgressDialog dialog) {
593         mPUKEntryProgressDialog = dialog;
594     }
595 
getPUKEntryProgressDialog()596     ProgressDialog getPUKEntryProgressDialog() {
597         return mPUKEntryProgressDialog;
598     }
599 
600     /**
601      * Controls whether or not the screen is allowed to sleep.
602      *
603      * Once sleep is allowed (WakeState is SLEEP), it will rely on the
604      * settings for the poke lock to determine when to timeout and let
605      * the device sleep {@link PhoneGlobals#setScreenTimeout}.
606      *
607      * @param ws tells the device to how to wake.
608      */
requestWakeState(WakeState ws)609     /* package */ void requestWakeState(WakeState ws) {
610         if (VDBG) Log.d(LOG_TAG, "requestWakeState(" + ws + ")...");
611         synchronized (this) {
612             if (mWakeState != ws) {
613                 switch (ws) {
614                     case PARTIAL:
615                         // acquire the processor wake lock, and release the FULL
616                         // lock if it is being held.
617                         mPartialWakeLock.acquire();
618                         if (mWakeLock.isHeld()) {
619                             mWakeLock.release();
620                         }
621                         break;
622                     case FULL:
623                         // acquire the full wake lock, and release the PARTIAL
624                         // lock if it is being held.
625                         mWakeLock.acquire();
626                         if (mPartialWakeLock.isHeld()) {
627                             mPartialWakeLock.release();
628                         }
629                         break;
630                     case SLEEP:
631                     default:
632                         // release both the PARTIAL and FULL locks.
633                         if (mWakeLock.isHeld()) {
634                             mWakeLock.release();
635                         }
636                         if (mPartialWakeLock.isHeld()) {
637                             mPartialWakeLock.release();
638                         }
639                         break;
640                 }
641                 mWakeState = ws;
642             }
643         }
644     }
645 
646     /**
647      * If we are not currently keeping the screen on, then poke the power
648      * manager to wake up the screen for the user activity timeout duration.
649      */
wakeUpScreen()650     /* package */ void wakeUpScreen() {
651         synchronized (this) {
652             if (mWakeState == WakeState.SLEEP) {
653                 if (DBG) Log.d(LOG_TAG, "pulse screen lock");
654                 mPowerManager.wakeUp(SystemClock.uptimeMillis());
655             }
656         }
657     }
658 
659     /**
660      * Sets the wake state and screen timeout based on the current state
661      * of the phone, and the current state of the in-call UI.
662      *
663      * This method is a "UI Policy" wrapper around
664      * {@link PhoneGlobals#requestWakeState} and {@link PhoneGlobals#setScreenTimeout}.
665      *
666      * It's safe to call this method regardless of the state of the Phone
667      * (e.g. whether or not it's idle), and regardless of the state of the
668      * Phone UI (e.g. whether or not the InCallScreen is active.)
669      */
updateWakeState()670     /* package */ void updateWakeState() {
671         PhoneConstants.State state = mCM.getState();
672 
673         // True if the speakerphone is in use.  (If so, we *always* use
674         // the default timeout.  Since the user is obviously not holding
675         // the phone up to his/her face, we don't need to worry about
676         // false touches, and thus don't need to turn the screen off so
677         // aggressively.)
678         // Note that we need to make a fresh call to this method any
679         // time the speaker state changes.  (That happens in
680         // PhoneUtils.turnOnSpeaker().)
681         boolean isSpeakerInUse = (state == PhoneConstants.State.OFFHOOK) && PhoneUtils.isSpeakerOn(this);
682 
683         // TODO (bug 1440854): The screen timeout *might* also need to
684         // depend on the bluetooth state, but this isn't as clear-cut as
685         // the speaker state (since while using BT it's common for the
686         // user to put the phone straight into a pocket, in which case the
687         // timeout should probably still be short.)
688 
689         // Decide whether to force the screen on or not.
690         //
691         // Force the screen to be on if the phone is ringing or dialing,
692         // or if we're displaying the "Call ended" UI for a connection in
693         // the "disconnected" state.
694         // However, if the phone is disconnected while the user is in the
695         // middle of selecting a quick response message, we should not force
696         // the screen to be on.
697         //
698         boolean isRinging = (state == PhoneConstants.State.RINGING);
699         boolean isDialing = (mCM.getFgPhone().getForegroundCall().getState() == Call.State.DIALING);
700         boolean keepScreenOn = isRinging || isDialing;
701         // keepScreenOn == true means we'll hold a full wake lock:
702         requestWakeState(keepScreenOn ? WakeState.FULL : WakeState.SLEEP);
703     }
704 
705     /**
706      * Manually pokes the PowerManager's userActivity method.  Since we
707      * set the {@link WindowManager.LayoutParams#INPUT_FEATURE_DISABLE_USER_ACTIVITY}
708      * flag while the InCallScreen is active when there is no proximity sensor,
709      * we need to do this for touch events that really do count as user activity
710      * (like pressing any onscreen UI elements.)
711      */
pokeUserActivity()712     /* package */ void pokeUserActivity() {
713         if (VDBG) Log.d(LOG_TAG, "pokeUserActivity()...");
714         mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
715     }
716 
717     /**
718      * Notifies the phone app when the phone state changes.
719      *
720      * This method will updates various states inside Phone app (e.g. update-lock state, etc.)
721      */
updatePhoneState(PhoneConstants.State state)722     /* package */ void updatePhoneState(PhoneConstants.State state) {
723         if (state != mLastPhoneState) {
724             mLastPhoneState = state;
725 
726             // Try to acquire or release UpdateLock.
727             //
728             // Watch out: we don't release the lock here when the screen is still in foreground.
729             // At that time InCallScreen will release it on onPause().
730             if (state != PhoneConstants.State.IDLE) {
731                 // UpdateLock is a recursive lock, while we may get "acquire" request twice and
732                 // "release" request once for a single call (RINGING + OFFHOOK and IDLE).
733                 // We need to manually ensure the lock is just acquired once for each (and this
734                 // will prevent other possible buggy situations too).
735                 if (!mUpdateLock.isHeld()) {
736                     mUpdateLock.acquire();
737                 }
738             } else {
739                 if (mUpdateLock.isHeld()) {
740                     mUpdateLock.release();
741                 }
742             }
743         }
744     }
745 
getPhoneState()746     /* package */ PhoneConstants.State getPhoneState() {
747         return mLastPhoneState;
748     }
749 
getKeyguardManager()750     KeyguardManager getKeyguardManager() {
751         return mKeyguardManager;
752     }
753 
onMMIComplete(AsyncResult r)754     private void onMMIComplete(AsyncResult r) {
755         if (VDBG) Log.d(LOG_TAG, "onMMIComplete()...");
756         MmiCode mmiCode = (MmiCode) r.result;
757         PhoneUtils.displayMMIComplete(mmiCode.getPhone(), getInstance(), mmiCode, null, null);
758     }
759 
initForNewRadioTechnology(int phoneId)760     private void initForNewRadioTechnology(int phoneId) {
761         if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology...");
762 
763         final Phone phone = PhoneFactory.getPhone(phoneId);
764 
765         if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
766             // Create an instance of CdmaPhoneCallState and initialize it to IDLE
767             cdmaPhoneCallState = new CdmaPhoneCallState();
768             cdmaPhoneCallState.CdmaPhoneCallStateInit();
769         }
770         if (!TelephonyCapabilities.supportsOtasp(phone)) {
771             //Clean up OTA data in GSM/UMTS. It is valid only for CDMA
772             clearOtaState();
773         }
774 
775         notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange();
776         callStateMonitor.updateAfterRadioTechnologyChange();
777 
778         // Update registration for ICC status after radio technology change
779         IccCard sim = phone.getIccCard();
780         if (sim != null) {
781             if (DBG) Log.d(LOG_TAG, "Update registration for ICC status...");
782 
783             //Register all events new to the new active phone
784             sim.registerForNetworkLocked(mHandler, EVENT_SIM_NETWORK_LOCKED, null);
785         }
786     }
787 
788     /**
789      * Receiver for misc intent broadcasts the Phone app cares about.
790      */
791     private class PhoneAppBroadcastReceiver extends BroadcastReceiver {
792         @Override
onReceive(Context context, Intent intent)793         public void onReceive(Context context, Intent intent) {
794             String action = intent.getAction();
795             if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
796                 boolean enabled = System.getInt(getContentResolver(),
797                         System.AIRPLANE_MODE_ON, 0) == 0;
798                 PhoneUtils.setRadioPower(enabled);
799             } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
800                 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
801                         SubscriptionManager.INVALID_SUBSCRIPTION_ID);
802                 int phoneId = SubscriptionManager.getPhoneId(subId);
803                 String state = intent.getStringExtra(PhoneConstants.STATE_KEY);
804                 if (VDBG) {
805                     Log.d(LOG_TAG, "mReceiver: ACTION_ANY_DATA_CONNECTION_STATE_CHANGED");
806                     Log.d(LOG_TAG, "- state: " + state);
807                     Log.d(LOG_TAG, "- reason: "
808                     + intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY));
809                     Log.d(LOG_TAG, "- subId: " + subId);
810                     Log.d(LOG_TAG, "- phoneId: " + phoneId);
811                 }
812                 Phone phone = SubscriptionManager.isValidPhoneId(phoneId) ?
813                         PhoneFactory.getPhone(phoneId) : PhoneFactory.getDefaultPhone();
814                 // The "data disconnected due to roaming" notification is shown
815                 // if (a) you have the "data roaming" feature turned off, and
816                 // (b) you just lost data connectivity because you're roaming.
817                 boolean disconnectedDueToRoaming =
818                         !phone.getDataRoamingEnabled()
819                         && PhoneConstants.DataState.DISCONNECTED.equals(state)
820                         && Phone.REASON_ROAMING_ON.equals(
821                             intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY));
822                 if (mDataDisconnectedDueToRoaming != disconnectedDueToRoaming) {
823                     mDataDisconnectedDueToRoaming = disconnectedDueToRoaming;
824                     mHandler.sendEmptyMessage(disconnectedDueToRoaming
825                             ? EVENT_DATA_ROAMING_DISCONNECTED : EVENT_DATA_ROAMING_OK);
826                 }
827             } else if ((action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) &&
828                     (mPUKEntryActivity != null)) {
829                 // if an attempt to un-PUK-lock the device was made, while we're
830                 // receiving this state change notification, notify the handler.
831                 // NOTE: This is ONLY triggered if an attempt to un-PUK-lock has
832                 // been attempted.
833                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SIM_STATE_CHANGED,
834                         intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)));
835             } else if (action.equals(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED)) {
836                 String newPhone = intent.getStringExtra(PhoneConstants.PHONE_NAME_KEY);
837                 int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY,
838                         SubscriptionManager.INVALID_PHONE_INDEX);
839                 Log.d(LOG_TAG, "Radio technology switched. Now " + newPhone + " (" + phoneId
840                         + ") is active.");
841                 initForNewRadioTechnology(phoneId);
842             } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) {
843                 handleServiceStateChanged(intent);
844             } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
845                 if (TelephonyCapabilities.supportsEcm(mCM.getFgPhone())) {
846                     Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp.");
847                     // Start Emergency Callback Mode service
848                     if (intent.getBooleanExtra("phoneinECMState", false)) {
849                         context.startService(new Intent(context,
850                                 EmergencyCallbackModeService.class));
851                     }
852                 } else {
853                     // It doesn't make sense to get ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
854                     // on a device that doesn't support ECM in the first place.
855                     Log.e(LOG_TAG, "Got ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, "
856                             + "but ECM isn't supported for phone: "
857                             + mCM.getFgPhone().getPhoneName());
858                 }
859             } else if (action.equals(Intent.ACTION_DOCK_EVENT)) {
860                 mDockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
861                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
862                 if (VDBG) Log.d(LOG_TAG, "ACTION_DOCK_EVENT -> mDockState = " + mDockState);
863                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_DOCK_STATE_CHANGED, 0));
864             }
865         }
866     }
867 
868     /**
869      * Accepts broadcast Intents which will be prepared by {@link NotificationMgr} and thus
870      * sent from framework's notification mechanism (which is outside Phone context).
871      * This should be visible from outside, but shouldn't be in "exported" state.
872      *
873      * TODO: If possible merge this into PhoneAppBroadcastReceiver.
874      */
875     public static class NotificationBroadcastReceiver extends BroadcastReceiver {
876         @Override
onReceive(Context context, Intent intent)877         public void onReceive(Context context, Intent intent) {
878             String action = intent.getAction();
879             // TODO: use "if (VDBG)" here.
880             Log.d(LOG_TAG, "Broadcast from Notification: " + action);
881 
882             if (action.equals(ACTION_HANG_UP_ONGOING_CALL)) {
883                 PhoneUtils.hangup(PhoneGlobals.getInstance().mCM);
884             } else {
885                 Log.w(LOG_TAG, "Received hang-up request from notification,"
886                         + " but there's no call the system can hang up.");
887             }
888         }
889     }
890 
handleServiceStateChanged(Intent intent)891     private void handleServiceStateChanged(Intent intent) {
892         /**
893          * This used to handle updating EriTextWidgetProvider this routine
894          * and and listening for ACTION_SERVICE_STATE_CHANGED intents could
895          * be removed. But leaving just in case it might be needed in the near
896          * future.
897          */
898 
899         // If service just returned, start sending out the queued messages
900         ServiceState ss = ServiceState.newFromBundle(intent.getExtras());
901 
902         if (ss != null) {
903             int state = ss.getState();
904             notificationMgr.updateNetworkSelection(state);
905         }
906     }
907 
isOtaCallInActiveState()908     public boolean isOtaCallInActiveState() {
909         boolean otaCallActive = false;
910         if (VDBG) Log.d(LOG_TAG, "- isOtaCallInActiveState " + otaCallActive);
911         return otaCallActive;
912     }
913 
isOtaCallInEndState()914     public boolean isOtaCallInEndState() {
915         boolean otaCallEnded = false;
916         if (VDBG) Log.d(LOG_TAG, "- isOtaCallInEndState " + otaCallEnded);
917         return otaCallEnded;
918     }
919 
920     // it is safe to call clearOtaState() even if the InCallScreen isn't active
clearOtaState()921     public void clearOtaState() {
922         if (DBG) Log.d(LOG_TAG, "- clearOtaState ...");
923         if (otaUtils != null) {
924             otaUtils.cleanOtaScreen(true);
925             if (DBG) Log.d(LOG_TAG, "  - clearOtaState clears OTA screen");
926         }
927     }
928 
929     // it is safe to call dismissOtaDialogs() even if the InCallScreen isn't active
dismissOtaDialogs()930     public void dismissOtaDialogs() {
931         if (DBG) Log.d(LOG_TAG, "- dismissOtaDialogs ...");
932         if (otaUtils != null) {
933             otaUtils.dismissAllOtaDialogs();
934             if (DBG) Log.d(LOG_TAG, "  - dismissOtaDialogs clears OTA dialogs");
935         }
936     }
937 
938     /**
939      * Triggers a refresh of the message waiting (voicemail) indicator.
940      *
941      * @param subId the subscription id we should refresh the notification for.
942      */
refreshMwiIndicator(int subId)943     public void refreshMwiIndicator(int subId) {
944         notificationMgr.refreshMwi(subId);
945     }
946 
947     /**
948      * "Call origin" may be used by Contacts app to specify where the phone call comes from.
949      * Currently, the only permitted value for this extra is {@link #ALLOWED_EXTRA_CALL_ORIGIN}.
950      * Any other value will be ignored, to make sure that malicious apps can't trick the in-call
951      * UI into launching some random other app after a call ends.
952      *
953      * TODO: make this more generic. Note that we should let the "origin" specify its package
954      * while we are now assuming it is "com.android.contacts"
955      */
956     public static final String EXTRA_CALL_ORIGIN = "com.android.phone.CALL_ORIGIN";
957     private static final String DEFAULT_CALL_ORIGIN_PACKAGE = "com.android.dialer";
958     private static final String ALLOWED_EXTRA_CALL_ORIGIN =
959             "com.android.dialer.DialtactsActivity";
960     /**
961      * Used to determine if the preserved call origin is fresh enough.
962      */
963     private static final long CALL_ORIGIN_EXPIRATION_MILLIS = 30 * 1000;
964 }
965