17
17
package com .android .internal .location ;
18
18
19
19
import java .io .UnsupportedEncodingException ;
20
+ import java .util .concurrent .TimeUnit ;
20
21
21
22
import android .app .Notification ;
22
23
import android .app .NotificationManager ;
27
28
import android .content .IntentFilter ;
28
29
import android .location .LocationManager ;
29
30
import android .location .INetInitiatedListener ;
31
+ import android .os .SystemClock ;
30
32
import android .telephony .TelephonyManager ;
31
33
import android .telephony .PhoneNumberUtils ;
32
34
import android .telephony .PhoneStateListener ;
33
- import android .os .Bundle ;
34
35
import android .os .RemoteException ;
35
36
import android .os .UserHandle ;
36
- import android .os .SystemProperties ;
37
37
import android .util .Log ;
38
38
39
39
import com .android .internal .notification .SystemNotificationChannels ;
40
40
import com .android .internal .R ;
41
41
import com .android .internal .telephony .GsmAlphabet ;
42
- import com .android .internal .telephony .TelephonyProperties ;
43
42
44
43
/**
45
44
* A GPS Network-initiated Handler class used by LocationManager.
@@ -50,8 +49,7 @@ public class GpsNetInitiatedHandler {
50
49
51
50
private static final String TAG = "GpsNetInitiatedHandler" ;
52
51
53
- private static final boolean DEBUG = true ;
54
- private static final boolean VERBOSE = false ;
52
+ private static final boolean DEBUG = Log .isLoggable (TAG , Log .DEBUG );
55
53
56
54
// NI verify activity for bringing up UI (not used yet)
57
55
public static final String ACTION_NI_VERIFY = "android.intent.action.NETWORK_INITIATED_VERIFY" ;
@@ -94,6 +92,9 @@ public class GpsNetInitiatedHandler {
94
92
public static final int GPS_ENC_SUPL_UCS2 = 3 ;
95
93
public static final int GPS_ENC_UNKNOWN = -1 ;
96
94
95
+ // Limit on SUPL NI emergency mode time extension after emergency sessions ends
96
+ private static final int MAX_EMERGENCY_MODE_EXTENSION_SECONDS = 300 ; // 5 minute maximum
97
+
97
98
private final Context mContext ;
98
99
private final TelephonyManager mTelephonyManager ;
99
100
private final PhoneStateListener mPhoneStateListener ;
@@ -109,7 +110,7 @@ public class GpsNetInitiatedHandler {
109
110
private volatile boolean mIsSuplEsEnabled ;
110
111
111
112
// Set to true if the phone is having emergency call.
112
- private volatile boolean mIsInEmergency ;
113
+ private volatile boolean mIsInEmergencyCall ;
113
114
114
115
// If Location function is enabled.
115
116
private volatile boolean mIsLocationEnabled = false ;
@@ -119,6 +120,10 @@ public class GpsNetInitiatedHandler {
119
120
// Set to true if string from HAL is encoded as Hex, e.g., "3F0039"
120
121
static private boolean mIsHexInput = true ;
121
122
123
+ // End time of emergency call, and extension, if set
124
+ private long mCallEndElapsedRealtimeMillis = 0 ;
125
+ private long mEmergencyExtensionMillis = 0 ;
126
+
122
127
public static class GpsNiNotification
123
128
{
124
129
public int notificationId ;
@@ -146,16 +151,12 @@ public static class GpsNiResponse {
146
151
if (action .equals (Intent .ACTION_NEW_OUTGOING_CALL )) {
147
152
String phoneNumber = intent .getStringExtra (Intent .EXTRA_PHONE_NUMBER );
148
153
/*
149
- Emergency Mode is when during emergency call or in emergency call back mode.
150
- For checking if it is during emergency call:
151
- mIsInEmergency records if the phone is in emergency call or not. It will
154
+ Tracks the emergency call:
155
+ mIsInEmergencyCall records if the phone is in emergency call or not. It will
152
156
be set to true when the phone is having emergency call, and then will
153
157
be set to false by mPhoneStateListener when the emergency call ends.
154
- For checking if it is in emergency call back mode:
155
- Emergency call back mode will be checked by reading system properties
156
- when necessary: SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)
157
158
*/
158
- setInEmergency ( PhoneNumberUtils .isEmergencyNumber (phoneNumber ) );
159
+ mIsInEmergencyCall = PhoneNumberUtils .isEmergencyNumber (phoneNumber );
159
160
if (DEBUG ) Log .v (TAG , "ACTION_NEW_OUTGOING_CALL - " + getInEmergency ());
160
161
} else if (action .equals (LocationManager .MODE_CHANGED_ACTION )) {
161
162
updateLocationMode ();
@@ -195,7 +196,10 @@ public void onCallStateChanged(int state, String incomingNumber) {
195
196
if (DEBUG ) Log .d (TAG , "onCallStateChanged(): state is " + state );
196
197
// listening for emergency call ends
197
198
if (state == TelephonyManager .CALL_STATE_IDLE ) {
198
- setInEmergency (false );
199
+ if (mIsInEmergencyCall ) {
200
+ mCallEndElapsedRealtimeMillis = SystemClock .elapsedRealtime ();
201
+ mIsInEmergencyCall = false ;
202
+ }
199
203
}
200
204
}
201
205
};
@@ -229,22 +233,35 @@ public boolean getLocationEnabled() {
229
233
return mIsLocationEnabled ;
230
234
}
231
235
232
- // Note: Currently, there are two mechanisms involved to determine if a
233
- // phone is in emergency mode:
234
- // 1. If the user is making an emergency call, this is provided by activly
235
- // monitoring the outgoing phone number;
236
- // 2. If the device is in a emergency callback state, this is provided by
237
- // system properties.
238
- // If either one of above exists, the phone is considered in an emergency
239
- // mode. Because of this complexity, we need to be careful about how to set
240
- // and clear the emergency state.
241
- public void setInEmergency (boolean isInEmergency ) {
242
- mIsInEmergency = isInEmergency ;
243
- }
244
-
236
+ /**
237
+ * Determines whether device is in user-initiated emergency session based on the following
238
+ * 1. If the user is making an emergency call, this is provided by actively
239
+ * monitoring the outgoing phone number;
240
+ * 2. If the user has recently ended an emergency call, and the device is in a configured time
241
+ * window after the end of that call.
242
+ * 3. If the device is in a emergency callback state, this is provided by querying
243
+ * TelephonyManager.
244
+ * @return true if is considered in user initiated emergency mode for NI purposes
245
+ */
245
246
public boolean getInEmergency () {
247
+ boolean isInEmergencyExtension =
248
+ (SystemClock .elapsedRealtime () - mCallEndElapsedRealtimeMillis ) <
249
+ mEmergencyExtensionMillis ;
246
250
boolean isInEmergencyCallback = mTelephonyManager .getEmergencyCallbackMode ();
247
- return mIsInEmergency || isInEmergencyCallback ;
251
+ return mIsInEmergencyCall || isInEmergencyCallback || isInEmergencyExtension ;
252
+ }
253
+
254
+ public void setEmergencyExtensionSeconds (int emergencyExtensionSeconds ) {
255
+ if (emergencyExtensionSeconds > MAX_EMERGENCY_MODE_EXTENSION_SECONDS ) {
256
+ Log .w (TAG , "emergencyExtensionSeconds " + emergencyExtensionSeconds
257
+ + " too high, reset to " + MAX_EMERGENCY_MODE_EXTENSION_SECONDS );
258
+ emergencyExtensionSeconds = MAX_EMERGENCY_MODE_EXTENSION_SECONDS ;
259
+ } else if (emergencyExtensionSeconds < 0 ) {
260
+ Log .w (TAG , "emergencyExtensionSeconds " + emergencyExtensionSeconds
261
+ + " is negative, reset to zero." );
262
+ emergencyExtensionSeconds = 0 ;
263
+ }
264
+ mEmergencyExtensionMillis = TimeUnit .SECONDS .toMillis (emergencyExtensionSeconds );
248
265
}
249
266
250
267
0 commit comments