• 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.ProgressDialog;
22 import android.content.BroadcastReceiver;
23 import android.content.ContentResolver;
24 import android.content.Context;
25 import android.content.ContextWrapper;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.media.AudioManager;
29 import android.net.ConnectivityManager;
30 import android.net.Uri;
31 import android.net.sip.SipManager;
32 import android.os.AsyncResult;
33 import android.os.Bundle;
34 import android.os.Handler;
35 import android.os.Message;
36 import android.os.PersistableBundle;
37 import android.os.PowerManager;
38 import android.os.SystemClock;
39 import android.os.SystemProperties;
40 import android.os.UpdateLock;
41 import android.os.UserManager;
42 import android.preference.PreferenceManager;
43 import android.provider.Settings;
44 import android.telephony.CarrierConfigManager;
45 import android.telephony.ServiceState;
46 import android.telephony.SubscriptionManager;
47 import android.telephony.TelephonyManager;
48 import android.util.LocalLog;
49 import android.util.Log;
50 import android.widget.Toast;
51 
52 import com.android.internal.telephony.Call;
53 import com.android.internal.telephony.CallManager;
54 import com.android.internal.telephony.IccCardConstants;
55 import com.android.internal.telephony.MmiCode;
56 import com.android.internal.telephony.Phone;
57 import com.android.internal.telephony.PhoneConstants;
58 import com.android.internal.telephony.PhoneFactory;
59 import com.android.internal.telephony.SettingsObserver;
60 import com.android.internal.telephony.TelephonyCapabilities;
61 import com.android.internal.telephony.TelephonyIntents;
62 import com.android.internal.telephony.dataconnection.DataConnectionReasons;
63 import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataDisallowedReasonType;
64 import com.android.internal.util.IndentingPrintWriter;
65 import com.android.phone.common.CallLogAsync;
66 import com.android.phone.settings.SettingsConstants;
67 import com.android.phone.vvm.CarrierVvmPackageInstalledReceiver;
68 import com.android.services.telephony.sip.SipAccountRegistry;
69 import com.android.services.telephony.sip.SipUtil;
70 
71 import java.io.FileDescriptor;
72 import java.io.PrintWriter;
73 
74 /**
75  * Global state for the telephony subsystem when running in the primary
76  * phone process.
77  */
78 public class PhoneGlobals extends ContextWrapper {
79     public static final String LOG_TAG = "PhoneGlobals";
80 
81     /**
82      * Phone app-wide debug level:
83      *   0 - no debug logging
84      *   1 - normal debug logging if ro.debuggable is set (which is true in
85      *       "eng" and "userdebug" builds but not "user" builds)
86      *   2 - ultra-verbose debug logging
87      *
88      * Most individual classes in the phone app have a local DBG constant,
89      * typically set to
90      *   (PhoneApp.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1)
91      * or else
92      *   (PhoneApp.DBG_LEVEL >= 2)
93      * depending on the desired verbosity.
94      *
95      * ***** DO NOT SUBMIT WITH DBG_LEVEL > 0 *************
96      */
97     public static final int DBG_LEVEL = 0;
98 
99     private static final boolean DBG =
100             (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
101     private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2);
102 
103     // Message codes; see mHandler below.
104     private static final int EVENT_SIM_NETWORK_LOCKED = 3;
105     private static final int EVENT_SIM_STATE_CHANGED = 8;
106     private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10;
107     private static final int EVENT_DATA_ROAMING_OK = 11;
108     private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12;
109     private static final int EVENT_RESTART_SIP = 13;
110     private static final int EVENT_DATA_ROAMING_SETTINGS_CHANGED = 14;
111     private static final int EVENT_MOBILE_DATA_SETTINGS_CHANGED = 15;
112 
113     // The MMI codes are also used by the InCallScreen.
114     public static final int MMI_INITIATE = 51;
115     public static final int MMI_COMPLETE = 52;
116     public static final int MMI_CANCEL = 53;
117     // Don't use message codes larger than 99 here; those are reserved for
118     // the individual Activities of the Phone UI.
119 
120     public static final int AIRPLANE_ON = 1;
121     public static final int AIRPLANE_OFF = 0;
122 
123     /**
124      * Allowable values for the wake lock code.
125      *   SLEEP means the device can be put to sleep.
126      *   PARTIAL means wake the processor, but we display can be kept off.
127      *   FULL means wake both the processor and the display.
128      */
129     public enum WakeState {
130         SLEEP,
131         PARTIAL,
132         FULL
133     }
134 
135     private static PhoneGlobals sMe;
136 
137     // A few important fields we expose to the rest of the package
138     // directly (rather than thru set/get methods) for efficiency.
139     CallController callController;
140     CallManager mCM;
141     CallNotifier notifier;
142     CallerInfoCache callerInfoCache;
143     NotificationMgr notificationMgr;
144     public PhoneInterfaceManager phoneMgr;
145     CarrierConfigLoader configLoader;
146 
147     private CallGatewayManager callGatewayManager;
148     private Phone phoneInEcm;
149 
150     static boolean sVoiceCapable = true;
151 
152     // TODO: Remove, no longer used.
153     CdmaPhoneCallState cdmaPhoneCallState;
154 
155     // The currently-active PUK entry activity and progress dialog.
156     // Normally, these are the Emergency Dialer and the subsequent
157     // progress dialog.  null if there is are no such objects in
158     // the foreground.
159     private Activity mPUKEntryActivity;
160     private ProgressDialog mPUKEntryProgressDialog;
161 
162     private boolean mNoDataDueToRoaming = false;
163 
164     private WakeState mWakeState = WakeState.SLEEP;
165 
166     private PowerManager mPowerManager;
167     private PowerManager.WakeLock mWakeLock;
168     private PowerManager.WakeLock mPartialWakeLock;
169     private KeyguardManager mKeyguardManager;
170 
171     private UpdateLock mUpdateLock;
172 
173     private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
174     private final LocalLog mDataRoamingNotifLog = new LocalLog(50);
175 
176     // Broadcast receiver for various intent broadcasts (see onCreate())
177     private final BroadcastReceiver mReceiver = new PhoneAppBroadcastReceiver();
178     // Broadcast receiver for SIP based intents (see onCreate())
179     private final SipReceiver mSipReceiver = new SipReceiver();
180 
181     private final CarrierVvmPackageInstalledReceiver mCarrierVvmPackageInstalledReceiver =
182             new CarrierVvmPackageInstalledReceiver();
183 
184     private final SettingsObserver mSettingsObserver;
185 
186     Handler mHandler = new Handler() {
187         @Override
188         public void handleMessage(Message msg) {
189             PhoneConstants.State phoneState;
190             if (VDBG) Log.v(LOG_TAG, "event=" + msg.what);
191             switch (msg.what) {
192                 // TODO: This event should be handled by the lock screen, just
193                 // like the "SIM missing" and "Sim locked" cases (bug 1804111).
194                 case EVENT_SIM_NETWORK_LOCKED:
195                     if (getCarrierConfig().getBoolean(
196                             CarrierConfigManager.KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL)) {
197                         // Some products don't have the concept of a "SIM network lock"
198                         Log.i(LOG_TAG, "Ignoring EVENT_SIM_NETWORK_LOCKED event; "
199                               + "not showing 'SIM network unlock' PIN entry screen");
200                     } else {
201                         // Normal case: show the "SIM network unlock" PIN entry screen.
202                         // The user won't be able to do anything else until
203                         // they enter a valid SIM network PIN.
204                         Log.i(LOG_TAG, "show sim depersonal panel");
205                         IccNetworkDepersonalizationPanel.showDialog();
206                     }
207                     break;
208 
209                 case EVENT_DATA_ROAMING_DISCONNECTED:
210                     notificationMgr.showDataDisconnectedRoaming();
211                     break;
212 
213                 case EVENT_DATA_ROAMING_OK:
214                     notificationMgr.hideDataDisconnectedRoaming();
215                     break;
216 
217                 case MMI_COMPLETE:
218                     onMMIComplete((AsyncResult) msg.obj);
219                     break;
220 
221                 case MMI_CANCEL:
222                     PhoneUtils.cancelMmiCode(mCM.getFgPhone());
223                     break;
224 
225                 case EVENT_SIM_STATE_CHANGED:
226                     // Marks the event where the SIM goes into ready state.
227                     // Right now, this is only used for the PUK-unlocking
228                     // process.
229                     if (msg.obj.equals(IccCardConstants.INTENT_VALUE_ICC_READY)) {
230                         // when the right event is triggered and there
231                         // are UI objects in the foreground, we close
232                         // them to display the lock panel.
233                         if (mPUKEntryActivity != null) {
234                             mPUKEntryActivity.finish();
235                             mPUKEntryActivity = null;
236                         }
237                         if (mPUKEntryProgressDialog != null) {
238                             mPUKEntryProgressDialog.dismiss();
239                             mPUKEntryProgressDialog = null;
240                         }
241                     }
242                     break;
243 
244                 case EVENT_UNSOL_CDMA_INFO_RECORD:
245                     //TODO: handle message here;
246                     break;
247                 case EVENT_RESTART_SIP:
248                     // This should only run if the Phone process crashed and was restarted. We do
249                     // not want this running if the device is still in the FBE encrypted state.
250                     // This is the same procedure that is triggered in the SipIncomingCallReceiver
251                     // upon BOOT_COMPLETED.
252                     UserManager userManager = UserManager.get(sMe);
253                     if (userManager != null && userManager.isUserUnlocked()) {
254                         SipUtil.startSipService();
255                     }
256                     break;
257                 case EVENT_DATA_ROAMING_SETTINGS_CHANGED:
258                 case EVENT_MOBILE_DATA_SETTINGS_CHANGED:
259                     updateDataRoamingStatus();
260                     break;
261             }
262         }
263     };
264 
PhoneGlobals(Context context)265     public PhoneGlobals(Context context) {
266         super(context);
267         sMe = this;
268         mSettingsObserver = new SettingsObserver(context, mHandler);
269     }
270 
onCreate()271     public void onCreate() {
272         if (VDBG) Log.v(LOG_TAG, "onCreate()...");
273 
274         ContentResolver resolver = getContentResolver();
275 
276         // Cache the "voice capable" flag.
277         // This flag currently comes from a resource (which is
278         // overrideable on a per-product basis):
279         sVoiceCapable =
280                 getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);
281         // ...but this might eventually become a PackageManager "system
282         // feature" instead, in which case we'd do something like:
283         // sVoiceCapable =
284         //   getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS);
285 
286         if (mCM == null) {
287             // Initialize the telephony framework
288             PhoneFactory.makeDefaultPhones(this);
289 
290             // Start TelephonyDebugService After the default phone is created.
291             Intent intent = new Intent(this, TelephonyDebugService.class);
292             startService(intent);
293 
294             mCM = CallManager.getInstance();
295             for (Phone phone : PhoneFactory.getPhones()) {
296                 mCM.registerPhone(phone);
297             }
298 
299             // Create the NotificationMgr singleton, which is used to display
300             // status bar icons and control other status bar behavior.
301             notificationMgr = NotificationMgr.init(this);
302 
303             // If PhoneGlobals has crashed and is being restarted, then restart.
304             mHandler.sendEmptyMessage(EVENT_RESTART_SIP);
305 
306             // Create an instance of CdmaPhoneCallState and initialize it to IDLE
307             cdmaPhoneCallState = new CdmaPhoneCallState();
308             cdmaPhoneCallState.CdmaPhoneCallStateInit();
309 
310             // before registering for phone state changes
311             mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
312             mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG);
313             // lock used to keep the processor awake, when we don't care for the display.
314             mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
315                     | PowerManager.ON_AFTER_RELEASE, LOG_TAG);
316 
317             mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
318 
319             // Get UpdateLock to suppress system-update related events (e.g. dialog show-up)
320             // during phone calls.
321             mUpdateLock = new UpdateLock("phone");
322 
323             if (DBG) Log.d(LOG_TAG, "onCreate: mUpdateLock: " + mUpdateLock);
324 
325             CallLogger callLogger = new CallLogger(this, new CallLogAsync());
326 
327             callGatewayManager = CallGatewayManager.getInstance();
328 
329             // Create the CallController singleton, which is the interface
330             // to the telephony layer for user-initiated telephony functionality
331             // (like making outgoing calls.)
332             callController = CallController.init(this, callLogger, callGatewayManager);
333 
334             // Create the CallerInfoCache singleton, which remembers custom ring tone and
335             // send-to-voicemail settings.
336             //
337             // The asynchronous caching will start just after this call.
338             callerInfoCache = CallerInfoCache.init(this);
339 
340             phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());
341 
342             configLoader = CarrierConfigLoader.init(this);
343 
344             // Create the CallNotifier singleton, which handles
345             // asynchronous events from the telephony layer (like
346             // launching the incoming-call UI when an incoming call comes
347             // in.)
348             notifier = CallNotifier.init(this);
349 
350             PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED);
351 
352             // register for MMI/USSD
353             mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);
354 
355             // register connection tracking to PhoneUtils
356             PhoneUtils.initializeConnectionHandler(mCM);
357 
358             // Register for misc other intent broadcasts.
359             IntentFilter intentFilter =
360                     new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
361             intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
362             intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
363             intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
364             intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
365             intentFilter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
366             intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
367             registerReceiver(mReceiver, intentFilter);
368 
369             IntentFilter sipIntentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
370             sipIntentFilter.addAction(SipManager.ACTION_SIP_SERVICE_UP);
371             sipIntentFilter.addAction(SipManager.ACTION_SIP_CALL_OPTION_CHANGED);
372             sipIntentFilter.addAction(SipManager.ACTION_SIP_REMOVE_PHONE);
373             registerReceiver(mSipReceiver, sipIntentFilter);
374 
375             mCarrierVvmPackageInstalledReceiver.register(this);
376 
377             //set the default values for the preferences in the phone.
378             PreferenceManager.setDefaultValues(this, R.xml.network_setting_fragment, false);
379 
380             PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false);
381 
382             // Make sure the audio mode (along with some
383             // audio-mode-related state of our own) is initialized
384             // correctly, given the current state of the phone.
385             PhoneUtils.setAudioMode(mCM);
386         }
387 
388         // XXX pre-load the SimProvider so that it's ready
389         resolver.getType(Uri.parse("content://icc/adn"));
390 
391         // TODO: Register for Cdma Information Records
392         // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null);
393 
394         // Read HAC settings and configure audio hardware
395         if (getResources().getBoolean(R.bool.hac_enabled)) {
396             int hac = android.provider.Settings.System.getInt(
397                     getContentResolver(),
398                     android.provider.Settings.System.HEARING_AID,
399                     0);
400             AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
401             audioManager.setParameter(SettingsConstants.HAC_KEY,
402                     hac == SettingsConstants.HAC_ENABLED
403                             ? SettingsConstants.HAC_VAL_ON : SettingsConstants.HAC_VAL_OFF);
404         }
405     }
406 
407     /**
408      * Returns the singleton instance of the PhoneApp.
409      */
getInstance()410     public static PhoneGlobals getInstance() {
411         if (sMe == null) {
412             throw new IllegalStateException("No PhoneGlobals here!");
413         }
414         return sMe;
415     }
416 
417     /**
418      * Returns the singleton instance of the PhoneApp if running as the
419      * primary user, otherwise null.
420      */
getInstanceIfPrimary()421     static PhoneGlobals getInstanceIfPrimary() {
422         return sMe;
423     }
424 
425     /**
426      * Returns the default phone.
427      *
428      * WARNING: This method should be used carefully, now that there may be multiple phones.
429      */
getPhone()430     public static Phone getPhone() {
431         return PhoneFactory.getDefaultPhone();
432     }
433 
getPhone(int subId)434     public static Phone getPhone(int subId) {
435         return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
436     }
437 
getCallManager()438     /* package */ CallManager getCallManager() {
439         return mCM;
440     }
441 
getCarrierConfig()442     public PersistableBundle getCarrierConfig() {
443         return getCarrierConfigForSubId(SubscriptionManager.getDefaultSubscriptionId());
444     }
445 
getCarrierConfigForSubId(int subId)446     public PersistableBundle getCarrierConfigForSubId(int subId) {
447         return configLoader.getConfigForSubId(subId);
448     }
449 
registerSettingsObserver()450     private void registerSettingsObserver() {
451         mSettingsObserver.unobserve();
452         String dataRoamingSetting = Settings.Global.DATA_ROAMING;
453         String mobileDataSetting = Settings.Global.MOBILE_DATA;
454         if (TelephonyManager.getDefault().getSimCount() > 1) {
455             int subId = mDefaultDataSubId;
456             if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
457                 dataRoamingSetting += subId;
458                 mobileDataSetting += subId;
459             }
460         }
461 
462         // Listen for user data roaming setting changed event
463         mSettingsObserver.observe(Settings.Global.getUriFor(dataRoamingSetting),
464                 EVENT_DATA_ROAMING_SETTINGS_CHANGED);
465 
466         // Listen for mobile data setting changed event
467         mSettingsObserver.observe(Settings.Global.getUriFor(mobileDataSetting),
468                 EVENT_MOBILE_DATA_SETTINGS_CHANGED);
469     }
470 
471     /**
472      * Sets the activity responsible for un-PUK-blocking the device
473      * so that we may close it when we receive a positive result.
474      * mPUKEntryActivity is also used to indicate to the device that
475      * we are trying to un-PUK-lock the phone. In other words, iff
476      * it is NOT null, then we are trying to unlock and waiting for
477      * the SIM to move to READY state.
478      *
479      * @param activity is the activity to close when PUK has
480      * finished unlocking. Can be set to null to indicate the unlock
481      * or SIM READYing process is over.
482      */
setPukEntryActivity(Activity activity)483     void setPukEntryActivity(Activity activity) {
484         mPUKEntryActivity = activity;
485     }
486 
getPUKEntryActivity()487     Activity getPUKEntryActivity() {
488         return mPUKEntryActivity;
489     }
490 
491     /**
492      * Sets the dialog responsible for notifying the user of un-PUK-
493      * blocking - SIM READYing progress, so that we may dismiss it
494      * when we receive a positive result.
495      *
496      * @param dialog indicates the progress dialog informing the user
497      * of the state of the device.  Dismissed upon completion of
498      * READYing process
499      */
setPukEntryProgressDialog(ProgressDialog dialog)500     void setPukEntryProgressDialog(ProgressDialog dialog) {
501         mPUKEntryProgressDialog = dialog;
502     }
503 
504     /**
505      * Controls whether or not the screen is allowed to sleep.
506      *
507      * Once sleep is allowed (WakeState is SLEEP), it will rely on the
508      * settings for the poke lock to determine when to timeout and let
509      * the device sleep {@link PhoneGlobals#setScreenTimeout}.
510      *
511      * @param ws tells the device to how to wake.
512      */
requestWakeState(WakeState ws)513     /* package */ void requestWakeState(WakeState ws) {
514         if (VDBG) Log.d(LOG_TAG, "requestWakeState(" + ws + ")...");
515         synchronized (this) {
516             if (mWakeState != ws) {
517                 switch (ws) {
518                     case PARTIAL:
519                         // acquire the processor wake lock, and release the FULL
520                         // lock if it is being held.
521                         mPartialWakeLock.acquire();
522                         if (mWakeLock.isHeld()) {
523                             mWakeLock.release();
524                         }
525                         break;
526                     case FULL:
527                         // acquire the full wake lock, and release the PARTIAL
528                         // lock if it is being held.
529                         mWakeLock.acquire();
530                         if (mPartialWakeLock.isHeld()) {
531                             mPartialWakeLock.release();
532                         }
533                         break;
534                     case SLEEP:
535                     default:
536                         // release both the PARTIAL and FULL locks.
537                         if (mWakeLock.isHeld()) {
538                             mWakeLock.release();
539                         }
540                         if (mPartialWakeLock.isHeld()) {
541                             mPartialWakeLock.release();
542                         }
543                         break;
544                 }
545                 mWakeState = ws;
546             }
547         }
548     }
549 
550     /**
551      * If we are not currently keeping the screen on, then poke the power
552      * manager to wake up the screen for the user activity timeout duration.
553      */
wakeUpScreen()554     /* package */ void wakeUpScreen() {
555         synchronized (this) {
556             if (mWakeState == WakeState.SLEEP) {
557                 if (DBG) Log.d(LOG_TAG, "pulse screen lock");
558                 mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.phone:WAKE");
559             }
560         }
561     }
562 
563     /**
564      * Sets the wake state and screen timeout based on the current state
565      * of the phone, and the current state of the in-call UI.
566      *
567      * This method is a "UI Policy" wrapper around
568      * {@link PhoneGlobals#requestWakeState} and {@link PhoneGlobals#setScreenTimeout}.
569      *
570      * It's safe to call this method regardless of the state of the Phone
571      * (e.g. whether or not it's idle), and regardless of the state of the
572      * Phone UI (e.g. whether or not the InCallScreen is active.)
573      */
updateWakeState()574     /* package */ void updateWakeState() {
575         PhoneConstants.State state = mCM.getState();
576 
577         // True if the speakerphone is in use.  (If so, we *always* use
578         // the default timeout.  Since the user is obviously not holding
579         // the phone up to his/her face, we don't need to worry about
580         // false touches, and thus don't need to turn the screen off so
581         // aggressively.)
582         // Note that we need to make a fresh call to this method any
583         // time the speaker state changes.  (That happens in
584         // PhoneUtils.turnOnSpeaker().)
585         boolean isSpeakerInUse = (state == PhoneConstants.State.OFFHOOK) && PhoneUtils.isSpeakerOn(this);
586 
587         // TODO (bug 1440854): The screen timeout *might* also need to
588         // depend on the bluetooth state, but this isn't as clear-cut as
589         // the speaker state (since while using BT it's common for the
590         // user to put the phone straight into a pocket, in which case the
591         // timeout should probably still be short.)
592 
593         // Decide whether to force the screen on or not.
594         //
595         // Force the screen to be on if the phone is ringing or dialing,
596         // or if we're displaying the "Call ended" UI for a connection in
597         // the "disconnected" state.
598         // However, if the phone is disconnected while the user is in the
599         // middle of selecting a quick response message, we should not force
600         // the screen to be on.
601         //
602         boolean isRinging = (state == PhoneConstants.State.RINGING);
603         boolean isDialing = (mCM.getFgPhone().getForegroundCall().getState() == Call.State.DIALING);
604         boolean keepScreenOn = isRinging || isDialing;
605         // keepScreenOn == true means we'll hold a full wake lock:
606         requestWakeState(keepScreenOn ? WakeState.FULL : WakeState.SLEEP);
607     }
608 
getKeyguardManager()609     KeyguardManager getKeyguardManager() {
610         return mKeyguardManager;
611     }
612 
onMMIComplete(AsyncResult r)613     private void onMMIComplete(AsyncResult r) {
614         if (VDBG) Log.d(LOG_TAG, "onMMIComplete()...");
615         MmiCode mmiCode = (MmiCode) r.result;
616         PhoneUtils.displayMMIComplete(mmiCode.getPhone(), getInstance(), mmiCode, null, null);
617     }
618 
initForNewRadioTechnology()619     private void initForNewRadioTechnology() {
620         if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology...");
621         notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange();
622     }
623 
handleAirplaneModeChange(Context context, int newMode)624     private void handleAirplaneModeChange(Context context, int newMode) {
625         int cellState = Settings.Global.getInt(context.getContentResolver(),
626                 Settings.Global.CELL_ON, PhoneConstants.CELL_ON_FLAG);
627         boolean isAirplaneNewlyOn = (newMode == 1);
628         switch (cellState) {
629             case PhoneConstants.CELL_OFF_FLAG:
630                 // Airplane mode does not affect the cell radio if user
631                 // has turned it off.
632                 break;
633             case PhoneConstants.CELL_ON_FLAG:
634                 maybeTurnCellOff(context, isAirplaneNewlyOn);
635                 break;
636             case PhoneConstants.CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG:
637                 maybeTurnCellOn(context, isAirplaneNewlyOn);
638                 break;
639         }
640     }
641 
642     /*
643      * Returns true if the radio must be turned off when entering airplane mode.
644      */
isCellOffInAirplaneMode(Context context)645     private boolean isCellOffInAirplaneMode(Context context) {
646         String airplaneModeRadios = Settings.Global.getString(context.getContentResolver(),
647                 Settings.Global.AIRPLANE_MODE_RADIOS);
648         return airplaneModeRadios == null
649                 || airplaneModeRadios.contains(Settings.Global.RADIO_CELL);
650     }
651 
setRadioPowerOff(Context context)652     private void setRadioPowerOff(Context context) {
653         Log.i(LOG_TAG, "Turning radio off - airplane");
654         Settings.Global.putInt(context.getContentResolver(), Settings.Global.CELL_ON,
655                  PhoneConstants.CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG);
656         SystemProperties.set("persist.radio.airplane_mode_on", "1");
657         Settings.Global.putInt(getContentResolver(), Settings.Global.ENABLE_CELLULAR_ON_BOOT, 0);
658         PhoneUtils.setRadioPower(false);
659     }
660 
setRadioPowerOn(Context context)661     private void setRadioPowerOn(Context context) {
662         Log.i(LOG_TAG, "Turning radio on - airplane");
663         Settings.Global.putInt(context.getContentResolver(), Settings.Global.CELL_ON,
664                 PhoneConstants.CELL_ON_FLAG);
665         Settings.Global.putInt(getContentResolver(), Settings.Global.ENABLE_CELLULAR_ON_BOOT,
666                 1);
667         SystemProperties.set("persist.radio.airplane_mode_on", "0");
668         PhoneUtils.setRadioPower(true);
669     }
670 
maybeTurnCellOff(Context context, boolean isAirplaneNewlyOn)671     private void maybeTurnCellOff(Context context, boolean isAirplaneNewlyOn) {
672         if (isAirplaneNewlyOn) {
673             // If we are trying to turn off the radio, make sure there are no active
674             // emergency calls.  If there are, switch airplane mode back to off.
675             if (PhoneUtils.isInEmergencyCall(mCM)) {
676                 // Switch airplane mode back to off.
677                 ConnectivityManager.from(this).setAirplaneMode(false);
678                 Toast.makeText(this, R.string.radio_off_during_emergency_call, Toast.LENGTH_LONG)
679                         .show();
680                 Log.i(LOG_TAG, "Ignoring airplane mode: emergency call. Turning airplane off");
681             } else if (isCellOffInAirplaneMode(context)) {
682                 setRadioPowerOff(context);
683             } else {
684                 Log.i(LOG_TAG, "Ignoring airplane mode: settings prevent cell radio power off");
685             }
686         }
687     }
688 
maybeTurnCellOn(Context context, boolean isAirplaneNewlyOn)689     private void maybeTurnCellOn(Context context, boolean isAirplaneNewlyOn) {
690         if (!isAirplaneNewlyOn) {
691             setRadioPowerOn(context);
692         }
693     }
694 
695     /**
696      * Receiver for misc intent broadcasts the Phone app cares about.
697      */
698     private class PhoneAppBroadcastReceiver extends BroadcastReceiver {
699         @Override
onReceive(Context context, Intent intent)700         public void onReceive(Context context, Intent intent) {
701             String action = intent.getAction();
702             if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
703                 int airplaneMode = Settings.Global.getInt(getContentResolver(),
704                         Settings.Global.AIRPLANE_MODE_ON, AIRPLANE_OFF);
705                 // Treat any non-OFF values as ON.
706                 if (airplaneMode != AIRPLANE_OFF) {
707                     airplaneMode = AIRPLANE_ON;
708                 }
709                 handleAirplaneModeChange(context, airplaneMode);
710             } else if ((action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) &&
711                     (mPUKEntryActivity != null)) {
712                 // if an attempt to un-PUK-lock the device was made, while we're
713                 // receiving this state change notification, notify the handler.
714                 // NOTE: This is ONLY triggered if an attempt to un-PUK-lock has
715                 // been attempted.
716                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SIM_STATE_CHANGED,
717                         intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)));
718             } else if (action.equals(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED)) {
719                 String newPhone = intent.getStringExtra(PhoneConstants.PHONE_NAME_KEY);
720                 Log.d(LOG_TAG, "Radio technology switched. Now " + newPhone + " is active.");
721                 initForNewRadioTechnology();
722             } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) {
723                 handleServiceStateChanged(intent);
724             } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
725                 int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY, 0);
726                 phoneInEcm = PhoneFactory.getPhone(phoneId);
727                 Log.d(LOG_TAG, "Emergency Callback Mode. phoneId:" + phoneId);
728                 if (phoneInEcm != null) {
729                     if (TelephonyCapabilities.supportsEcm(phoneInEcm)) {
730                         Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp.");
731                         // Start Emergency Callback Mode service
732                         if (intent.getBooleanExtra("phoneinECMState", false)) {
733                             context.startService(new Intent(context,
734                                     EmergencyCallbackModeService.class));
735                         } else {
736                             phoneInEcm = null;
737                         }
738                     } else {
739                         // It doesn't make sense to get ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
740                         // on a device that doesn't support ECM in the first place.
741                         Log.e(LOG_TAG, "Got ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, but "
742                                 + "ECM isn't supported for phone: " + phoneInEcm.getPhoneName());
743                         phoneInEcm = null;
744                     }
745                 } else {
746                     Log.w(LOG_TAG, "phoneInEcm is null.");
747                 }
748             } else if (action.equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
749                 // Roaming status could be overridden by carrier config, so we need to update it.
750                 if (VDBG) Log.v(LOG_TAG, "carrier config changed.");
751                 updateDataRoamingStatus();
752             } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
753                 // We also need to pay attention when default data subscription changes.
754                 if (VDBG) Log.v(LOG_TAG, "default data sub changed.");
755                 mDefaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId();
756                 registerSettingsObserver();
757                 Phone phone = getPhone(mDefaultDataSubId);
758                 if (phone != null) {
759                     updateDataRoamingStatus();
760                 }
761             }
762         }
763     }
764 
765     private class SipReceiver extends BroadcastReceiver {
766 
767         @Override
onReceive(Context context, Intent intent)768         public void onReceive(Context context, Intent intent) {
769             String action = intent.getAction();
770 
771             SipAccountRegistry sipAccountRegistry = SipAccountRegistry.getInstance();
772             if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
773                 SipUtil.startSipService();
774             } else if (action.equals(SipManager.ACTION_SIP_SERVICE_UP)
775                     || action.equals(SipManager.ACTION_SIP_CALL_OPTION_CHANGED)) {
776                 sipAccountRegistry.setup(context);
777             } else if (action.equals(SipManager.ACTION_SIP_REMOVE_PHONE)) {
778                 if (DBG) {
779                     Log.d(LOG_TAG, "SIP_REMOVE_PHONE "
780                             + intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
781                 }
782                 sipAccountRegistry.removeSipProfile(intent.getStringExtra(
783                         SipManager.EXTRA_LOCAL_URI));
784             } else {
785                 if (DBG) Log.d(LOG_TAG, "onReceive, action not processed: " + action);
786             }
787         }
788     }
789 
handleServiceStateChanged(Intent intent)790     private void handleServiceStateChanged(Intent intent) {
791         /**
792          * This used to handle updating EriTextWidgetProvider this routine
793          * and and listening for ACTION_SERVICE_STATE_CHANGED intents could
794          * be removed. But leaving just in case it might be needed in the near
795          * future.
796          */
797 
798         if (VDBG) Log.v(LOG_TAG, "handleServiceStateChanged");
799         // If service just returned, start sending out the queued messages
800         Bundle extras = intent.getExtras();
801         if (extras != null) {
802             ServiceState ss = ServiceState.newFromBundle(extras);
803             if (ss != null) {
804                 int state = ss.getState();
805                 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
806                         SubscriptionManager.INVALID_SUBSCRIPTION_ID);
807                 notificationMgr.updateNetworkSelection(state, subId);
808 
809                 if (VDBG) {
810                     Log.v(LOG_TAG, "subId=" + subId + ",mDefaultDataSubId="
811                             + mDefaultDataSubId + ",ss roaming=" + ss.getDataRoaming());
812                 }
813                 if (subId == mDefaultDataSubId) {
814                     updateDataRoamingStatus();
815                 }
816             }
817         }
818     }
819 
820     /**
821      * When roaming, if mobile data cannot be established due to data roaming not enabled, we need
822      * to notify the user so they can enable it through settings. Vise versa if the condition
823      * changes, we need to dismiss the notification.
824      */
updateDataRoamingStatus()825     private void updateDataRoamingStatus() {
826         if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatus");
827         Phone phone = getPhone(mDefaultDataSubId);
828         if (phone == null) {
829             Log.w(LOG_TAG, "Can't get phone with sub id = " + mDefaultDataSubId);
830             return;
831         }
832 
833         DataConnectionReasons reasons = new DataConnectionReasons();
834         boolean dataAllowed = phone.isDataAllowed(reasons);
835         mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons);
836         if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons);
837         if (!mNoDataDueToRoaming
838                 && !dataAllowed
839                 && reasons.containsOnly(DataDisallowedReasonType.ROAMING_DISABLED)) {
840             // If the only reason of no data is data roaming disabled, then we notify the user
841             // so the user can turn on data roaming.
842             mNoDataDueToRoaming = true;
843             Log.d(LOG_TAG, "Show roaming disconnected notification");
844             mDataRoamingNotifLog.log("Show");
845             mHandler.sendEmptyMessage(EVENT_DATA_ROAMING_DISCONNECTED);
846         } else if (mNoDataDueToRoaming && (dataAllowed
847                 || !reasons.containsOnly(DataDisallowedReasonType.ROAMING_DISABLED))) {
848             // Otherwise dismiss the notification we showed earlier.
849             mNoDataDueToRoaming = false;
850             Log.d(LOG_TAG, "Dismiss roaming disconnected notification");
851             mDataRoamingNotifLog.log("Hide. data allowed=" + dataAllowed + ", reasons=" + reasons);
852             mHandler.sendEmptyMessage(EVENT_DATA_ROAMING_OK);
853         }
854     }
855 
getPhoneInEcm()856     public Phone getPhoneInEcm() {
857         return phoneInEcm;
858     }
859 
860     /**
861      * Triggers a refresh of the message waiting (voicemail) indicator.
862      *
863      * @param subId the subscription id we should refresh the notification for.
864      */
refreshMwiIndicator(int subId)865     public void refreshMwiIndicator(int subId) {
866         notificationMgr.refreshMwi(subId);
867     }
868 
869     /**
870      * Dismisses the message waiting (voicemail) indicator.
871      *
872      * @param subId the subscription id we should dismiss the notification for.
873      */
clearMwiIndicator(int subId)874     public void clearMwiIndicator(int subId) {
875         // Setting voiceMessageCount to 0 will remove the current notification and clear the system
876         // cached value.
877         Phone phone = getPhone(subId);
878         if (phone == null) {
879             Log.w(LOG_TAG, "clearMwiIndicator on null phone, subId:" + subId);
880         } else {
881             phone.setVoiceMessageCount(0);
882         }
883     }
884 
885     /**
886      * Enables or disables the visual voicemail check for message waiting indicator. Default value
887      * is true. MWI is the traditional voicemail notification which should be suppressed if visual
888      * voicemail is active. {@link NotificationMgr#updateMwi(int, boolean, boolean)} currently
889      * checks the {@link android.provider.VoicemailContract.Status#CONFIGURATION_STATE} to suppress
890      * the MWI, but there are several issues. b/31229016 is a bug that when the device boots the
891      * configuration state will be cleared and the MWI for voicemail that arrives when the device
892      * is offline will be cleared, even if the account cannot be activated. A full solution will be
893      * adding a setMwiEnabled() method and stop checking the configuration state, but that is too
894      * risky at this moment. This is a temporary workaround to shut down the configuration state
895      * check if visual voicemail cannot be activated.
896      * <p>TODO(twyen): implement the setMwiEnabled() mentioned above.
897      *
898      * @param subId the account to set the enabled state
899      */
setShouldCheckVisualVoicemailConfigurationForMwi(int subId, boolean enabled)900     public void setShouldCheckVisualVoicemailConfigurationForMwi(int subId, boolean enabled) {
901         notificationMgr.setShouldCheckVisualVoicemailConfigurationForMwi(subId, enabled);
902     }
903 
904     /**
905      * Dump the state of the object, add calls to other objects as desired.
906      *
907      * @param fd File descriptor
908      * @param printWriter Print writer
909      * @param args Arguments
910      */
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)911     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
912         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
913         pw.println("------- PhoneGlobals -------");
914         pw.increaseIndent();
915         pw.println("mNoDataDueToRoaming=" + mNoDataDueToRoaming);
916         pw.println("mDefaultDataSubId=" + mDefaultDataSubId);
917         pw.println("mDataRoamingNotifLog:");
918         pw.increaseIndent();
919         mDataRoamingNotifLog.dump(fd, pw, args);
920         pw.decreaseIndent();
921         pw.decreaseIndent();
922         pw.println("------- End PhoneGlobals -------");
923     }
924 }
925