Blanket copy of PhoneApp to services/Telephony.

First phase of splitting out InCallUI from PhoneApp.

Change-Id: I237341c4ff00e96c677caa4580b251ef3432931b
diff --git a/src/com/android/phone/EmergencyCallbackModeService.java b/src/com/android/phone/EmergencyCallbackModeService.java
new file mode 100644
index 0000000..b506598
--- /dev/null
+++ b/src/com/android/phone/EmergencyCallbackModeService.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.os.AsyncResult;
+import android.os.Binder;
+import android.os.CountDownTimer;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import com.android.internal.telephony.cdma.CDMAPhone;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+
+/**
+ * Application service that inserts/removes Emergency Callback Mode notification and
+ * updates Emergency Callback Mode countdown clock in the notification
+ *
+ * @see EmergencyCallbackModeExitDialog
+ */
+public class EmergencyCallbackModeService extends Service {
+
+    // Default Emergency Callback Mode timeout value
+    private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
+    private static final String LOG_TAG = "EmergencyCallbackModeService";
+
+    private NotificationManager mNotificationManager = null;
+    private CountDownTimer mTimer = null;
+    private long mTimeLeft = 0;
+    private Phone mPhone = null;
+    private boolean mInEmergencyCall = false;
+
+    private static final int ECM_TIMER_RESET = 1;
+
+    private Handler mHandler = new Handler () {
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case ECM_TIMER_RESET:
+                    resetEcmTimer((AsyncResult) msg.obj);
+                    break;
+            }
+        }
+    };
+
+    @Override
+    public void onCreate() {
+        // Check if it is CDMA phone
+        if (PhoneFactory.getDefaultPhone().getPhoneType() != PhoneConstants.PHONE_TYPE_CDMA) {
+            Log.e(LOG_TAG, "Error! Emergency Callback Mode not supported for " +
+                    PhoneFactory.getDefaultPhone().getPhoneName() + " phones");
+            stopSelf();
+        }
+
+        // Register receiver for intents
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
+        filter.addAction(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS);
+        registerReceiver(mEcmReceiver, filter);
+
+        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+
+        // Register ECM timer reset notfication
+        mPhone = PhoneFactory.getDefaultPhone();
+        mPhone.registerForEcmTimerReset(mHandler, ECM_TIMER_RESET, null);
+
+        startTimerNotification();
+    }
+
+    @Override
+    public void onDestroy() {
+        // Unregister receiver
+        unregisterReceiver(mEcmReceiver);
+        // Unregister ECM timer reset notification
+        mPhone.unregisterForEcmTimerReset(mHandler);
+
+        // Cancel the notification and timer
+        mNotificationManager.cancel(R.string.phone_in_ecm_notification_title);
+        mTimer.cancel();
+    }
+
+    /**
+     * Listens for Emergency Callback Mode intents
+     */
+    private BroadcastReceiver mEcmReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // Stop the service when phone exits Emergency Callback Mode
+            if (intent.getAction().equals(
+                    TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
+                if (intent.getBooleanExtra("phoneinECMState", false) == false) {
+                    stopSelf();
+                }
+            }
+            // Show dialog box
+            else if (intent.getAction().equals(
+                    TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS)) {
+                    context.startActivity(
+                            new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS)
+                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+            }
+        }
+    };
+
+    /**
+     * Start timer notification for Emergency Callback Mode
+     */
+    private void startTimerNotification() {
+        // Get Emergency Callback Mode timeout value
+        long ecmTimeout = SystemProperties.getLong(
+                    TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
+
+        // Show the notification
+        showNotification(ecmTimeout);
+
+        // Start countdown timer for the notification updates
+        mTimer = new CountDownTimer(ecmTimeout, 1000) {
+
+            @Override
+            public void onTick(long millisUntilFinished) {
+                mTimeLeft = millisUntilFinished;
+                EmergencyCallbackModeService.this.showNotification(millisUntilFinished);
+            }
+
+            @Override
+            public void onFinish() {
+                //Do nothing
+            }
+
+        }.start();
+    }
+
+    /**
+     * Shows notification for Emergency Callback Mode
+     */
+    private void showNotification(long millisUntilFinished) {
+
+        // Set the icon and text
+        Notification notification = new Notification(
+                R.drawable.picture_emergency25x25,
+                getText(R.string.phone_entered_ecm_text), 0);
+
+        // PendingIntent to launch Emergency Callback Mode Exit activity if the user selects
+        // this notification
+        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+                new Intent(EmergencyCallbackModeExitDialog.ACTION_SHOW_ECM_EXIT_DIALOG), 0);
+
+        // Format notification string
+        String text = null;
+        if(mInEmergencyCall) {
+            text = getText(R.string.phone_in_ecm_call_notification_text).toString();
+        } else {
+            int minutes = (int)(millisUntilFinished / 60000);
+            String time = String.format("%d:%02d", minutes, (millisUntilFinished % 60000) / 1000);
+            text = String.format(getResources().getQuantityText(
+                     R.plurals.phone_in_ecm_notification_time, minutes).toString(), time);
+        }
+        // Set the info in the notification
+        notification.setLatestEventInfo(this, getText(R.string.phone_in_ecm_notification_title),
+                text, contentIntent);
+
+        notification.flags = Notification.FLAG_ONGOING_EVENT;
+
+        // Show notification
+        mNotificationManager.notify(R.string.phone_in_ecm_notification_title, notification);
+    }
+
+    /**
+     * Handle ECM_TIMER_RESET notification
+     */
+    private void resetEcmTimer(AsyncResult r) {
+        boolean isTimerCanceled = ((Boolean)r.result).booleanValue();
+
+        if (isTimerCanceled) {
+            mInEmergencyCall = true;
+            mTimer.cancel();
+            showNotification(0);
+        } else {
+            mInEmergencyCall = false;
+            startTimerNotification();
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    // This is the object that receives interactions from clients.
+    private final IBinder mBinder = new LocalBinder();
+
+    /**
+     * Class for clients to access
+     */
+    public class LocalBinder extends Binder {
+        EmergencyCallbackModeService getService() {
+            return EmergencyCallbackModeService.this;
+        }
+    }
+
+    /**
+     * Returns Emergency Callback Mode timeout value
+     */
+    public long getEmergencyCallbackModeTimeout() {
+        return mTimeLeft;
+    }
+
+    /**
+     * Returns Emergency Callback Mode call state
+     */
+    public boolean getEmergencyCallbackModeCallState() {
+        return mInEmergencyCall;
+    }
+}