blob: b163b10977b16236ba5072c871163ba9a5311156 [file] [log] [blame]
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001/*
2 * Copyright (C) 2009 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
17package com.android.phone;
18
19import android.app.Notification;
20import android.app.NotificationManager;
21import android.app.PendingIntent;
22import android.app.Service;
23import android.content.BroadcastReceiver;
24import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
27import android.content.res.Resources;
Tyler Gunn625eb0b2014-08-27 20:37:32 -070028import android.graphics.BitmapFactory;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070029import android.os.AsyncResult;
30import android.os.Binder;
31import android.os.CountDownTimer;
32import android.os.Handler;
33import android.os.IBinder;
34import android.os.Message;
35import android.os.SystemProperties;
36import android.util.Log;
37
Santos Cordon7d4ddf62013-07-10 11:58:08 -070038import com.android.internal.telephony.Phone;
39import com.android.internal.telephony.PhoneConstants;
40import com.android.internal.telephony.PhoneFactory;
41import com.android.internal.telephony.TelephonyIntents;
42import com.android.internal.telephony.TelephonyProperties;
fionaxu75b66a72017-04-19 19:01:56 -070043import com.android.internal.telephony.util.TelephonyNotificationBuilder;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070044
45/**
46 * Application service that inserts/removes Emergency Callback Mode notification and
47 * updates Emergency Callback Mode countdown clock in the notification
48 *
49 * @see EmergencyCallbackModeExitDialog
50 */
51public class EmergencyCallbackModeService extends Service {
52
53 // Default Emergency Callback Mode timeout value
54 private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
55 private static final String LOG_TAG = "EmergencyCallbackModeService";
56
57 private NotificationManager mNotificationManager = null;
58 private CountDownTimer mTimer = null;
59 private long mTimeLeft = 0;
60 private Phone mPhone = null;
61 private boolean mInEmergencyCall = false;
62
63 private static final int ECM_TIMER_RESET = 1;
64
65 private Handler mHandler = new Handler () {
66 public void handleMessage(Message msg) {
67 switch (msg.what) {
68 case ECM_TIMER_RESET:
69 resetEcmTimer((AsyncResult) msg.obj);
70 break;
71 }
72 }
73 };
74
75 @Override
76 public void onCreate() {
Sandeep Kuntade73a6a2014-10-15 18:45:56 +053077 Phone phoneInEcm = PhoneGlobals.getInstance().getPhoneInEcm();
Santos Cordon7d4ddf62013-07-10 11:58:08 -070078 // Check if it is CDMA phone
Sandeep Kuntade73a6a2014-10-15 18:45:56 +053079 if (phoneInEcm == null || ((phoneInEcm.getPhoneType() != PhoneConstants.PHONE_TYPE_CDMA)
80 && (phoneInEcm.getImsPhone() == null))) {
81 Log.e(LOG_TAG, "Error! Emergency Callback Mode not supported for " + phoneInEcm);
Santos Cordon7d4ddf62013-07-10 11:58:08 -070082 stopSelf();
Sandeep Kuntade73a6a2014-10-15 18:45:56 +053083 return;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070084 }
85
86 // Register receiver for intents
87 IntentFilter filter = new IntentFilter();
88 filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
89 filter.addAction(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS);
90 registerReceiver(mEcmReceiver, filter);
91
92 mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
93
94 // Register ECM timer reset notfication
Sandeep Kuntade73a6a2014-10-15 18:45:56 +053095 mPhone = phoneInEcm;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070096 mPhone.registerForEcmTimerReset(mHandler, ECM_TIMER_RESET, null);
97
98 startTimerNotification();
99 }
100
101 @Override
102 public void onDestroy() {
Sandeep Kunta55a6ae82015-12-14 17:49:02 +0530103 if (mPhone != null) {
104 // Unregister receiver
105 unregisterReceiver(mEcmReceiver);
106 // Unregister ECM timer reset notification
107 mPhone.unregisterForEcmTimerReset(mHandler);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700108
Sandeep Kunta55a6ae82015-12-14 17:49:02 +0530109 // Cancel the notification and timer
110 mNotificationManager.cancel(R.string.phone_in_ecm_notification_title);
111 mTimer.cancel();
112 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700113 }
114
115 /**
116 * Listens for Emergency Callback Mode intents
117 */
118 private BroadcastReceiver mEcmReceiver = new BroadcastReceiver() {
119 @Override
120 public void onReceive(Context context, Intent intent) {
121 // Stop the service when phone exits Emergency Callback Mode
122 if (intent.getAction().equals(
123 TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
124 if (intent.getBooleanExtra("phoneinECMState", false) == false) {
125 stopSelf();
126 }
127 }
128 // Show dialog box
129 else if (intent.getAction().equals(
130 TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS)) {
131 context.startActivity(
132 new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS)
133 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
134 }
135 }
136 };
137
138 /**
139 * Start timer notification for Emergency Callback Mode
140 */
141 private void startTimerNotification() {
142 // Get Emergency Callback Mode timeout value
143 long ecmTimeout = SystemProperties.getLong(
144 TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
145
146 // Show the notification
147 showNotification(ecmTimeout);
148
149 // Start countdown timer for the notification updates
Yorke Lee34a72cb2014-10-12 13:17:04 -0700150 if (mTimer != null) {
151 mTimer.cancel();
152 } else {
153 mTimer = new CountDownTimer(ecmTimeout, 1000) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700154
Yorke Lee34a72cb2014-10-12 13:17:04 -0700155 @Override
156 public void onTick(long millisUntilFinished) {
157 mTimeLeft = millisUntilFinished;
158 EmergencyCallbackModeService.this.showNotification(millisUntilFinished);
159 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700160
Yorke Lee34a72cb2014-10-12 13:17:04 -0700161 @Override
162 public void onFinish() {
163 //Do nothing
164 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700165
Yorke Lee34a72cb2014-10-12 13:17:04 -0700166 };
167 }
168 mTimer.start();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700169 }
170
171 /**
172 * Shows notification for Emergency Callback Mode
173 */
174 private void showNotification(long millisUntilFinished) {
Amit Mahajan6a2f8752016-07-25 11:38:10 -0700175 Phone imsPhone = mPhone.getImsPhone();
176 boolean isInEcm = mPhone.isInEcm() || (imsPhone != null && imsPhone.isInEcm());
Yorke Lee34a72cb2014-10-12 13:17:04 -0700177 if (!isInEcm) {
178 Log.i(LOG_TAG, "Asked to show notification but not in ECM mode");
179 if (mTimer != null) {
180 mTimer.cancel();
181 }
182 return;
183 }
fionaxu75b66a72017-04-19 19:01:56 -0700184 final Notification.Builder builder = new TelephonyNotificationBuilder(
185 getApplicationContext());
Tyler Gunn625eb0b2014-08-27 20:37:32 -0700186 builder.setOngoing(true);
187 builder.setPriority(Notification.PRIORITY_HIGH);
188 builder.setSmallIcon(R.drawable.ic_emergency_callback_mode);
189 builder.setTicker(getText(R.string.phone_entered_ecm_text));
190 builder.setContentTitle(getText(R.string.phone_in_ecm_notification_title));
191 builder.setColor(getResources().getColor(R.color.dialer_theme_color));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700192
193 // PendingIntent to launch Emergency Callback Mode Exit activity if the user selects
194 // this notification
195 PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
196 new Intent(EmergencyCallbackModeExitDialog.ACTION_SHOW_ECM_EXIT_DIALOG), 0);
Tyler Gunn625eb0b2014-08-27 20:37:32 -0700197 builder.setContentIntent(contentIntent);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700198
199 // Format notification string
200 String text = null;
201 if(mInEmergencyCall) {
202 text = getText(R.string.phone_in_ecm_call_notification_text).toString();
203 } else {
204 int minutes = (int)(millisUntilFinished / 60000);
205 String time = String.format("%d:%02d", minutes, (millisUntilFinished % 60000) / 1000);
206 text = String.format(getResources().getQuantityText(
207 R.plurals.phone_in_ecm_notification_time, minutes).toString(), time);
208 }
Tyler Gunn625eb0b2014-08-27 20:37:32 -0700209 builder.setContentText(text);
Julia Reynolds86a3fc52017-04-25 13:54:33 -0400210 builder.setChannelId(TelephonyNotificationBuilder.CHANNEL_ID_ALERT);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700211
212 // Show notification
Tyler Gunn625eb0b2014-08-27 20:37:32 -0700213 mNotificationManager.notify(R.string.phone_in_ecm_notification_title, builder.build());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700214 }
215
216 /**
217 * Handle ECM_TIMER_RESET notification
218 */
219 private void resetEcmTimer(AsyncResult r) {
220 boolean isTimerCanceled = ((Boolean)r.result).booleanValue();
221
222 if (isTimerCanceled) {
223 mInEmergencyCall = true;
224 mTimer.cancel();
225 showNotification(0);
226 } else {
227 mInEmergencyCall = false;
228 startTimerNotification();
229 }
230 }
231
232 @Override
233 public IBinder onBind(Intent intent) {
234 return mBinder;
235 }
236
237 // This is the object that receives interactions from clients.
238 private final IBinder mBinder = new LocalBinder();
239
240 /**
241 * Class for clients to access
242 */
243 public class LocalBinder extends Binder {
244 EmergencyCallbackModeService getService() {
245 return EmergencyCallbackModeService.this;
246 }
247 }
248
249 /**
250 * Returns Emergency Callback Mode timeout value
251 */
252 public long getEmergencyCallbackModeTimeout() {
253 return mTimeLeft;
254 }
255
256 /**
257 * Returns Emergency Callback Mode call state
258 */
259 public boolean getEmergencyCallbackModeCallState() {
260 return mInEmergencyCall;
261 }
262}