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