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