• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.phone;
18 
19 import android.app.Notification;
20 import android.app.NotificationManager;
21 import android.app.PendingIntent;
22 import android.app.Service;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.res.Resources;
28 import android.os.AsyncResult;
29 import android.os.Binder;
30 import android.os.CountDownTimer;
31 import android.os.Handler;
32 import android.os.IBinder;
33 import android.os.Message;
34 import android.os.SystemProperties;
35 import android.util.Log;
36 
37 import com.android.internal.telephony.cdma.CDMAPhone;
38 import com.android.internal.telephony.Phone;
39 import com.android.internal.telephony.PhoneConstants;
40 import com.android.internal.telephony.PhoneFactory;
41 import com.android.internal.telephony.TelephonyIntents;
42 import com.android.internal.telephony.TelephonyProperties;
43 
44 /**
45  * Application service that inserts/removes Emergency Callback Mode notification and
46  * updates Emergency Callback Mode countdown clock in the notification
47  *
48  * @see EmergencyCallbackModeExitDialog
49  */
50 public class EmergencyCallbackModeService extends Service {
51 
52     // Default Emergency Callback Mode timeout value
53     private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
54     private static final String LOG_TAG = "EmergencyCallbackModeService";
55 
56     private NotificationManager mNotificationManager = null;
57     private CountDownTimer mTimer = null;
58     private long mTimeLeft = 0;
59     private Phone mPhone = null;
60     private boolean mInEmergencyCall = false;
61 
62     private static final int ECM_TIMER_RESET = 1;
63 
64     private Handler mHandler = new Handler () {
65         public void handleMessage(Message msg) {
66             switch (msg.what) {
67                 case ECM_TIMER_RESET:
68                     resetEcmTimer((AsyncResult) msg.obj);
69                     break;
70             }
71         }
72     };
73 
74     @Override
onCreate()75     public void onCreate() {
76         // Check if it is CDMA phone
77         if (PhoneFactory.getDefaultPhone().getPhoneType() != PhoneConstants.PHONE_TYPE_CDMA) {
78             Log.e(LOG_TAG, "Error! Emergency Callback Mode not supported for " +
79                     PhoneFactory.getDefaultPhone().getPhoneName() + " phones");
80             stopSelf();
81         }
82 
83         // Register receiver for intents
84         IntentFilter filter = new IntentFilter();
85         filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
86         filter.addAction(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS);
87         registerReceiver(mEcmReceiver, filter);
88 
89         mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
90 
91         // Register ECM timer reset notfication
92         mPhone = PhoneFactory.getDefaultPhone();
93         mPhone.registerForEcmTimerReset(mHandler, ECM_TIMER_RESET, null);
94 
95         startTimerNotification();
96     }
97 
98     @Override
onDestroy()99     public void onDestroy() {
100         // Unregister receiver
101         unregisterReceiver(mEcmReceiver);
102         // Unregister ECM timer reset notification
103         mPhone.unregisterForEcmTimerReset(mHandler);
104 
105         // Cancel the notification and timer
106         mNotificationManager.cancel(R.string.phone_in_ecm_notification_title);
107         mTimer.cancel();
108     }
109 
110     /**
111      * Listens for Emergency Callback Mode intents
112      */
113     private BroadcastReceiver mEcmReceiver = new BroadcastReceiver() {
114         @Override
115         public void onReceive(Context context, Intent intent) {
116             // Stop the service when phone exits Emergency Callback Mode
117             if (intent.getAction().equals(
118                     TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
119                 if (intent.getBooleanExtra("phoneinECMState", false) == false) {
120                     stopSelf();
121                 }
122             }
123             // Show dialog box
124             else if (intent.getAction().equals(
125                     TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS)) {
126                     context.startActivity(
127                             new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS)
128                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
129             }
130         }
131     };
132 
133     /**
134      * Start timer notification for Emergency Callback Mode
135      */
startTimerNotification()136     private void startTimerNotification() {
137         // Get Emergency Callback Mode timeout value
138         long ecmTimeout = SystemProperties.getLong(
139                     TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
140 
141         // Show the notification
142         showNotification(ecmTimeout);
143 
144         // Start countdown timer for the notification updates
145         mTimer = new CountDownTimer(ecmTimeout, 1000) {
146 
147             @Override
148             public void onTick(long millisUntilFinished) {
149                 mTimeLeft = millisUntilFinished;
150                 EmergencyCallbackModeService.this.showNotification(millisUntilFinished);
151             }
152 
153             @Override
154             public void onFinish() {
155                 //Do nothing
156             }
157 
158         }.start();
159     }
160 
161     /**
162      * Shows notification for Emergency Callback Mode
163      */
showNotification(long millisUntilFinished)164     private void showNotification(long millisUntilFinished) {
165 
166         // Set the icon and text
167         Notification notification = new Notification(
168                 R.drawable.picture_emergency25x25,
169                 getText(R.string.phone_entered_ecm_text), 0);
170 
171         // PendingIntent to launch Emergency Callback Mode Exit activity if the user selects
172         // this notification
173         PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
174                 new Intent(EmergencyCallbackModeExitDialog.ACTION_SHOW_ECM_EXIT_DIALOG), 0);
175 
176         // Format notification string
177         String text = null;
178         if(mInEmergencyCall) {
179             text = getText(R.string.phone_in_ecm_call_notification_text).toString();
180         } else {
181             int minutes = (int)(millisUntilFinished / 60000);
182             String time = String.format("%d:%02d", minutes, (millisUntilFinished % 60000) / 1000);
183             text = String.format(getResources().getQuantityText(
184                      R.plurals.phone_in_ecm_notification_time, minutes).toString(), time);
185         }
186         // Set the info in the notification
187         notification.setLatestEventInfo(this, getText(R.string.phone_in_ecm_notification_title),
188                 text, contentIntent);
189 
190         notification.flags = Notification.FLAG_ONGOING_EVENT;
191 
192         // Show notification
193         mNotificationManager.notify(R.string.phone_in_ecm_notification_title, notification);
194     }
195 
196     /**
197      * Handle ECM_TIMER_RESET notification
198      */
resetEcmTimer(AsyncResult r)199     private void resetEcmTimer(AsyncResult r) {
200         boolean isTimerCanceled = ((Boolean)r.result).booleanValue();
201 
202         if (isTimerCanceled) {
203             mInEmergencyCall = true;
204             mTimer.cancel();
205             showNotification(0);
206         } else {
207             mInEmergencyCall = false;
208             startTimerNotification();
209         }
210     }
211 
212     @Override
onBind(Intent intent)213     public IBinder onBind(Intent intent) {
214         return mBinder;
215     }
216 
217     // This is the object that receives interactions from clients.
218     private final IBinder mBinder = new LocalBinder();
219 
220     /**
221      * Class for clients to access
222      */
223     public class LocalBinder extends Binder {
getService()224         EmergencyCallbackModeService getService() {
225             return EmergencyCallbackModeService.this;
226         }
227     }
228 
229     /**
230      * Returns Emergency Callback Mode timeout value
231      */
getEmergencyCallbackModeTimeout()232     public long getEmergencyCallbackModeTimeout() {
233         return mTimeLeft;
234     }
235 
236     /**
237      * Returns Emergency Callback Mode call state
238      */
getEmergencyCallbackModeCallState()239     public boolean getEmergencyCallbackModeCallState() {
240         return mInEmergencyCall;
241     }
242 }
243