Merge "Enable HOLD capability for IMS-based CDMA connections." into lmp-mr1-dev
diff --git a/src/com/android/phone/AccelerometerListener.java b/src/com/android/phone/AccelerometerListener.java
deleted file mode 100644
index 49d4a72..0000000
--- a/src/com/android/phone/AccelerometerListener.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-
-/**
- * This class is used to listen to the accelerometer to monitor the
- * orientation of the phone. The client of this class is notified when
- * the orientation changes between horizontal and vertical.
- */
-public final class AccelerometerListener {
-    private static final String TAG = "AccelerometerListener";
-    private static final boolean DEBUG = true;
-    private static final boolean VDEBUG = false;
-
-    private SensorManager mSensorManager;
-    private Sensor mSensor;
-
-    // mOrientation is the orientation value most recently reported to the client.
-    private int mOrientation;
-
-    // mPendingOrientation is the latest orientation computed based on the sensor value.
-    // This is sent to the client after a rebounce delay, at which point it is copied to
-    // mOrientation.
-    private int mPendingOrientation;
-
-    private OrientationListener mListener;
-
-    // Device orientation
-    public static final int ORIENTATION_UNKNOWN = 0;
-    public static final int ORIENTATION_VERTICAL = 1;
-    public static final int ORIENTATION_HORIZONTAL = 2;
-
-    private static final int ORIENTATION_CHANGED = 1234;
-
-    private static final int VERTICAL_DEBOUNCE = 100;
-    private static final int HORIZONTAL_DEBOUNCE = 500;
-    private static final double VERTICAL_ANGLE = 50.0;
-
-    public interface OrientationListener {
-        public void orientationChanged(int orientation);
-    }
-
-    public AccelerometerListener(Context context, OrientationListener listener) {
-        mListener = listener;
-        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
-        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
-    }
-
-    public void enable(boolean enable) {
-        if (DEBUG) Log.d(TAG, "enable(" + enable + ")");
-        synchronized (this) {
-            if (enable) {
-                mOrientation = ORIENTATION_UNKNOWN;
-                mPendingOrientation = ORIENTATION_UNKNOWN;
-                mSensorManager.registerListener(mSensorListener, mSensor,
-                        SensorManager.SENSOR_DELAY_NORMAL);
-            } else {
-                mSensorManager.unregisterListener(mSensorListener);
-                mHandler.removeMessages(ORIENTATION_CHANGED);
-            }
-        }
-    }
-
-    private void setOrientation(int orientation) {
-        synchronized (this) {
-            if (mPendingOrientation == orientation) {
-                // Pending orientation has not changed, so do nothing.
-                return;
-            }
-
-            // Cancel any pending messages.
-            // We will either start a new timer or cancel alltogether
-            // if the orientation has not changed.
-            mHandler.removeMessages(ORIENTATION_CHANGED);
-
-            if (mOrientation != orientation) {
-                // Set timer to send an event if the orientation has changed since its
-                // previously reported value.
-                mPendingOrientation = orientation;
-                Message m = mHandler.obtainMessage(ORIENTATION_CHANGED);
-                // set delay to our debounce timeout
-                int delay = (orientation == ORIENTATION_VERTICAL ? VERTICAL_DEBOUNCE
-                                                                 : HORIZONTAL_DEBOUNCE);
-                mHandler.sendMessageDelayed(m, delay);
-            } else {
-                // no message is pending
-                mPendingOrientation = ORIENTATION_UNKNOWN;
-            }
-        }
-    }
-
-    private void onSensorEvent(double x, double y, double z) {
-        if (VDEBUG) Log.d(TAG, "onSensorEvent(" + x + ", " + y + ", " + z + ")");
-
-        // If some values are exactly zero, then likely the sensor is not powered up yet.
-        // ignore these events to avoid false horizontal positives.
-        if (x == 0.0 || y == 0.0 || z == 0.0) return;
-
-        // magnitude of the acceleration vector projected onto XY plane
-        double xy = Math.sqrt(x*x + y*y);
-        // compute the vertical angle
-        double angle = Math.atan2(xy, z);
-        // convert to degrees
-        angle = angle * 180.0 / Math.PI;
-        int orientation = (angle >  VERTICAL_ANGLE ? ORIENTATION_VERTICAL : ORIENTATION_HORIZONTAL);
-        if (VDEBUG) Log.d(TAG, "angle: " + angle + " orientation: " + orientation);
-        setOrientation(orientation);
-    }
-
-    SensorEventListener mSensorListener = new SensorEventListener() {
-        public void onSensorChanged(SensorEvent event) {
-            onSensorEvent(event.values[0], event.values[1], event.values[2]);
-        }
-
-        public void onAccuracyChanged(Sensor sensor, int accuracy) {
-            // ignore
-        }
-    };
-
-    Handler mHandler = new Handler() {
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-            case ORIENTATION_CHANGED:
-                synchronized (this) {
-                    mOrientation = mPendingOrientation;
-                    if (DEBUG) {
-                        Log.d(TAG, "orientation: " +
-                            (mOrientation == ORIENTATION_HORIZONTAL ? "horizontal"
-                                : (mOrientation == ORIENTATION_VERTICAL ? "vertical"
-                                    : "unknown")));
-                    }
-                    mListener.orientationChanged(mOrientation);
-                }
-                break;
-            }
-        }
-    };
-}
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index feccf95..6ed9cbc 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -24,8 +24,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.UserInfo;
 import android.net.Uri;
 import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.preference.PreferenceManager;
 import android.provider.ContactsContract.PhoneLookup;
 import android.provider.Settings;
@@ -40,6 +43,8 @@
 import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.TelephonyCapabilities;
 
+import java.util.List;
+
 /**
  * NotificationManager-related utility code for the Phone app.
  *
@@ -73,6 +78,7 @@
     private Context mContext;
     private NotificationManager mNotificationManager;
     private StatusBarManager mStatusBarManager;
+    private UserManager mUserManager;
     private Toast mToast;
 
     public StatusBarHelper statusBarHelper;
@@ -96,6 +102,7 @@
                 (NotificationManager) app.getSystemService(Context.NOTIFICATION_SERVICE);
         mStatusBarManager =
                 (StatusBarManager) app.getSystemService(Context.STATUS_BAR_SERVICE);
+        mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
         mPhone = app.phone;  // TODO: better style to use mCM.getDefaultPhone() everywhere instead
         statusBarHelper = new StatusBarHelper();
     }
@@ -324,19 +331,29 @@
                     .setContentText(notificationText)
                     .setContentIntent(pendingIntent)
                     .setSound(ringtoneUri)
-                    .setColor(mContext.getResources().getColor(R.color.dialer_theme_color));
-            Notification notification = builder.getNotification();
+                    .setColor(mContext.getResources().getColor(R.color.dialer_theme_color))
+                    .setOngoing(true);
 
             CallFeaturesSetting.migrateVoicemailVibrationSettingsIfNeeded(prefs);
             final boolean vibrate = prefs.getBoolean(
                     CallFeaturesSetting.BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, false);
             if (vibrate) {
-                notification.defaults |= Notification.DEFAULT_VIBRATE;
+                builder.setDefaults(Notification.DEFAULT_VIBRATE);
             }
-            notification.flags |= Notification.FLAG_NO_CLEAR;
-            mNotificationManager.notify(VOICEMAIL_NOTIFICATION, notification);
+
+            final Notification notification = builder.build();
+            List<UserInfo> users = mUserManager.getUsers(true);
+            for (int i = 0; i < users.size(); i++) {
+                UserHandle userHandle = users.get(i).getUserHandle();
+                if (!mUserManager.hasUserRestriction(
+                        UserManager.DISALLOW_OUTGOING_CALLS, userHandle)) {
+                    mNotificationManager.notifyAsUser(
+                            null /* tag */, VOICEMAIL_NOTIFICATION, notification, userHandle);
+                }
+            }
         } else {
-            mNotificationManager.cancel(VOICEMAIL_NOTIFICATION);
+            mNotificationManager.cancelAsUser(
+                    null /* tag */, VOICEMAIL_NOTIFICATION, UserHandle.ALL);
         }
     }
 
@@ -359,39 +376,28 @@
             // effort though, since there are multiple layers of messages that
             // will need to propagate that information.
 
-            Notification notification;
-            final boolean showExpandedNotification = true;
-            if (showExpandedNotification) {
-                Intent intent = new Intent(Intent.ACTION_MAIN);
-                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                intent.setClassName("com.android.phone",
-                        "com.android.phone.CallFeaturesSetting");
+            Notification.Builder builder = new Notification.Builder(mContext)
+                    .setSmallIcon(R.drawable.stat_sys_phone_call_forward)
+                    .setContentTitle(mContext.getString(R.string.labelCF))
+                    .setContentText(mContext.getString(R.string.sum_cfu_enabled_indicator))
+                    .setShowWhen(false)
+                    .setOngoing(true);
 
-                notification = new Notification(
-                        R.drawable.stat_sys_phone_call_forward,  // icon
-                        null, // tickerText
-                        0); // The "timestamp" of this notification is meaningless;
-                            // we only care about whether CFI is currently on or not.
-                notification.setLatestEventInfo(
-                        mContext, // context
-                        mContext.getString(R.string.labelCF), // expandedTitle
-                        mContext.getString(R.string.sum_cfu_enabled_indicator), // expandedText
-                        PendingIntent.getActivity(mContext, 0, intent, 0)); // contentIntent
-            } else {
-                notification = new Notification(
-                        R.drawable.stat_sys_phone_call_forward,  // icon
-                        null,  // tickerText
-                        System.currentTimeMillis()  // when
-                        );
+            Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setClassName("com.android.phone", "com.android.phone.CallFeaturesSetting");
+            PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+
+            List<UserInfo> users = mUserManager.getUsers(true);
+            for (int i = 0; i < users.size(); i++) {
+                UserHandle userHandle = users.get(i).getUserHandle();
+                builder.setContentIntent(userHandle.isOwner() ? contentIntent : null);
+                    mNotificationManager.notifyAsUser(
+                            null /* tag */, CALL_FORWARD_NOTIFICATION, builder.build(), userHandle);
             }
-
-            notification.flags |= Notification.FLAG_ONGOING_EVENT;  // also implies FLAG_NO_CLEAR
-
-            mNotificationManager.notify(
-                    CALL_FORWARD_NOTIFICATION,
-                    notification);
         } else {
-            mNotificationManager.cancel(CALL_FORWARD_NOTIFICATION);
+            mNotificationManager.cancelAsUser(
+                    null /* tag */, CALL_FORWARD_NOTIFICATION, UserHandle.ALL);
         }
     }
 
@@ -405,20 +411,25 @@
 
         // "Mobile network settings" screen / dialog
         Intent intent = new Intent(mContext, com.android.phone.MobileNetworkSettings.class);
+        PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
 
         final CharSequence contentText = mContext.getText(R.string.roaming_reenable_message);
 
-        final Notification.Builder builder = new Notification.Builder(mContext);
-        builder.setSmallIcon(android.R.drawable.stat_sys_warning);
-        builder.setContentTitle(mContext.getText(R.string.roaming));
-        builder.setColor(mContext.getResources().getColor(R.color.dialer_theme_color));
-        builder.setContentText(contentText);
-        builder.setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0));
+        final Notification.Builder builder = new Notification.Builder(mContext)
+                .setSmallIcon(android.R.drawable.stat_sys_warning)
+                .setContentTitle(mContext.getText(R.string.roaming))
+                .setColor(mContext.getResources().getColor(R.color.dialer_theme_color))
+                .setContentText(contentText);
 
-        final Notification notif = new Notification.BigTextStyle(builder).bigText(contentText)
-                .build();
-
-        mNotificationManager.notify(DATA_DISCONNECTED_ROAMING_NOTIFICATION, notif);
+        List<UserInfo> users = mUserManager.getUsers(true);
+        for (int i = 0; i < users.size(); i++) {
+            UserHandle userHandle = users.get(i).getUserHandle();
+            builder.setContentIntent(userHandle.isOwner() ? contentIntent : null);
+            final Notification notif =
+                    new Notification.BigTextStyle(builder).bigText(contentText).build();
+            mNotificationManager.notifyAsUser(
+                    null /* tag */, DATA_DISCONNECTED_ROAMING_NOTIFICATION, notif, userHandle);
+        }
     }
 
     /**
@@ -436,16 +447,13 @@
     private void showNetworkSelection(String operator) {
         if (DBG) log("showNetworkSelection(" + operator + ")...");
 
-        String titleText = mContext.getString(
-                R.string.notification_network_selection_title);
-        String expandedText = mContext.getString(
-                R.string.notification_network_selection_text, operator);
-
-        Notification notification = new Notification();
-        notification.icon = android.R.drawable.stat_sys_warning;
-        notification.when = 0;
-        notification.flags = Notification.FLAG_ONGOING_EVENT;
-        notification.tickerText = null;
+        Notification.Builder builder = new Notification.Builder(mContext)
+                .setSmallIcon(android.R.drawable.stat_sys_warning)
+                .setContentTitle(mContext.getString(R.string.notification_network_selection_title))
+                .setContentText(
+                        mContext.getString(R.string.notification_network_selection_text, operator))
+                .setShowWhen(false)
+                .setOngoing(true);
 
         // create the target network operators settings intent
         Intent intent = new Intent(Intent.ACTION_MAIN);
@@ -454,11 +462,18 @@
         // Use NetworkSetting to handle the selection intent
         intent.setComponent(new ComponentName("com.android.phone",
                 "com.android.phone.NetworkSetting"));
-        PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
+        PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
 
-        notification.setLatestEventInfo(mContext, titleText, expandedText, pi);
-
-        mNotificationManager.notify(SELECTED_OPERATOR_FAIL_NOTIFICATION, notification);
+        List<UserInfo> users = mUserManager.getUsers(true);
+        for (int i = 0; i < users.size(); i++) {
+            UserHandle userHandle = users.get(i).getUserHandle();
+            builder.setContentIntent(userHandle.isOwner() ? contentIntent : null);
+            mNotificationManager.notifyAsUser(
+                    null /* tag */,
+                    SELECTED_OPERATOR_FAIL_NOTIFICATION,
+                    builder.build(),
+                    userHandle);
+        }
     }
 
     /**
@@ -466,7 +481,8 @@
      */
     private void cancelNetworkSelection() {
         if (DBG) log("cancelNetworkSelection()...");
-        mNotificationManager.cancel(SELECTED_OPERATOR_FAIL_NOTIFICATION);
+        mNotificationManager.cancelAsUser(
+                null /* tag */, SELECTED_OPERATOR_FAIL_NOTIFICATION, UserHandle.ALL);
     }
 
     /**
diff --git a/src/com/android/phone/Ringer.java b/src/com/android/phone/Ringer.java
deleted file mode 100644
index b542ede..0000000
--- a/src/com/android/phone/Ringer.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2006 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.content.Context;
-import android.media.AudioAttributes;
-import android.media.AudioManager;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.IPowerManager;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.SystemVibrator;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.util.Log;
-
-import com.android.internal.telephony.Phone;
-import com.android.phone.common.util.SettingsUtil;
-
-/**
- * Ringer manager for the Phone app.
- */
-public class Ringer {
-    private static final String LOG_TAG = "Ringer";
-    private static final boolean DBG =
-            (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
-
-    private static final int PLAY_RING_ONCE = 1;
-    private static final int STOP_RING = 3;
-
-    private static final int VIBRATE_LENGTH = 1000; // ms
-    private static final int PAUSE_LENGTH = 1000; // ms
-
-    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
-            .build();
-
-    /** The singleton instance. */
-    private static Ringer sInstance;
-
-    // Uri for the ringtone.
-    Uri mCustomRingtoneUri = Settings.System.DEFAULT_RINGTONE_URI;
-
-    private final BluetoothManager mBluetoothManager;
-    Ringtone mRingtone;
-    Vibrator mVibrator;
-    IPowerManager mPowerManager;
-    volatile boolean mContinueVibrating;
-    VibratorThread mVibratorThread;
-    Context mContext;
-    private Worker mRingThread;
-    private Handler mRingHandler;
-    private long mFirstRingEventTime = -1;
-    private long mFirstRingStartTime = -1;
-
-    /**
-     * Initialize the singleton Ringer instance.
-     * This is only done once, at startup, from PhoneApp.onCreate().
-     */
-    /* package */ static Ringer init(Context context, BluetoothManager bluetoothManager) {
-        synchronized (Ringer.class) {
-            if (sInstance == null) {
-                sInstance = new Ringer(context, bluetoothManager);
-            } else {
-                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
-            }
-            return sInstance;
-        }
-    }
-
-    /** Private constructor; @see init() */
-    private Ringer(Context context, BluetoothManager bluetoothManager) {
-        mContext = context;
-        mBluetoothManager = bluetoothManager;
-        mPowerManager = IPowerManager.Stub.asInterface(
-                ServiceManager.getService(Context.POWER_SERVICE));
-        // We don't rely on getSystemService(Context.VIBRATOR_SERVICE) to make sure this
-        // vibrator object will be isolated from others.
-        mVibrator = new SystemVibrator(context);
-    }
-
-    /**
-     * After a radio technology change, e.g. from CDMA to GSM or vice versa,
-     * the Context of the Ringer has to be updated. This is done by that function.
-     *
-     * @parameter Phone, the new active phone for the appropriate radio
-     * technology
-     */
-    void updateRingerContextAfterRadioTechnologyChange(Phone phone) {
-        if(DBG) Log.d(LOG_TAG, "updateRingerContextAfterRadioTechnologyChange...");
-        mContext = phone.getContext();
-    }
-
-    /**
-     * @return true if we're playing a ringtone and/or vibrating
-     *     to indicate that there's an incoming call.
-     *     ("Ringing" here is used in the general sense.  If you literally
-     *     need to know if we're playing a ringtone or vibrating, use
-     *     isRingtonePlaying() or isVibrating() instead.)
-     *
-     * @see isVibrating
-     * @see isRingtonePlaying
-     */
-    boolean isRinging() {
-        synchronized (this) {
-            return (isRingtonePlaying() || isVibrating());
-        }
-    }
-
-    /**
-     * @return true if the ringtone is playing
-     * @see isVibrating
-     * @see isRinging
-     */
-    private boolean isRingtonePlaying() {
-        synchronized (this) {
-            return (mRingtone != null && mRingtone.isPlaying()) ||
-                    (mRingHandler != null && mRingHandler.hasMessages(PLAY_RING_ONCE));
-        }
-    }
-
-    /**
-     * @return true if we're vibrating in response to an incoming call
-     * @see isVibrating
-     * @see isRinging
-     */
-    private boolean isVibrating() {
-        synchronized (this) {
-            return (mVibratorThread != null);
-        }
-    }
-
-    /**
-     * Starts the ringtone and/or vibrator
-     */
-    void ring() {
-        if (DBG) log("ring()...");
-
-        synchronized (this) {
-            try {
-                if (mBluetoothManager.showBluetoothIndication()) {
-                    mPowerManager.setAttentionLight(true, 0x000000ff);
-                } else {
-                    mPowerManager.setAttentionLight(true, 0x00ffffff);
-                }
-            } catch (RemoteException ex) {
-                // the other end of this binder call is in the system process.
-            }
-
-            if (shouldVibrate() && mVibratorThread == null) {
-                mContinueVibrating = true;
-                mVibratorThread = new VibratorThread();
-                if (DBG) log("- starting vibrator...");
-                mVibratorThread.start();
-            }
-            AudioManager audioManager =
-                    (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-
-            if (audioManager.getStreamVolume(AudioManager.STREAM_RING) == 0) {
-                if (DBG) log("skipping ring because volume is zero");
-                return;
-            }
-
-            makeLooper();
-            if (mFirstRingEventTime < 0) {
-                mFirstRingEventTime = SystemClock.elapsedRealtime();
-                mRingHandler.sendEmptyMessage(PLAY_RING_ONCE);
-            } else {
-                // For repeat rings, figure out by how much to delay
-                // the ring so that it happens the correct amount of
-                // time after the previous ring
-                if (mFirstRingStartTime > 0) {
-                    // Delay subsequent rings by the delta between event
-                    // and play time of the first ring
-                    if (DBG) {
-                        log("delaying ring by " + (mFirstRingStartTime - mFirstRingEventTime));
-                    }
-                    mRingHandler.sendEmptyMessageDelayed(PLAY_RING_ONCE,
-                            mFirstRingStartTime - mFirstRingEventTime);
-                } else {
-                    // We've gotten two ring events so far, but the ring
-                    // still hasn't started. Reset the event time to the
-                    // time of this event to maintain correct spacing.
-                    mFirstRingEventTime = SystemClock.elapsedRealtime();
-                }
-            }
-        }
-    }
-
-    boolean shouldVibrate() {
-        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-        int ringerMode = audioManager.getRingerMode();
-        if (SettingsUtil.getVibrateWhenRingingSetting(mContext)) {
-            return ringerMode != AudioManager.RINGER_MODE_SILENT;
-        } else {
-            return ringerMode == AudioManager.RINGER_MODE_VIBRATE;
-        }
-    }
-
-    /**
-     * Stops the ringtone and/or vibrator if any of these are actually
-     * ringing/vibrating.
-     */
-    void stopRing() {
-        synchronized (this) {
-            if (DBG) log("stopRing()...");
-
-            try {
-                mPowerManager.setAttentionLight(false, 0x00000000);
-            } catch (RemoteException ex) {
-                // the other end of this binder call is in the system process.
-            }
-
-            if (mRingHandler != null) {
-                mRingHandler.removeCallbacksAndMessages(null);
-                Message msg = mRingHandler.obtainMessage(STOP_RING);
-                msg.obj = mRingtone;
-                mRingHandler.sendMessage(msg);
-                PhoneUtils.setAudioMode();
-                mRingThread = null;
-                mRingHandler = null;
-                mRingtone = null;
-                mFirstRingEventTime = -1;
-                mFirstRingStartTime = -1;
-            } else {
-                if (DBG) log("- stopRing: null mRingHandler!");
-            }
-
-            if (mVibratorThread != null) {
-                if (DBG) log("- stopRing: cleaning up vibrator thread...");
-                mContinueVibrating = false;
-                mVibratorThread = null;
-            }
-            // Also immediately cancel any vibration in progress.
-            mVibrator.cancel();
-        }
-    }
-
-    private class VibratorThread extends Thread {
-        public void run() {
-            while (mContinueVibrating) {
-                mVibrator.vibrate(VIBRATE_LENGTH, VIBRATION_ATTRIBUTES);
-                SystemClock.sleep(VIBRATE_LENGTH + PAUSE_LENGTH);
-            }
-        }
-    }
-    private class Worker implements Runnable {
-        private final Object mLock = new Object();
-        private Looper mLooper;
-
-        Worker(String name) {
-            Thread t = new Thread(null, this, name);
-            t.start();
-            synchronized (mLock) {
-                while (mLooper == null) {
-                    try {
-                        mLock.wait();
-                    } catch (InterruptedException ex) {
-                    }
-                }
-            }
-        }
-
-        public Looper getLooper() {
-            return mLooper;
-        }
-
-        public void run() {
-            synchronized (mLock) {
-                Looper.prepare();
-                mLooper = Looper.myLooper();
-                mLock.notifyAll();
-            }
-            Looper.loop();
-        }
-
-        public void quit() {
-            mLooper.quit();
-        }
-    }
-
-    /**
-     * Sets the ringtone uri in preparation for ringtone creation
-     * in makeLooper().  This uri is defaulted to the phone-wide
-     * default ringtone.
-     */
-    void setCustomRingtoneUri (Uri uri) {
-        if (uri != null) {
-            mCustomRingtoneUri = uri;
-        }
-    }
-
-    private void makeLooper() {
-        if (mRingThread == null) {
-            mRingThread = new Worker("ringer");
-            mRingHandler = new Handler(mRingThread.getLooper()) {
-                @Override
-                public void handleMessage(Message msg) {
-                    Ringtone r = null;
-                    switch (msg.what) {
-                        case PLAY_RING_ONCE:
-                            if (DBG) log("mRingHandler: PLAY_RING_ONCE...");
-                            if (mRingtone == null && !hasMessages(STOP_RING)) {
-                                // create the ringtone with the uri
-                                if (DBG) log("creating ringtone: " + mCustomRingtoneUri);
-                                r = RingtoneManager.getRingtone(mContext, mCustomRingtoneUri);
-                                synchronized (Ringer.this) {
-                                    if (!hasMessages(STOP_RING)) {
-                                        mRingtone = r;
-                                    }
-                                }
-                            }
-                            r = mRingtone;
-                            if (r != null && !hasMessages(STOP_RING) && !r.isPlaying()) {
-                                PhoneUtils.setAudioMode();
-                                r.play();
-                                synchronized (Ringer.this) {
-                                    if (mFirstRingStartTime < 0) {
-                                        mFirstRingStartTime = SystemClock.elapsedRealtime();
-                                    }
-                                }
-                            }
-                            break;
-                        case STOP_RING:
-                            if (DBG) log("mRingHandler: STOP_RING...");
-                            r = (Ringtone) msg.obj;
-                            if (r != null) {
-                                r.stop();
-                            } else {
-                                if (DBG) log("- STOP_RING with null ringtone!  msg = " + msg);
-                            }
-                            getLooper().quit();
-                            break;
-                    }
-                }
-            };
-        }
-    }
-
-    private static void log(String msg) {
-        Log.d(LOG_TAG, msg);
-    }
-}
diff --git a/src/com/android/phone/SmallerHitTargetTouchListener.java b/src/com/android/phone/SmallerHitTargetTouchListener.java
deleted file mode 100644
index 8e1bf16..0000000
--- a/src/com/android/phone/SmallerHitTargetTouchListener.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2012 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.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-
-/**
- * OnTouchListener used to shrink the "hit target" of some onscreen buttons.
- *
- * We do this for a few specific buttons which are vulnerable to
- * "false touches" because either (1) they're near the edge of the
- * screen and might be unintentionally touched while holding the
- * device in your hand, (2) they're in the upper corners and might
- * be touched by the user's ear before the prox sensor has a chance to
- * kick in, or (3) they are close to other buttons.
- */
-public class SmallerHitTargetTouchListener implements View.OnTouchListener {
-    private static final String TAG = "SmallerHitTargetTouchListener";
-
-    /**
-     * Edge dimensions where a touch does not register an action (in DIP).
-     */
-    private static final int HIT_TARGET_EDGE_IGNORE_DP_X = 30;
-    private static final int HIT_TARGET_EDGE_IGNORE_DP_Y = 10;
-    private static final int HIT_TARGET_MIN_SIZE_DP_X = HIT_TARGET_EDGE_IGNORE_DP_X * 3;
-    private static final int HIT_TARGET_MIN_SIZE_DP_Y = HIT_TARGET_EDGE_IGNORE_DP_Y * 3;
-
-    // True if the most recent DOWN event was a "hit".
-    boolean mDownEventHit;
-
-    /**
-     * Called when a touch event is dispatched to a view. This allows listeners to
-     * get a chance to respond before the target view.
-     *
-     * @return True if the listener has consumed the event, false otherwise.
-     *         (In other words, we return true when the touch is *outside*
-     *         the "smaller hit target", which will prevent the actual
-     *         button from handling these events.)
-     */
-    @Override
-    public boolean onTouch(View v, MotionEvent event) {
-        // if (DBG) log("SmallerHitTargetTouchListener: " + v + ", event " + event);
-
-        if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            // Note that event.getX() and event.getY() are already
-            // translated into the View's coordinates.  (In other words,
-            // "0,0" is a touch on the upper-left-most corner of the view.)
-            final int touchX = (int) event.getX();
-            final int touchY = (int) event.getY();
-
-            final int viewWidth = v.getWidth();
-            final int viewHeight = v.getHeight();
-
-            final float pixelDensity = v.getResources().getDisplayMetrics().density;
-            final int targetMinSizeX = (int) (HIT_TARGET_MIN_SIZE_DP_X * pixelDensity);
-            final int targetMinSizeY = (int) (HIT_TARGET_MIN_SIZE_DP_Y * pixelDensity);
-
-            int edgeIgnoreX = (int) (HIT_TARGET_EDGE_IGNORE_DP_X * pixelDensity);
-            int edgeIgnoreY = (int) (HIT_TARGET_EDGE_IGNORE_DP_Y * pixelDensity);
-
-            // If we are dealing with smaller buttons where the dead zone defined by
-            // HIT_TARGET_EDGE_IGNORE_DP_[X|Y] is too large.
-            if (viewWidth < targetMinSizeX || viewHeight < targetMinSizeY) {
-                // This really should not happen given our two use cases (as of this writing)
-                // in the call edge button and secondary calling card. However, we leave
-                // this is as a precautionary measure.
-                Log.w(TAG, "onTouch: view is too small for SmallerHitTargetTouchListener");
-                edgeIgnoreX = 0;
-                edgeIgnoreY = 0;
-            }
-
-            final int minTouchX = edgeIgnoreX;
-            final int maxTouchX = viewWidth - edgeIgnoreX;
-            final int minTouchY = edgeIgnoreY;
-            final int maxTouchY = viewHeight - edgeIgnoreY;
-
-            if (touchX < minTouchX || touchX > maxTouchX ||
-                    touchY < minTouchY || touchY > maxTouchY) {
-                // Missed!
-                // if (DBG) log("  -> MISSED!");
-                mDownEventHit = false;
-                return true;  // Consume this event; don't let the button see it
-            } else {
-                // Hit!
-                // if (DBG) log("  -> HIT!");
-                mDownEventHit = true;
-                return false;  // Let this event through to the actual button
-            }
-        } else {
-            // This is a MOVE, UP or CANCEL event.
-            //
-            // We only do the "smaller hit target" check on DOWN events.
-            // For the subsequent MOVE/UP/CANCEL events, we let them
-            // through to the actual button IFF the previous DOWN event
-            // got through to the actual button (i.e. it was a "hit".)
-            return !mDownEventHit;
-        }
-    }
-}
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index b337622..bbd65cc 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -256,7 +256,9 @@
                 new ComponentName(phone.getContext(), TelephonyConnectionService.class);
         // TODO: Should use some sort of special hidden flag to decorate this account as
         // an emergency-only account
-        String id = isEmergency ? "E" : prefix + String.valueOf(phone.getSubId());
+        TelecomManager telecomManager = TelecomManager.from(phone.getContext());
+        String id = isEmergency ?
+            "E" : prefix + telecomManager.getPhoneAccountIdForSubscriptionId(phone.getSubId());
         return new PhoneAccountHandle(pstnConnectionServiceName, id);
     }