| 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 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 19 | import android.bluetooth.BluetoothAdapter; | 
|  | 20 | import android.bluetooth.BluetoothHeadset; | 
|  | 21 | import android.bluetooth.BluetoothProfile; | 
|  | 22 | import android.content.Context; | 
|  | 23 | import android.media.AudioManager; | 
| Amit Mahajan | b8f1320 | 2020-01-27 18:16:07 -0800 | [diff] [blame] | 24 | import android.media.AudioSystem; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 25 | import android.media.ToneGenerator; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 26 | import android.os.AsyncResult; | 
|  | 27 | import android.os.Handler; | 
| Zoey Chen | 5719bac | 2021-01-28 15:05:49 +0800 | [diff] [blame] | 28 | import android.os.HandlerExecutor; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 29 | import android.os.Message; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 30 | import android.os.SystemProperties; | 
| Pavel Zhamaitsiak | 82256c0 | 2014-12-10 17:11:40 -0800 | [diff] [blame] | 31 | import android.telecom.TelecomManager; | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 32 | import android.telephony.SubscriptionInfo; | 
|  | 33 | import android.telephony.SubscriptionManager; | 
|  | 34 | import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; | 
| Zoey Chen | 5ec326b | 2021-02-22 21:21:28 +0800 | [diff] [blame] | 35 | import android.telephony.TelephonyCallback; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 36 | import android.telephony.TelephonyManager; | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 37 | import android.util.ArrayMap; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 38 | import android.util.Log; | 
|  | 39 |  | 
| Aravind Sreekumar | afc08c5 | 2018-04-10 15:34:32 -0700 | [diff] [blame] | 40 | import com.android.internal.telephony.CallManager; | 
|  | 41 | import com.android.internal.telephony.Phone; | 
|  | 42 | import com.android.internal.telephony.PhoneConstants; | 
|  | 43 | import com.android.internal.telephony.SubscriptionController; | 
|  | 44 | import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaDisplayInfoRec; | 
|  | 45 | import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec; | 
|  | 46 | import com.android.internal.telephony.cdma.SignalToneUtil; | 
|  | 47 |  | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 48 | import java.util.ArrayList; | 
|  | 49 | import java.util.Collections; | 
|  | 50 | import java.util.Comparator; | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 51 | import java.util.List; | 
|  | 52 | import java.util.Map; | 
|  | 53 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 54 | /** | 
|  | 55 | * Phone app module that listens for phone state changes and various other | 
|  | 56 | * events from the telephony layer, and triggers any resulting UI behavior | 
| Santos Cordon | 5422a8d | 2014-09-12 04:20:56 -0700 | [diff] [blame] | 57 | * (like starting the Incoming Call UI, playing in-call tones, | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 58 | * updating notifications, writing call log entries, etc.) | 
|  | 59 | */ | 
| Santos Cordon | 5422a8d | 2014-09-12 04:20:56 -0700 | [diff] [blame] | 60 | public class CallNotifier extends Handler { | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 61 | private static final String LOG_TAG = "CallNotifier"; | 
|  | 62 | private static final boolean DBG = | 
|  | 63 | (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1); | 
|  | 64 | private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2); | 
|  | 65 |  | 
| Anthony Lee | e946853 | 2014-11-15 15:21:00 -0800 | [diff] [blame] | 66 | // Time to display the message from the underlying phone layers. | 
|  | 67 | private static final int SHOW_MESSAGE_NOTIFICATION_TIME = 3000; // msec | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 68 |  | 
|  | 69 | /** The singleton instance. */ | 
|  | 70 | private static CallNotifier sInstance; | 
|  | 71 |  | 
| Zoey Chen | 5ec326b | 2021-02-22 21:21:28 +0800 | [diff] [blame] | 72 | private Map<Integer, CallNotifierTelephonyCallback> mTelephonyCallback = | 
|  | 73 | new ArrayMap<Integer, CallNotifierTelephonyCallback>(); | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 74 | private Map<Integer, Boolean> mCFIStatus = new ArrayMap<Integer, Boolean>(); | 
|  | 75 | private Map<Integer, Boolean> mMWIStatus = new ArrayMap<Integer, Boolean>(); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 76 | private PhoneGlobals mApplication; | 
|  | 77 | private CallManager mCM; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 78 | private BluetoothHeadset mBluetoothHeadset; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 79 |  | 
|  | 80 | // ToneGenerator instance for playing SignalInfo tones | 
|  | 81 | private ToneGenerator mSignalInfoToneGenerator; | 
|  | 82 |  | 
|  | 83 | // The tone volume relative to other sounds in the stream SignalInfo | 
|  | 84 | private static final int TONE_RELATIVE_VOLUME_SIGNALINFO = 80; | 
|  | 85 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 86 | private boolean mVoicePrivacyState = false; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 87 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 88 | // Cached AudioManager | 
|  | 89 | private AudioManager mAudioManager; | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 90 | private SubscriptionManager mSubscriptionManager; | 
|  | 91 | private TelephonyManager mTelephonyManager; | 
| Santos Cordon | 27a3c1f | 2013-08-06 07:49:27 -0700 | [diff] [blame] | 92 |  | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 93 | // Events from the Phone object: | 
|  | 94 | public static final int PHONE_DISCONNECT = 3; | 
|  | 95 | public static final int PHONE_STATE_DISPLAYINFO = 6; | 
|  | 96 | public static final int PHONE_STATE_SIGNALINFO = 7; | 
|  | 97 | public static final int PHONE_ENHANCED_VP_ON = 9; | 
|  | 98 | public static final int PHONE_ENHANCED_VP_OFF = 10; | 
|  | 99 | public static final int PHONE_SUPP_SERVICE_FAILED = 14; | 
|  | 100 | public static final int PHONE_TTY_MODE_RECEIVED = 15; | 
|  | 101 | // Events generated internally. | 
|  | 102 | // We should store all the possible event type values in one place to make sure that | 
|  | 103 | // they don't step on each others' toes. | 
|  | 104 | public static final int INTERNAL_SHOW_MESSAGE_NOTIFICATION_DONE = 22; | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 105 |  | 
| Srikanth Chintala | 4baf0b9 | 2017-11-14 15:52:47 +0530 | [diff] [blame] | 106 | public static final int UPDATE_TYPE_MWI = 0; | 
|  | 107 | public static final int UPDATE_TYPE_CFI = 1; | 
|  | 108 | public static final int UPDATE_TYPE_MWI_CFI = 2; | 
|  | 109 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 110 | /** | 
|  | 111 | * Initialize the singleton CallNotifier instance. | 
|  | 112 | * This is only done once, at startup, from PhoneApp.onCreate(). | 
|  | 113 | */ | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 114 | /* package */ static CallNotifier init( | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 115 | PhoneGlobals app) { | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 116 | synchronized (CallNotifier.class) { | 
|  | 117 | if (sInstance == null) { | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 118 | sInstance = new CallNotifier(app); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 119 | } else { | 
|  | 120 | Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance); | 
|  | 121 | } | 
|  | 122 | return sInstance; | 
|  | 123 | } | 
|  | 124 | } | 
|  | 125 |  | 
|  | 126 | /** Private constructor; @see init() */ | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 127 | private CallNotifier( | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 128 | PhoneGlobals app) { | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 129 | mApplication = app; | 
|  | 130 | mCM = app.mCM; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 131 |  | 
|  | 132 | mAudioManager = (AudioManager) mApplication.getSystemService(Context.AUDIO_SERVICE); | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 133 | mTelephonyManager = | 
|  | 134 | (TelephonyManager) mApplication.getSystemService(Context.TELEPHONY_SERVICE); | 
|  | 135 | mSubscriptionManager = (SubscriptionManager) mApplication.getSystemService( | 
|  | 136 | Context.TELEPHONY_SUBSCRIPTION_SERVICE); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 137 |  | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 138 | registerForNotifications(); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 139 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 140 | BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); | 
|  | 141 | if (adapter != null) { | 
|  | 142 | adapter.getProfileProxy(mApplication.getApplicationContext(), | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 143 | mBluetoothProfileServiceListener, | 
|  | 144 | BluetoothProfile.HEADSET); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 145 | } | 
|  | 146 |  | 
| Wink Saville | f67832f | 2015-01-12 16:51:50 -0800 | [diff] [blame] | 147 | mSubscriptionManager.addOnSubscriptionsChangedListener( | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 148 | new OnSubscriptionsChangedListener() { | 
|  | 149 | @Override | 
|  | 150 | public void onSubscriptionsChanged() { | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 151 | updatePhoneStateListeners(true); | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 152 | } | 
|  | 153 | }); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 154 | } | 
|  | 155 |  | 
|  | 156 | private void createSignalInfoToneGenerator() { | 
|  | 157 | // Instantiate the ToneGenerator for SignalInfo and CallWaiting | 
|  | 158 | // TODO: We probably don't need the mSignalInfoToneGenerator instance | 
|  | 159 | // around forever. Need to change it so as to create a ToneGenerator instance only | 
|  | 160 | // when a tone is being played and releases it after its done playing. | 
|  | 161 | if (mSignalInfoToneGenerator == null) { | 
|  | 162 | try { | 
|  | 163 | mSignalInfoToneGenerator = new ToneGenerator(AudioManager.STREAM_VOICE_CALL, | 
|  | 164 | TONE_RELATIVE_VOLUME_SIGNALINFO); | 
|  | 165 | Log.d(LOG_TAG, "CallNotifier: mSignalInfoToneGenerator created when toneplay"); | 
|  | 166 | } catch (RuntimeException e) { | 
|  | 167 | Log.w(LOG_TAG, "CallNotifier: Exception caught while creating " + | 
|  | 168 | "mSignalInfoToneGenerator: " + e); | 
|  | 169 | mSignalInfoToneGenerator = null; | 
|  | 170 | } | 
|  | 171 | } else { | 
|  | 172 | Log.d(LOG_TAG, "mSignalInfoToneGenerator created already, hence skipping"); | 
|  | 173 | } | 
|  | 174 | } | 
|  | 175 |  | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 176 | /** | 
|  | 177 | * Register for call state notifications with the CallManager. | 
|  | 178 | */ | 
|  | 179 | private void registerForNotifications() { | 
|  | 180 | mCM.registerForDisconnect(this, PHONE_DISCONNECT, null); | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 181 | mCM.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null); | 
|  | 182 | mCM.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null); | 
|  | 183 | mCM.registerForInCallVoicePrivacyOn(this, PHONE_ENHANCED_VP_ON, null); | 
|  | 184 | mCM.registerForInCallVoicePrivacyOff(this, PHONE_ENHANCED_VP_OFF, null); | 
|  | 185 | mCM.registerForSuppServiceFailed(this, PHONE_SUPP_SERVICE_FAILED, null); | 
|  | 186 | mCM.registerForTtyModeReceived(this, PHONE_TTY_MODE_RECEIVED, null); | 
|  | 187 | } | 
|  | 188 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 189 | @Override | 
|  | 190 | public void handleMessage(Message msg) { | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 191 | if (DBG) { | 
|  | 192 | Log.d(LOG_TAG, "handleMessage(" + msg.what + ")"); | 
|  | 193 | } | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 194 | switch (msg.what) { | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 195 | case PHONE_DISCONNECT: | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 196 | if (DBG) log("DISCONNECT"); | 
| Roshan Pius | 19f39cf | 2015-08-12 10:44:38 -0700 | [diff] [blame] | 197 | // Stop any signalInfo tone being played when a call gets ended, the rest of the | 
|  | 198 | // disconnect functionality in onDisconnect() is handled in ConnectionService. | 
|  | 199 | stopSignalInfoTone(); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 200 | break; | 
|  | 201 |  | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 202 | case PHONE_STATE_DISPLAYINFO: | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 203 | if (DBG) log("Received PHONE_STATE_DISPLAYINFO event"); | 
|  | 204 | onDisplayInfo((AsyncResult) msg.obj); | 
|  | 205 | break; | 
|  | 206 |  | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 207 | case PHONE_STATE_SIGNALINFO: | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 208 | if (DBG) log("Received PHONE_STATE_SIGNALINFO event"); | 
|  | 209 | onSignalInfo((AsyncResult) msg.obj); | 
|  | 210 | break; | 
|  | 211 |  | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 212 | case INTERNAL_SHOW_MESSAGE_NOTIFICATION_DONE: | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 213 | if (DBG) log("Received Display Info notification done event ..."); | 
| Anthony Lee | e946853 | 2014-11-15 15:21:00 -0800 | [diff] [blame] | 214 | PhoneDisplayMessage.dismissMessage(); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 215 | break; | 
|  | 216 |  | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 217 | case PHONE_ENHANCED_VP_ON: | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 218 | if (DBG) log("PHONE_ENHANCED_VP_ON..."); | 
|  | 219 | if (!mVoicePrivacyState) { | 
|  | 220 | int toneToPlay = InCallTonePlayer.TONE_VOICE_PRIVACY; | 
|  | 221 | new InCallTonePlayer(toneToPlay).start(); | 
|  | 222 | mVoicePrivacyState = true; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 223 | } | 
|  | 224 | break; | 
|  | 225 |  | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 226 | case PHONE_ENHANCED_VP_OFF: | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 227 | if (DBG) log("PHONE_ENHANCED_VP_OFF..."); | 
|  | 228 | if (mVoicePrivacyState) { | 
|  | 229 | int toneToPlay = InCallTonePlayer.TONE_VOICE_PRIVACY; | 
|  | 230 | new InCallTonePlayer(toneToPlay).start(); | 
|  | 231 | mVoicePrivacyState = false; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 232 | } | 
|  | 233 | break; | 
|  | 234 |  | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 235 | case PHONE_SUPP_SERVICE_FAILED: | 
| Anthony Lee | e946853 | 2014-11-15 15:21:00 -0800 | [diff] [blame] | 236 | if (DBG) log("PHONE_SUPP_SERVICE_FAILED..."); | 
|  | 237 | onSuppServiceFailed((AsyncResult) msg.obj); | 
|  | 238 | break; | 
|  | 239 |  | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 240 | case PHONE_TTY_MODE_RECEIVED: | 
| Pavel Zhamaitsiak | 82256c0 | 2014-12-10 17:11:40 -0800 | [diff] [blame] | 241 | if (DBG) log("Received PHONE_TTY_MODE_RECEIVED event"); | 
|  | 242 | onTtyModeReceived((AsyncResult) msg.obj); | 
|  | 243 | break; | 
|  | 244 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 245 | default: | 
|  | 246 | // super.handleMessage(msg); | 
|  | 247 | } | 
|  | 248 | } | 
|  | 249 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 250 | void updateCallNotifierRegistrationsAfterRadioTechnologyChange() { | 
|  | 251 | if (DBG) Log.d(LOG_TAG, "updateCallNotifierRegistrationsAfterRadioTechnologyChange..."); | 
|  | 252 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 253 | // Instantiate mSignalInfoToneGenerator | 
|  | 254 | createSignalInfoToneGenerator(); | 
|  | 255 | } | 
|  | 256 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 257 | /** | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 258 | * Helper class to play tones through the earpiece (or speaker / BT) | 
|  | 259 | * during a call, using the ToneGenerator. | 
|  | 260 | * | 
|  | 261 | * To use, just instantiate a new InCallTonePlayer | 
|  | 262 | * (passing in the TONE_* constant for the tone you want) | 
|  | 263 | * and start() it. | 
|  | 264 | * | 
|  | 265 | * When we're done playing the tone, if the phone is idle at that | 
|  | 266 | * point, we'll reset the audio routing and speaker state. | 
|  | 267 | * (That means that for tones that get played *after* a call | 
|  | 268 | * disconnects, like "busy" or "congestion" or "call ended", you | 
|  | 269 | * should NOT call resetAudioStateAfterDisconnect() yourself. | 
|  | 270 | * Instead, just start the InCallTonePlayer, which will automatically | 
|  | 271 | * defer the resetAudioStateAfterDisconnect() call until the tone | 
|  | 272 | * finishes playing.) | 
|  | 273 | */ | 
|  | 274 | private class InCallTonePlayer extends Thread { | 
|  | 275 | private int mToneId; | 
|  | 276 | private int mState; | 
|  | 277 | // The possible tones we can play. | 
|  | 278 | public static final int TONE_NONE = 0; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 279 | public static final int TONE_VOICE_PRIVACY = 5; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 280 |  | 
|  | 281 | // The tone volume relative to other sounds in the stream | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 282 | static final int TONE_RELATIVE_VOLUME_HIPRI = 80; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 283 |  | 
|  | 284 | // Buffer time (in msec) to add on to tone timeout value. | 
|  | 285 | // Needed mainly when the timeout value for a tone is the | 
|  | 286 | // exact duration of the tone itself. | 
|  | 287 | static final int TONE_TIMEOUT_BUFFER = 20; | 
|  | 288 |  | 
|  | 289 | // The tone state | 
|  | 290 | static final int TONE_OFF = 0; | 
|  | 291 | static final int TONE_ON = 1; | 
|  | 292 | static final int TONE_STOPPED = 2; | 
|  | 293 |  | 
|  | 294 | InCallTonePlayer(int toneId) { | 
|  | 295 | super(); | 
|  | 296 | mToneId = toneId; | 
|  | 297 | mState = TONE_OFF; | 
|  | 298 | } | 
|  | 299 |  | 
|  | 300 | @Override | 
|  | 301 | public void run() { | 
|  | 302 | log("InCallTonePlayer.run(toneId = " + mToneId + ")..."); | 
|  | 303 |  | 
|  | 304 | int toneType = 0;  // passed to ToneGenerator.startTone() | 
|  | 305 | int toneVolume;  // passed to the ToneGenerator constructor | 
|  | 306 | int toneLengthMillis; | 
|  | 307 | int phoneType = mCM.getFgPhone().getPhoneType(); | 
|  | 308 |  | 
|  | 309 | switch (mToneId) { | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 310 | case TONE_VOICE_PRIVACY: | 
|  | 311 | toneType = ToneGenerator.TONE_CDMA_ALERT_NETWORK_LITE; | 
|  | 312 | toneVolume = TONE_RELATIVE_VOLUME_HIPRI; | 
|  | 313 | toneLengthMillis = 5000; | 
|  | 314 | break; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 315 | default: | 
|  | 316 | throw new IllegalArgumentException("Bad toneId: " + mToneId); | 
|  | 317 | } | 
|  | 318 |  | 
|  | 319 | // If the mToneGenerator creation fails, just continue without it.  It is | 
|  | 320 | // a local audio signal, and is not as important. | 
|  | 321 | ToneGenerator toneGenerator; | 
|  | 322 | try { | 
|  | 323 | int stream; | 
|  | 324 | if (mBluetoothHeadset != null) { | 
| Amit Mahajan | b8f1320 | 2020-01-27 18:16:07 -0800 | [diff] [blame] | 325 | stream = isBluetoothAudioOn() ? AudioSystem.STREAM_BLUETOOTH_SCO : | 
|  | 326 | AudioSystem.STREAM_VOICE_CALL; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 327 | } else { | 
| Amit Mahajan | b8f1320 | 2020-01-27 18:16:07 -0800 | [diff] [blame] | 328 | stream = AudioSystem.STREAM_VOICE_CALL; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 329 | } | 
|  | 330 | toneGenerator = new ToneGenerator(stream, toneVolume); | 
|  | 331 | // if (DBG) log("- created toneGenerator: " + toneGenerator); | 
|  | 332 | } catch (RuntimeException e) { | 
|  | 333 | Log.w(LOG_TAG, | 
|  | 334 | "InCallTonePlayer: Exception caught while creating ToneGenerator: " + e); | 
|  | 335 | toneGenerator = null; | 
|  | 336 | } | 
|  | 337 |  | 
|  | 338 | // Using the ToneGenerator (with the CALL_WAITING / BUSY / | 
|  | 339 | // CONGESTION tones at least), the ToneGenerator itself knows | 
|  | 340 | // the right pattern of tones to play; we do NOT need to | 
|  | 341 | // manually start/stop each individual tone, or manually | 
|  | 342 | // insert the correct delay between tones.  (We just start it | 
|  | 343 | // and let it run for however long we want the tone pattern to | 
|  | 344 | // continue.) | 
|  | 345 | // | 
|  | 346 | // TODO: When we stop the ToneGenerator in the middle of a | 
|  | 347 | // "tone pattern", it sounds bad if we cut if off while the | 
|  | 348 | // tone is actually playing.  Consider adding API to the | 
|  | 349 | // ToneGenerator to say "stop at the next silent part of the | 
|  | 350 | // pattern", or simply "play the pattern N times and then | 
|  | 351 | // stop." | 
|  | 352 | boolean needToStopTone = true; | 
|  | 353 | boolean okToPlayTone = false; | 
|  | 354 |  | 
|  | 355 | if (toneGenerator != null) { | 
|  | 356 | int ringerMode = mAudioManager.getRingerMode(); | 
|  | 357 | if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { | 
|  | 358 | if (toneType == ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD) { | 
|  | 359 | if ((ringerMode != AudioManager.RINGER_MODE_SILENT) && | 
|  | 360 | (ringerMode != AudioManager.RINGER_MODE_VIBRATE)) { | 
|  | 361 | if (DBG) log("- InCallTonePlayer: start playing call tone=" + toneType); | 
|  | 362 | okToPlayTone = true; | 
|  | 363 | needToStopTone = false; | 
|  | 364 | } | 
|  | 365 | } else if ((toneType == ToneGenerator.TONE_CDMA_NETWORK_BUSY_ONE_SHOT) || | 
|  | 366 | (toneType == ToneGenerator.TONE_CDMA_REORDER) || | 
|  | 367 | (toneType == ToneGenerator.TONE_CDMA_ABBR_REORDER) || | 
|  | 368 | (toneType == ToneGenerator.TONE_CDMA_ABBR_INTERCEPT) || | 
|  | 369 | (toneType == ToneGenerator.TONE_CDMA_CALLDROP_LITE)) { | 
|  | 370 | if (ringerMode != AudioManager.RINGER_MODE_SILENT) { | 
|  | 371 | if (DBG) log("InCallTonePlayer:playing call fail tone:" + toneType); | 
|  | 372 | okToPlayTone = true; | 
|  | 373 | needToStopTone = false; | 
|  | 374 | } | 
|  | 375 | } else if ((toneType == ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE) || | 
|  | 376 | (toneType == ToneGenerator.TONE_CDMA_ALERT_NETWORK_LITE)) { | 
|  | 377 | if ((ringerMode != AudioManager.RINGER_MODE_SILENT) && | 
|  | 378 | (ringerMode != AudioManager.RINGER_MODE_VIBRATE)) { | 
|  | 379 | if (DBG) log("InCallTonePlayer:playing tone for toneType=" + toneType); | 
|  | 380 | okToPlayTone = true; | 
|  | 381 | needToStopTone = false; | 
|  | 382 | } | 
|  | 383 | } else { // For the rest of the tones, always OK to play. | 
|  | 384 | okToPlayTone = true; | 
|  | 385 | } | 
|  | 386 | } else {  // Not "CDMA" | 
|  | 387 | okToPlayTone = true; | 
|  | 388 | } | 
|  | 389 |  | 
|  | 390 | synchronized (this) { | 
|  | 391 | if (okToPlayTone && mState != TONE_STOPPED) { | 
|  | 392 | mState = TONE_ON; | 
|  | 393 | toneGenerator.startTone(toneType); | 
|  | 394 | try { | 
|  | 395 | wait(toneLengthMillis + TONE_TIMEOUT_BUFFER); | 
|  | 396 | } catch  (InterruptedException e) { | 
|  | 397 | Log.w(LOG_TAG, | 
|  | 398 | "InCallTonePlayer stopped: " + e); | 
|  | 399 | } | 
|  | 400 | if (needToStopTone) { | 
|  | 401 | toneGenerator.stopTone(); | 
|  | 402 | } | 
|  | 403 | } | 
|  | 404 | // if (DBG) log("- InCallTonePlayer: done playing."); | 
|  | 405 | toneGenerator.release(); | 
|  | 406 | mState = TONE_OFF; | 
|  | 407 | } | 
|  | 408 | } | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 409 | } | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 410 | } | 
|  | 411 |  | 
| Jordan Liu | 1c85e77 | 2019-08-06 16:06:19 -0700 | [diff] [blame] | 412 | // Returns whether there are any connected Bluetooth audio devices | 
|  | 413 | private boolean isBluetoothAudioOn() { | 
|  | 414 | return mBluetoothHeadset.getConnectedDevices().size() > 0; | 
|  | 415 | } | 
|  | 416 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 417 | /** | 
|  | 418 | * Displays a notification when the phone receives a DisplayInfo record. | 
|  | 419 | */ | 
|  | 420 | private void onDisplayInfo(AsyncResult r) { | 
|  | 421 | // Extract the DisplayInfo String from the message | 
|  | 422 | CdmaDisplayInfoRec displayInfoRec = (CdmaDisplayInfoRec)(r.result); | 
|  | 423 |  | 
|  | 424 | if (displayInfoRec != null) { | 
|  | 425 | String displayInfo = displayInfoRec.alpha; | 
|  | 426 | if (DBG) log("onDisplayInfo: displayInfo=" + displayInfo); | 
| Anthony Lee | e946853 | 2014-11-15 15:21:00 -0800 | [diff] [blame] | 427 | PhoneDisplayMessage.displayNetworkMessage(mApplication, displayInfo); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 428 |  | 
| Anthony Lee | e946853 | 2014-11-15 15:21:00 -0800 | [diff] [blame] | 429 | // start a timer that kills the dialog | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 430 | sendEmptyMessageDelayed(INTERNAL_SHOW_MESSAGE_NOTIFICATION_DONE, | 
| Anthony Lee | e946853 | 2014-11-15 15:21:00 -0800 | [diff] [blame] | 431 | SHOW_MESSAGE_NOTIFICATION_TIME); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 432 | } | 
|  | 433 | } | 
|  | 434 |  | 
|  | 435 | /** | 
| Anthony Lee | e946853 | 2014-11-15 15:21:00 -0800 | [diff] [blame] | 436 | * Displays a notification when the phone receives a notice that a supplemental | 
|  | 437 | * service has failed. | 
| Anthony Lee | e946853 | 2014-11-15 15:21:00 -0800 | [diff] [blame] | 438 | */ | 
|  | 439 | private void onSuppServiceFailed(AsyncResult r) { | 
| Tyler Gunn | 9dd07d0 | 2014-12-08 10:52:57 -0800 | [diff] [blame] | 440 | String mergeFailedString = ""; | 
|  | 441 | if (r.result == Phone.SuppService.CONFERENCE) { | 
|  | 442 | if (DBG) log("onSuppServiceFailed: displaying merge failure message"); | 
|  | 443 | mergeFailedString = mApplication.getResources().getString( | 
|  | 444 | R.string.incall_error_supp_service_conference); | 
|  | 445 | } else if (r.result == Phone.SuppService.RESUME) { | 
| Tyler Gunn | 93f9ff5 | 2018-04-11 13:53:04 -0700 | [diff] [blame] | 446 | if (DBG) log("onSuppServiceFailed: displaying resume failure message"); | 
| Tyler Gunn | 9dd07d0 | 2014-12-08 10:52:57 -0800 | [diff] [blame] | 447 | mergeFailedString = mApplication.getResources().getString( | 
| Tyler Gunn | 93f9ff5 | 2018-04-11 13:53:04 -0700 | [diff] [blame] | 448 | R.string.incall_error_supp_service_resume); | 
| Anju Mathapati | 4effeb2 | 2016-01-25 22:25:09 -0800 | [diff] [blame] | 449 | } else if (r.result == Phone.SuppService.HOLD) { | 
| Tyler Gunn | a7de7d3 | 2017-06-09 16:21:00 -0700 | [diff] [blame] | 450 | if (DBG) log("onSuppServiceFailed: displaying hold failure message"); | 
| Anju Mathapati | 4effeb2 | 2016-01-25 22:25:09 -0800 | [diff] [blame] | 451 | mergeFailedString = mApplication.getResources().getString( | 
|  | 452 | R.string.incall_error_supp_service_hold); | 
| Tyler Gunn | a7de7d3 | 2017-06-09 16:21:00 -0700 | [diff] [blame] | 453 | } else if (r.result == Phone.SuppService.TRANSFER) { | 
|  | 454 | if (DBG) log("onSuppServiceFailed: displaying transfer failure message"); | 
|  | 455 | mergeFailedString = mApplication.getResources().getString( | 
|  | 456 | R.string.incall_error_supp_service_transfer); | 
|  | 457 | } else if (r.result == Phone.SuppService.SEPARATE) { | 
|  | 458 | if (DBG) log("onSuppServiceFailed: displaying separate failure message"); | 
|  | 459 | mergeFailedString = mApplication.getResources().getString( | 
|  | 460 | R.string.incall_error_supp_service_separate); | 
|  | 461 | } else if (r.result == Phone.SuppService.SWITCH) { | 
|  | 462 | if (DBG) log("onSuppServiceFailed: displaying switch failure message"); | 
| Shashidhar Vithalrao Kulkarni | a557d62 | 2018-05-10 13:41:42 +0530 | [diff] [blame] | 463 | mergeFailedString = mApplication.getResources().getString( | 
| Tyler Gunn | a7de7d3 | 2017-06-09 16:21:00 -0700 | [diff] [blame] | 464 | R.string.incall_error_supp_service_switch); | 
|  | 465 | } else if (r.result == Phone.SuppService.REJECT) { | 
|  | 466 | if (DBG) log("onSuppServiceFailed: displaying reject failure message"); | 
| Shashidhar Vithalrao Kulkarni | a557d62 | 2018-05-10 13:41:42 +0530 | [diff] [blame] | 467 | mergeFailedString = mApplication.getResources().getString( | 
| Tyler Gunn | a7de7d3 | 2017-06-09 16:21:00 -0700 | [diff] [blame] | 468 | R.string.incall_error_supp_service_reject); | 
| Shashidhar Vithalrao Kulkarni | a557d62 | 2018-05-10 13:41:42 +0530 | [diff] [blame] | 469 | } else if (r.result == Phone.SuppService.HANGUP) { | 
|  | 470 | mergeFailedString = mApplication.getResources().getString( | 
|  | 471 | R.string.incall_error_supp_service_hangup); | 
|  | 472 | }  else { | 
| Tyler Gunn | a7de7d3 | 2017-06-09 16:21:00 -0700 | [diff] [blame] | 473 | if (DBG) log("onSuppServiceFailed: unknown failure"); | 
|  | 474 | return; | 
| Tyler Gunn | 9dd07d0 | 2014-12-08 10:52:57 -0800 | [diff] [blame] | 475 | } | 
| Tyler Gunn | a7de7d3 | 2017-06-09 16:21:00 -0700 | [diff] [blame] | 476 |  | 
| Anthony Lee | e946853 | 2014-11-15 15:21:00 -0800 | [diff] [blame] | 477 | PhoneDisplayMessage.displayErrorMessage(mApplication, mergeFailedString); | 
|  | 478 |  | 
|  | 479 | // start a timer that kills the dialog | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 480 | sendEmptyMessageDelayed(INTERNAL_SHOW_MESSAGE_NOTIFICATION_DONE, | 
| Anthony Lee | e946853 | 2014-11-15 15:21:00 -0800 | [diff] [blame] | 481 | SHOW_MESSAGE_NOTIFICATION_TIME); | 
|  | 482 | } | 
|  | 483 |  | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 484 | public void updatePhoneStateListeners(boolean isRefresh) { | 
| Srikanth Chintala | 4baf0b9 | 2017-11-14 15:52:47 +0530 | [diff] [blame] | 485 | updatePhoneStateListeners(isRefresh, UPDATE_TYPE_MWI_CFI, | 
|  | 486 | SubscriptionManager.INVALID_SUBSCRIPTION_ID); | 
|  | 487 | } | 
|  | 488 |  | 
|  | 489 | public void updatePhoneStateListeners(boolean isRefresh, int updateType, int subIdToUpdate) { | 
| Malcolm Chen | a336e2a | 2019-02-12 18:51:37 -0800 | [diff] [blame] | 490 | List<SubscriptionInfo> subInfos = SubscriptionController.getInstance() | 
| Philip P. Moltmann | 700a959 | 2019-10-03 11:53:50 -0700 | [diff] [blame] | 491 | .getActiveSubscriptionInfoList(mApplication.getOpPackageName(), | 
| Philip P. Moltmann | e6bb1cd | 2020-03-05 16:24:02 -0800 | [diff] [blame] | 492 | mApplication.getAttributionTag()); | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 493 |  | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 494 | // Sort sub id list based on slot id, so that CFI/MWI notifications will be updated for | 
|  | 495 | // slot 0 first then slot 1. This is needed to ensure that when CFI or MWI is enabled for | 
|  | 496 | // both slots, user always sees icon related to slot 0 on left side followed by that of | 
|  | 497 | // slot 1. | 
| Zoey Chen | 5ec326b | 2021-02-22 21:21:28 +0800 | [diff] [blame] | 498 | List<Integer> subIdList = new ArrayList<Integer>(mTelephonyCallback.keySet()); | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 499 | Collections.sort(subIdList, new Comparator<Integer>() { | 
|  | 500 | public int compare(Integer sub1, Integer sub2) { | 
|  | 501 | int slotId1 = SubscriptionController.getInstance().getSlotIndex(sub1); | 
|  | 502 | int slotId2 = SubscriptionController.getInstance().getSlotIndex(sub2); | 
|  | 503 | return slotId1 > slotId2 ? 0 : -1; | 
|  | 504 | } | 
|  | 505 | }); | 
|  | 506 |  | 
|  | 507 | for (int subIdCounter = (subIdList.size() - 1); subIdCounter >= 0; subIdCounter--) { | 
|  | 508 | int subId = subIdList.get(subIdCounter); | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 509 | if (subInfos == null || !containsSubId(subInfos, subId)) { | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 510 | Log.d(LOG_TAG, "updatePhoneStateListeners: Hide the outstanding notifications."); | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 511 | // Hide the outstanding notifications. | 
|  | 512 | mApplication.notificationMgr.updateMwi(subId, false); | 
|  | 513 | mApplication.notificationMgr.updateCfi(subId, false); | 
|  | 514 |  | 
| Zoey Chen | 5719bac | 2021-01-28 15:05:49 +0800 | [diff] [blame] | 515 | // Unregister the listener. | 
| Zoey Chen | 5ec326b | 2021-02-22 21:21:28 +0800 | [diff] [blame] | 516 | mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback.get(subId)); | 
|  | 517 | mTelephonyCallback.remove(subId); | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 518 | } else { | 
|  | 519 | Log.d(LOG_TAG, "updatePhoneStateListeners: update CF notifications."); | 
|  | 520 |  | 
|  | 521 | if (mCFIStatus.containsKey(subId)) { | 
| Srikanth Chintala | 4baf0b9 | 2017-11-14 15:52:47 +0530 | [diff] [blame] | 522 | if ((updateType == UPDATE_TYPE_CFI) && (subId == subIdToUpdate)) { | 
|  | 523 | mApplication.notificationMgr.updateCfi(subId, mCFIStatus.get(subId), | 
|  | 524 | isRefresh); | 
|  | 525 | } else { | 
|  | 526 | mApplication.notificationMgr.updateCfi(subId, mCFIStatus.get(subId), true); | 
|  | 527 | } | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 528 | } | 
|  | 529 | if (mMWIStatus.containsKey(subId)) { | 
| Srikanth Chintala | 4baf0b9 | 2017-11-14 15:52:47 +0530 | [diff] [blame] | 530 | if ((updateType == UPDATE_TYPE_MWI) && (subId == subIdToUpdate)) { | 
|  | 531 | mApplication.notificationMgr.updateMwi(subId, mMWIStatus.get(subId), | 
|  | 532 | isRefresh); | 
|  | 533 | } else { | 
|  | 534 | mApplication.notificationMgr.updateMwi(subId, mMWIStatus.get(subId), true); | 
|  | 535 | } | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 536 | } | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 537 | } | 
|  | 538 | } | 
|  | 539 |  | 
|  | 540 | if (subInfos == null) { | 
|  | 541 | return; | 
|  | 542 | } | 
|  | 543 |  | 
|  | 544 | // Register new phone listeners for active subscriptions. | 
|  | 545 | for (int i = 0; i < subInfos.size(); i++) { | 
|  | 546 | int subId = subInfos.get(i).getSubscriptionId(); | 
| Zoey Chen | 5ec326b | 2021-02-22 21:21:28 +0800 | [diff] [blame] | 547 | if (!mTelephonyCallback.containsKey(subId)) { | 
|  | 548 | CallNotifierTelephonyCallback listener = new CallNotifierTelephonyCallback(subId); | 
|  | 549 | mTelephonyManager.createForSubscriptionId(subId).registerTelephonyCallback( | 
| Zoey Chen | 5719bac | 2021-01-28 15:05:49 +0800 | [diff] [blame] | 550 | new HandlerExecutor(this), listener); | 
| Zoey Chen | 5ec326b | 2021-02-22 21:21:28 +0800 | [diff] [blame] | 551 | mTelephonyCallback.put(subId, listener); | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 552 | } | 
|  | 553 | } | 
|  | 554 | } | 
|  | 555 |  | 
|  | 556 | /** | 
|  | 557 | * @return {@code true} if the list contains SubscriptionInfo with the given subscription id. | 
|  | 558 | */ | 
|  | 559 | private boolean containsSubId(List<SubscriptionInfo> subInfos, int subId) { | 
|  | 560 | if (subInfos == null) { | 
|  | 561 | return false; | 
|  | 562 | } | 
|  | 563 |  | 
|  | 564 | for (int i = 0; i < subInfos.size(); i++) { | 
|  | 565 | if (subInfos.get(i).getSubscriptionId() == subId) { | 
|  | 566 | return true; | 
|  | 567 | } | 
|  | 568 | } | 
|  | 569 | return false; | 
|  | 570 | } | 
|  | 571 |  | 
| Anthony Lee | e946853 | 2014-11-15 15:21:00 -0800 | [diff] [blame] | 572 | /** | 
| Pavel Zhamaitsiak | 82256c0 | 2014-12-10 17:11:40 -0800 | [diff] [blame] | 573 | * Displays a notification when the phone receives a notice that TTY mode | 
|  | 574 | * has changed on remote end. | 
|  | 575 | */ | 
|  | 576 | private void onTtyModeReceived(AsyncResult r) { | 
|  | 577 | if (DBG) log("TtyModeReceived: displaying notification message"); | 
|  | 578 |  | 
|  | 579 | int resId = 0; | 
|  | 580 | switch (((Integer)r.result).intValue()) { | 
|  | 581 | case TelecomManager.TTY_MODE_FULL: | 
| Daniel Bright | ebb4eb7 | 2020-02-18 15:16:33 -0800 | [diff] [blame] | 582 | resId = com.android.internal.R.string.peerTtyModeFull; | 
| Pavel Zhamaitsiak | 82256c0 | 2014-12-10 17:11:40 -0800 | [diff] [blame] | 583 | break; | 
|  | 584 | case TelecomManager.TTY_MODE_HCO: | 
| Daniel Bright | ebb4eb7 | 2020-02-18 15:16:33 -0800 | [diff] [blame] | 585 | resId = com.android.internal.R.string.peerTtyModeHco; | 
| Pavel Zhamaitsiak | 82256c0 | 2014-12-10 17:11:40 -0800 | [diff] [blame] | 586 | break; | 
|  | 587 | case TelecomManager.TTY_MODE_VCO: | 
| Daniel Bright | ebb4eb7 | 2020-02-18 15:16:33 -0800 | [diff] [blame] | 588 | resId = com.android.internal.R.string.peerTtyModeVco; | 
| Pavel Zhamaitsiak | 82256c0 | 2014-12-10 17:11:40 -0800 | [diff] [blame] | 589 | break; | 
|  | 590 | case TelecomManager.TTY_MODE_OFF: | 
| Daniel Bright | ebb4eb7 | 2020-02-18 15:16:33 -0800 | [diff] [blame] | 591 | resId = com.android.internal.R.string.peerTtyModeOff; | 
| Pavel Zhamaitsiak | 82256c0 | 2014-12-10 17:11:40 -0800 | [diff] [blame] | 592 | break; | 
|  | 593 | default: | 
|  | 594 | Log.e(LOG_TAG, "Unsupported TTY mode: " + r.result); | 
|  | 595 | break; | 
|  | 596 | } | 
|  | 597 | if (resId != 0) { | 
|  | 598 | PhoneDisplayMessage.displayNetworkMessage(mApplication, | 
| Daniel Bright | ebb4eb7 | 2020-02-18 15:16:33 -0800 | [diff] [blame] | 599 | mApplication.getResources().getString(resId)); | 
| Pavel Zhamaitsiak | 82256c0 | 2014-12-10 17:11:40 -0800 | [diff] [blame] | 600 |  | 
|  | 601 | // start a timer that kills the dialog | 
| Brad Ebinger | a9c6b6d | 2016-01-07 17:24:16 -0800 | [diff] [blame] | 602 | sendEmptyMessageDelayed(INTERNAL_SHOW_MESSAGE_NOTIFICATION_DONE, | 
| Pavel Zhamaitsiak | 82256c0 | 2014-12-10 17:11:40 -0800 | [diff] [blame] | 603 | SHOW_MESSAGE_NOTIFICATION_TIME); | 
|  | 604 | } | 
|  | 605 | } | 
|  | 606 |  | 
|  | 607 | /** | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 608 | * Helper class to play SignalInfo tones using the ToneGenerator. | 
|  | 609 | * | 
|  | 610 | * To use, just instantiate a new SignalInfoTonePlayer | 
|  | 611 | * (passing in the ToneID constant for the tone you want) | 
|  | 612 | * and start() it. | 
|  | 613 | */ | 
|  | 614 | private class SignalInfoTonePlayer extends Thread { | 
|  | 615 | private int mToneId; | 
|  | 616 |  | 
|  | 617 | SignalInfoTonePlayer(int toneId) { | 
|  | 618 | super(); | 
|  | 619 | mToneId = toneId; | 
|  | 620 | } | 
|  | 621 |  | 
|  | 622 | @Override | 
|  | 623 | public void run() { | 
|  | 624 | log("SignalInfoTonePlayer.run(toneId = " + mToneId + ")..."); | 
| Yorke Lee | 65cbd16 | 2014-10-08 11:26:02 -0700 | [diff] [blame] | 625 | createSignalInfoToneGenerator(); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 626 | if (mSignalInfoToneGenerator != null) { | 
|  | 627 | //First stop any ongoing SignalInfo tone | 
|  | 628 | mSignalInfoToneGenerator.stopTone(); | 
|  | 629 |  | 
|  | 630 | //Start playing the new tone if its a valid tone | 
|  | 631 | mSignalInfoToneGenerator.startTone(mToneId); | 
|  | 632 | } | 
|  | 633 | } | 
|  | 634 | } | 
|  | 635 |  | 
|  | 636 | /** | 
|  | 637 | * Plays a tone when the phone receives a SignalInfo record. | 
|  | 638 | */ | 
|  | 639 | private void onSignalInfo(AsyncResult r) { | 
|  | 640 | // Signal Info are totally ignored on non-voice-capable devices. | 
|  | 641 | if (!PhoneGlobals.sVoiceCapable) { | 
|  | 642 | Log.w(LOG_TAG, "Got onSignalInfo() on non-voice-capable device! Ignoring..."); | 
|  | 643 | return; | 
|  | 644 | } | 
|  | 645 |  | 
|  | 646 | if (PhoneUtils.isRealIncomingCall(mCM.getFirstActiveRingingCall().getState())) { | 
|  | 647 | // Do not start any new SignalInfo tone when Call state is INCOMING | 
|  | 648 | // and stop any previous SignalInfo tone which is being played | 
|  | 649 | stopSignalInfoTone(); | 
|  | 650 | } else { | 
|  | 651 | // Extract the SignalInfo String from the message | 
|  | 652 | CdmaSignalInfoRec signalInfoRec = (CdmaSignalInfoRec)(r.result); | 
|  | 653 | // Only proceed if a Signal info is present. | 
|  | 654 | if (signalInfoRec != null) { | 
|  | 655 | boolean isPresent = signalInfoRec.isPresent; | 
|  | 656 | if (DBG) log("onSignalInfo: isPresent=" + isPresent); | 
|  | 657 | if (isPresent) {// if tone is valid | 
|  | 658 | int uSignalType = signalInfoRec.signalType; | 
|  | 659 | int uAlertPitch = signalInfoRec.alertPitch; | 
|  | 660 | int uSignal = signalInfoRec.signal; | 
|  | 661 |  | 
|  | 662 | if (DBG) log("onSignalInfo: uSignalType=" + uSignalType + ", uAlertPitch=" + | 
|  | 663 | uAlertPitch + ", uSignal=" + uSignal); | 
|  | 664 | //Map the Signal to a ToneGenerator ToneID only if Signal info is present | 
|  | 665 | int toneID = SignalToneUtil.getAudioToneFromSignalInfo | 
|  | 666 | (uSignalType, uAlertPitch, uSignal); | 
|  | 667 |  | 
|  | 668 | //Create the SignalInfo tone player and pass the ToneID | 
|  | 669 | new SignalInfoTonePlayer(toneID).start(); | 
|  | 670 | } | 
|  | 671 | } | 
|  | 672 | } | 
|  | 673 | } | 
|  | 674 |  | 
|  | 675 | /** | 
|  | 676 | * Stops a SignalInfo tone in the following condition | 
|  | 677 | * 1 - On receiving a New Ringing Call | 
|  | 678 | * 2 - On disconnecting a call | 
|  | 679 | * 3 - On answering a Call Waiting Call | 
|  | 680 | */ | 
|  | 681 | /* package */ void stopSignalInfoTone() { | 
|  | 682 | if (DBG) log("stopSignalInfoTone: Stopping SignalInfo tone player"); | 
|  | 683 | new SignalInfoTonePlayer(ToneGenerator.TONE_CDMA_SIGNAL_OFF).start(); | 
|  | 684 | } | 
|  | 685 |  | 
| Santos Cordon | 5c04672 | 2014-09-18 15:41:13 -0700 | [diff] [blame] | 686 | private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 687 | new BluetoothProfile.ServiceListener() { | 
|  | 688 | public void onServiceConnected(int profile, BluetoothProfile proxy) { | 
|  | 689 | mBluetoothHeadset = (BluetoothHeadset) proxy; | 
|  | 690 | if (VDBG) log("- Got BluetoothHeadset: " + mBluetoothHeadset); | 
|  | 691 | } | 
|  | 692 |  | 
|  | 693 | public void onServiceDisconnected(int profile) { | 
|  | 694 | mBluetoothHeadset = null; | 
|  | 695 | } | 
|  | 696 | }; | 
|  | 697 |  | 
| Zoey Chen | 5ec326b | 2021-02-22 21:21:28 +0800 | [diff] [blame] | 698 | private class CallNotifierTelephonyCallback extends TelephonyCallback implements | 
|  | 699 | TelephonyCallback.MessageWaitingIndicatorListener, | 
|  | 700 | TelephonyCallback.CallForwardingIndicatorListener { | 
| Zoey Chen | 5719bac | 2021-01-28 15:05:49 +0800 | [diff] [blame] | 701 |  | 
| Meng Wang | 7f34c9c | 2020-01-14 14:57:57 -0800 | [diff] [blame] | 702 | private final int mSubId; | 
|  | 703 |  | 
| Zoey Chen | 5ec326b | 2021-02-22 21:21:28 +0800 | [diff] [blame] | 704 | CallNotifierTelephonyCallback(int subId) { | 
| chen xu | 0694647 | 2019-03-20 14:55:59 -0700 | [diff] [blame] | 705 | super(); | 
| Meng Wang | 7f34c9c | 2020-01-14 14:57:57 -0800 | [diff] [blame] | 706 | this.mSubId = subId; | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 707 | } | 
|  | 708 |  | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 709 | @Override | 
|  | 710 | public void onMessageWaitingIndicatorChanged(boolean visible) { | 
|  | 711 | if (VDBG) log("onMessageWaitingIndicatorChanged(): " + this.mSubId + " " + visible); | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 712 | mMWIStatus.put(this.mSubId, visible); | 
| Srikanth Chintala | 4baf0b9 | 2017-11-14 15:52:47 +0530 | [diff] [blame] | 713 | updatePhoneStateListeners(false, UPDATE_TYPE_MWI, this.mSubId); | 
| Andrew Lee | 2fcb6c3 | 2014-12-04 14:52:35 -0800 | [diff] [blame] | 714 | } | 
|  | 715 |  | 
|  | 716 | @Override | 
|  | 717 | public void onCallForwardingIndicatorChanged(boolean visible) { | 
| Tyler Gunn | 17bffd0 | 2017-09-19 11:40:12 -0700 | [diff] [blame] | 718 | Log.i(LOG_TAG, "onCallForwardingIndicatorChanged(): subId=" + this.mSubId | 
|  | 719 | + ", visible=" + (visible ? "Y" : "N")); | 
| Kazuya Ohshiro | 263737d | 2017-10-06 19:42:03 +0900 | [diff] [blame] | 720 | mCFIStatus.put(this.mSubId, visible); | 
| Srikanth Chintala | 4baf0b9 | 2017-11-14 15:52:47 +0530 | [diff] [blame] | 721 | updatePhoneStateListeners(false, UPDATE_TYPE_CFI, this.mSubId); | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 722 | } | 
| Zoey Chen | 5719bac | 2021-01-28 15:05:49 +0800 | [diff] [blame] | 723 | } | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 724 |  | 
| Santos Cordon | 7d4ddf6 | 2013-07-10 11:58:08 -0700 | [diff] [blame] | 725 | private void log(String msg) { | 
|  | 726 | Log.d(LOG_TAG, msg); | 
|  | 727 | } | 
|  | 728 | } |