Merge "Change subId to int from long" into lmp-mr1-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e7a7781..88e90ae 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -38,13 +38,6 @@
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.BROADCAST_CALLLOG_INFO" />
- <!-- Protects the ability to register any PhoneAccount with a capability flags of either
- PhoneAccount#CAPABILITY_CALL_PROVIDER or PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. -->
- <permission
- android:name="com.android.server.telecom.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION"
- android:label="Register CALL_PROVIDER or SIM_SUBSCRIPTION PhoneAccount"
- android:protectionLevel="signature"/>
-
<permission
android:name="android.permission.BROADCAST_CALLLOG_INFO"
android:label="Broadcast the call type/duration information"
diff --git a/src/com/android/server/telecom/BluetoothPhoneService.java b/src/com/android/server/telecom/BluetoothPhoneService.java
index 51dbbdf..8bf50ae 100644
--- a/src/com/android/server/telecom/BluetoothPhoneService.java
+++ b/src/com/android/server/telecom/BluetoothPhoneService.java
@@ -329,16 +329,63 @@
@Override
public void onCallStateChanged(Call call, int oldState, int newState) {
+ // If a call is being put on hold because of a new connecting call, ignore the
+ // CONNECTING since the BT state update needs to send out the numHeld = 1 + dialing
+ // state atomically.
+ // When the call later transitions to DIALING/DISCONNECTED we will then send out the
+ // aggregated update.
+ if (oldState == CallState.ACTIVE && newState == CallState.ON_HOLD) {
+ for (Call otherCall : CallsManager.getInstance().getCalls()) {
+ if (otherCall.getState() == CallState.CONNECTING) {
+ return;
+ }
+ }
+ }
+
+ // To have an active call and another dialing at the same time is an invalid BT
+ // state. We can assume that the active call will be automatically held which will
+ // send another update at which point we will be in the right state.
+ if (CallsManager.getInstance().getActiveCall() != null
+ && oldState == CallState.CONNECTING && newState == CallState.DIALING) {
+ return;
+ }
updateHeadsetWithCallState(false /* force */);
}
@Override
public void onForegroundCallChanged(Call oldForegroundCall, Call newForegroundCall) {
- updateHeadsetWithCallState(false /* force */);
+ // The BluetoothPhoneService does not need to respond to changes in foreground calls,
+ // which are always accompanied by call state changes anyway.
}
@Override
public void onIsConferencedChanged(Call call) {
+ /*
+ * Filter certain onIsConferencedChanged callbacks. Unfortunately this needs to be done
+ * because conference change events are not atomic and multiple callbacks get fired
+ * when two calls are conferenced together. This confuses updateHeadsetWithCallState
+ * if it runs in the middle of two calls being conferenced and can cause spurious and
+ * incorrect headset state updates. One of the scenarios is described below for CDMA
+ * conference calls.
+ *
+ * 1) Call 1 and Call 2 are being merged into conference Call 3.
+ * 2) Call 1 has its parent set to Call 3, but Call 2 does not have a parent yet.
+ * 3) updateHeadsetWithCallState now thinks that there are two active calls (Call 2 and
+ * Call 3) when there is actually only one active call (Call 3).
+ */
+ if (call.getParentCall() != null) {
+ // If this call is newly conferenced, ignore the callback. We only care about the
+ // one sent for the parent conference call.
+ Log.d(this, "Ignoring onIsConferenceChanged from child call with new parent");
+ return;
+ }
+ if (call.getChildCalls().size() == 1) {
+ // If this is a parent call with only one child, ignore the callback as well since
+ // the minimum number of child calls to start a conference call is 2. We expect
+ // this to be called again when the parent call has another child call added.
+ Log.d(this, "Ignoring onIsConferenceChanged from parent with only one child call");
+ return;
+ }
updateHeadsetWithCallState(false /* force */);
}
};
@@ -649,6 +696,7 @@
// For conference calls which support swapping the active call within the conference
// (namely CDMA calls) we need to expose that as a held call in order for the BT device
// to show "swap" and "merge" functionality.
+ boolean ignoreHeldCallChange = false;
if (activeCall != null && activeCall.isConference()) {
if (activeCall.can(PhoneCapabilities.SWAP_CONFERENCE)) {
// Indicate that BT device should show SWAP command by indicating that there is a
@@ -657,6 +705,16 @@
} else if (activeCall.can(PhoneCapabilities.MERGE_CONFERENCE)) {
numHeldCalls = 1; // Merge is available, so expose via numHeldCalls.
}
+
+ for (Call childCall : activeCall.getChildCalls()) {
+ // Held call has changed due to it being combined into a CDMA conference. Keep
+ // track of this and ignore any future update since it doesn't really count as
+ // a call change.
+ if (mOldHeldCall == childCall) {
+ ignoreHeldCallChange = true;
+ break;
+ }
+ }
}
if (mBluetoothHeadset != null &&
@@ -665,7 +723,7 @@
bluetoothCallState != mBluetoothCallState ||
!TextUtils.equals(ringingAddress, mRingingAddress) ||
ringingAddressType != mRingingAddressType ||
- heldCall != mOldHeldCall ||
+ (heldCall != mOldHeldCall && !ignoreHeldCallChange) ||
force)) {
// If the call is transitioning into the alerting state, send DIALING first.
@@ -682,7 +740,18 @@
mRingingAddressType = ringingAddressType;
if (sendDialingFirst) {
- Log.i(TAG, "Sending dialing state");
+ // Log in full to make logs easier to debug.
+ Log.i(TAG, "updateHeadsetWithCallState " +
+ "numActive %s, " +
+ "numHeld %s, " +
+ "callState %s, " +
+ "ringing number %s, " +
+ "ringing type %s",
+ mNumActiveCalls,
+ mNumHeldCalls,
+ CALL_STATE_DIALING,
+ Log.pii(mRingingAddress),
+ mRingingAddressType);
mBluetoothHeadset.phoneStateChanged(
mNumActiveCalls,
mNumHeldCalls,
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index eb6b745..3b6192a 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -29,6 +29,7 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionManager;
import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
@@ -206,6 +207,14 @@
return;
}
+ if (getPhoneAccount(accountHandle).hasCapabilities(
+ PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
+ // If the account selected is a SIM account, propagate down to the subscription
+ // record.
+ long subId = getSubscriptionIdForPhoneAccount(accountHandle);
+ SubscriptionManager.setDefaultVoiceSubId(subId);
+ }
+
mState.defaultOutgoing = accountHandle;
}
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 5df44c4..95a7e75 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -51,7 +51,9 @@
*/
public class TelecomServiceImpl extends ITelecomService.Stub {
private static final String REGISTER_PROVIDER_OR_SUBSCRIPTION =
- "com.android.server.telecom.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION";
+ android.Manifest.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION;
+ private static final String REGISTER_CONNECTION_MANAGER =
+ android.Manifest.permission.REGISTER_CONNECTION_MANAGER;
/** The context. */
private Context mContext;
@@ -305,6 +307,9 @@
account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
enforceRegisterProviderOrSubscriptionPermission();
}
+ if (account.hasCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)) {
+ enforceRegisterConnectionManagerPermission();
+ }
mPhoneAccountRegistrar.registerPhoneAccount(account);
} catch (Exception e) {
@@ -596,6 +601,10 @@
enforcePermission(REGISTER_PROVIDER_OR_SUBSCRIPTION);
}
+ private void enforceRegisterConnectionManagerPermission() {
+ enforcePermission(REGISTER_CONNECTION_MANAGER);
+ }
+
private void enforceReadPermission() {
enforcePermission(Manifest.permission.READ_PHONE_STATE);
}