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