Register PhoneAccounts for telephony on startup.

Change-Id: I597a0565696a742540ba7156f17d6b1d188d7eb7
diff --git a/src/com/android/phone/PhoneSearchIndexablesProvider.java b/src/com/android/phone/PhoneSearchIndexablesProvider.java
index 4b2476c..f1dacd9 100644
--- a/src/com/android/phone/PhoneSearchIndexablesProvider.java
+++ b/src/com/android/phone/PhoneSearchIndexablesProvider.java
@@ -75,4 +75,4 @@
         MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS);
         return cursor;
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/services/telephony/AddAccountsReceiver.java b/src/com/android/services/telephony/AddAccountsReceiver.java
index 2e635c7..f106e7d 100644
--- a/src/com/android/services/telephony/AddAccountsReceiver.java
+++ b/src/com/android/services/telephony/AddAccountsReceiver.java
@@ -16,58 +16,17 @@
 
 package com.android.services.telephony;
 
-import com.android.phone.R;
-
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.net.Uri;
-import android.telecomm.PhoneAccount;
-import android.telecomm.PhoneAccountMetadata;
-import android.telecomm.TelecommManager;
 
 public class AddAccountsReceiver extends BroadcastReceiver {
-
-    private static String SCHEME_TEL = "tel";
-
     @Override
     public void onReceive(Context context, Intent intent) {
-        Log.d(this, "onReceive");
-        try {
-            TelecommManager telecommManager = TelecommManager.from(context);
-            telecommManager.clearAccounts(context.getPackageName());
-            PhoneAccountMetadata[] accounts = makeAccounts(context);
-            for (int i = 0; i < accounts.length; i++) {
-                telecommManager.registerPhoneAccount(accounts[i]);
-            }
-        } catch (Exception e) {
-            Log.e(this, e, "onReceive");
-            throw e;
+        String action = intent.getAction();
+        Log.d(this, "onReceive(%s)", action);
+        if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+            TelecommAccountRegistry.getInstance(context).setup();
         }
     }
-
-    public static PhoneAccountMetadata[] makeAccounts(Context context) {
-        ComponentName componentName = new ComponentName(
-                context.getPackageName(),
-                TelephonyConnectionService.class.getName());
-        return new PhoneAccountMetadata[]{
-                new PhoneAccountMetadata(
-                        new PhoneAccount(componentName, "sim_0"),
-                        Uri.fromParts(SCHEME_TEL, "650-555-1212", null),
-                        PhoneAccountMetadata.CAPABILITY_CALL_PROVIDER,
-                        R.drawable.fab_ic_call,
-                        "Zero SIM Account",
-                        "Short description for SIM card zero",
-                        false),
-                new PhoneAccountMetadata(
-                        new PhoneAccount(componentName, "sim_1"),
-                        Uri.fromParts(SCHEME_TEL, "650-555-1234", null),
-                        PhoneAccountMetadata.CAPABILITY_CALL_PROVIDER,
-                        R.drawable.fab_ic_call,
-                        "One SIM Account",
-                        "Short description for SIM card one",
-                        false)
-        };
-    }
 }
diff --git a/src/com/android/services/telephony/PstnIncomingCallNotifier.java b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
index 1ba4a4e..b24758f 100644
--- a/src/com/android/services/telephony/PstnIncomingCallNotifier.java
+++ b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
@@ -17,6 +17,8 @@
 package com.android.services.telephony;
 
 import android.content.BroadcastReceiver;
+
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -24,6 +26,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.UserHandle;
+import android.telecomm.PhoneAccount;
 import android.telecomm.TelecommConstants;
 
 import com.android.internal.telephony.Call;
@@ -156,7 +159,7 @@
         Intent intent = new Intent(TelecommConstants.ACTION_INCOMING_CALL);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.putExtra(TelecommConstants.EXTRA_PHONE_ACCOUNT,
-                AddAccountsReceiver.makeAccounts(context)[0].getAccount());
+                TelecommAccountRegistry.makePstnPhoneAccount(mPhoneProxy));
 
         Log.d(this, "Sending incoming call intent: %s", intent);
         context.startActivityAsUser(intent, UserHandle.CURRENT);
diff --git a/src/com/android/services/telephony/TelecommAccountRegistry.java b/src/com/android/services/telephony/TelecommAccountRegistry.java
new file mode 100644
index 0000000..ac8bb91
--- /dev/null
+++ b/src/com/android/services/telephony/TelecommAccountRegistry.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2014 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.services.telephony;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.Uri;
+import android.telecomm.PhoneAccount;
+import android.telecomm.PhoneAccountMetadata;
+import android.telecomm.TelecommManager;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.PhoneProxy;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Owns all data we have registered with Telecomm including handling dynamic addition and
+ * removal of SIMs and SIP accounts.
+ */
+final class TelecommAccountRegistry {
+    private final class AccountEntry {
+        private final Phone mPhone;
+        private final PhoneAccountMetadata mMetadata;
+        private final PstnIncomingCallNotifier mIncomingCallNotifier;
+
+        AccountEntry(Phone phone, boolean isDummy) {
+            mPhone = phone;
+            mMetadata = registerPstnPhoneAccount(isDummy);
+            mIncomingCallNotifier = new PstnIncomingCallNotifier((PhoneProxy) mPhone);
+        }
+
+        /**
+         * Registers the specified account with Telecomm as a PhoneAccount.
+         */
+        private PhoneAccountMetadata registerPstnPhoneAccount(boolean isDummyAccount) {
+            TelephonyManager telephonyManager = TelephonyManager.from(mContext);
+            String dummyPrefix = isDummyAccount ? "Dummy " : "";
+
+            // Build the Phone account handle.
+            PhoneAccount phoneAccount = isDummyAccount ?
+                    makePstnPhoneAccountWithPrefix(mPhone, dummyPrefix) :
+                    makePstnPhoneAccount(mPhone);
+
+            // Populate the phone account data.
+            long subId = mPhone.getSubId();
+            int slotId = mPhone.getPhoneId() + 1;
+            PhoneAccountMetadata metadata = new PhoneAccountMetadata(
+                    phoneAccount,
+                    Uri.fromParts(TEL_SCHEME, telephonyManager.getLine1Number(subId), null),
+                    PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
+                            PhoneAccountMetadata.CAPABILITY_CALL_PROVIDER,
+                    com.android.phone.R.mipmap.ic_launcher_phone,
+                    dummyPrefix + "SIM " + slotId,
+                    dummyPrefix + "SIM card in slot " + slotId,
+                    true /* supportsVideoCalling */);
+
+            // Register with Telecomm and put into the account entry.
+            mTelecommManager.registerPhoneAccount(metadata);
+            return metadata;
+        }
+    }
+
+    private static final String TEL_SCHEME = "tel";
+    private static TelecommAccountRegistry sInstance;
+    private final Context mContext;
+    private final TelecommManager mTelecommManager;
+    private List<AccountEntry> mAccounts = new LinkedList<AccountEntry>();
+
+    TelecommAccountRegistry(Context context) {
+        mContext = context;
+        mTelecommManager = TelecommManager.from(context);
+    }
+
+    static synchronized final TelecommAccountRegistry getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new TelecommAccountRegistry(context);
+        }
+        return sInstance;
+    }
+
+    /**
+     * Sets up all the phone accounts for SIM and SIP accounts on first boot.
+     */
+    void setup() {
+        // Before we do anything, we need to clear whatever entries we registered at boot.
+        mTelecommManager.clearAccounts(mContext.getPackageName());
+
+        // Go through SIM-based phones and register ourselves
+        Phone[] phones = PhoneFactory.getPhones();
+        Log.d(this, "Found %d phones.  Attempting to register.", phones.length);
+        for (Phone phone : phones) {
+            long subscriptionId = phone.getSubId();
+            Log.d(this, "Phone with subscription id %d", subscriptionId);
+            if (subscriptionId >= 0) {
+                mAccounts.add(new AccountEntry(phone, false /* isDummy */));
+            }
+        }
+
+        // Add a fake account entry.
+        if (phones.length > 0 && "TRUE".equals(System.getProperty("dummy_sim"))) {
+            mAccounts.add(new AccountEntry(phones[0], true /* isDummy */));
+        }
+
+        // TODO: Add SIP accounts.
+    }
+
+    static PhoneAccount makePstnPhoneAccount(Phone phone) {
+        return makePstnPhoneAccountWithPrefix(phone, "");
+    }
+
+    private static PhoneAccount makePstnPhoneAccountWithPrefix(Phone phone, String prefix) {
+        ComponentName pstnConnectionServiceName =
+                new ComponentName(phone.getContext(), TelephonyConnectionService.class);
+        return new PhoneAccount(
+                pstnConnectionServiceName, prefix + String.valueOf(phone.getSubId()));
+    }
+}
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index bf2e3a0..0572d49 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -17,27 +17,26 @@
 package com.android.services.telephony;
 
 import android.content.ComponentName;
-import android.content.Context;
 import android.net.Uri;
-import android.os.Debug;
-import android.telecomm.PhoneAccountMetadata;
-import android.telecomm.TelecommManager;
-import android.telephony.DisconnectCause;
-import android.telephony.ServiceState;
-import android.text.TextUtils;
 import android.telecomm.CallCapabilities;
 import android.telecomm.Connection;
 import android.telecomm.ConnectionRequest;
 import android.telecomm.ConnectionService;
 import android.telecomm.PhoneAccount;
 import android.telecomm.Response;
+import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
+import android.text.TextUtils;
 
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.SubscriptionController;
+
+import java.util.Objects;
 
 /**
  * Service for making GSM and CDMA connections.
@@ -45,9 +44,16 @@
 public class TelephonyConnectionService extends ConnectionService {
     private static String SCHEME_TEL = "tel";
 
+    private ComponentName mExpectedComponentName = null;
     private EmergencyCallHelper mEmergencyCallHelper;
 
     @Override
+    public void onCreate() {
+        super.onCreate();
+        mExpectedComponentName = new ComponentName(this, this.getClass());
+    }
+
+    @Override
     protected void onCreateOutgoingConnection(
             final ConnectionRequest request,
             final CreateConnectionResponse<Connection> response) {
@@ -75,7 +81,8 @@
             return;
         }
 
-        final Phone phone = PhoneFactory.getDefaultPhone();
+        // Get the right phone object from the account data passed in.
+        final Phone phone = getPhoneForAccount(request.getAccount());
         if (phone == null) {
             Log.d(this, "onCreateOutgoingConnection, phone is null");
             response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, "Phone is null");
@@ -153,7 +160,12 @@
             CreateConnectionResponse<Connection> response) {
         Log.v(this, "onCreateIncomingConnection, request: " + request);
 
-        Phone phone = PhoneFactory.getDefaultPhone();
+        Phone phone = getPhoneForAccount(request.getAccount());
+        if (phone == null) {
+            response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, null);
+            return;
+        }
+
         Call call = phone.getRingingCall();
         if (!call.getState().isRinging()) {
             Log.v(this, "onCreateIncomingConnection, no ringing call");
@@ -261,6 +273,15 @@
         return false;
     }
 
+    private Phone getPhoneForAccount(PhoneAccount account) {
+        if (Objects.equals(mExpectedComponentName, account.getComponentName())) {
+            int phoneId = SubscriptionController.getInstance().getPhoneId(
+                    Long.parseLong(account.getId()));
+            return PhoneFactory.getPhone(phoneId);
+        }
+        return null;
+    }
+
     static Uri getHandleFromAddress(String address) {
         // Address can be null for blocked calls.
         if (address == null) {
diff --git a/src/com/android/services/telephony/TelephonyGlobals.java b/src/com/android/services/telephony/TelephonyGlobals.java
index daf370b..daeece6 100644
--- a/src/com/android/services/telephony/TelephonyGlobals.java
+++ b/src/com/android/services/telephony/TelephonyGlobals.java
@@ -32,12 +32,11 @@
  * {@link #onCreate}.
  */
 public class TelephonyGlobals {
+    private static TelephonyGlobals sInstance;
+
     /** The application context. */
     private final Context mContext;
 
-    /** Handles incoming calls for PSTN calls. */
-    private PstnIncomingCallNotifier mPtsnIncomingCallNotifier;
-
     private TtyManager mTtyManager;
 
     /**
@@ -49,23 +48,18 @@
         mContext = context.getApplicationContext();
     }
 
-    public void onCreate() {
-        setupIncomingCallNotifiers();
+    public static synchronized TelephonyGlobals getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new TelephonyGlobals(context);
+        }
+        return sInstance;
+    }
 
+    public void onCreate() {
+        // TODO: Make this work with Multi-SIM devices
         Phone phone = PhoneFactory.getDefaultPhone();
         if (phone != null) {
             mTtyManager = new TtyManager(mContext, phone);
         }
     }
-
-    /**
-     * Sets up incoming call notifiers for all the connection services.
-     */
-    private void setupIncomingCallNotifiers() {
-        PhoneProxy defaultPhone = (PhoneProxy) PhoneFactory.getDefaultPhone();
-        Log.i(this, "Default phone: %s.", defaultPhone);
-
-        Log.i(this, "Registering the PSTN listener.");
-        mPtsnIncomingCallNotifier = new PstnIncomingCallNotifier(defaultPhone);
-    }
 }