Fix initialization of SIM accounts.
- Moves setup out of a broadcast receiver and into TelephonyGlobals
- Reruns setup whenever the SIM state changes (hotswap support)
- When no SIM is inserted, register an emergency-only PhoneAccount.
Bug: 16491446
Bug: 16445149
Bug: 16495971
Change-Id: Icee8013c35f7439c58af7b7777af9a99798bff43
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index cdc6a4c..da9da33 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -585,13 +585,5 @@
<action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" />
</intent-filter>
</provider>
-
- <receiver android:name="com.android.services.telephony.AddAccountsReceiver"
- android:singleUser="true" >
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </receiver>
</application>
</manifest>
diff --git a/src/com/android/services/telephony/AddAccountsReceiver.java b/src/com/android/services/telephony/AddAccountsReceiver.java
deleted file mode 100644
index f106e7d..0000000
--- a/src/com/android/services/telephony/AddAccountsReceiver.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-public class AddAccountsReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- Log.d(this, "onReceive(%s)", action);
- if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
- TelecommAccountRegistry.getInstance(context).setup();
- }
- }
-}
diff --git a/src/com/android/services/telephony/PstnIncomingCallNotifier.java b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
index edf1b2b..183cbb0 100644
--- a/src/com/android/services/telephony/PstnIncomingCallNotifier.java
+++ b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
@@ -103,6 +103,11 @@
mPhoneProxy.getContext().registerReceiver(mRATReceiver, intentFilter);
}
+ void teardown() {
+ unregisterForNotifications();
+ mPhoneProxy.getContext().unregisterReceiver(mRATReceiver);
+ }
+
/**
* Register for notifications from the base phone.
* TODO(santoscordon): We should only need to interact with the phoneproxy directly. However,
@@ -130,6 +135,12 @@
}
}
+ private void unregisterForNotifications() {
+ if (mPhoneBase != null) {
+ mPhoneBase.unregisterForNewRingingConnection(mHandler);
+ }
+ }
+
/**
* Verifies the incoming call and triggers sending the incoming-call intent to Telecomm.
*
diff --git a/src/com/android/services/telephony/TelecommAccountRegistry.java b/src/com/android/services/telephony/TelecommAccountRegistry.java
index cef546d..78aa057 100644
--- a/src/com/android/services/telephony/TelecommAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecommAccountRegistry.java
@@ -16,8 +16,11 @@
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;
import android.net.Uri;
import android.telecomm.PhoneAccount;
import android.telecomm.PhoneAccountHandle;
@@ -27,6 +30,7 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.TelephonyIntents;
import java.util.LinkedList;
import java.util.List;
@@ -36,30 +40,36 @@
* removal of SIMs and SIP accounts.
*/
final class TelecommAccountRegistry {
+
private final class AccountEntry {
private final Phone mPhone;
private final PhoneAccount mAccount;
private final PstnIncomingCallNotifier mIncomingCallNotifier;
- AccountEntry(Phone phone, boolean isDummy) {
+ AccountEntry(Phone phone, boolean isEmergency, boolean isDummy) {
mPhone = phone;
- mAccount = registerPstnPhoneAccount(isDummy);
+ mAccount = registerPstnPhoneAccount(isEmergency, isDummy);
Log.d(this, "Registered phoneAccount: %s with handle: %s",
mAccount, mAccount.getAccountHandle());
mIncomingCallNotifier = new PstnIncomingCallNotifier((PhoneProxy) mPhone);
}
+ void teardown() {
+ mTelecommManager.unregisterPhoneAccount(mAccount.getAccountHandle());
+ mIncomingCallNotifier.teardown();
+ }
+
/**
* Registers the specified account with Telecomm as a PhoneAccountHandle.
*/
- private PhoneAccount registerPstnPhoneAccount(boolean isDummyAccount) {
+ private PhoneAccount registerPstnPhoneAccount(
+ boolean isEmergency, boolean isDummyAccount) {
TelephonyManager telephonyManager = TelephonyManager.from(mContext);
String dummyPrefix = isDummyAccount ? "Dummy " : "";
// Build the Phone account handle.
- PhoneAccountHandle phoneAccountHandle = isDummyAccount ?
- makePstnPhoneAccountHandleWithPrefix(mPhone, dummyPrefix) :
- makePstnPhoneAccountHandle(mPhone);
+ PhoneAccountHandle phoneAccountHandle =
+ makePstnPhoneAccountHandleWithPrefix(mPhone, dummyPrefix, isEmergency);
// Populate the phone account data.
long subId = mPhone.getSubId();
@@ -68,15 +78,22 @@
if (line1Number == null) {
line1Number = "";
}
+ String subNumber = isEmergency ? "" : mPhone.getPhoneSubInfo().getLine1Number();
+ String label = isEmergency
+ ? "Emergency calls"
+ : dummyPrefix + "SIM " + slotId;
+ String description = isEmergency
+ ? "Emergency calling only"
+ : dummyPrefix + "SIM card in slot " + slotId;
PhoneAccount account = new PhoneAccount(
phoneAccountHandle,
Uri.fromParts(TEL_SCHEME, line1Number, null),
- mPhone.getPhoneSubInfo().getLine1Number(),
+ subNumber,
PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
PhoneAccount.CAPABILITY_CALL_PROVIDER,
com.android.phone.R.mipmap.ic_launcher_phone,
- dummyPrefix + "SIM " + slotId,
- dummyPrefix + "SIM card in slot " + slotId,
+ label,
+ description,
true /* supportsVideoCalling */);
// Register with Telecomm and put into the account entry.
@@ -85,6 +102,19 @@
}
}
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
+ Log.d(this, "SIM_STATE_CHANGED - rerun setup");
+ // Anytime the SIM state changes...rerun the setup.
+ tearDownAccounts();
+ setupAccounts();
+ }
+ }
+ };
+
private static final String TEL_SCHEME = "tel";
private static TelecommAccountRegistry sInstance;
private final Context mContext;
@@ -106,9 +136,29 @@
/**
* Sets up all the phone accounts for SIM and SIP accounts on first boot.
*/
- void setup() {
- // Initialize the PhoneFactory, since the PhoneApp may not yet have been set up
- PhoneFactory.makeDefaultPhones(mContext);
+ void setupOnBoot() {
+ IntentFilter intentFilter =
+ new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ mContext.registerReceiver(mReceiver, intentFilter);
+
+ setupAccounts();
+ }
+
+ static PhoneAccountHandle makePstnPhoneAccountHandle(Phone phone) {
+ return makePstnPhoneAccountHandleWithPrefix(phone, "", false);
+ }
+
+ private static PhoneAccountHandle makePstnPhoneAccountHandleWithPrefix(
+ Phone phone, String prefix, boolean isEmergency) {
+ ComponentName pstnConnectionServiceName =
+ new ComponentName(phone.getContext(), TelephonyConnectionService.class);
+ // TODO: Should use some sort of special hidden flag to decorate this account as
+ // an emergency-only account
+ String id = isEmergency ? "E" : prefix + String.valueOf(phone.getSubId());
+ return new PhoneAccountHandle(pstnConnectionServiceName, id);
+ }
+
+ private void setupAccounts() {
// Before we do anything, we need to clear whatever entries we registered at boot.
mTelecommManager.clearAccounts(mContext.getPackageName());
@@ -119,27 +169,30 @@
long subscriptionId = phone.getSubId();
Log.d(this, "Phone with subscription id %d", subscriptionId);
if (subscriptionId >= 0) {
- mAccounts.add(new AccountEntry(phone, false /* isDummy */));
+ mAccounts.add(new AccountEntry(phone, false, false /* isDummy */));
}
}
+ // If we did not list ANY accounts, we need to provide a "default" SIM account
+ // for emergency numbers since no actual SIM is needed for dialing emergency
+ // numbers but a phone account is.
+ if (mAccounts.isEmpty()) {
+ mAccounts.add(new AccountEntry(
+ PhoneFactory.getDefaultPhone(), true /*emergency*/, 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 */));
+ mAccounts.add(new AccountEntry(phones[0], false, true /* isDummy */));
}
// TODO: Add SIP accounts.
}
- static PhoneAccountHandle makePstnPhoneAccountHandle(Phone phone) {
- return makePstnPhoneAccountHandleWithPrefix(phone, "");
- }
-
- private static PhoneAccountHandle makePstnPhoneAccountHandleWithPrefix(
- Phone phone, String prefix) {
- ComponentName pstnConnectionServiceName =
- new ComponentName(phone.getContext(), TelephonyConnectionService.class);
- return new PhoneAccountHandle(
- pstnConnectionServiceName, prefix + String.valueOf(phone.getSubId()));
+ private void tearDownAccounts() {
+ for (AccountEntry entry : mAccounts) {
+ entry.teardown();
+ }
+ mAccounts.clear();
}
}
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 00fc362..513692f 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -33,7 +33,6 @@
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Phone;
-
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SubscriptionController;
@@ -83,15 +82,16 @@
return;
}
+ boolean isEmergencyNumber = PhoneNumberUtils.isPotentialEmergencyNumber(number);
+
// Get the right phone object from the account data passed in.
- final Phone phone = getPhoneForAccount(request.getAccountHandle());
+ final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber);
if (phone == null) {
Log.d(this, "onCreateOutgoingConnection, phone is null");
response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, "Phone is null");
return;
}
- boolean isEmergencyNumber = PhoneNumberUtils.isPotentialEmergencyNumber(number);
if (!isEmergencyNumber) {
int state = phone.getServiceState().getState();
switch (state) {
@@ -162,7 +162,7 @@
CreateConnectionResponse<Connection> response) {
Log.v(this, "onCreateIncomingConnection, request: " + request);
- Phone phone = getPhoneForAccount(request.getAccountHandle());
+ Phone phone = getPhoneForAccount(request.getAccountHandle(), false);
if (phone == null) {
response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, null);
return;
@@ -261,12 +261,20 @@
return false;
}
- private Phone getPhoneForAccount(PhoneAccountHandle accountHandle) {
+ private Phone getPhoneForAccount(PhoneAccountHandle accountHandle, boolean isEmergency) {
+ if (isEmergency) {
+ return PhoneFactory.getDefaultPhone();
+ }
+
if (Objects.equals(mExpectedComponentName, accountHandle.getComponentName())) {
if (accountHandle.getId() != null) {
- int phoneId = SubscriptionController.getInstance().getPhoneId(
- Long.parseLong(accountHandle.getId()));
- return PhoneFactory.getPhone(phoneId);
+ try {
+ int phoneId = SubscriptionController.getInstance().getPhoneId(
+ Long.parseLong(accountHandle.getId()));
+ return PhoneFactory.getPhone(phoneId);
+ } catch (NumberFormatException e) {
+ Log.w(this, "Could not get subId from account: " + accountHandle.getId());
+ }
}
}
return null;
diff --git a/src/com/android/services/telephony/TelephonyGlobals.java b/src/com/android/services/telephony/TelephonyGlobals.java
index daeece6..70b287d 100644
--- a/src/com/android/services/telephony/TelephonyGlobals.java
+++ b/src/com/android/services/telephony/TelephonyGlobals.java
@@ -61,5 +61,7 @@
if (phone != null) {
mTtyManager = new TtyManager(mContext, phone);
}
+
+ TelecommAccountRegistry.getInstance(mContext).setupOnBoot();
}
}