Preparatory work to move Telecom to system service.

- Removed use of TelecomApp.getInstance() as context.
- Refactored singleton logic and initialization to support being
performed from a SystemService.
- Note: You will see some commented out references to
"import com.android.internal.R"; these must uncommented when the code
is moved to a system service.
- You will also notice in PhoneAccountRegistrar.java a comment block with:
"UNCOMMENT_FOR_MOVE_TO_SYSTEM_SERVICE"
The code in that comment block will replace the existing file path
code.
These were added as a convenience so that I can run a simple sed script
to make the required changes to the code in an automated manner once it
is moved to its new location.

Bug: 17364651
Change-Id: I8e80e9cffc481b688c10a2bca0b59f5ccf8e0fb2
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 2c1cd7b..706dda7 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -178,20 +178,8 @@
             </intent-filter>
         </activity-alias>
 
-        <receiver android:name="TelecomBroadcastReceiver" android:exported="false">
-            <intent-filter>
-                <action android:name="com.android.server.telecom.ACTION_CALL_BACK_FROM_NOTIFICATION" />
-                <action android:name="com.android.server.telecom.ACTION_CALL_BACK_FROM_NOTIFICATION" />
-                <action android:name="com.android.server.telecom.ACTION_SEND_SMS_FROM_NOTIFICATION" />
-            </intent-filter>
-        </receiver>
-
-        <receiver android:name="PhoneAccountBroadcastReceiver">
-            <intent-filter>
-                <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
-                <data android:scheme="package" />
-            </intent-filter>
-        </receiver>
+        <!-- Note: Broadcast receivers are now set up in TelecomApp as a step in the transition to
+             running under the system process. -->
 
         <activity android:name=".RespondViaSmsSettings$Settings"
                   android:label="@string/respond_via_sms_setting_title"
diff --git a/src/com/android/server/telecom/AsyncRingtonePlayer.java b/src/com/android/server/telecom/AsyncRingtonePlayer.java
index 343abfb..4434424 100644
--- a/src/com/android/server/telecom/AsyncRingtonePlayer.java
+++ b/src/com/android/server/telecom/AsyncRingtonePlayer.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom;
 
+import android.content.Context;
 import android.media.AudioManager;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
@@ -25,7 +26,7 @@
 import android.os.Message;
 import android.provider.Settings;
 
-import com.google.common.base.Preconditions;
+import com.android.internal.util.Preconditions;
 
 /**
  * Plays the default ringtone. Uses {@link Ringtone} in a separate thread so that this class can be
@@ -46,6 +47,15 @@
     /** The current ringtone. Only used by the ringtone thread. */
     private Ringtone mRingtone;
 
+    /**
+     * The context.
+     */
+    private final Context mContext;
+
+    AsyncRingtonePlayer(Context context) {
+        mContext = context;
+    }
+
     /** Plays the ringtone. */
     void play(Uri ringtone) {
         Log.d(this, "Posting play.");
@@ -185,7 +195,7 @@
             ringtoneUri = Settings.System.DEFAULT_RINGTONE_URI;
         }
 
-        Ringtone ringtone = RingtoneManager.getRingtone(TelecomApp.getInstance(), ringtoneUri);
+        Ringtone ringtone = RingtoneManager.getRingtone(mContext, ringtoneUri);
         ringtone.setStreamType(AudioManager.STREAM_RING);
         return ringtone;
     }
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 906be74..7d4223a 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom;
 
+import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -44,7 +45,7 @@
 import com.android.internal.telephony.SmsApplication;
 import com.android.server.telecom.ContactsAsyncHelper.OnImageLoadCompleteListener;
 
-import com.google.common.base.Preconditions;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -275,10 +276,13 @@
     private boolean mIsVoipAudioMode;
     private StatusHints mStatusHints;
     private final ConnectionServiceRepository mRepository;
+    private final Context mContext;
 
     /**
      * Persists the specified parameters and initializes the new instance.
      *
+     * @param context The context.
+     * @param repository The connection service repository.
      * @param handle The handle to dial.
      * @param gatewayInfo Gateway information to use for the call.
      * @param connectionManagerPhoneAccountHandle Account to use for the service managing the call.
@@ -289,6 +293,7 @@
      * @param isIncoming True if this is an incoming call.
      */
     Call(
+            Context context,
             ConnectionServiceRepository repository,
             Uri handle,
             GatewayInfo gatewayInfo,
@@ -297,6 +302,7 @@
             boolean isIncoming,
             boolean isConference) {
         mState = isConference ? CallState.ACTIVE : CallState.NEW;
+        mContext = context;
         mRepository = repository;
         setHandle(handle);
         setHandle(handle, TelecomManager.PRESENTATION_ALLOWED);
@@ -384,8 +390,8 @@
         if (!Objects.equals(handle, mHandle) || presentation != mHandlePresentation) {
             mHandle = handle;
             mHandlePresentation = presentation;
-            mIsEmergencyCall = mHandle != null && PhoneNumberUtils.isLocalEmergencyNumber(
-                    TelecomApp.getInstance(), mHandle.getSchemeSpecificPart());
+            mIsEmergencyCall = mHandle != null && PhoneNumberUtils.isLocalEmergencyNumber(mContext,
+                    mHandle.getSchemeSpecificPart());
             startCallerInfoLookup();
             for (Listener l : mListeners) {
                 l.onHandleChanged(this);
@@ -543,6 +549,15 @@
         return mConnectionService;
     }
 
+    /**
+     * Retrieves the {@link Context} for the call.
+     *
+     * @return The {@link Context}.
+     */
+    Context getContext() {
+        return mContext;
+    }
+
     void setConnectionService(ConnectionServiceWrapper service) {
         Preconditions.checkNotNull(service);
 
@@ -597,10 +612,13 @@
     /**
      * Starts the create connection sequence. Upon completion, there should exist an active
      * connection through a connection service (or the call will have failed).
+     *
+     * @param phoneAccountRegistrar The phone account registrar.
      */
-    void startCreateConnection() {
+    void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {
         Preconditions.checkState(mCreateConnectionProcessor == null);
-        mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this);
+        mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
+                phoneAccountRegistrar, mContext);
         mCreateConnectionProcessor.process();
     }
 
@@ -635,7 +653,8 @@
 
             // Timeout the direct-to-voicemail lookup execution so that we dont wait too long before
             // showing the user the incoming call screen.
-            mHandler.postDelayed(mDirectToVoicemailRunnable, Timeouts.getDirectToVoicemailMillis());
+            mHandler.postDelayed(mDirectToVoicemailRunnable, Timeouts.getDirectToVoicemailMillis(
+                    mContext.getContentResolver()));
         } else {
             for (Listener l : mListeners) {
                 l.onSuccessfulOutgoingCall(this,
@@ -955,7 +974,7 @@
         }
 
         // Is there a valid SMS application on the phone?
-        if (SmsApplication.getDefaultRespondViaMessageApplication(TelecomApp.getInstance(),
+        if (SmsApplication.getDefaultRespondViaMessageApplication(mContext,
                 true /*updateIfNeeded*/) == null) {
             return false;
         }
@@ -1015,7 +1034,7 @@
             Log.v(this, "Looking up information for: %s.", Log.piiHandle(number));
             CallerInfoAsyncQuery.startQuery(
                     mQueryToken,
-                    TelecomApp.getInstance(),
+                    mContext,
                     number,
                     sCallerInfoQueryListener,
                     this);
@@ -1041,7 +1060,7 @@
                         mCallerInfo.contactDisplayPhotoUri, this);
                 ContactsAsyncHelper.startObtainPhotoAsync(
                         token,
-                        TelecomApp.getInstance(),
+                        mContext,
                         mCallerInfo.contactDisplayPhotoUri,
                         sPhotoLoadListener,
                         this);
@@ -1100,7 +1119,8 @@
                             Log.w(Call.this, "Error obtaining canned SMS responses: %d %s", code,
                                     msg);
                         }
-                    }
+                    },
+                    mContext
             );
         } else {
             Log.d(this, "maybeLoadCannedSmsResponses: doing nothing");
diff --git a/src/com/android/server/telecom/CallActivity.java b/src/com/android/server/telecom/CallActivity.java
index 96ffb96..a4dc1a8 100644
--- a/src/com/android/server/telecom/CallActivity.java
+++ b/src/com/android/server/telecom/CallActivity.java
@@ -32,6 +32,8 @@
 import android.text.TextUtils;
 import android.widget.Toast;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
+
 /**
  * Activity that handles system CALL actions and forwards them to {@link CallsManager}.
  * Handles all three CALL action types: CALL, CALL_PRIVILEGED, and CALL_EMERGENCY.
@@ -159,7 +161,7 @@
             setResult(RESULT_CANCELED);
         } else {
             NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
-                    mCallsManager, call, intent, isDefaultDialer());
+                    this, mCallsManager, call, intent, isDefaultDialer());
             final int result = broadcaster.processIntent();
             final boolean success = result == DisconnectCause.NOT_DISCONNECTED;
 
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index 312f58f..e3b2e42 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -21,7 +21,7 @@
 import android.telecom.AudioState;
 import android.telecom.CallState;
 
-import com.google.common.base.Preconditions;
+import com.android.internal.util.Preconditions;
 
 import java.util.Objects;
 
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index 4704647..89d9316 100644
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -26,6 +26,7 @@
 import android.telecom.VideoProfile;
 import android.telephony.PhoneNumberUtils;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
 import com.android.internal.telephony.CallerInfo;
 import com.android.internal.telephony.PhoneConstants;
 
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 6936c5c..420bdf8 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom;
 
+import android.content.Context;
 import android.net.Uri;
 import android.os.Bundle;
 
@@ -30,6 +31,7 @@
 import android.telephony.TelephonyManager;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.IndentingPrintWriter;
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
 
@@ -68,7 +70,12 @@
         void onVideoStateChanged(Call call);
     }
 
-    private static final CallsManager INSTANCE = new CallsManager();
+    /**
+     * Singleton instance of the {@link CallsManager}, initialized from {@link TelecomService}.
+     */
+    private static CallsManager INSTANCE = null;
+
+    private static final String TAG = "CallsManager";
 
     private static final int MAXIMUM_LIVE_CALLS = 1;
     private static final int MAXIMUM_HOLD_CALLS = 1;
@@ -92,10 +99,9 @@
     private final Set<Call> mCalls = Collections.newSetFromMap(
             new ConcurrentHashMap<Call, Boolean>(8, 0.9f, 1));
 
-    private final ConnectionServiceRepository mConnectionServiceRepository =
-            new ConnectionServiceRepository();
-    private final DtmfLocalTonePlayer mDtmfLocalTonePlayer = new DtmfLocalTonePlayer();
-    private final InCallController mInCallController = new InCallController();
+    private final ConnectionServiceRepository mConnectionServiceRepository;
+    private final DtmfLocalTonePlayer mDtmfLocalTonePlayer;
+    private final InCallController mInCallController;
     private final CallAudioManager mCallAudioManager;
     private final Ringer mRinger;
     // For this set initial table size to 16 because we add 13 listeners in
@@ -108,6 +114,9 @@
     private final ProximitySensorManager mProximitySensorManager;
     private final PhoneStateBroadcaster mPhoneStateBroadcaster;
     private final CallLogManager mCallLogManager;
+    private final Context mContext;
+    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
+    private final MissedCallNotifier mMissedCallNotifier;
 
     /**
      * The call the user is currently interacting with. This is the call that should have audio
@@ -121,21 +130,36 @@
     }
 
     /**
+     * Sets the static singleton instance.
+     *
+     * @param instance The instance to set.
+     */
+    static void initialize(CallsManager instance) {
+        INSTANCE = instance;
+    }
+
+    /**
      * Initializes the required Telecom components.
      */
-    private CallsManager() {
-        TelecomApp app = TelecomApp.getInstance();
-
-        StatusBarNotifier statusBarNotifier = new StatusBarNotifier(app, this);
-        mWiredHeadsetManager = new WiredHeadsetManager(app);
-        mCallAudioManager = new CallAudioManager(app, statusBarNotifier, mWiredHeadsetManager);
+     CallsManager(Context context, MissedCallNotifier missedCallNotifier,
+             PhoneAccountRegistrar phoneAccountRegistrar) {
+        mContext = context;
+        mPhoneAccountRegistrar = phoneAccountRegistrar;
+        mMissedCallNotifier = missedCallNotifier;
+        StatusBarNotifier statusBarNotifier = new StatusBarNotifier(context, this);
+        mWiredHeadsetManager = new WiredHeadsetManager(context);
+        mCallAudioManager = new CallAudioManager(context, statusBarNotifier, mWiredHeadsetManager);
         InCallTonePlayer.Factory playerFactory = new InCallTonePlayer.Factory(mCallAudioManager);
-        mRinger = new Ringer(mCallAudioManager, this, playerFactory, app);
-        mHeadsetMediaButton = new HeadsetMediaButton(app, this);
-        mTtyManager = new TtyManager(app, mWiredHeadsetManager);
-        mProximitySensorManager = new ProximitySensorManager(app);
+        mRinger = new Ringer(mCallAudioManager, this, playerFactory, context);
+        mHeadsetMediaButton = new HeadsetMediaButton(context, this);
+        mTtyManager = new TtyManager(context, mWiredHeadsetManager);
+        mProximitySensorManager = new ProximitySensorManager(context);
         mPhoneStateBroadcaster = new PhoneStateBroadcaster();
-        mCallLogManager = new CallLogManager(app);
+        mCallLogManager = new CallLogManager(context);
+        mInCallController = new InCallController(context);
+        mDtmfLocalTonePlayer = new DtmfLocalTonePlayer(context);
+        mConnectionServiceRepository = new ConnectionServiceRepository(mPhoneAccountRegistrar,
+                context);
 
         mListeners.add(statusBarNotifier);
         mListeners.add(mCallLogManager);
@@ -145,7 +169,7 @@
         mListeners.add(new RingbackPlayer(this, playerFactory));
         mListeners.add(new InCallToneMonitor(playerFactory, this));
         mListeners.add(mCallAudioManager);
-        mListeners.add(app.getMissedCallNotifier());
+        mListeners.add(missedCallNotifier);
         mListeners.add(mDtmfLocalTonePlayer);
         mListeners.add(mHeadsetMediaButton);
         mListeners.add(RespondViaSmsManager.getInstance());
@@ -188,8 +212,7 @@
             incomingCall.reject(false, null);
             // since the call was not added to the list of calls, we have to call the missed
             // call notifier and the call logger manually.
-            TelecomApp.getInstance().getMissedCallNotifier()
-                    .showMissedCallNotification(incomingCall);
+            mMissedCallNotifier.showMissedCallNotification(incomingCall);
             mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE);
         } else {
             addCall(incomingCall);
@@ -290,6 +313,7 @@
         Log.d(this, "processIncomingCallIntent");
         Uri handle = extras.getParcelable(TelephonyManager.EXTRA_INCOMING_NUMBER);
         Call call = new Call(
+                mContext,
                 mConnectionServiceRepository,
                 handle,
                 null /* gatewayInfo */,
@@ -301,7 +325,7 @@
         call.setExtras(extras);
         // TODO: Move this to be a part of addCall()
         call.addListener(this);
-        call.startCreateConnection();
+        call.startCreateConnection(mPhoneAccountRegistrar);
     }
 
     /**
@@ -313,14 +337,12 @@
      * @param extras The optional extras Bundle passed with the intent used for the incoming call.
      */
     Call startOutgoingCall(Uri handle, PhoneAccountHandle phoneAccountHandle, Bundle extras) {
-        TelecomApp app = TelecomApp.getInstance();
-
         // Only dial with the requested phoneAccount if it is still valid. Otherwise treat this call
         // as if a phoneAccount was not specified (does the default behavior instead).
         // Note: We will not attempt to dial with a requested phoneAccount if it is disabled.
         if (phoneAccountHandle != null) {
             List<PhoneAccountHandle> accounts =
-                    app.getPhoneAccountRegistrar().getCallCapablePhoneAccounts(handle.getScheme());
+                    mPhoneAccountRegistrar.getCallCapablePhoneAccounts(handle.getScheme());
             if (!accounts.contains(phoneAccountHandle)) {
                 phoneAccountHandle = null;
             }
@@ -330,7 +352,7 @@
             // No preset account, check if default exists that supports the URI scheme for the
             // handle.
             PhoneAccountHandle defaultAccountHandle =
-                    app.getPhoneAccountRegistrar().getDefaultOutgoingPhoneAccount(
+                    mPhoneAccountRegistrar.getDefaultOutgoingPhoneAccount(
                             handle.getScheme());
             if (defaultAccountHandle != null) {
                 phoneAccountHandle = defaultAccountHandle;
@@ -340,6 +362,7 @@
         // Create a call with original handle. The handle may be changed when the call is attached
         // to a connection service, but in most cases will remain the same.
         Call call = new Call(
+                mContext,
                 mConnectionServiceRepository,
                 handle,
                 null /* gatewayInfo */,
@@ -349,7 +372,8 @@
                 false /* isConference */);
         call.setExtras(extras);
 
-        boolean isEmergencyCall = TelephonyUtil.shouldProcessAsEmergency(app, call.getHandle());
+        boolean isEmergencyCall = TelephonyUtil.shouldProcessAsEmergency(mContext,
+                call.getHandle());
 
         // Do not support any more live calls.  Our options are to move a call to hold, disconnect
         // a call, or cancel this call altogether.
@@ -405,8 +429,8 @@
         call.setStartWithSpeakerphoneOn(speakerphoneOn);
         call.setVideoState(videoState);
 
-        TelecomApp app = TelecomApp.getInstance();
-        boolean isEmergencyCall = TelephonyUtil.shouldProcessAsEmergency(app, call.getHandle());
+        boolean isEmergencyCall = TelephonyUtil.shouldProcessAsEmergency(mContext,
+                call.getHandle());
         if (isEmergencyCall) {
             // Emergency -- CreateConnectionProcessor will choose accounts automatically
             call.setTargetPhoneAccount(null);
@@ -415,7 +439,7 @@
         if (call.getTargetPhoneAccount() != null || isEmergencyCall) {
             // If the account has been set, proceed to place the outgoing call.
             // Otherwise the connection will be initiated when the account is set by the user.
-            call.startCreateConnection();
+            call.startCreateConnection(mPhoneAccountRegistrar);
         }
     }
 
@@ -628,7 +652,7 @@
             // Note: emergency calls never go through account selection dialog so they never
             // arrive here.
             if (makeRoomForOutgoingCall(call, false /* isEmergencyCall */)) {
-                call.startCreateConnection();
+                call.startCreateConnection(mPhoneAccountRegistrar);
             } else {
                 call.disconnect();
             }
@@ -800,6 +824,7 @@
             PhoneAccountHandle phoneAccount,
             ParcelableConference parcelableConference) {
         Call call = new Call(
+                mContext,
                 mConnectionServiceRepository,
                 null /* handle */,
                 null /* gatewayInfo */,
@@ -828,6 +853,23 @@
     }
 
     /**
+     * Retrieves the {@link PhoneAccountRegistrar}.
+     *
+     * @return The {@link PhoneAccountRegistrar}.
+     */
+    PhoneAccountRegistrar getPhoneAccountRegistrar() {
+        return mPhoneAccountRegistrar;
+    }
+
+    /**
+     * Retrieves the {@link MissedCallNotifier}
+     * @return The {@link MissedCallNotifier}.
+     */
+    MissedCallNotifier getMissedCallNotifier() {
+        return mMissedCallNotifier;
+    }
+
+    /**
      * Adds the specified call to the main list of live calls.
      *
      * @param call The call to add.
@@ -1018,4 +1060,23 @@
         }
         return true;
     }
+
+    /**
+     * Dumps the state of the {@link CallsManager}.
+     *
+     * @param pw The {@code IndentingPrintWriter} to write the state to.
+     */
+    public void dump(IndentingPrintWriter pw) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        pw.increaseIndent();
+        if (mCalls != null) {
+            pw.println("mCalls: ");
+            pw.increaseIndent();
+            for (Call call : mCalls) {
+                pw.println(call);
+            }
+            pw.decreaseIndent();
+        }
+        pw.decreaseIndent();
+    }
 }
diff --git a/src/com/android/server/telecom/ConnectionServiceRepository.java b/src/com/android/server/telecom/ConnectionServiceRepository.java
index d7a6d3e..e9a447d 100644
--- a/src/com/android/server/telecom/ConnectionServiceRepository.java
+++ b/src/com/android/server/telecom/ConnectionServiceRepository.java
@@ -17,6 +17,7 @@
 package com.android.server.telecom;
 
 import android.content.ComponentName;
+import android.content.Context;
 
 import java.util.HashMap;
 
@@ -27,8 +28,12 @@
         implements ServiceBinder.Listener<ConnectionServiceWrapper> {
     private final HashMap<ComponentName, ConnectionServiceWrapper> mServiceCache =
             new HashMap<ComponentName, ConnectionServiceWrapper>();
+    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
+    private final Context mContext;
 
-    ConnectionServiceRepository() {
+    ConnectionServiceRepository(PhoneAccountRegistrar phoneAccountRegistrar, Context context) {
+        mPhoneAccountRegistrar = phoneAccountRegistrar;
+        mContext = context;
     }
 
     ConnectionServiceWrapper getService(ComponentName componentName) {
@@ -37,7 +42,8 @@
             service = new ConnectionServiceWrapper(
                     componentName,
                     this,
-                    TelecomApp.getInstance().getPhoneAccountRegistrar());
+                    mPhoneAccountRegistrar,
+                    mContext);
             service.addListener(this);
             mServiceCache.put(componentName, service);
         }
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index e77b896..efa01e9 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -17,6 +17,7 @@
 package com.android.server.telecom;
 
 import android.content.ComponentName;
+import android.content.Context;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -42,7 +43,7 @@
 import com.android.internal.telecom.IConnectionServiceAdapter;
 import com.android.internal.telecom.IVideoProvider;
 import com.android.internal.telecom.RemoteServiceCallback;
-import com.google.common.base.Preconditions;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -560,6 +561,7 @@
     private Binder mBinder = new Binder();
     private IConnectionService mServiceInterface;
     private final ConnectionServiceRepository mConnectionServiceRepository;
+    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
 
     /**
      * Creates a connection service.
@@ -567,17 +569,20 @@
      * @param componentName The component name of the service with which to bind.
      * @param connectionServiceRepository Connection service repository.
      * @param phoneAccountRegistrar Phone account registrar
+     * @param context The context.
      */
     ConnectionServiceWrapper(
             ComponentName componentName,
             ConnectionServiceRepository connectionServiceRepository,
-            PhoneAccountRegistrar phoneAccountRegistrar) {
-        super(ConnectionService.SERVICE_INTERFACE, componentName);
+            PhoneAccountRegistrar phoneAccountRegistrar,
+            Context context) {
+        super(ConnectionService.SERVICE_INTERFACE, componentName, context);
         mConnectionServiceRepository = connectionServiceRepository;
         phoneAccountRegistrar.addListener(new PhoneAccountRegistrar.Listener() {
             // TODO -- Upon changes to PhoneAccountRegistrar, need to re-wire connections
             // To do this, we must proxy remote ConnectionService objects
         });
+        mPhoneAccountRegistrar = phoneAccountRegistrar;
     }
 
     /** See {@link IConnectionService#addConnectionServiceAdapter}. */
@@ -913,11 +918,9 @@
     }
 
     private void queryRemoteConnectionServices(final RemoteServiceCallback callback) {
-        PhoneAccountRegistrar registrar = TelecomApp.getInstance().getPhoneAccountRegistrar();
-
         // Only give remote connection services to this connection service if it is listed as
         // the connection manager.
-        PhoneAccountHandle simCallManager = registrar.getSimCallManager();
+        PhoneAccountHandle simCallManager = mPhoneAccountRegistrar.getSimCallManager();
         Log.d(this, "queryRemoteConnectionServices finds simCallManager = %s", simCallManager);
         if (simCallManager == null ||
                 !simCallManager.getComponentName().equals(getComponentName())) {
@@ -928,8 +931,8 @@
         // Make a list of ConnectionServices that are listed as being associated with SIM accounts
         final Set<ConnectionServiceWrapper> simServices = Collections.newSetFromMap(
                 new ConcurrentHashMap<ConnectionServiceWrapper, Boolean>(8, 0.9f, 1));
-        for (PhoneAccountHandle handle : registrar.getCallCapablePhoneAccounts()) {
-            PhoneAccount account = registrar.getPhoneAccount(handle);
+        for (PhoneAccountHandle handle : mPhoneAccountRegistrar.getCallCapablePhoneAccounts()) {
+            PhoneAccount account = mPhoneAccountRegistrar.getPhoneAccount(handle);
             if ((account.getCapabilities() & PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0) {
                 ConnectionServiceWrapper service =
                         mConnectionServiceRepository.getService(handle.getComponentName());
diff --git a/src/com/android/server/telecom/ContactsAsyncHelper.java b/src/com/android/server/telecom/ContactsAsyncHelper.java
index aa99ac3..1fbf5ee 100644
--- a/src/com/android/server/telecom/ContactsAsyncHelper.java
+++ b/src/com/android/server/telecom/ContactsAsyncHelper.java
@@ -27,6 +27,8 @@
 import android.os.Looper;
 import android.os.Message;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
+
 import java.io.IOException;
 import java.io.InputStream;
 
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index c019881..6adb72c 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -16,11 +16,15 @@
 
 package com.android.server.telecom;
 
+import android.content.Context;
 import android.telecom.DisconnectCause;
 import android.telecom.ParcelableConnection;
+import android.telecom.Phone;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
+
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -83,12 +87,17 @@
     private Iterator<CallAttemptRecord> mAttemptRecordIterator;
     private CreateConnectionResponse mResponse;
     private DisconnectCause mLastErrorDisconnectCause;
+    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
+    private final Context mContext;
 
     CreateConnectionProcessor(
-            Call call, ConnectionServiceRepository repository, CreateConnectionResponse response) {
+            Call call, ConnectionServiceRepository repository, CreateConnectionResponse response,
+            PhoneAccountRegistrar phoneAccountRegistrar, Context context) {
         mCall = call;
         mRepository = repository;
         mResponse = response;
+        mPhoneAccountRegistrar = phoneAccountRegistrar;
+        mContext = context;
     }
 
     void process() {
@@ -124,12 +133,12 @@
 
     private void attemptNextPhoneAccount() {
         Log.v(this, "attemptNextPhoneAccount");
-        PhoneAccountRegistrar registrar = TelecomApp.getInstance().getPhoneAccountRegistrar();
         CallAttemptRecord attempt = null;
         if (mAttemptRecordIterator.hasNext()) {
             attempt = mAttemptRecordIterator.next();
 
-            if (!registrar.phoneAccountHasPermission(attempt.connectionManagerPhoneAccount)) {
+            if (!mPhoneAccountRegistrar.phoneAccountHasPermission(
+                    attempt.connectionManagerPhoneAccount)) {
                 Log.w(this,
                         "Connection mgr does not have BIND_CONNECTION_SERVICE for attempt: %s",
                         attempt);
@@ -140,7 +149,7 @@
             // If the target PhoneAccount differs from the ConnectionManager phone acount, ensure it
             // also has BIND_CONNECTION_SERVICE permission.
             if (!attempt.connectionManagerPhoneAccount.equals(attempt.targetPhoneAccount) &&
-                    !registrar.phoneAccountHasPermission(attempt.targetPhoneAccount)) {
+                    !mPhoneAccountRegistrar.phoneAccountHasPermission(attempt.targetPhoneAccount)) {
                 Log.w(this,
                         "Target PhoneAccount does not have BIND_CONNECTION_SERVICE for attempt: %s",
                         attempt);
@@ -185,8 +194,7 @@
             return false;
         }
 
-        PhoneAccountRegistrar registrar = TelecomApp.getInstance().getPhoneAccountRegistrar();
-        PhoneAccountHandle connectionManager = registrar.getSimCallManager();
+        PhoneAccountHandle connectionManager = mPhoneAccountRegistrar.getSimCallManager();
         if (connectionManager == null) {
             return false;
         }
@@ -197,7 +205,8 @@
         }
 
         // Connection managers are only allowed to manage SIM subscriptions.
-        PhoneAccount targetPhoneAccount = registrar.getPhoneAccount(targetPhoneAccountHandle);
+        PhoneAccount targetPhoneAccount = mPhoneAccountRegistrar.getPhoneAccount(
+                targetPhoneAccountHandle);
         boolean isSimSubscription = (targetPhoneAccount.getCapabilities() &
                 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0;
         if (!isSimSubscription) {
@@ -211,7 +220,7 @@
     private void adjustAttemptsForConnectionManager() {
         if (shouldSetConnectionManager()) {
             CallAttemptRecord record = new CallAttemptRecord(
-                    TelecomApp.getInstance().getPhoneAccountRegistrar().getSimCallManager(),
+                    mPhoneAccountRegistrar.getSimCallManager(),
                     mAttemptRecords.get(0).targetPhoneAccount);
             Log.v(this, "setConnectionManager, changing %s -> %s",
                     mAttemptRecords.get(0).targetPhoneAccount, record);
@@ -224,11 +233,10 @@
     // If we are possibly attempting to call a local emergency number, ensure that the
     // plain PSTN connection services are listed, and nothing else.
     private void adjustAttemptsForEmergency()  {
-        if (TelephonyUtil.shouldProcessAsEmergency(TelecomApp.getInstance(), mCall.getHandle())) {
+        if (TelephonyUtil.shouldProcessAsEmergency(mContext, mCall.getHandle())) {
             Log.i(this, "Emergency number detected");
             mAttemptRecords.clear();
-            List<PhoneAccount> allAccounts = TelecomApp.getInstance()
-                    .getPhoneAccountRegistrar().getAllPhoneAccounts();
+            List<PhoneAccount> allAccounts = mPhoneAccountRegistrar.getAllPhoneAccounts();
             // First, add SIM phone accounts which can place emergency calls.
             for (PhoneAccount phoneAccount : allAccounts) {
                 if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS) &&
@@ -243,14 +251,13 @@
             }
 
             // Next, add the connection manager account as a backup if it can place emergency calls.
-            PhoneAccountHandle callManagerHandle = TelecomApp.getInstance()
-                    .getPhoneAccountRegistrar().getSimCallManager();
+            PhoneAccountHandle callManagerHandle = mPhoneAccountRegistrar.getSimCallManager();
             if (callManagerHandle != null) {
-                PhoneAccount callManager = TelecomApp.getInstance()
-                        .getPhoneAccountRegistrar().getPhoneAccount(callManagerHandle);
+                PhoneAccount callManager = mPhoneAccountRegistrar
+                        .getPhoneAccount(callManagerHandle);
                 if (callManager.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)) {
                     CallAttemptRecord callAttemptRecord = new CallAttemptRecord(callManagerHandle,
-                            TelecomApp.getInstance().getPhoneAccountRegistrar().
+                            mPhoneAccountRegistrar.
                                     getDefaultOutgoingPhoneAccount(mCall.getHandle().getScheme())
                     );
 
diff --git a/src/com/android/server/telecom/DtmfLocalTonePlayer.java b/src/com/android/server/telecom/DtmfLocalTonePlayer.java
index eb3f9a0..6b4b74d 100644
--- a/src/com/android/server/telecom/DtmfLocalTonePlayer.java
+++ b/src/com/android/server/telecom/DtmfLocalTonePlayer.java
@@ -16,10 +16,12 @@
 
 package com.android.server.telecom;
 
+import android.content.Context;
 import android.media.AudioManager;
 import android.media.ToneGenerator;
 import android.provider.Settings;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
 import com.google.common.collect.ImmutableMap;
 
 import java.util.Map;
@@ -53,6 +55,13 @@
     /** The current call associated with an existing dtmf session. */
     private Call mCall;
 
+    /** The context. */
+    private final Context mContext;
+
+    public DtmfLocalTonePlayer(Context context) {
+        mContext = context;
+    }
+
     /** {@inheritDoc} */
     @Override
     public void onForegroundCallChanged(Call oldForegroundCall, Call newForegroundCall) {
@@ -110,12 +119,11 @@
         if (call == null) {
             return;
         }
-        TelecomApp app = TelecomApp.getInstance();
-
+        final Context context = call.getContext();
         final boolean areLocalTonesEnabled;
-        if (app.getResources().getBoolean(R.bool.allow_local_dtmf_tones)) {
+        if (context.getResources().getBoolean(R.bool.allow_local_dtmf_tones)) {
             areLocalTonesEnabled = Settings.System.getInt(
-                    app.getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;
+                    context.getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;
         } else {
             areLocalTonesEnabled = false;
         }
diff --git a/src/com/android/server/telecom/ErrorDialogActivity.java b/src/com/android/server/telecom/ErrorDialogActivity.java
index 0e6bca0..a669f10 100644
--- a/src/com/android/server/telecom/ErrorDialogActivity.java
+++ b/src/com/android/server/telecom/ErrorDialogActivity.java
@@ -22,6 +22,8 @@
 import android.content.Intent;
 import android.os.Bundle;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
+
 /**
  * Used to display an error dialog from within the Telecom service when an outgoing call fails
  */
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index a80d9af..2dc30da 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -38,6 +38,7 @@
 import android.telecom.TelecomManager;
 import android.util.ArrayMap;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
 import com.android.internal.telecom.IInCallService;
 import com.google.common.collect.ImmutableCollection;
 
@@ -135,9 +136,11 @@
     /** The {@link ComponentName} of the default InCall UI. */
     private final ComponentName mInCallComponentName;
 
-    public InCallController() {
-        Context context = TelecomApp.getInstance();
-        Resources resources = context.getResources();
+    private final Context mContext;
+
+    public InCallController(Context context) {
+        mContext = context;
+        Resources resources = mContext.getResources();
 
         mInCallComponentName = new ComponentName(
                 resources.getString(R.string.ui_default_package),
@@ -245,7 +248,7 @@
             mServiceConnections.entrySet().iterator();
         while (iterator.hasNext()) {
             Log.i(this, "Unbinding from InCallService %s");
-            TelecomApp.getInstance().unbindService(iterator.next().getValue());
+            mContext.unbindService(iterator.next().getValue());
             iterator.remove();
         }
         mInCallServices.clear();
@@ -259,8 +262,8 @@
         ThreadUtil.checkOnMainThread();
         if (mInCallServices.isEmpty()) {
             mServiceConnections.clear();
-            Context context = TelecomApp.getInstance();
-            PackageManager packageManager = TelecomApp.getInstance().getPackageManager();
+
+            PackageManager packageManager = mContext.getPackageManager();
             Intent serviceIntent = new Intent(InCallService.SERVICE_INTERFACE);
 
             for (ResolveInfo entry : packageManager.queryIntentServices(serviceIntent, 0)) {
@@ -295,7 +298,7 @@
                         Intent intent = new Intent(InCallService.SERVICE_INTERFACE);
                         intent.setComponent(componentName);
 
-                        if (context.bindServiceAsUser(intent, inCallServiceConnection,
+                        if (mContext.bindServiceAsUser(intent, inCallServiceConnection,
                                 Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
                             mServiceConnections.put(componentName, inCallServiceConnection);
                         }
@@ -359,7 +362,6 @@
     private void onDisconnected(ComponentName disconnectedComponent) {
         Log.i(this, "onDisconnected from %s", disconnectedComponent);
         ThreadUtil.checkOnMainThread();
-        Context context = TelecomApp.getInstance();
 
         if (mInCallServices.containsKey(disconnectedComponent)) {
             mInCallServices.remove(disconnectedComponent);
@@ -382,7 +384,7 @@
                         mServiceConnections.get(disconnectedComponent);
 
                 // We still need to call unbind even though it disconnected.
-                context.unbindService(serviceConnection);
+                mContext.unbindService(serviceConnection);
 
                 mServiceConnections.remove(disconnectedComponent);
                 mInCallServices.remove(disconnectedComponent);
diff --git a/src/com/android/server/telecom/Log.java b/src/com/android/server/telecom/Log.java
index ff3c8ce..6e3ff6d 100644
--- a/src/com/android/server/telecom/Log.java
+++ b/src/com/android/server/telecom/Log.java
@@ -48,82 +48,82 @@
 
     public static void d(String prefix, String format, Object... args) {
         if (DEBUG) {
-            android.util.Log.d(TAG, buildMessage(prefix, format, args));
+            android.util.Slog.d(TAG, buildMessage(prefix, format, args));
         }
     }
 
     public static void d(Object objectPrefix, String format, Object... args) {
         if (DEBUG) {
-            android.util.Log.d(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
+            android.util.Slog.d(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
         }
     }
 
     public static void i(String prefix, String format, Object... args) {
         if (INFO) {
-            android.util.Log.i(TAG, buildMessage(prefix, format, args));
+            android.util.Slog.i(TAG, buildMessage(prefix, format, args));
         }
     }
 
     public static void i(Object objectPrefix, String format, Object... args) {
         if (INFO) {
-            android.util.Log.i(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
+            android.util.Slog.i(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
         }
     }
 
     public static void v(String prefix, String format, Object... args) {
         if (VERBOSE) {
-            android.util.Log.v(TAG, buildMessage(prefix, format, args));
+            android.util.Slog.v(TAG, buildMessage(prefix, format, args));
         }
     }
 
     public static void v(Object objectPrefix, String format, Object... args) {
         if (VERBOSE) {
-            android.util.Log.v(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
+            android.util.Slog.v(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
         }
     }
 
     public static void w(String prefix, String format, Object... args) {
         if (WARN) {
-            android.util.Log.w(TAG, buildMessage(prefix, format, args));
+            android.util.Slog.w(TAG, buildMessage(prefix, format, args));
         }
     }
 
     public static void w(Object objectPrefix, String format, Object... args) {
         if (WARN) {
-            android.util.Log.w(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
+            android.util.Slog.w(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
         }
     }
 
     public static void e(String prefix, Throwable tr, String format, Object... args) {
         if (ERROR) {
-            android.util.Log.e(TAG, buildMessage(prefix, format, args), tr);
+            android.util.Slog.e(TAG, buildMessage(prefix, format, args), tr);
         }
     }
 
     public static void e(Object objectPrefix, Throwable tr, String format, Object... args) {
         if (ERROR) {
-            android.util.Log.e(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
+            android.util.Slog.e(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
                     tr);
         }
     }
 
     public static void wtf(String prefix, Throwable tr, String format, Object... args) {
-        android.util.Log.wtf(TAG, buildMessage(prefix, format, args), tr);
+        android.util.Slog.wtf(TAG, buildMessage(prefix, format, args), tr);
     }
 
     public static void wtf(Object objectPrefix, Throwable tr, String format, Object... args) {
-        android.util.Log.wtf(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
+        android.util.Slog.wtf(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
                 tr);
     }
 
     public static void wtf(String prefix, String format, Object... args) {
         String msg = buildMessage(prefix, format, args);
-        android.util.Log.wtf(TAG, msg, new IllegalStateException(msg));
+        android.util.Slog.wtf(TAG, msg, new IllegalStateException(msg));
     }
 
     public static void wtf(Object objectPrefix, String format, Object... args) {
         String msg = buildMessage(getPrefixFromObject(objectPrefix), format, args);
-        android.util.Log.wtf(TAG, msg, new IllegalStateException(msg));
+        android.util.Slog.wtf(TAG, msg, new IllegalStateException(msg));
     }
 
     public static String piiHandle(Object pii) {
diff --git a/src/com/android/server/telecom/MissedCallNotifier.java b/src/com/android/server/telecom/MissedCallNotifier.java
index de6a423..8abd5b7 100644
--- a/src/com/android/server/telecom/MissedCallNotifier.java
+++ b/src/com/android/server/telecom/MissedCallNotifier.java
@@ -37,6 +37,8 @@
 import android.text.TextDirectionHeuristics;
 import android.text.TextUtils;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
+
 /**
  * Creates a notification for calls that the user missed (neither answered nor rejected).
  * TODO: Make TelephonyManager.clearMissedCalls call into this class.
@@ -284,7 +286,8 @@
                             }
 
                             // Convert the data to a call object
-                            Call call = new Call(null, null, null, null, null, true, false);
+                            Call call = new Call(mContext, null, null, null, null, null, true,
+                                    false);
                             call.setDisconnectCause(new DisconnectCause(DisconnectCause.MISSED));
                             call.setState(CallState.DISCONNECTED);
 
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index 3fbe498..cd2195c 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -31,6 +31,8 @@
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
+
 /**
  * OutgoingCallIntentBroadcaster receives CALL and CALL_PRIVILEGED Intents, and broadcasts the
  * ACTION_NEW_OUTGOING_CALL intent. ACTION_NEW_OUTGOING_CALL is an ordered broadcast intent which
@@ -69,14 +71,17 @@
     private final CallsManager mCallsManager;
     private final Call mCall;
     private final Intent mIntent;
+    private final Context mContext;
+
     /*
      * Whether or not the outgoing call intent originated from the default phone application. If
      * so, it will be allowed to make emergency calls, even with the ACTION_CALL intent.
      */
     private final boolean mIsDefaultOrSystemPhoneApp;
 
-    NewOutgoingCallIntentBroadcaster(CallsManager callsManager, Call call, Intent intent,
-            boolean isDefaultPhoneApp) {
+    NewOutgoingCallIntentBroadcaster(Context context, CallsManager callsManager, Call call,
+            Intent intent, boolean isDefaultPhoneApp) {
+        mContext = context;
         mCallsManager = callsManager;
         mCall = call;
         mIntent = intent;
@@ -102,7 +107,7 @@
             if (resultNumber == null) {
                 Log.v(this, "Call cancelled (null number), returning...");
                 endEarly = true;
-            } else if (PhoneNumberUtils.isPotentialLocalEmergencyNumber(context, resultNumber)) {
+            } else if (PhoneNumberUtils.isPotentialLocalEmergencyNumber(mContext, resultNumber)) {
                 Log.w(this, "Cannot modify outgoing call to emergency number %s.", resultNumber);
                 endEarly = true;
             }
@@ -153,8 +158,6 @@
     int processIntent() {
         Log.v(this, "Processing call intent in OutgoingCallIntentBroadcaster.");
 
-        final Context context = TelecomApp.getInstance();
-
         Intent intent = mIntent;
         String action = intent.getAction();
         final Uri handle = intent.getData();
@@ -183,7 +186,7 @@
             }
         }
 
-        String number = PhoneNumberUtils.getNumberFromIntent(intent, context);
+        String number = PhoneNumberUtils.getNumberFromIntent(intent, mContext);
         if (TextUtils.isEmpty(number)) {
             Log.w(this, "Empty number obtained from the call intent.");
             return DisconnectCause.NO_PHONE_NUMBER_SUPPLIED;
@@ -195,7 +198,7 @@
             number = PhoneNumberUtils.stripSeparators(number);
         }
 
-        final boolean isPotentialEmergencyNumber = isPotentialEmergencyNumber(context, number);
+        final boolean isPotentialEmergencyNumber = isPotentialEmergencyNumber(number);
         Log.v(this, "isPotentialEmergencyNumber = %s", isPotentialEmergencyNumber);
 
         rewriteCallIntentAction(intent, isPotentialEmergencyNumber);
@@ -209,7 +212,7 @@
                 if (!mIsDefaultOrSystemPhoneApp) {
                     Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s "
                             + "unless caller is system or default dialer.", number, intent);
-                    launchSystemDialer(context, intent.getData());
+                    launchSystemDialer(intent.getData());
                     return DisconnectCause.OUTGOING_CANCELED;
                 } else {
                     callImmediately = true;
@@ -245,7 +248,7 @@
             // initiate the call again because of the presence of the EXTRA_ALREADY_CALLED extra.
         }
 
-        broadcastIntent(intent, number, context, !callImmediately);
+        broadcastIntent(intent, number, !callImmediately);
         return DisconnectCause.NOT_DISCONNECTED;
     }
 
@@ -255,14 +258,12 @@
      *
      * @param originalCallIntent The original call intent.
      * @param number Call number that was stored in the original call intent.
-     * @param context Valid context to send the ordered broadcast using.
      * @param receiverRequired Whether or not the result from the ordered broadcast should be
      *     processed using a {@link NewOutgoingCallIntentBroadcaster}.
      */
     private void broadcastIntent(
             Intent originalCallIntent,
             String number,
-            Context context,
             boolean receiverRequired) {
         Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
         if (number != null) {
@@ -276,7 +277,7 @@
 
         checkAndCopyProviderExtras(originalCallIntent, broadcastIntent);
 
-        context.sendOrderedBroadcastAsUser(
+        mContext.sendOrderedBroadcastAsUser(
                 broadcastIntent,
                 UserHandle.OWNER,
                 PERMISSION,
@@ -350,9 +351,9 @@
         return null;
     }
 
-    private void launchSystemDialer(Context context, Uri handle) {
+    private void launchSystemDialer(Uri handle) {
         Intent systemDialerIntent = new Intent();
-        final Resources resources = context.getResources();
+        final Resources resources = mContext.getResources();
         systemDialerIntent.setClassName(
                 resources.getString(R.string.ui_default_package),
                 resources.getString(R.string.dialer_default_class));
@@ -360,7 +361,7 @@
         systemDialerIntent.setData(handle);
         systemDialerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         Log.v(this, "calling startActivity for default dialer: %s", systemDialerIntent);
-        context.startActivity(systemDialerIntent);
+        mContext.startActivity(systemDialerIntent);
     }
 
     /**
@@ -373,14 +374,14 @@
      * still result in an emergency call with some networks), we use
      * isPotentialLocalEmergencyNumber instead of isLocalEmergencyNumber.
      *
-     * @param context Valid context
      * @param number number to inspect in order to determine whether or not an emergency number
      * is potentially being dialed
      * @return True if the handle is potentially an emergency number.
      */
-    private boolean isPotentialEmergencyNumber(Context context, String number) {
+    private boolean isPotentialEmergencyNumber(String number) {
         Log.v(this, "Checking restrictions for number : %s", Log.pii(number));
-        return (number != null) && PhoneNumberUtils.isPotentialLocalEmergencyNumber(context,number);
+        return (number != null) && PhoneNumberUtils.isPotentialLocalEmergencyNumber(mContext,
+                number);
     }
 
     /**
diff --git a/src/com/android/server/telecom/PhoneAccountBroadcastReceiver.java b/src/com/android/server/telecom/PhoneAccountBroadcastReceiver.java
index 6152bef..d2516b1 100644
--- a/src/com/android/server/telecom/PhoneAccountBroadcastReceiver.java
+++ b/src/com/android/server/telecom/PhoneAccountBroadcastReceiver.java
@@ -35,6 +35,16 @@
  * the enabled state of the accounts is retained.
  */
 public class PhoneAccountBroadcastReceiver extends BroadcastReceiver {
+
+    /**
+     * The {@link PhoneAccountRegistrar}.
+     */
+    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
+
+    public PhoneAccountBroadcastReceiver(PhoneAccountRegistrar phoneAccountRegistrar) {
+        mPhoneAccountRegistrar = phoneAccountRegistrar;
+    }
+
     /**
      * Receives the intents the class is configured to received.
      *
@@ -61,16 +71,6 @@
      * @param packageName The name of the removed package.
      */
     private void handlePackageRemoved(Context context, String packageName) {
-        TelecomApp telecomApp = TelecomApp.getInstance();
-        if (telecomApp == null) {
-            return;
-        }
-
-        PhoneAccountRegistrar registrar = telecomApp.getPhoneAccountRegistrar();
-        if (registrar == null) {
-            return;
-        }
-
-        registrar.clearAccounts(packageName);
+        mPhoneAccountRegistrar.clearAccounts(packageName);
     }
 }
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index 4e098b4..e6aeac5 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -21,6 +21,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.os.Environment;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.telecom.ConnectionService;
 import android.telecom.PhoneAccount;
@@ -33,6 +35,7 @@
 import android.util.AtomicFile;
 import android.util.Xml;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
@@ -94,8 +97,16 @@
 
     @VisibleForTesting
     public PhoneAccountRegistrar(Context context, String fileName) {
-        // TODO: Change file location when Telecom is part of system
+        // TODO: This file path is subject to change -- it is storing the phone account registry
+        // state file in the path /data/system/users/0/, which is likely not correct in a
+        // multi-user setting.
+        /** UNCOMMENT_FOR_MOVE_TO_SYSTEM_SERVICE
+        String filePath = Environment.getUserSystemDirectory(UserHandle.myUserId()).
+                getAbsolutePath();
+        mAtomicFile = new AtomicFile(new File(filePath, fileName));
+         UNCOMMENT_FOR_MOVE_TO_SYSTEM_SERVICE */
         mAtomicFile = new AtomicFile(new File(context.getFilesDir(), fileName));
+
         mState = new State();
         mContext = context;
         read();
@@ -419,7 +430,7 @@
      * @return {@code True} if the phone account has permission.
      */
     public boolean phoneAccountHasPermission(PhoneAccountHandle phoneAccountHandle) {
-        PackageManager packageManager = TelecomApp.getInstance().getPackageManager();
+        PackageManager packageManager = mContext.getPackageManager();
         try {
             ServiceInfo serviceInfo = packageManager.getServiceInfo(
                     phoneAccountHandle.getComponentName(), 0);
diff --git a/src/com/android/server/telecom/QuickResponseUtils.java b/src/com/android/server/telecom/QuickResponseUtils.java
index dad2907..ec77b33 100644
--- a/src/com/android/server/telecom/QuickResponseUtils.java
+++ b/src/com/android/server/telecom/QuickResponseUtils.java
@@ -21,6 +21,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
 
 /**
  * Utils class that exposes some helper routines to used to manage the QuickResponses
@@ -48,7 +49,7 @@
      * current SharedPreferences.  This is a lazy migration as it happens only when
      * the QuickResponse settings are viewed or if they are queried via RespondViaSmsManager.
      */
-    public static void maybeMigrateLegacyQuickResponses() {
+    public static void maybeMigrateLegacyQuickResponses(Context context) {
         // The algorithm will go as such:
         // If Telecom QuickResponses exist, we will skip migration because this implies
         // that a user has already specified their desired QuickResponses and have abandoned any
@@ -59,11 +60,9 @@
         // function is called.
 
         Log.d(LOG_TAG, "maybeMigrateLegacyQuickResponses() - Starting");
-
-        final Context telecomContext = TelecomApp.getInstance();
-        final SharedPreferences prefs = telecomContext.getSharedPreferences(
+        final SharedPreferences prefs = context.getSharedPreferences(
                 SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
-        final Resources res = telecomContext.getResources();
+        final Resources res = context.getResources();
 
         final boolean responsesExist = prefs.contains(KEY_CANNED_RESPONSE_PREF_1);
         if (responsesExist) {
@@ -84,7 +83,7 @@
         // the Telephony package and we'll fall back on using our default values.
         Context telephonyContext = null;
         try {
-            telephonyContext = telecomContext.createPackageContext(PACKAGE_NAME_TELEPHONY, 0);
+            telephonyContext = context.createPackageContext(PACKAGE_NAME_TELEPHONY, 0);
         } catch (PackageManager.NameNotFoundException e) {
             Log.e(LOG_TAG, e, "maybeMigrateLegacyQuickResponses() - Can't find Telephony package.");
         }
diff --git a/src/com/android/server/telecom/RespondViaSmsManager.java b/src/com/android/server/telecom/RespondViaSmsManager.java
index 6c054e6..2ac9379 100644
--- a/src/com/android/server/telecom/RespondViaSmsManager.java
+++ b/src/com/android/server/telecom/RespondViaSmsManager.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.telephony.SmsApplication;
 
@@ -47,7 +48,7 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case MSG_CANNED_TEXT_MESSAGES_READY:
+                case MSG_CANNED_TEXT_MESSAGES_READY: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
                         Response<Void, List<String>> response =
@@ -63,9 +64,18 @@
                         args.recycle();
                     }
                     break;
-                case MSG_SHOW_SENT_TOAST:
-                    showMessageSentToast((String) msg.obj);
+                }
+                case MSG_SHOW_SENT_TOAST: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        String toastMessage = (String) args.arg1;
+                        Context context = (Context) args.arg2;
+                        showMessageSentToast(toastMessage, context);
+                    } finally {
+                        args.recycle();
+                    }
                     break;
+                }
             }
         }
     };
@@ -83,8 +93,10 @@
      *
      * @param response An object to receive an async reply, which will be called from
      *                 the main thread.
+     * @param context The context.
      */
-    public void loadCannedTextMessages(final Response<Void, List<String>> response) {
+    public void loadCannedTextMessages(final Response<Void, List<String>> response,
+            final Context context) {
         new Thread() {
             @Override
             public void run() {
@@ -93,11 +105,11 @@
                 // This function guarantees that QuickResponses will be in our
                 // SharedPreferences with the proper values considering there may be
                 // old QuickResponses in Telephony pre L.
-                QuickResponseUtils.maybeMigrateLegacyQuickResponses();
+                QuickResponseUtils.maybeMigrateLegacyQuickResponses(context);
 
-                final SharedPreferences prefs = TelecomApp.getInstance().getSharedPreferences(
+                final SharedPreferences prefs = context.getSharedPreferences(
                         QuickResponseUtils.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
-                final Resources res = TelecomApp.getInstance().getInstance().getResources();
+                final Resources res = context.getResources();
 
                 final ArrayList<String> textMessages = new ArrayList<>(
                         QuickResponseUtils.NUM_CANNED_RESPONSES);
@@ -128,19 +140,21 @@
     @Override
     public void onIncomingCallRejected(Call call, boolean rejectWithMessage, String textMessage) {
         if (rejectWithMessage) {
-            rejectCallWithMessage(call.getHandle().getSchemeSpecificPart(), textMessage);
+
+            rejectCallWithMessage(call.getContext(), call.getHandle().getSchemeSpecificPart(),
+                    textMessage);
         }
     }
 
-    private void showMessageSentToast(final String phoneNumber) {
+    private void showMessageSentToast(final String phoneNumber, final Context context) {
         // ...and show a brief confirmation to the user (since
         // otherwise it's hard to be sure that anything actually
         // happened.)
-        final Resources res = TelecomApp.getInstance().getResources();
+        final Resources res = context.getResources();
         final String formatString = res.getString(
                 R.string.respond_via_sms_confirmation_format);
         final String confirmationMsg = String.format(formatString, phoneNumber);
-        Toast.makeText(TelecomApp.getInstance(), confirmationMsg,
+        Toast.makeText(context, confirmationMsg,
                 Toast.LENGTH_LONG).show();
 
         // TODO: If the device is locked, this toast won't actually ever
@@ -161,19 +175,23 @@
     /**
      * Reject the call with the specified message. If message is null this call is ignored.
      */
-    private void rejectCallWithMessage(String phoneNumber, String textMessage) {
+    private void rejectCallWithMessage(Context context, String phoneNumber, String textMessage) {
         if (textMessage != null) {
             final ComponentName component =
-                    SmsApplication.getDefaultRespondViaMessageApplication(
-                            TelecomApp.getInstance(), true /*updateIfNeeded*/);
+                    SmsApplication.getDefaultRespondViaMessageApplication(context,
+                            true /*updateIfNeeded*/);
             if (component != null) {
                 // Build and send the intent
                 final Uri uri = Uri.fromParts(Constants.SCHEME_SMSTO, phoneNumber, null);
                 final Intent intent = new Intent(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE, uri);
                 intent.putExtra(Intent.EXTRA_TEXT, textMessage);
-                mHandler.obtainMessage(MSG_SHOW_SENT_TOAST, phoneNumber).sendToTarget();
+
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = phoneNumber;
+                args.arg2 = context;
+                mHandler.obtainMessage(MSG_SHOW_SENT_TOAST, args).sendToTarget();
                 intent.setComponent(component);
-                TelecomApp.getInstance().startService(intent);
+                context.startService(intent);
             }
         }
     }
diff --git a/src/com/android/server/telecom/RespondViaSmsSettings.java b/src/com/android/server/telecom/RespondViaSmsSettings.java
index 23bf7b2..b537162 100644
--- a/src/com/android/server/telecom/RespondViaSmsSettings.java
+++ b/src/com/android/server/telecom/RespondViaSmsSettings.java
@@ -27,6 +27,8 @@
 import android.view.Menu;
 import android.view.MenuItem;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
+
 /**
  * Helper class to manage the "Respond via SMS Message" feature for incoming calls.
  */
@@ -52,7 +54,7 @@
             // This function guarantees that QuickResponses will be in our
             // SharedPreferences with the proper values considering there may be
             // old QuickResponses in Telephony pre L.
-            QuickResponseUtils.maybeMigrateLegacyQuickResponses();
+            QuickResponseUtils.maybeMigrateLegacyQuickResponses(this);
 
             getPreferenceManager().setSharedPreferencesName(
                     QuickResponseUtils.SHARED_PREFERENCES_NAME);
diff --git a/src/com/android/server/telecom/RingbackPlayer.java b/src/com/android/server/telecom/RingbackPlayer.java
index dc06c95..e6d703c 100644
--- a/src/com/android/server/telecom/RingbackPlayer.java
+++ b/src/com/android/server/telecom/RingbackPlayer.java
@@ -18,7 +18,7 @@
 
 import android.telecom.CallState;
 
-import com.google.common.base.Preconditions;
+import com.android.internal.util.Preconditions;
 
 /**
  * Plays ringback tones. Ringback is different from other tones because it operates as the current
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index 34f6829..cf65a11 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -49,7 +49,7 @@
     /** Indicate that we want the pattern to repeat at the step which turns on vibration. */
     private static final int VIBRATION_PATTERN_REPEAT = 1;
 
-    private final AsyncRingtonePlayer mRingtonePlayer = new AsyncRingtonePlayer();
+    private final AsyncRingtonePlayer mRingtonePlayer;
 
     /**
      * Used to keep ordering of unanswered incoming calls. There can easily exist multiple incoming
@@ -83,7 +83,8 @@
         mContext = context;
         // We don't rely on getSystemService(Context.VIBRATOR_SERVICE) to make sure this
         // vibrator object will be isolated from others.
-        mVibrator = new SystemVibrator(TelecomApp.getInstance());
+        mVibrator = new SystemVibrator(context);
+        mRingtonePlayer = new AsyncRingtonePlayer(context);
     }
 
     @Override
@@ -197,7 +198,7 @@
                 Log.v(this, "startRingingOrCallWaiting, skipping because volume is 0");
             }
 
-            if (shouldVibrate(TelecomApp.getInstance()) && !mIsVibrating) {
+            if (shouldVibrate(mContext) && !mIsVibrating) {
                 mVibrator.vibrate(VIBRATION_PATTERN, VIBRATION_PATTERN_REPEAT,
                         VIBRATION_ATTRIBUTES);
                 mIsVibrating = true;
diff --git a/src/com/android/server/telecom/ServiceBinder.java b/src/com/android/server/telecom/ServiceBinder.java
index 98e7bd0..fb747f2 100644
--- a/src/com/android/server/telecom/ServiceBinder.java
+++ b/src/com/android/server/telecom/ServiceBinder.java
@@ -23,7 +23,7 @@
 import android.os.IBinder;
 import android.os.IInterface;
 
-import com.google.common.base.Preconditions;
+import com.android.internal.util.Preconditions;
 import com.google.common.base.Strings;
 
 import com.google.common.collect.Sets;
@@ -166,12 +166,13 @@
      *
      * @param serviceAction The intent-action used with {@link Context#bindService}.
      * @param componentName The component name of the service with which to bind.
+     * @param context The context.
      */
-    protected ServiceBinder(String serviceAction, ComponentName componentName) {
+    protected ServiceBinder(String serviceAction, ComponentName componentName, Context context) {
         Preconditions.checkState(!Strings.isNullOrEmpty(serviceAction));
         Preconditions.checkNotNull(componentName);
 
-        mContext = TelecomApp.getInstance();
+        mContext = context;
         mServiceAction = serviceAction;
         mComponentName = componentName;
     }
diff --git a/src/com/android/server/telecom/StatusBarNotifier.java b/src/com/android/server/telecom/StatusBarNotifier.java
index 14253a0..c8c3c18 100644
--- a/src/com/android/server/telecom/StatusBarNotifier.java
+++ b/src/com/android/server/telecom/StatusBarNotifier.java
@@ -19,6 +19,8 @@
 import android.app.StatusBarManager;
 import android.content.Context;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
+
 /**
  * Manages the special status bar notifications used by the phone app.
  */
diff --git a/src/com/android/server/telecom/TelecomApp.java b/src/com/android/server/telecom/TelecomApp.java
index c2e79eb..b8519c3 100644
--- a/src/com/android/server/telecom/TelecomApp.java
+++ b/src/com/android/server/telecom/TelecomApp.java
@@ -17,7 +17,11 @@
 package com.android.server.telecom;
 
 import android.app.Application;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.UserHandle;
+import android.os.ServiceManager;
 
 /**
  * Top-level Application class for Telecom.
@@ -28,6 +32,11 @@
     private static TelecomApp sInstance;
 
     /**
+     * The Telecom service implementation.
+     */
+    private TelecomServiceImpl mTelecomService;
+
+    /**
      * Missed call notifier. Exists here so that the instance can be shared with
      * {@link TelecomBroadcastReceiver}.
      */
@@ -38,17 +47,55 @@
      */
     private PhoneAccountRegistrar mPhoneAccountRegistrar;
 
+    /**
+     * The calls manager for the Telecom service.
+     */
+    private CallsManager mCallsManager;
+
+    /**
+     * The Telecom broadcast receiver.
+     */
+    private TelecomBroadcastReceiver mTelecomBroadcastReceiver;
+
+    /**
+     * The {@link android.telecomm.PhoneAccount} broadcast receiver.
+     */
+    private PhoneAccountBroadcastReceiver mPhoneAccountBroadcastReceiver;
+
     /** {@inheritDoc} */
     @Override public void onCreate() {
         super.onCreate();
         sInstance = this;
 
+        // Note: This style of initialization mimics what will be performed once Telecom is moved
+        // to run in the system service.  The emphasis is on ensuring that initialization of all
+        // telecom classes happens in one place without relying on Singleton initialization.
         mMissedCallNotifier = new MissedCallNotifier(this);
         mPhoneAccountRegistrar = new PhoneAccountRegistrar(this);
 
+        mCallsManager = new CallsManager(this, mMissedCallNotifier, mPhoneAccountRegistrar);
+        CallsManager.initialize(mCallsManager);
+
+        mTelecomService = new TelecomServiceImpl(mMissedCallNotifier, mPhoneAccountRegistrar,
+                mCallsManager, this);
+        ServiceManager.addService(Context.TELECOM_SERVICE, mTelecomService);
+        mPhoneAccountBroadcastReceiver = new PhoneAccountBroadcastReceiver(mPhoneAccountRegistrar);
+        mTelecomBroadcastReceiver = new TelecomBroadcastReceiver(mMissedCallNotifier);
+
         if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
-            TelecomServiceImpl.init(mMissedCallNotifier, mPhoneAccountRegistrar);
+            //TelecomServiceImpl.init(mMissedCallNotifier, mPhoneAccountRegistrar);
         }
+        // Setup broadcast listener for telecom intents.
+        IntentFilter telecomFilter = new IntentFilter();
+        telecomFilter.addAction(TelecomBroadcastReceiver.ACTION_CALL_BACK_FROM_NOTIFICATION);
+        telecomFilter.addAction(TelecomBroadcastReceiver.ACTION_CALL_BACK_FROM_NOTIFICATION);
+        telecomFilter.addAction(TelecomBroadcastReceiver.ACTION_SEND_SMS_FROM_NOTIFICATION);
+        registerReceiver(mTelecomBroadcastReceiver, telecomFilter);
+
+        IntentFilter phoneAccountFilter = new IntentFilter();
+        phoneAccountFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
+        phoneAccountFilter.addDataScheme("package");
+        registerReceiver(mPhoneAccountBroadcastReceiver, phoneAccountFilter);
     }
 
     public static TelecomApp getInstance() {
diff --git a/src/com/android/server/telecom/TelecomBroadcastReceiver.java b/src/com/android/server/telecom/TelecomBroadcastReceiver.java
index 36c23fc..9a777d6 100644
--- a/src/com/android/server/telecom/TelecomBroadcastReceiver.java
+++ b/src/com/android/server/telecom/TelecomBroadcastReceiver.java
@@ -38,6 +38,12 @@
     static final String ACTION_CLEAR_MISSED_CALLS =
             "com.android.server.telecom.ACTION_CLEAR_MISSED_CALLS";
 
+    /** The missed call notifier. */
+    private final MissedCallNotifier mMissedCallNotifier;
+
+    public TelecomBroadcastReceiver(MissedCallNotifier missedCallNotifier) {
+        mMissedCallNotifier = missedCallNotifier;
+    }
 
     /** {@inheritDoc} */
     @Override
@@ -46,13 +52,11 @@
 
         Log.v(this, "Action received: %s.", action);
 
-        MissedCallNotifier missedCallNotifier = TelecomApp.getInstance().getMissedCallNotifier();
-
         // Send an SMS from the missed call notification.
         if (ACTION_SEND_SMS_FROM_NOTIFICATION.equals(action)) {
             // Close the notification shade and the notification itself.
             closeSystemDialogs(context);
-            missedCallNotifier.clearMissedCalls();
+            mMissedCallNotifier.clearMissedCalls();
 
             Intent callIntent = new Intent(Intent.ACTION_SENDTO, intent.getData());
             callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -62,7 +66,7 @@
         } else if (ACTION_CALL_BACK_FROM_NOTIFICATION.equals(action)) {
             // Close the notification shade and the notification itself.
             closeSystemDialogs(context);
-            missedCallNotifier.clearMissedCalls();
+            mMissedCallNotifier.clearMissedCalls();
 
             Intent callIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED, intent.getData());
             callIntent.setFlags(
@@ -71,7 +75,7 @@
 
         // Clear the missed call notification and call log entries.
         } else if (ACTION_CLEAR_MISSED_CALLS.equals(action)) {
-            missedCallNotifier.clearMissedCalls();
+            mMissedCallNotifier.clearMissedCalls();
         }
     }
 
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 2f5fa68..b41b294 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -37,8 +37,12 @@
 import android.telecom.TelecomManager;
 import android.telephony.TelephonyManager;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
 import com.android.internal.telecom.ITelecomService;
+import com.android.internal.util.IndentingPrintWriter;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.List;
 
 /**
@@ -48,6 +52,9 @@
     private static final String REGISTER_PROVIDER_OR_SUBSCRIPTION =
             "com.android.server.telecom.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION";
 
+    /** The context. */
+    private Context mContext;
+
     /** ${inheritDoc} */
     @Override
     public IBinder asBinder() {
@@ -125,35 +132,19 @@
     private static TelecomServiceImpl sInstance;
 
     private final MainThreadHandler mMainThreadHandler = new MainThreadHandler();
-    private final CallsManager mCallsManager = CallsManager.getInstance();
+    private final CallsManager mCallsManager;
     private final MissedCallNotifier mMissedCallNotifier;
     private final PhoneAccountRegistrar mPhoneAccountRegistrar;
     private final AppOpsManager mAppOpsManager;
 
-    private TelecomServiceImpl(
-            MissedCallNotifier missedCallNotifier, PhoneAccountRegistrar phoneAccountRegistrar) {
+    public TelecomServiceImpl(
+            MissedCallNotifier missedCallNotifier, PhoneAccountRegistrar phoneAccountRegistrar,
+            CallsManager callsManager, Context context) {
         mMissedCallNotifier = missedCallNotifier;
         mPhoneAccountRegistrar = phoneAccountRegistrar;
-        mAppOpsManager =
-                (AppOpsManager) TelecomApp.getInstance().getSystemService(Context.APP_OPS_SERVICE);
-
-        publish();
-    }
-
-    /**
-     * Initialize the singleton TelecommServiceImpl instance.
-     * This is only done once, at startup, from TelecommApp.onCreate().
-     */
-    static TelecomServiceImpl init(
-            MissedCallNotifier missedCallNotifier, PhoneAccountRegistrar phoneAccountRegistrar) {
-        synchronized (TelecomServiceImpl.class) {
-            if (sInstance == null) {
-                sInstance = new TelecomServiceImpl(missedCallNotifier, phoneAccountRegistrar);
-            } else {
-                Log.wtf(TAG, "init() called multiple times!  sInstance %s", sInstance);
-            }
-            return sInstance;
-        }
+        mCallsManager = callsManager;
+        mContext = context;
+        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
     }
 
     //
@@ -341,7 +332,7 @@
      */
     @Override
     public ComponentName getDefaultPhoneApp() {
-        Resources resources = TelecomApp.getInstance().getResources();
+        Resources resources = mContext.getResources();
         return new ComponentName(
                 resources.getString(R.string.ui_default_package),
                 resources.getString(R.string.dialer_default_class));
@@ -456,7 +447,7 @@
                     Binder.getCallingUid(), phoneAccountHandle.getComponentName().getPackageName());
 
             Intent intent = new Intent(TelecomManager.ACTION_INCOMING_CALL);
-            intent.setPackage(TelecomApp.getInstance().getPackageName());
+            intent.setPackage(mContext.getPackageName());
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
             if (extras != null) {
@@ -464,7 +455,7 @@
             }
 
             long token = Binder.clearCallingIdentity();
-            TelecomApp.getInstance().startActivityAsUser(intent, UserHandle.CURRENT);
+            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
             Binder.restoreCallingIdentity(token);
         }
     }
@@ -507,8 +498,7 @@
     private void enforcePhoneAccountModificationForPackage(String packageName) {
         // TODO: Use a new telecomm permission for this instead of reusing modify.
 
-        int result = TelecomApp.getInstance().checkCallingOrSelfPermission(
-                Manifest.permission.MODIFY_PHONE_STATE);
+        int result = mContext.checkCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
 
         // Callers with MODIFY_PHONE_STATE can use the PhoneAccount mechanism to implement
         // built-in behavior even when PhoneAccounts are not exposed as a third-part API. They
@@ -556,11 +546,11 @@
     }
 
     private void enforcePermission(String permission) {
-        TelecomApp.getInstance().enforceCallingOrSelfPermission(permission, null);
+        mContext.enforceCallingOrSelfPermission(permission, null);
     }
 
     private void enforceFeature(String feature) {
-        PackageManager pm = TelecomApp.getInstance().getPackageManager();
+        PackageManager pm = mContext.getPackageManager();
         if (!pm.hasSystemFeature(feature)) {
             throw new UnsupportedOperationException(
                     "System does not support feature " + feature);
@@ -582,13 +572,7 @@
     }
 
     private TelephonyManager getTelephonyManager() {
-        return (TelephonyManager)
-                TelecomApp.getInstance().getSystemService(Context.TELEPHONY_SERVICE);
-    }
-
-    private void publish() {
-        Log.d(this, "publish: %s", this);
-        ServiceManager.addService(SERVICE_NAME, this);
+        return (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
     }
 
     private MainThreadRequest sendRequestAsync(int command, int arg1) {
@@ -622,4 +606,16 @@
             return request.result;
         }
     }
+
+    @Override
+    protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
+        if (mCallsManager != null) {
+            pw.println("mCallsManager: ");
+            pw.increaseIndent();
+            mCallsManager.dump(pw);
+            pw.decreaseIndent();
+        }
+    }
 }
diff --git a/src/com/android/server/telecom/Timeouts.java b/src/com/android/server/telecom/Timeouts.java
index 4434db4..35f61ae 100644
--- a/src/com/android/server/telecom/Timeouts.java
+++ b/src/com/android/server/telecom/Timeouts.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom;
 
+import android.content.ContentResolver;
 import android.provider.Settings;
 
 /**
@@ -34,13 +35,13 @@
      * Returns the timeout value from Settings or the default value if it hasn't been changed. This
      * method is safe to call from any thread, including the UI thread.
      *
+     * @param contentResolver The content resolved.
      * @param key Settings key to retrieve.
      * @param defaultValue Default value, in milliseconds.
      * @return The timeout value from Settings or the default value if it hasn't been changed.
      */
-    private static long get(String key, long defaultValue) {
-        return Settings.Secure.getLong(
-                TelecomApp.getInstance().getContentResolver(), PREFIX + key, defaultValue);
+    private static long get(ContentResolver contentResolver, String key, long defaultValue) {
+        return Settings.Secure.getLong(contentResolver, PREFIX + key, defaultValue);
     }
 
     /**
@@ -48,7 +49,7 @@
      * to complete. If the query goes beyond this timeout, the incoming call screen is shown to the
      * user.
      */
-    public static long getDirectToVoicemailMillis() {
-        return get("direct_to_voicemail_ms", 500L);
+    public static long getDirectToVoicemailMillis(ContentResolver contentResolver) {
+        return get(contentResolver, "direct_to_voicemail_ms", 500L);
     }
 }
diff --git a/src/com/android/server/telecom/TtyManager.java b/src/com/android/server/telecom/TtyManager.java
index 945da5e..b21f165 100644
--- a/src/com/android/server/telecom/TtyManager.java
+++ b/src/com/android/server/telecom/TtyManager.java
@@ -25,6 +25,8 @@
 import android.provider.Settings;
 import android.telecom.TelecomManager;
 
+// TODO: Needed for move to system service: import com.android.internal.R;
+
 final class TtyManager implements WiredHeadsetManager.Listener {
     private final TtyBroadcastReceiver mReceiver = new TtyBroadcastReceiver();
     private final Context mContext;