Merge changes I02fb643b,If62d66bc into udc-dev
* changes: Sync facilitators on transport ready Small context sync telecom bugfixes
This commit is contained in:
committed by
Android (Google) Code Review
commit
b9de8fb70d
@@ -42,6 +42,9 @@ message Telecom {
|
|||||||
ONGOING = 2;
|
ONGOING = 2;
|
||||||
ON_HOLD = 3;
|
ON_HOLD = 3;
|
||||||
RINGING_SILENCED = 4;
|
RINGING_SILENCED = 4;
|
||||||
|
AUDIO_PROCESSING = 5;
|
||||||
|
RINGING_SIMULATED = 6;
|
||||||
|
DISCONNECTED = 7;
|
||||||
}
|
}
|
||||||
Status status = 3;
|
Status status = 3;
|
||||||
|
|
||||||
@@ -89,8 +92,6 @@ message Telecom {
|
|||||||
END = 6;
|
END = 6;
|
||||||
PUT_ON_HOLD = 7;
|
PUT_ON_HOLD = 7;
|
||||||
TAKE_OFF_HOLD = 8;
|
TAKE_OFF_HOLD = 8;
|
||||||
REJECT_AND_BLOCK = 9;
|
|
||||||
IGNORE = 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The list of active calls.
|
// The list of active calls.
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.companion;
|
package com.android.server.companion;
|
||||||
|
|
||||||
|
import android.os.Binder;
|
||||||
import android.provider.DeviceConfig;
|
import android.provider.DeviceConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +35,12 @@ public class CompanionDeviceConfig {
|
|||||||
* Returns whether the given flag is currently enabled, with a default value of {@code false}.
|
* Returns whether the given flag is currently enabled, with a default value of {@code false}.
|
||||||
*/
|
*/
|
||||||
public static boolean isEnabled(String flag) {
|
public static boolean isEnabled(String flag) {
|
||||||
|
final long token = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
return DeviceConfig.getBoolean(NAMESPACE_COMPANION, flag, /* defaultValue= */ false);
|
return DeviceConfig.getBoolean(NAMESPACE_COMPANION, flag, /* defaultValue= */ false);
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1383,10 +1383,11 @@ public class CompanionDeviceManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerCallMetadataSyncCallback(CrossDeviceSyncControllerCallback callback) {
|
public void registerCallMetadataSyncCallback(CrossDeviceSyncControllerCallback callback,
|
||||||
|
@CrossDeviceSyncControllerCallback.Type int type) {
|
||||||
if (CompanionDeviceConfig.isEnabled(
|
if (CompanionDeviceConfig.isEnabled(
|
||||||
CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
|
CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
|
||||||
mCrossDeviceSyncController.registerCallMetadataSyncCallback(callback);
|
mCrossDeviceSyncController.registerCallMetadataSyncCallback(callback, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ public interface CompanionDeviceManagerServiceInternal {
|
|||||||
* Registers a callback from an InCallService / ConnectionService to CDM to process sync
|
* Registers a callback from an InCallService / ConnectionService to CDM to process sync
|
||||||
* requests and perform call control actions.
|
* requests and perform call control actions.
|
||||||
*/
|
*/
|
||||||
void registerCallMetadataSyncCallback(CrossDeviceSyncControllerCallback callback);
|
void registerCallMetadataSyncCallback(CrossDeviceSyncControllerCallback callback,
|
||||||
|
@CrossDeviceSyncControllerCallback.Type int type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests a sync from an InCallService / ConnectionService to CDM, for the given association
|
* Requests a sync from an InCallService / ConnectionService to CDM, for the given association
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.server.companion.datatransfer.contextsync;
|
package com.android.server.companion.datatransfer.contextsync;
|
||||||
|
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.telecom.Call;
|
import android.telecom.Call;
|
||||||
import android.telecom.Connection;
|
import android.telecom.Connection;
|
||||||
@@ -62,20 +63,14 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
final CallMetadataSyncConnection existingConnection =
|
final CallMetadataSyncConnection existingConnection =
|
||||||
mActiveConnections.get(new CallMetadataSyncConnectionIdentifier(
|
mActiveConnections.get(new CallMetadataSyncConnectionIdentifier(
|
||||||
associationId, call.getId()));
|
associationId, call.getId()));
|
||||||
if (existingConnection == null) {
|
if (existingConnection != null) {
|
||||||
final Bundle extras = new Bundle();
|
|
||||||
extras.putInt(CrossDeviceSyncController.EXTRA_ASSOCIATION_ID,
|
|
||||||
associationId);
|
|
||||||
extras.putParcelable(CrossDeviceSyncController.EXTRA_CALL, call);
|
|
||||||
mTelecomManager.addNewIncomingCall(call.getPhoneAccountHandle(),
|
|
||||||
extras);
|
|
||||||
} else {
|
|
||||||
existingConnection.update(call);
|
existingConnection.update(call);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove obsolete calls.
|
// Remove obsolete calls.
|
||||||
mActiveConnections.values().removeIf(connection -> {
|
mActiveConnections.values().removeIf(connection -> {
|
||||||
if (!callMetadataSyncData.hasCall(connection.getCallId())) {
|
if (associationId == connection.getAssociationId()
|
||||||
|
&& !callMetadataSyncData.hasCall(connection.getCallId())) {
|
||||||
connection.setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
|
connection.setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -91,7 +86,8 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
mAudioManager = getSystemService(AudioManager.class);
|
mAudioManager = getSystemService(AudioManager.class);
|
||||||
mTelecomManager = getSystemService(TelecomManager.class);
|
mTelecomManager = getSystemService(TelecomManager.class);
|
||||||
mCdmsi = LocalServices.getService(CompanionDeviceManagerServiceInternal.class);
|
mCdmsi = LocalServices.getService(CompanionDeviceManagerServiceInternal.class);
|
||||||
mCdmsi.registerCallMetadataSyncCallback(mCrossDeviceSyncControllerCallback);
|
mCdmsi.registerCallMetadataSyncCallback(mCrossDeviceSyncControllerCallback,
|
||||||
|
CrossDeviceSyncControllerCallback.TYPE_CONNECTION_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -101,6 +97,11 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
CrossDeviceSyncController.EXTRA_ASSOCIATION_ID);
|
CrossDeviceSyncController.EXTRA_ASSOCIATION_ID);
|
||||||
final CallMetadataSyncData.Call call = connectionRequest.getExtras().getParcelable(
|
final CallMetadataSyncData.Call call = connectionRequest.getExtras().getParcelable(
|
||||||
CrossDeviceSyncController.EXTRA_CALL, CallMetadataSyncData.Call.class);
|
CrossDeviceSyncController.EXTRA_CALL, CallMetadataSyncData.Call.class);
|
||||||
|
// InCallServices outside of framework (like Dialer's) might try to read this, and crash
|
||||||
|
// when they can't. Remove it once we're done with it, as well as the other internal ones.
|
||||||
|
connectionRequest.getExtras().remove(CrossDeviceSyncController.EXTRA_CALL);
|
||||||
|
connectionRequest.getExtras().remove(CrossDeviceSyncController.EXTRA_CALL_FACILITATOR_ID);
|
||||||
|
connectionRequest.getExtras().remove(CrossDeviceSyncController.EXTRA_ASSOCIATION_ID);
|
||||||
final CallMetadataSyncConnection connection = new CallMetadataSyncConnection(
|
final CallMetadataSyncConnection connection = new CallMetadataSyncConnection(
|
||||||
mTelecomManager,
|
mTelecomManager,
|
||||||
mAudioManager,
|
mAudioManager,
|
||||||
@@ -113,15 +114,17 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
CrossDeviceSyncController.createCallControlMessage(callId, action));
|
CrossDeviceSyncController.createCallControlMessage(callId, action));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connection.setConnectionProperties(
|
connection.setConnectionProperties(Connection.PROPERTY_IS_EXTERNAL_CALL);
|
||||||
Connection.PROPERTY_IS_EXTERNAL_CALL | Connection.PROPERTY_SELF_MANAGED);
|
connection.setInitializing();
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateIncomingConnectionFailed(PhoneAccountHandle phoneAccountHandle,
|
public void onCreateIncomingConnectionFailed(PhoneAccountHandle phoneAccountHandle,
|
||||||
ConnectionRequest connectionRequest) {
|
ConnectionRequest connectionRequest) {
|
||||||
Slog.e(TAG, "onCreateIncomingConnectionFailed for: " + phoneAccountHandle.getId());
|
final String id =
|
||||||
|
phoneAccountHandle != null ? phoneAccountHandle.getId() : "unknown PhoneAccount";
|
||||||
|
Slog.e(TAG, "onCreateOutgoingConnectionFailed for: " + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -132,7 +135,6 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
final CallMetadataSyncData.Call call = new CallMetadataSyncData.Call();
|
final CallMetadataSyncData.Call call = new CallMetadataSyncData.Call();
|
||||||
call.setId(UUID.randomUUID().toString());
|
call.setId(UUID.randomUUID().toString());
|
||||||
call.setStatus(android.companion.Telecom.Call.UNKNOWN_STATUS);
|
call.setStatus(android.companion.Telecom.Call.UNKNOWN_STATUS);
|
||||||
call.setPhoneAccountHandle(phoneAccountHandle);
|
|
||||||
final CallMetadataSyncData.CallFacilitator callFacilitator =
|
final CallMetadataSyncData.CallFacilitator callFacilitator =
|
||||||
new CallMetadataSyncData.CallFacilitator(phoneAccount.getLabel().toString(),
|
new CallMetadataSyncData.CallFacilitator(phoneAccount.getLabel().toString(),
|
||||||
phoneAccount.getExtras().getString(
|
phoneAccount.getExtras().getString(
|
||||||
@@ -142,6 +144,10 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
final int associationId = connectionRequest.getExtras().getInt(
|
final int associationId = connectionRequest.getExtras().getInt(
|
||||||
CrossDeviceSyncController.EXTRA_ASSOCIATION_ID);
|
CrossDeviceSyncController.EXTRA_ASSOCIATION_ID);
|
||||||
|
|
||||||
|
connectionRequest.getExtras().remove(CrossDeviceSyncController.EXTRA_CALL);
|
||||||
|
connectionRequest.getExtras().remove(CrossDeviceSyncController.EXTRA_CALL_FACILITATOR_ID);
|
||||||
|
connectionRequest.getExtras().remove(CrossDeviceSyncController.EXTRA_ASSOCIATION_ID);
|
||||||
|
|
||||||
final CallMetadataSyncConnection connection = new CallMetadataSyncConnection(
|
final CallMetadataSyncConnection connection = new CallMetadataSyncConnection(
|
||||||
mTelecomManager,
|
mTelecomManager,
|
||||||
mAudioManager,
|
mAudioManager,
|
||||||
@@ -154,8 +160,7 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
CrossDeviceSyncController.createCallControlMessage(callId, action));
|
CrossDeviceSyncController.createCallControlMessage(callId, action));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connection.setConnectionProperties(
|
connection.setConnectionProperties(Connection.PROPERTY_IS_EXTERNAL_CALL);
|
||||||
Connection.PROPERTY_IS_EXTERNAL_CALL | Connection.PROPERTY_SELF_MANAGED);
|
|
||||||
|
|
||||||
mCdmsi.sendCrossDeviceSyncMessage(associationId,
|
mCdmsi.sendCrossDeviceSyncMessage(associationId,
|
||||||
CrossDeviceSyncController.createCallCreateMessage(call.getId(),
|
CrossDeviceSyncController.createCallCreateMessage(call.getId(),
|
||||||
@@ -168,13 +173,21 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreateOutgoingConnectionFailed(PhoneAccountHandle phoneAccountHandle,
|
public void onCreateOutgoingConnectionFailed(PhoneAccountHandle phoneAccountHandle,
|
||||||
ConnectionRequest connectionRequest) {
|
ConnectionRequest connectionRequest) {
|
||||||
Slog.e(TAG, "onCreateIncomingConnectionFailed for: " + phoneAccountHandle.getId());
|
final String id =
|
||||||
|
phoneAccountHandle != null ? phoneAccountHandle.getId() : "unknown PhoneAccount";
|
||||||
|
Slog.e(TAG, "onCreateOutgoingConnectionFailed for: " + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateConnectionComplete(Connection connection) {
|
public void onCreateConnectionComplete(Connection connection) {
|
||||||
if (connection instanceof CallMetadataSyncConnection) {
|
if (connection instanceof CallMetadataSyncConnection) {
|
||||||
((CallMetadataSyncConnection) connection).initialize();
|
final CallMetadataSyncConnection callMetadataSyncConnection =
|
||||||
|
(CallMetadataSyncConnection) connection;
|
||||||
|
callMetadataSyncConnection.initialize();
|
||||||
|
mActiveConnections.put(new CallMetadataSyncConnectionIdentifier(
|
||||||
|
callMetadataSyncConnection.getAssociationId(),
|
||||||
|
callMetadataSyncConnection.getCallId()),
|
||||||
|
callMetadataSyncConnection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +255,11 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
return mCall.getId();
|
return mCall.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public int getAssociationId() {
|
||||||
|
return mAssociationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize() {
|
||||||
final int status = mCall.getStatus();
|
final int status = mCall.getStatus();
|
||||||
if (status == android.companion.Telecom.Call.RINGING_SILENCED) {
|
if (status == android.companion.Telecom.Call.RINGING_SILENCED) {
|
||||||
mTelecomManager.silenceRinger();
|
mTelecomManager.silenceRinger();
|
||||||
@@ -254,12 +271,21 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
setActive();
|
setActive();
|
||||||
} else if (state == Call.STATE_HOLDING) {
|
} else if (state == Call.STATE_HOLDING) {
|
||||||
setOnHold();
|
setOnHold();
|
||||||
|
} else if (state == Call.STATE_DISCONNECTED) {
|
||||||
|
setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
|
||||||
} else {
|
} else {
|
||||||
Slog.e(TAG, "Could not initialize call to unknown state");
|
setInitialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
final String callerId = mCall.getCallerId();
|
||||||
|
if (callerId != null) {
|
||||||
|
setCallerDisplayName(callerId, TelecomManager.PRESENTATION_ALLOWED);
|
||||||
|
setAddress(Uri.fromParts("custom", mCall.getCallerId(), null),
|
||||||
|
TelecomManager.PRESENTATION_ALLOWED);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Bundle extras = new Bundle();
|
final Bundle extras = new Bundle();
|
||||||
extras.putString(CrossDeviceCall.EXTRA_CALL_ID, mCall.getId());
|
extras.putString(CrossDeviceSyncController.EXTRA_CALL_ID, mCall.getId());
|
||||||
putExtras(extras);
|
putExtras(extras);
|
||||||
|
|
||||||
int capabilities = getConnectionCapabilities();
|
int capabilities = getConnectionCapabilities();
|
||||||
@@ -280,7 +306,7 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(CallMetadataSyncData.Call call) {
|
private void update(CallMetadataSyncData.Call call) {
|
||||||
final int status = call.getStatus();
|
final int status = call.getStatus();
|
||||||
if (status == android.companion.Telecom.Call.RINGING_SILENCED
|
if (status == android.companion.Telecom.Call.RINGING_SILENCED
|
||||||
&& mCall.getStatus() != android.companion.Telecom.Call.RINGING_SILENCED) {
|
&& mCall.getStatus() != android.companion.Telecom.Call.RINGING_SILENCED) {
|
||||||
@@ -295,32 +321,30 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
|
|||||||
setActive();
|
setActive();
|
||||||
} else if (state == Call.STATE_HOLDING) {
|
} else if (state == Call.STATE_HOLDING) {
|
||||||
setOnHold();
|
setOnHold();
|
||||||
|
} else if (state == Call.STATE_DISCONNECTED) {
|
||||||
|
setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
|
||||||
} else {
|
} else {
|
||||||
Slog.e(TAG, "Could not update call to unknown state");
|
Slog.e(TAG, "Could not update call to unknown state");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int capabilities = getConnectionCapabilities();
|
int capabilities = getConnectionCapabilities();
|
||||||
|
mCall.setControls(call.getControls());
|
||||||
final boolean hasHoldControl = mCall.hasControl(
|
final boolean hasHoldControl = mCall.hasControl(
|
||||||
android.companion.Telecom.PUT_ON_HOLD)
|
android.companion.Telecom.PUT_ON_HOLD)
|
||||||
|| mCall.hasControl(android.companion.Telecom.TAKE_OFF_HOLD);
|
|| mCall.hasControl(android.companion.Telecom.TAKE_OFF_HOLD);
|
||||||
if (hasHoldControl != ((getConnectionCapabilities() & CAPABILITY_HOLD)
|
|
||||||
== CAPABILITY_HOLD)) {
|
|
||||||
if (hasHoldControl) {
|
if (hasHoldControl) {
|
||||||
capabilities |= CAPABILITY_HOLD;
|
capabilities |= CAPABILITY_HOLD;
|
||||||
} else {
|
} else {
|
||||||
capabilities &= ~CAPABILITY_HOLD;
|
capabilities &= ~CAPABILITY_HOLD;
|
||||||
}
|
}
|
||||||
}
|
final boolean hasMuteControl = mCall.hasControl(android.companion.Telecom.MUTE)
|
||||||
final boolean hasMuteControl = mCall.hasControl(android.companion.Telecom.MUTE);
|
|| mCall.hasControl(android.companion.Telecom.UNMUTE);
|
||||||
if (hasMuteControl != ((getConnectionCapabilities() & CAPABILITY_MUTE)
|
|
||||||
== CAPABILITY_MUTE)) {
|
|
||||||
if (hasMuteControl) {
|
if (hasMuteControl) {
|
||||||
capabilities |= CAPABILITY_MUTE;
|
capabilities |= CAPABILITY_MUTE;
|
||||||
} else {
|
} else {
|
||||||
capabilities &= ~CAPABILITY_MUTE;
|
capabilities &= ~CAPABILITY_MUTE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
mAudioManager.setMicrophoneMute(
|
mAudioManager.setMicrophoneMute(
|
||||||
mCall.hasControl(android.companion.Telecom.UNMUTE));
|
mCall.hasControl(android.companion.Telecom.UNMUTE));
|
||||||
if (capabilities != getConnectionCapabilities()) {
|
if (capabilities != getConnectionCapabilities()) {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
|
|||||||
import android.companion.ContextSyncMessage;
|
import android.companion.ContextSyncMessage;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.telecom.PhoneAccountHandle;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -189,7 +188,6 @@ class CallMetadataSyncData {
|
|||||||
private String mCallerId;
|
private String mCallerId;
|
||||||
private byte[] mAppIcon;
|
private byte[] mAppIcon;
|
||||||
private CallFacilitator mFacilitator;
|
private CallFacilitator mFacilitator;
|
||||||
private PhoneAccountHandle mPhoneAccountHandle;
|
|
||||||
private int mStatus;
|
private int mStatus;
|
||||||
private final Set<Integer> mControls = new HashSet<>();
|
private final Set<Integer> mControls = new HashSet<>();
|
||||||
|
|
||||||
@@ -200,9 +198,6 @@ class CallMetadataSyncData {
|
|||||||
call.setAppIcon(parcel.readBlob());
|
call.setAppIcon(parcel.readBlob());
|
||||||
call.setFacilitator(parcel.readParcelable(CallFacilitator.class.getClassLoader(),
|
call.setFacilitator(parcel.readParcelable(CallFacilitator.class.getClassLoader(),
|
||||||
CallFacilitator.class));
|
CallFacilitator.class));
|
||||||
call.setPhoneAccountHandle(
|
|
||||||
parcel.readParcelable(PhoneAccountHandle.class.getClassLoader(),
|
|
||||||
android.telecom.PhoneAccountHandle.class));
|
|
||||||
call.setStatus(parcel.readInt());
|
call.setStatus(parcel.readInt());
|
||||||
final int numberOfControls = parcel.readInt();
|
final int numberOfControls = parcel.readInt();
|
||||||
for (int i = 0; i < numberOfControls; i++) {
|
for (int i = 0; i < numberOfControls; i++) {
|
||||||
@@ -217,7 +212,6 @@ class CallMetadataSyncData {
|
|||||||
parcel.writeString(mCallerId);
|
parcel.writeString(mCallerId);
|
||||||
parcel.writeBlob(mAppIcon);
|
parcel.writeBlob(mAppIcon);
|
||||||
parcel.writeParcelable(mFacilitator, parcelableFlags);
|
parcel.writeParcelable(mFacilitator, parcelableFlags);
|
||||||
parcel.writeParcelable(mPhoneAccountHandle, parcelableFlags);
|
|
||||||
parcel.writeInt(mStatus);
|
parcel.writeInt(mStatus);
|
||||||
parcel.writeInt(mControls.size());
|
parcel.writeInt(mControls.size());
|
||||||
for (int control : mControls) {
|
for (int control : mControls) {
|
||||||
@@ -241,10 +235,6 @@ class CallMetadataSyncData {
|
|||||||
mFacilitator = facilitator;
|
mFacilitator = facilitator;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
|
|
||||||
mPhoneAccountHandle = phoneAccountHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStatus(int status) {
|
void setStatus(int status) {
|
||||||
mStatus = status;
|
mStatus = status;
|
||||||
}
|
}
|
||||||
@@ -253,6 +243,11 @@ class CallMetadataSyncData {
|
|||||||
mControls.add(control);
|
mControls.add(control);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setControls(Set<Integer> controls) {
|
||||||
|
mControls.clear();
|
||||||
|
mControls.addAll(controls);
|
||||||
|
}
|
||||||
|
|
||||||
String getId() {
|
String getId() {
|
||||||
return mId;
|
return mId;
|
||||||
}
|
}
|
||||||
@@ -269,10 +264,6 @@ class CallMetadataSyncData {
|
|||||||
return mFacilitator;
|
return mFacilitator;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhoneAccountHandle getPhoneAccountHandle() {
|
|
||||||
return mPhoneAccountHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getStatus() {
|
int getStatus() {
|
||||||
return mStatus;
|
return mStatus;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,16 +79,15 @@ public class CallMetadataSyncInCallService extends InCallService {
|
|||||||
int callControlAction) {
|
int callControlAction) {
|
||||||
final CrossDeviceCall crossDeviceCall = getCallForId(crossDeviceCallId,
|
final CrossDeviceCall crossDeviceCall = getCallForId(crossDeviceCallId,
|
||||||
mCurrentCalls.values());
|
mCurrentCalls.values());
|
||||||
|
if (crossDeviceCall == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (callControlAction) {
|
switch (callControlAction) {
|
||||||
case android.companion.Telecom.ACCEPT:
|
case android.companion.Telecom.ACCEPT:
|
||||||
if (crossDeviceCall != null) {
|
|
||||||
crossDeviceCall.doAccept();
|
crossDeviceCall.doAccept();
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case android.companion.Telecom.REJECT:
|
case android.companion.Telecom.REJECT:
|
||||||
if (crossDeviceCall != null) {
|
|
||||||
crossDeviceCall.doReject();
|
crossDeviceCall.doReject();
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case android.companion.Telecom.SILENCE:
|
case android.companion.Telecom.SILENCE:
|
||||||
doSilence();
|
doSilence();
|
||||||
@@ -100,19 +99,13 @@ public class CallMetadataSyncInCallService extends InCallService {
|
|||||||
doUnmute();
|
doUnmute();
|
||||||
break;
|
break;
|
||||||
case android.companion.Telecom.END:
|
case android.companion.Telecom.END:
|
||||||
if (crossDeviceCall != null) {
|
|
||||||
crossDeviceCall.doEnd();
|
crossDeviceCall.doEnd();
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case android.companion.Telecom.PUT_ON_HOLD:
|
case android.companion.Telecom.PUT_ON_HOLD:
|
||||||
if (crossDeviceCall != null) {
|
|
||||||
crossDeviceCall.doPutOnHold();
|
crossDeviceCall.doPutOnHold();
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case android.companion.Telecom.TAKE_OFF_HOLD:
|
case android.companion.Telecom.TAKE_OFF_HOLD:
|
||||||
if (crossDeviceCall != null) {
|
|
||||||
crossDeviceCall.doTakeOffHold();
|
crossDeviceCall.doTakeOffHold();
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@@ -148,7 +141,8 @@ public class CallMetadataSyncInCallService extends InCallService {
|
|||||||
super.onCreate();
|
super.onCreate();
|
||||||
if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
|
if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
|
||||||
mCdmsi = LocalServices.getService(CompanionDeviceManagerServiceInternal.class);
|
mCdmsi = LocalServices.getService(CompanionDeviceManagerServiceInternal.class);
|
||||||
mCdmsi.registerCallMetadataSyncCallback(mCrossDeviceSyncControllerCallback);
|
mCdmsi.registerCallMetadataSyncCallback(mCrossDeviceSyncControllerCallback,
|
||||||
|
CrossDeviceSyncControllerCallback.TYPE_IN_CALL_SERVICE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +150,7 @@ public class CallMetadataSyncInCallService extends InCallService {
|
|||||||
if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)
|
if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)
|
||||||
&& mNumberOfActiveSyncAssociations > 0) {
|
&& mNumberOfActiveSyncAssociations > 0) {
|
||||||
mCurrentCalls.putAll(getCalls().stream().collect(Collectors.toMap(call -> call,
|
mCurrentCalls.putAll(getCalls().stream().collect(Collectors.toMap(call -> call,
|
||||||
call -> new CrossDeviceCall(getPackageManager(), call, getCallAudioState()))));
|
call -> new CrossDeviceCall(this, call, getCallAudioState()))));
|
||||||
mCurrentCalls.keySet().forEach(call -> call.registerCallback(mTelecomCallback,
|
mCurrentCalls.keySet().forEach(call -> call.registerCallback(mTelecomCallback,
|
||||||
getMainThreadHandler()));
|
getMainThreadHandler()));
|
||||||
sync(getUserId());
|
sync(getUserId());
|
||||||
@@ -182,7 +176,7 @@ public class CallMetadataSyncInCallService extends InCallService {
|
|||||||
if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)
|
if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)
|
||||||
&& mNumberOfActiveSyncAssociations > 0) {
|
&& mNumberOfActiveSyncAssociations > 0) {
|
||||||
mCurrentCalls.put(call,
|
mCurrentCalls.put(call,
|
||||||
new CrossDeviceCall(getPackageManager(), call, getCallAudioState()));
|
new CrossDeviceCall(this, call, getCallAudioState()));
|
||||||
call.registerCallback(mTelecomCallback);
|
call.registerCallback(mTelecomCallback);
|
||||||
sync(getUserId());
|
sync(getUserId());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,15 @@
|
|||||||
package com.android.server.companion.datatransfer.contextsync;
|
package com.android.server.companion.datatransfer.contextsync;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.Uri;
|
||||||
import android.telecom.Call;
|
import android.telecom.Call;
|
||||||
import android.telecom.CallAudioState;
|
import android.telecom.CallAudioState;
|
||||||
|
import android.telecom.TelecomManager;
|
||||||
import android.telecom.VideoProfile;
|
import android.telecom.VideoProfile;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
@@ -35,40 +40,51 @@ public class CrossDeviceCall {
|
|||||||
|
|
||||||
private static final String TAG = "CrossDeviceCall";
|
private static final String TAG = "CrossDeviceCall";
|
||||||
|
|
||||||
public static final String EXTRA_CALL_ID =
|
|
||||||
"com.android.companion.datatransfer.contextsync.extra.CALL_ID";
|
|
||||||
|
|
||||||
private final String mId;
|
private final String mId;
|
||||||
private Call mCall;
|
private final Call mCall;
|
||||||
@VisibleForTesting boolean mIsEnterprise;
|
@VisibleForTesting boolean mIsEnterprise;
|
||||||
@VisibleForTesting boolean mIsOtt;
|
|
||||||
private final String mCallingAppPackageName;
|
private final String mCallingAppPackageName;
|
||||||
private String mCallingAppName;
|
private String mCallingAppName;
|
||||||
private byte[] mCallingAppIcon;
|
private byte[] mCallingAppIcon;
|
||||||
private String mCallerDisplayName;
|
private String mCallerDisplayName;
|
||||||
|
private int mCallerDisplayNamePresentation;
|
||||||
private int mStatus = android.companion.Telecom.Call.UNKNOWN_STATUS;
|
private int mStatus = android.companion.Telecom.Call.UNKNOWN_STATUS;
|
||||||
private String mContactDisplayName;
|
private String mContactDisplayName;
|
||||||
|
private Uri mHandle;
|
||||||
|
private int mHandlePresentation;
|
||||||
private boolean mIsMuted;
|
private boolean mIsMuted;
|
||||||
private final Set<Integer> mControls = new HashSet<>();
|
private final Set<Integer> mControls = new HashSet<>();
|
||||||
|
private final boolean mIsCallPlacedByContextSync;
|
||||||
|
|
||||||
public CrossDeviceCall(PackageManager packageManager, @NonNull Call call,
|
public CrossDeviceCall(Context context, @NonNull Call call,
|
||||||
CallAudioState callAudioState) {
|
CallAudioState callAudioState) {
|
||||||
this(packageManager, call.getDetails(), callAudioState);
|
this(context, call, call.getDetails(), callAudioState);
|
||||||
mCall = call;
|
|
||||||
call.putExtra(EXTRA_CALL_ID, mId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CrossDeviceCall(PackageManager packageManager, Call.Details callDetails,
|
CrossDeviceCall(Context context, Call.Details callDetails,
|
||||||
CallAudioState callAudioState) {
|
CallAudioState callAudioState) {
|
||||||
|
this(context, /* call= */ null, callDetails, callAudioState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CrossDeviceCall(Context context, @Nullable Call call,
|
||||||
|
Call.Details callDetails, CallAudioState callAudioState) {
|
||||||
|
mCall = call;
|
||||||
final String predefinedId = callDetails.getIntentExtras() != null
|
final String predefinedId = callDetails.getIntentExtras() != null
|
||||||
? callDetails.getIntentExtras().getString(EXTRA_CALL_ID) : null;
|
? callDetails.getIntentExtras().getString(CrossDeviceSyncController.EXTRA_CALL_ID)
|
||||||
mId = predefinedId != null ? predefinedId : UUID.randomUUID().toString();
|
: null;
|
||||||
|
final String generatedId = UUID.randomUUID().toString();
|
||||||
|
mId = predefinedId != null ? (generatedId + predefinedId) : generatedId;
|
||||||
|
if (call != null) {
|
||||||
|
call.putExtra(CrossDeviceSyncController.EXTRA_CALL_ID, mId);
|
||||||
|
}
|
||||||
|
mIsCallPlacedByContextSync =
|
||||||
|
new ComponentName(context, CallMetadataSyncConnectionService.class)
|
||||||
|
.equals(callDetails.getAccountHandle().getComponentName());
|
||||||
mCallingAppPackageName =
|
mCallingAppPackageName =
|
||||||
callDetails.getAccountHandle().getComponentName().getPackageName();
|
callDetails.getAccountHandle().getComponentName().getPackageName();
|
||||||
mIsOtt = (callDetails.getCallCapabilities() & Call.Details.PROPERTY_SELF_MANAGED)
|
|
||||||
== Call.Details.PROPERTY_SELF_MANAGED;
|
|
||||||
mIsEnterprise = (callDetails.getCallProperties() & Call.Details.PROPERTY_ENTERPRISE_CALL)
|
mIsEnterprise = (callDetails.getCallProperties() & Call.Details.PROPERTY_ENTERPRISE_CALL)
|
||||||
== Call.Details.PROPERTY_ENTERPRISE_CALL;
|
== Call.Details.PROPERTY_ENTERPRISE_CALL;
|
||||||
|
final PackageManager packageManager = context.getPackageManager();
|
||||||
try {
|
try {
|
||||||
final ApplicationInfo applicationInfo = packageManager
|
final ApplicationInfo applicationInfo = packageManager
|
||||||
.getApplicationInfo(mCallingAppPackageName,
|
.getApplicationInfo(mCallingAppPackageName,
|
||||||
@@ -108,7 +124,10 @@ public class CrossDeviceCall {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void updateCallDetails(Call.Details callDetails) {
|
void updateCallDetails(Call.Details callDetails) {
|
||||||
mCallerDisplayName = callDetails.getCallerDisplayName();
|
mCallerDisplayName = callDetails.getCallerDisplayName();
|
||||||
|
mCallerDisplayNamePresentation = callDetails.getCallerDisplayNamePresentation();
|
||||||
mContactDisplayName = callDetails.getContactDisplayName();
|
mContactDisplayName = callDetails.getContactDisplayName();
|
||||||
|
mHandle = callDetails.getHandle();
|
||||||
|
mHandlePresentation = callDetails.getHandlePresentation();
|
||||||
mStatus = convertStateToStatus(callDetails.getState());
|
mStatus = convertStateToStatus(callDetails.getState());
|
||||||
mControls.clear();
|
mControls.clear();
|
||||||
if (mStatus == android.companion.Telecom.Call.RINGING
|
if (mStatus == android.companion.Telecom.Call.RINGING
|
||||||
@@ -145,7 +164,14 @@ public class CrossDeviceCall {
|
|||||||
return android.companion.Telecom.Call.ONGOING;
|
return android.companion.Telecom.Call.ONGOING;
|
||||||
case Call.STATE_RINGING:
|
case Call.STATE_RINGING:
|
||||||
return android.companion.Telecom.Call.RINGING;
|
return android.companion.Telecom.Call.RINGING;
|
||||||
|
case Call.STATE_AUDIO_PROCESSING:
|
||||||
|
return android.companion.Telecom.Call.AUDIO_PROCESSING;
|
||||||
|
case Call.STATE_SIMULATED_RINGING:
|
||||||
|
return android.companion.Telecom.Call.RINGING_SIMULATED;
|
||||||
|
case Call.STATE_DISCONNECTED:
|
||||||
|
return android.companion.Telecom.Call.DISCONNECTED;
|
||||||
default:
|
default:
|
||||||
|
Slog.e(TAG, "Couldn't resolve state to status: " + callState);
|
||||||
return android.companion.Telecom.Call.UNKNOWN_STATUS;
|
return android.companion.Telecom.Call.UNKNOWN_STATUS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,6 +189,12 @@ public class CrossDeviceCall {
|
|||||||
case android.companion.Telecom.Call.RINGING:
|
case android.companion.Telecom.Call.RINGING:
|
||||||
case android.companion.Telecom.Call.RINGING_SILENCED:
|
case android.companion.Telecom.Call.RINGING_SILENCED:
|
||||||
return Call.STATE_RINGING;
|
return Call.STATE_RINGING;
|
||||||
|
case android.companion.Telecom.Call.AUDIO_PROCESSING:
|
||||||
|
return Call.STATE_AUDIO_PROCESSING;
|
||||||
|
case android.companion.Telecom.Call.RINGING_SIMULATED:
|
||||||
|
return Call.STATE_SIMULATED_RINGING;
|
||||||
|
case android.companion.Telecom.Call.DISCONNECTED:
|
||||||
|
return Call.STATE_DISCONNECTED;
|
||||||
case android.companion.Telecom.Call.UNKNOWN_STATUS:
|
case android.companion.Telecom.Call.UNKNOWN_STATUS:
|
||||||
default:
|
default:
|
||||||
return Call.STATE_NEW;
|
return Call.STATE_NEW;
|
||||||
@@ -195,10 +227,23 @@ public class CrossDeviceCall {
|
|||||||
* @param isAdminBlocked whether there is an admin that has blocked contacts over Bluetooth
|
* @param isAdminBlocked whether there is an admin that has blocked contacts over Bluetooth
|
||||||
*/
|
*/
|
||||||
public String getReadableCallerId(boolean isAdminBlocked) {
|
public String getReadableCallerId(boolean isAdminBlocked) {
|
||||||
if (mIsOtt) {
|
if (mIsEnterprise && isAdminBlocked) {
|
||||||
|
// Cannot use any contact information.
|
||||||
|
return getNonContactString();
|
||||||
|
}
|
||||||
|
return mContactDisplayName != null ? mContactDisplayName : getNonContactString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getNonContactString() {
|
||||||
|
if (mCallerDisplayName != null
|
||||||
|
&& mCallerDisplayNamePresentation == TelecomManager.PRESENTATION_ALLOWED) {
|
||||||
return mCallerDisplayName;
|
return mCallerDisplayName;
|
||||||
}
|
}
|
||||||
return mIsEnterprise && isAdminBlocked ? mCallerDisplayName : mContactDisplayName;
|
if (mHandle != null && mHandle.getSchemeSpecificPart() != null
|
||||||
|
&& mHandlePresentation == TelecomManager.PRESENTATION_ALLOWED) {
|
||||||
|
return mHandle.getSchemeSpecificPart();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getStatus() {
|
public int getStatus() {
|
||||||
@@ -209,6 +254,10 @@ public class CrossDeviceCall {
|
|||||||
return mControls;
|
return mControls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCallPlacedByContextSync() {
|
||||||
|
return mIsCallPlacedByContextSync;
|
||||||
|
}
|
||||||
|
|
||||||
void doAccept() {
|
void doAccept() {
|
||||||
mCall.answer(VideoProfile.STATE_AUDIO_ONLY);
|
mCall.answer(VideoProfile.STATE_AUDIO_ONLY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_C
|
|||||||
|
|
||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.companion.AssociationInfo;
|
import android.companion.AssociationInfo;
|
||||||
|
import android.companion.CompanionDeviceManager;
|
||||||
import android.companion.ContextSyncMessage;
|
import android.companion.ContextSyncMessage;
|
||||||
import android.companion.IOnMessageReceivedListener;
|
import android.companion.IOnMessageReceivedListener;
|
||||||
import android.companion.IOnTransportsChangedListener;
|
import android.companion.IOnTransportsChangedListener;
|
||||||
@@ -44,8 +45,10 @@ import com.android.server.companion.CompanionDeviceConfig;
|
|||||||
import com.android.server.companion.transport.CompanionTransportManager;
|
import com.android.server.companion.transport.CompanionTransportManager;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -54,6 +57,7 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Monitors connections and sending / receiving of synced data.
|
* Monitors connections and sending / receiving of synced data.
|
||||||
@@ -62,6 +66,13 @@ public class CrossDeviceSyncController {
|
|||||||
|
|
||||||
private static final String TAG = "CrossDeviceSyncController";
|
private static final String TAG = "CrossDeviceSyncController";
|
||||||
|
|
||||||
|
public static final String EXTRA_CALL_ID =
|
||||||
|
"com.android.companion.datatransfer.contextsync.extra.CALL_ID";
|
||||||
|
static final String EXTRA_FACILITATOR_ICON =
|
||||||
|
"com.android.companion.datatransfer.contextsync.extra.FACILITATOR_ICON";
|
||||||
|
static final String EXTRA_IS_REMOTE_ORIGIN =
|
||||||
|
"com.android.companion.datatransfer.contextsync.extra.IS_REMOTE_ORIGIN";
|
||||||
|
|
||||||
static final String EXTRA_ASSOCIATION_ID =
|
static final String EXTRA_ASSOCIATION_ID =
|
||||||
"com.android.server.companion.datatransfer.contextsync.extra.ASSOCIATION_ID";
|
"com.android.server.companion.datatransfer.contextsync.extra.ASSOCIATION_ID";
|
||||||
static final String EXTRA_CALL =
|
static final String EXTRA_CALL =
|
||||||
@@ -78,11 +89,13 @@ public class CrossDeviceSyncController {
|
|||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final CompanionTransportManager mCompanionTransportManager;
|
private final CompanionTransportManager mCompanionTransportManager;
|
||||||
private final PhoneAccountManager mPhoneAccountManager;
|
private final PhoneAccountManager mPhoneAccountManager;
|
||||||
|
private final CallManager mCallManager;
|
||||||
private final List<AssociationInfo> mConnectedAssociations = new ArrayList<>();
|
private final List<AssociationInfo> mConnectedAssociations = new ArrayList<>();
|
||||||
private final Set<Integer> mBlocklist = new HashSet<>();
|
private final Set<Integer> mBlocklist = new HashSet<>();
|
||||||
private final List<CallMetadataSyncData.CallFacilitator> mCallFacilitators = new ArrayList<>();
|
private final List<CallMetadataSyncData.CallFacilitator> mCallFacilitators = new ArrayList<>();
|
||||||
|
|
||||||
private CrossDeviceSyncControllerCallback mCrossDeviceSyncControllerCallback;
|
private WeakReference<CrossDeviceSyncControllerCallback> mInCallServiceCallbackRef;
|
||||||
|
private WeakReference<CrossDeviceSyncControllerCallback> mConnectionServiceCallbackRef;
|
||||||
|
|
||||||
public CrossDeviceSyncController(Context context,
|
public CrossDeviceSyncController(Context context,
|
||||||
CompanionTransportManager companionTransportManager) {
|
CompanionTransportManager companionTransportManager) {
|
||||||
@@ -104,25 +117,77 @@ public class CrossDeviceSyncController {
|
|||||||
mConnectedAssociations);
|
mConnectedAssociations);
|
||||||
mConnectedAssociations.clear();
|
mConnectedAssociations.clear();
|
||||||
mConnectedAssociations.addAll(newAssociations);
|
mConnectedAssociations.addAll(newAssociations);
|
||||||
if (mCrossDeviceSyncControllerCallback == null) {
|
|
||||||
Slog.w(TAG, "No callback to report transports changed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (AssociationInfo associationInfo : newAssociations) {
|
for (AssociationInfo associationInfo : newAssociations) {
|
||||||
if (!existingAssociations.contains(associationInfo)
|
if (!existingAssociations.contains(associationInfo)) {
|
||||||
&& !isAssociationBlocked(associationInfo.getId())) {
|
// New association.
|
||||||
mCrossDeviceSyncControllerCallback.updateNumberOfActiveSyncAssociations(
|
if (!isAssociationBlocked(associationInfo)) {
|
||||||
|
final CrossDeviceSyncControllerCallback callback =
|
||||||
|
mInCallServiceCallbackRef != null
|
||||||
|
? mInCallServiceCallbackRef.get() : null;
|
||||||
|
if (callback != null) {
|
||||||
|
callback.updateNumberOfActiveSyncAssociations(
|
||||||
associationInfo.getUserId(), /* added= */ true);
|
associationInfo.getUserId(), /* added= */ true);
|
||||||
mCrossDeviceSyncControllerCallback.requestCrossDeviceSync(associationInfo);
|
callback.requestCrossDeviceSync(associationInfo);
|
||||||
|
} else {
|
||||||
|
Slog.w(TAG, "No callback to report new transport");
|
||||||
|
syncMessageToDevice(associationInfo.getId(),
|
||||||
|
createFacilitatorMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mBlocklist.add(associationInfo.getId());
|
||||||
|
Slog.i(TAG, "New association was blocked from context syncing");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (AssociationInfo associationInfo : existingAssociations) {
|
for (AssociationInfo associationInfo : existingAssociations) {
|
||||||
if (!newAssociations.contains(associationInfo)) {
|
if (!newAssociations.contains(associationInfo)) {
|
||||||
if (isAssociationBlocked(associationInfo.getId())) {
|
// Removed association!
|
||||||
mBlocklist.remove(associationInfo.getId());
|
mBlocklist.remove(associationInfo.getId());
|
||||||
} else {
|
if (!isAssociationBlockedLocal(associationInfo.getId())) {
|
||||||
mCrossDeviceSyncControllerCallback.updateNumberOfActiveSyncAssociations(
|
final CrossDeviceSyncControllerCallback callback =
|
||||||
|
mInCallServiceCallbackRef != null
|
||||||
|
? mInCallServiceCallbackRef.get() : null;
|
||||||
|
if (callback != null) {
|
||||||
|
callback.updateNumberOfActiveSyncAssociations(
|
||||||
associationInfo.getUserId(), /* added= */ false);
|
associationInfo.getUserId(), /* added= */ false);
|
||||||
|
} else {
|
||||||
|
Slog.w(TAG, "No callback to report removed transport");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Stable association!
|
||||||
|
final boolean systemBlocked = isAssociationBlocked(associationInfo);
|
||||||
|
if (isAssociationBlockedLocal(associationInfo.getId()) != systemBlocked) {
|
||||||
|
// Block state has changed.
|
||||||
|
final CrossDeviceSyncControllerCallback callback =
|
||||||
|
mInCallServiceCallbackRef != null
|
||||||
|
? mInCallServiceCallbackRef.get() : null;
|
||||||
|
if (!systemBlocked) {
|
||||||
|
Slog.i(TAG, "Unblocking existing association for context sync");
|
||||||
|
mBlocklist.remove(associationInfo.getId());
|
||||||
|
if (callback != null) {
|
||||||
|
callback.updateNumberOfActiveSyncAssociations(
|
||||||
|
associationInfo.getUserId(), /* added= */ true);
|
||||||
|
callback.requestCrossDeviceSync(associationInfo);
|
||||||
|
} else {
|
||||||
|
Slog.w(TAG, "No callback to report changed transport");
|
||||||
|
syncMessageToDevice(associationInfo.getId(),
|
||||||
|
createFacilitatorMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Slog.i(TAG, "Blocking existing association for context sync");
|
||||||
|
mBlocklist.add(associationInfo.getId());
|
||||||
|
if (callback != null) {
|
||||||
|
callback.updateNumberOfActiveSyncAssociations(
|
||||||
|
associationInfo.getUserId(), /* added= */ false);
|
||||||
|
} else {
|
||||||
|
Slog.w(TAG, "No callback to report changed transport");
|
||||||
|
}
|
||||||
|
// Send empty message to device to clear its data (otherwise it
|
||||||
|
// will get stale)
|
||||||
|
syncMessageToDevice(associationInfo.getId(),
|
||||||
|
createEmptyMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,18 +197,48 @@ public class CrossDeviceSyncController {
|
|||||||
new IOnMessageReceivedListener.Stub() {
|
new IOnMessageReceivedListener.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void onMessageReceived(int associationId, byte[] data) {
|
public void onMessageReceived(int associationId, byte[] data) {
|
||||||
|
if (isAssociationBlockedLocal(associationId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final CallMetadataSyncData processedData = processTelecomDataFromSync(data);
|
final CallMetadataSyncData processedData = processTelecomDataFromSync(data);
|
||||||
mPhoneAccountManager.updateFacilitators(associationId, processedData);
|
mPhoneAccountManager.updateFacilitators(associationId, processedData);
|
||||||
processCallCreateRequests(associationId, processedData);
|
mCallManager.updateCalls(associationId, processedData);
|
||||||
if (mCrossDeviceSyncControllerCallback == null) {
|
processCallCreateRequests(processedData);
|
||||||
|
if (mInCallServiceCallbackRef == null
|
||||||
|
&& mConnectionServiceCallbackRef == null) {
|
||||||
Slog.w(TAG, "No callback to process context sync message");
|
Slog.w(TAG, "No callback to process context sync message");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mCrossDeviceSyncControllerCallback.processContextSyncMessage(associationId,
|
final CrossDeviceSyncControllerCallback inCallServiceCallback =
|
||||||
|
mInCallServiceCallbackRef != null ? mInCallServiceCallbackRef.get()
|
||||||
|
: null;
|
||||||
|
if (inCallServiceCallback != null) {
|
||||||
|
inCallServiceCallback.processContextSyncMessage(associationId,
|
||||||
processedData);
|
processedData);
|
||||||
|
} else {
|
||||||
|
// This is dead; get rid of it lazily
|
||||||
|
mInCallServiceCallbackRef = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final CrossDeviceSyncControllerCallback connectionServiceCallback =
|
||||||
|
mConnectionServiceCallbackRef != null
|
||||||
|
? mConnectionServiceCallbackRef.get() : null;
|
||||||
|
if (connectionServiceCallback != null) {
|
||||||
|
connectionServiceCallback.processContextSyncMessage(associationId,
|
||||||
|
processedData);
|
||||||
|
} else {
|
||||||
|
// This is dead; get rid of it lazily
|
||||||
|
mConnectionServiceCallbackRef = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mPhoneAccountManager = new PhoneAccountManager(mContext);
|
mPhoneAccountManager = new PhoneAccountManager(mContext);
|
||||||
|
mCallManager = new CallManager(mContext, mPhoneAccountManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isAssociationBlocked(AssociationInfo info) {
|
||||||
|
return (info.getSystemDataSyncFlags() & CompanionDeviceManager.FLAG_CALL_METADATA)
|
||||||
|
!= CompanionDeviceManager.FLAG_CALL_METADATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Invoke set-up tasks that happen when boot is completed. */
|
/** Invoke set-up tasks that happen when boot is completed. */
|
||||||
@@ -155,7 +250,7 @@ public class CrossDeviceSyncController {
|
|||||||
mPhoneAccountManager.onBootCompleted();
|
mPhoneAccountManager.onBootCompleted();
|
||||||
|
|
||||||
final TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
|
final TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
|
||||||
if (telecomManager.getCallCapablePhoneAccounts().size() != 0) {
|
if (telecomManager != null && telecomManager.getCallCapablePhoneAccounts().size() != 0) {
|
||||||
final PhoneAccountHandle defaultOutgoingTelAccountHandle =
|
final PhoneAccountHandle defaultOutgoingTelAccountHandle =
|
||||||
telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
|
telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
|
||||||
if (defaultOutgoingTelAccountHandle != null) {
|
if (defaultOutgoingTelAccountHandle != null) {
|
||||||
@@ -171,8 +266,7 @@ public class CrossDeviceSyncController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processCallCreateRequests(int associationId,
|
private void processCallCreateRequests(CallMetadataSyncData callMetadataSyncData) {
|
||||||
CallMetadataSyncData callMetadataSyncData) {
|
|
||||||
final Iterator<CallMetadataSyncData.CallCreateRequest> iterator =
|
final Iterator<CallMetadataSyncData.CallCreateRequest> iterator =
|
||||||
callMetadataSyncData.getCallCreateRequests().iterator();
|
callMetadataSyncData.getCallCreateRequests().iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
@@ -184,7 +278,7 @@ public class CrossDeviceSyncController {
|
|||||||
final Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL,
|
final Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL,
|
||||||
request.getAddress().replaceAll("\\D+", ""), /* fragment= */ null);
|
request.getAddress().replaceAll("\\D+", ""), /* fragment= */ null);
|
||||||
final Bundle extras = new Bundle();
|
final Bundle extras = new Bundle();
|
||||||
extras.putString(CrossDeviceCall.EXTRA_CALL_ID, request.getId());
|
extras.putString(EXTRA_CALL_ID, request.getId());
|
||||||
final Bundle outerExtras = new Bundle();
|
final Bundle outerExtras = new Bundle();
|
||||||
outerExtras.putParcelable(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
|
outerExtras.putParcelable(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
|
||||||
mContext.getSystemService(TelecomManager.class).placeCall(uri, outerExtras);
|
mContext.getSystemService(TelecomManager.class).placeCall(uri, outerExtras);
|
||||||
@@ -196,40 +290,34 @@ public class CrossDeviceSyncController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAssociationBlocked(int associationId) {
|
/**
|
||||||
|
* This keeps track of "previous" state to calculate deltas. Use {@link #isAssociationBlocked}
|
||||||
|
* for all other use cases.
|
||||||
|
*/
|
||||||
|
private boolean isAssociationBlockedLocal(int associationId) {
|
||||||
return mBlocklist.contains(associationId);
|
return mBlocklist.contains(associationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Registers the call metadata callback. */
|
/** Registers the call metadata callback. */
|
||||||
public void registerCallMetadataSyncCallback(CrossDeviceSyncControllerCallback callback) {
|
public void registerCallMetadataSyncCallback(CrossDeviceSyncControllerCallback callback,
|
||||||
mCrossDeviceSyncControllerCallback = callback;
|
@CrossDeviceSyncControllerCallback.Type int type) {
|
||||||
|
if (type == CrossDeviceSyncControllerCallback.TYPE_IN_CALL_SERVICE) {
|
||||||
|
mInCallServiceCallbackRef = new WeakReference<>(callback);
|
||||||
for (AssociationInfo associationInfo : mConnectedAssociations) {
|
for (AssociationInfo associationInfo : mConnectedAssociations) {
|
||||||
if (!isAssociationBlocked(associationInfo.getId())) {
|
if (!isAssociationBlocked(associationInfo)) {
|
||||||
mCrossDeviceSyncControllerCallback.updateNumberOfActiveSyncAssociations(
|
|
||||||
associationInfo.getUserId(), /* added= */ true);
|
|
||||||
mCrossDeviceSyncControllerCallback.requestCrossDeviceSync(associationInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Allow specific associated devices to enable / disable syncing. */
|
|
||||||
public void setSyncEnabled(AssociationInfo associationInfo, boolean enabled) {
|
|
||||||
if (enabled) {
|
|
||||||
if (isAssociationBlocked(associationInfo.getId())) {
|
|
||||||
mBlocklist.remove(associationInfo.getId());
|
mBlocklist.remove(associationInfo.getId());
|
||||||
mCrossDeviceSyncControllerCallback.updateNumberOfActiveSyncAssociations(
|
callback.updateNumberOfActiveSyncAssociations(associationInfo.getUserId(),
|
||||||
associationInfo.getUserId(), /* added= */ true);
|
/* added= */ true);
|
||||||
mCrossDeviceSyncControllerCallback.requestCrossDeviceSync(associationInfo);
|
callback.requestCrossDeviceSync(associationInfo);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!isAssociationBlocked(associationInfo.getId())) {
|
|
||||||
mBlocklist.add(associationInfo.getId());
|
mBlocklist.add(associationInfo.getId());
|
||||||
mCrossDeviceSyncControllerCallback.updateNumberOfActiveSyncAssociations(
|
|
||||||
associationInfo.getUserId(), /* added= */ false);
|
|
||||||
// Send empty message to device to clear its data (otherwise it will get stale)
|
|
||||||
syncMessageToDevice(associationInfo.getId(), createEmptyMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (type == CrossDeviceSyncControllerCallback.TYPE_CONNECTION_SERVICE) {
|
||||||
|
mConnectionServiceCallbackRef = new WeakReference<>(callback);
|
||||||
|
} else {
|
||||||
|
Slog.e(TAG, "Cannot register callback of unknown type: " + type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAdminBlocked(int userId) {
|
private boolean isAdminBlocked(int userId) {
|
||||||
@@ -246,8 +334,7 @@ public class CrossDeviceSyncController {
|
|||||||
public void syncToAllDevicesForUserId(int userId, Collection<CrossDeviceCall> calls) {
|
public void syncToAllDevicesForUserId(int userId, Collection<CrossDeviceCall> calls) {
|
||||||
final Set<Integer> associationIds = new HashSet<>();
|
final Set<Integer> associationIds = new HashSet<>();
|
||||||
for (AssociationInfo associationInfo : mConnectedAssociations) {
|
for (AssociationInfo associationInfo : mConnectedAssociations) {
|
||||||
if (associationInfo.getUserId() == userId && !isAssociationBlocked(
|
if (associationInfo.getUserId() == userId && !isAssociationBlocked(associationInfo)) {
|
||||||
associationInfo.getId())) {
|
|
||||||
associationIds.add(associationInfo.getId());
|
associationIds.add(associationInfo.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,7 +356,7 @@ public class CrossDeviceSyncController {
|
|||||||
*/
|
*/
|
||||||
public void syncToSingleDevice(AssociationInfo associationInfo,
|
public void syncToSingleDevice(AssociationInfo associationInfo,
|
||||||
Collection<CrossDeviceCall> calls) {
|
Collection<CrossDeviceCall> calls) {
|
||||||
if (isAssociationBlocked(associationInfo.getId())) {
|
if (isAssociationBlocked(associationInfo)) {
|
||||||
Slog.e(TAG, "Cannot sync to requested device; connection is blocked");
|
Slog.e(TAG, "Cannot sync to requested device; connection is blocked");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -286,7 +373,7 @@ public class CrossDeviceSyncController {
|
|||||||
* @param message The message to sync.
|
* @param message The message to sync.
|
||||||
*/
|
*/
|
||||||
public void syncMessageToDevice(int associationId, byte[] message) {
|
public void syncMessageToDevice(int associationId, byte[] message) {
|
||||||
if (isAssociationBlocked(associationId)) {
|
if (isAssociationBlockedLocal(associationId)) {
|
||||||
Slog.e(TAG, "Cannot sync to requested device; connection is blocked");
|
Slog.e(TAG, "Cannot sync to requested device; connection is blocked");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -491,6 +578,10 @@ public class CrossDeviceSyncController {
|
|||||||
pos.write(ContextSyncMessage.VERSION, CURRENT_VERSION);
|
pos.write(ContextSyncMessage.VERSION, CURRENT_VERSION);
|
||||||
final long telecomToken = pos.start(ContextSyncMessage.TELECOM);
|
final long telecomToken = pos.start(ContextSyncMessage.TELECOM);
|
||||||
for (CrossDeviceCall call : calls) {
|
for (CrossDeviceCall call : calls) {
|
||||||
|
if (call.isCallPlacedByContextSync()) {
|
||||||
|
// Do not sync any calls which our "ours" as that would be duplicative.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final long callsToken = pos.start(Telecom.CALLS);
|
final long callsToken = pos.start(Telecom.CALLS);
|
||||||
pos.write(Telecom.Call.ID, call.getId());
|
pos.write(Telecom.Call.ID, call.getId());
|
||||||
final long originToken = pos.start(Telecom.Call.ORIGIN);
|
final long originToken = pos.start(Telecom.Call.ORIGIN);
|
||||||
@@ -559,6 +650,50 @@ public class CrossDeviceSyncController {
|
|||||||
return pos.getBytes();
|
return pos.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Create a facilitator-only message, used before any calls are available as a call intake. */
|
||||||
|
private byte[] createFacilitatorMessage() {
|
||||||
|
return createCallUpdateMessage(Collections.emptyList(), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static class CallManager {
|
||||||
|
|
||||||
|
@VisibleForTesting final Map<Integer, Set<String>> mCallIds = new HashMap<>();
|
||||||
|
private final TelecomManager mTelecomManager;
|
||||||
|
private final PhoneAccountManager mPhoneAccountManager;
|
||||||
|
|
||||||
|
CallManager(Context context, PhoneAccountManager phoneAccountManager) {
|
||||||
|
mTelecomManager = context.getSystemService(TelecomManager.class);
|
||||||
|
mPhoneAccountManager = phoneAccountManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add any new calls to Telecom. The ConnectionService will handle everything else. */
|
||||||
|
void updateCalls(int associationId, CallMetadataSyncData data) {
|
||||||
|
final Set<String> oldCallIds = mCallIds.getOrDefault(associationId, new HashSet<>());
|
||||||
|
final Set<String> newCallIds = data.getCalls().stream().map(
|
||||||
|
CallMetadataSyncData.Call::getId).collect(Collectors.toSet());
|
||||||
|
if (oldCallIds.equals(newCallIds)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CallMetadataSyncData.Call currentCall : data.getCalls()) {
|
||||||
|
if (!oldCallIds.contains(currentCall.getId())
|
||||||
|
&& currentCall.getFacilitator() != null) {
|
||||||
|
final Bundle extras = new Bundle();
|
||||||
|
extras.putInt(EXTRA_ASSOCIATION_ID, associationId);
|
||||||
|
extras.putBoolean(EXTRA_IS_REMOTE_ORIGIN, true);
|
||||||
|
extras.putParcelable(EXTRA_CALL, currentCall);
|
||||||
|
extras.putString(EXTRA_CALL_ID, currentCall.getId());
|
||||||
|
extras.putByteArray(EXTRA_FACILITATOR_ICON, currentCall.getAppIcon());
|
||||||
|
final PhoneAccountHandle handle = mPhoneAccountManager.getPhoneAccountHandle(
|
||||||
|
associationId, currentCall.getFacilitator().getIdentifier());
|
||||||
|
mTelecomManager.addNewIncomingCall(handle, extras);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mCallIds.put(associationId, newCallIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class PhoneAccountManager {
|
static class PhoneAccountManager {
|
||||||
private final Map<PhoneAccountHandleIdentifier, PhoneAccountHandle> mPhoneAccountHandles =
|
private final Map<PhoneAccountHandleIdentifier, PhoneAccountHandle> mPhoneAccountHandles =
|
||||||
new HashMap<>();
|
new HashMap<>();
|
||||||
|
|||||||
@@ -16,11 +16,25 @@
|
|||||||
|
|
||||||
package com.android.server.companion.datatransfer.contextsync;
|
package com.android.server.companion.datatransfer.contextsync;
|
||||||
|
|
||||||
|
import android.annotation.IntDef;
|
||||||
import android.companion.AssociationInfo;
|
import android.companion.AssociationInfo;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
/** Callback for call metadata syncing. */
|
/** Callback for call metadata syncing. */
|
||||||
public abstract class CrossDeviceSyncControllerCallback {
|
public abstract class CrossDeviceSyncControllerCallback {
|
||||||
|
|
||||||
|
static final int TYPE_CONNECTION_SERVICE = 1;
|
||||||
|
static final int TYPE_IN_CALL_SERVICE = 2;
|
||||||
|
@IntDef(prefix = { "TYPE_" }, value = {
|
||||||
|
TYPE_CONNECTION_SERVICE,
|
||||||
|
TYPE_IN_CALL_SERVICE,
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Type {
|
||||||
|
}
|
||||||
|
|
||||||
void processContextSyncMessage(int associationId, CallMetadataSyncData callMetadataSyncData) {}
|
void processContextSyncMessage(int associationId, CallMetadataSyncData callMetadataSyncData) {}
|
||||||
|
|
||||||
void requestCrossDeviceSync(AssociationInfo associationInfo) {}
|
void requestCrossDeviceSync(AssociationInfo associationInfo) {}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class CallMetadataSyncConnectionServiceTest {
|
|||||||
callMetadataSyncData.addCall(call);
|
callMetadataSyncData.addCall(call);
|
||||||
mSyncConnectionService.mCrossDeviceSyncControllerCallback.processContextSyncMessage(
|
mSyncConnectionService.mCrossDeviceSyncControllerCallback.processContextSyncMessage(
|
||||||
/* associationId= */ 0, callMetadataSyncData);
|
/* associationId= */ 0, callMetadataSyncData);
|
||||||
verify(mMockTelecomManager, times(1)).addNewIncomingCall(any(), any());
|
verify(mMockTelecomManager, times(0)).addNewIncomingCall(any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.platform.test.annotations.Presubmit;
|
|||||||
import android.telecom.Call;
|
import android.telecom.Call;
|
||||||
import android.telecom.ParcelableCall;
|
import android.telecom.ParcelableCall;
|
||||||
import android.telecom.PhoneAccountHandle;
|
import android.telecom.PhoneAccountHandle;
|
||||||
|
import android.telecom.TelecomManager;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
@@ -45,7 +46,7 @@ public class CrossDeviceCallTest {
|
|||||||
@Test
|
@Test
|
||||||
public void updateCallDetails_uninitialized() {
|
public void updateCallDetails_uninitialized() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
|
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
|
||||||
.isEqualTo(android.companion.Telecom.Call.UNKNOWN_STATUS);
|
.isEqualTo(android.companion.Telecom.Call.UNKNOWN_STATUS);
|
||||||
@@ -55,7 +56,7 @@ public class CrossDeviceCallTest {
|
|||||||
@Test
|
@Test
|
||||||
public void updateCallDetails_ringing() {
|
public void updateCallDetails_ringing() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_RINGING,
|
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_RINGING,
|
||||||
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
||||||
@@ -70,7 +71,7 @@ public class CrossDeviceCallTest {
|
|||||||
@Test
|
@Test
|
||||||
public void updateCallDetails_ongoing() {
|
public void updateCallDetails_ongoing() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_ACTIVE,
|
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_ACTIVE,
|
||||||
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
||||||
@@ -85,7 +86,7 @@ public class CrossDeviceCallTest {
|
|||||||
@Test
|
@Test
|
||||||
public void updateCallDetails_holding() {
|
public void updateCallDetails_holding() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_HOLDING,
|
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_HOLDING,
|
||||||
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
||||||
@@ -99,7 +100,7 @@ public class CrossDeviceCallTest {
|
|||||||
@Test
|
@Test
|
||||||
public void updateCallDetails_cannotHold() {
|
public void updateCallDetails_cannotHold() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.updateCallDetails(
|
crossDeviceCall.updateCallDetails(
|
||||||
createCallDetails(Call.STATE_ACTIVE, Call.Details.CAPABILITY_MUTE));
|
createCallDetails(Call.STATE_ACTIVE, Call.Details.CAPABILITY_MUTE));
|
||||||
@@ -113,7 +114,7 @@ public class CrossDeviceCallTest {
|
|||||||
@Test
|
@Test
|
||||||
public void updateCallDetails_cannotMute() {
|
public void updateCallDetails_cannotMute() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.updateCallDetails(
|
crossDeviceCall.updateCallDetails(
|
||||||
createCallDetails(Call.STATE_ACTIVE, Call.Details.CAPABILITY_HOLD));
|
createCallDetails(Call.STATE_ACTIVE, Call.Details.CAPABILITY_HOLD));
|
||||||
@@ -127,7 +128,7 @@ public class CrossDeviceCallTest {
|
|||||||
@Test
|
@Test
|
||||||
public void updateCallDetails_transitionRingingToOngoing() {
|
public void updateCallDetails_transitionRingingToOngoing() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_RINGING,
|
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_RINGING,
|
||||||
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
||||||
@@ -150,7 +151,7 @@ public class CrossDeviceCallTest {
|
|||||||
@Test
|
@Test
|
||||||
public void updateSilencedIfRinging_ringing_silenced() {
|
public void updateSilencedIfRinging_ringing_silenced() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_RINGING,
|
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_RINGING,
|
||||||
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
||||||
@@ -165,7 +166,7 @@ public class CrossDeviceCallTest {
|
|||||||
@Test
|
@Test
|
||||||
public void updateSilencedIfRinging_notRinging_notSilenced() {
|
public void updateSilencedIfRinging_notRinging_notSilenced() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_ACTIVE,
|
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_ACTIVE,
|
||||||
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
|
||||||
@@ -179,12 +180,11 @@ public class CrossDeviceCallTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getReadableCallerId_enterpriseCall_adminBlocked_ott() {
|
public void getReadableCallerId_enterpriseCall_adminBlocked_hasContact() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.mIsEnterprise = true;
|
crossDeviceCall.mIsEnterprise = true;
|
||||||
crossDeviceCall.mIsOtt = true;
|
|
||||||
crossDeviceCall.updateCallDetails(
|
crossDeviceCall.updateCallDetails(
|
||||||
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0));
|
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0));
|
||||||
|
|
||||||
@@ -195,76 +195,74 @@ public class CrossDeviceCallTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getReadableCallerId_enterpriseCall_adminUnblocked_ott() {
|
public void getReadableCallerId_enterpriseCall_adminUnblocked_hasContact() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.mIsEnterprise = true;
|
crossDeviceCall.mIsEnterprise = true;
|
||||||
crossDeviceCall.mIsOtt = true;
|
|
||||||
crossDeviceCall.updateCallDetails(
|
crossDeviceCall.updateCallDetails(
|
||||||
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0));
|
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0));
|
||||||
|
|
||||||
final String result = crossDeviceCall.getReadableCallerId(false);
|
final String result = crossDeviceCall.getReadableCallerId(false);
|
||||||
|
|
||||||
|
assertWithMessage("Wrong caller id").that(result)
|
||||||
|
.isEqualTo(CONTACT_DISPLAY_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getReadableCallerId_enterpriseCall_adminBlocked_noContact() {
|
||||||
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
|
InstrumentationRegistry.getTargetContext(),
|
||||||
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
|
crossDeviceCall.mIsEnterprise = true;
|
||||||
|
crossDeviceCall.updateCallDetails(
|
||||||
|
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0, /* hasContactName= */
|
||||||
|
false));
|
||||||
|
|
||||||
|
final String result = crossDeviceCall.getReadableCallerId(true);
|
||||||
|
|
||||||
|
assertWithMessage("Wrong caller id").that(result)
|
||||||
|
.isEqualTo(CALLER_DISPLAY_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getReadableCallerId_nonEnterpriseCall_adminBlocked_noContact() {
|
||||||
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
|
InstrumentationRegistry.getTargetContext(),
|
||||||
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
|
crossDeviceCall.mIsEnterprise = false;
|
||||||
|
crossDeviceCall.updateCallDetails(
|
||||||
|
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0, /* hasContactName= */
|
||||||
|
false));
|
||||||
|
|
||||||
|
final String result = crossDeviceCall.getReadableCallerId(true);
|
||||||
|
|
||||||
|
assertWithMessage("Wrong caller id").that(result)
|
||||||
|
.isEqualTo(CALLER_DISPLAY_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getReadableCallerId_nonEnterpriseCall_adminUnblocked_noContact() {
|
||||||
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
|
InstrumentationRegistry.getTargetContext(),
|
||||||
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
|
crossDeviceCall.mIsEnterprise = false;
|
||||||
|
crossDeviceCall.updateCallDetails(
|
||||||
|
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0, /* hasContactName= */
|
||||||
|
false));
|
||||||
|
|
||||||
|
final String result = crossDeviceCall.getReadableCallerId(false);
|
||||||
|
|
||||||
assertWithMessage("Wrong caller id").that(result)
|
assertWithMessage("Wrong caller id").that(result)
|
||||||
.isEqualTo(CALLER_DISPLAY_NAME);
|
.isEqualTo(CALLER_DISPLAY_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getReadableCallerId_enterpriseCall_adminBlocked_pstn() {
|
public void getReadableCallerId_nonEnterpriseCall_adminBlocked_hasContact() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
|
||||||
crossDeviceCall.mIsEnterprise = true;
|
|
||||||
crossDeviceCall.mIsOtt = false;
|
|
||||||
crossDeviceCall.updateCallDetails(
|
|
||||||
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0));
|
|
||||||
|
|
||||||
final String result = crossDeviceCall.getReadableCallerId(true);
|
|
||||||
|
|
||||||
assertWithMessage("Wrong caller id").that(result)
|
|
||||||
.isEqualTo(CALLER_DISPLAY_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getReadableCallerId_nonEnterpriseCall_adminBlocked_ott() {
|
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.mIsEnterprise = false;
|
crossDeviceCall.mIsEnterprise = false;
|
||||||
crossDeviceCall.mIsOtt = true;
|
|
||||||
crossDeviceCall.updateCallDetails(
|
|
||||||
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0));
|
|
||||||
|
|
||||||
final String result = crossDeviceCall.getReadableCallerId(true);
|
|
||||||
|
|
||||||
assertWithMessage("Wrong caller id").that(result)
|
|
||||||
.isEqualTo(CALLER_DISPLAY_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getReadableCallerId_nonEnterpriseCall_adminUnblocked_ott() {
|
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
|
||||||
crossDeviceCall.mIsEnterprise = false;
|
|
||||||
crossDeviceCall.mIsOtt = true;
|
|
||||||
crossDeviceCall.updateCallDetails(
|
|
||||||
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0));
|
|
||||||
|
|
||||||
final String result = crossDeviceCall.getReadableCallerId(false);
|
|
||||||
|
|
||||||
assertWithMessage("Wrong caller id").that(result)
|
|
||||||
.isEqualTo(CALLER_DISPLAY_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getReadableCallerId_nonEnterpriseCall_adminBlocked_pstn() {
|
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
|
||||||
crossDeviceCall.mIsEnterprise = false;
|
|
||||||
crossDeviceCall.mIsOtt = false;
|
|
||||||
crossDeviceCall.updateCallDetails(
|
crossDeviceCall.updateCallDetails(
|
||||||
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0));
|
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0));
|
||||||
|
|
||||||
@@ -275,12 +273,11 @@ public class CrossDeviceCallTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getReadableCallerId_nonEnterpriseCall_adminUnblocked_pstn() {
|
public void getReadableCallerId_nonEnterpriseCall_adminUnblocked_hasContact() {
|
||||||
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
|
||||||
InstrumentationRegistry.getTargetContext().getPackageManager(),
|
InstrumentationRegistry.getTargetContext(),
|
||||||
mUninitializedCallDetails, /* callAudioState= */ null);
|
mUninitializedCallDetails, /* callAudioState= */ null);
|
||||||
crossDeviceCall.mIsEnterprise = false;
|
crossDeviceCall.mIsEnterprise = false;
|
||||||
crossDeviceCall.mIsOtt = false;
|
|
||||||
crossDeviceCall.updateCallDetails(
|
crossDeviceCall.updateCallDetails(
|
||||||
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0));
|
createCallDetails(Call.STATE_ACTIVE, /* capabilities= */ 0));
|
||||||
|
|
||||||
@@ -291,10 +288,17 @@ public class CrossDeviceCallTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Call.Details createCallDetails(int state, int capabilities) {
|
private Call.Details createCallDetails(int state, int capabilities) {
|
||||||
|
return createCallDetails(state, capabilities, /* hasContactName= */ true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Call.Details createCallDetails(int state, int capabilities, boolean hasContactName) {
|
||||||
final ParcelableCall.ParcelableCallBuilder parcelableCallBuilder =
|
final ParcelableCall.ParcelableCallBuilder parcelableCallBuilder =
|
||||||
new ParcelableCall.ParcelableCallBuilder();
|
new ParcelableCall.ParcelableCallBuilder();
|
||||||
parcelableCallBuilder.setCallerDisplayName(CALLER_DISPLAY_NAME);
|
parcelableCallBuilder.setCallerDisplayName(CALLER_DISPLAY_NAME);
|
||||||
|
if (hasContactName) {
|
||||||
parcelableCallBuilder.setContactDisplayName(CONTACT_DISPLAY_NAME);
|
parcelableCallBuilder.setContactDisplayName(CONTACT_DISPLAY_NAME);
|
||||||
|
}
|
||||||
|
parcelableCallBuilder.setCallerDisplayNamePresentation(TelecomManager.PRESENTATION_ALLOWED);
|
||||||
parcelableCallBuilder.setCapabilities(capabilities);
|
parcelableCallBuilder.setCapabilities(capabilities);
|
||||||
parcelableCallBuilder.setState(state);
|
parcelableCallBuilder.setState(state);
|
||||||
parcelableCallBuilder.setConferenceableCallIds(Collections.emptyList());
|
parcelableCallBuilder.setConferenceableCallIds(Collections.emptyList());
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
|
|||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.Mockito.doNothing;
|
import static org.mockito.Mockito.doNothing;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -211,4 +212,62 @@ public class CrossDeviceSyncControllerTest {
|
|||||||
verify(mMockTelecomManager, times(1)).registerPhoneAccount(any());
|
verify(mMockTelecomManager, times(1)).registerPhoneAccount(any());
|
||||||
verify(mMockTelecomManager, times(1)).unregisterPhoneAccount(any());
|
verify(mMockTelecomManager, times(1)).unregisterPhoneAccount(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateCalls_newCall() {
|
||||||
|
final CallMetadataSyncData.Call call = new CallMetadataSyncData.Call();
|
||||||
|
call.setId("123abc");
|
||||||
|
call.setFacilitator(new CallMetadataSyncData.CallFacilitator("name", "com.android.test"));
|
||||||
|
final CallMetadataSyncData callMetadataSyncData = new CallMetadataSyncData();
|
||||||
|
callMetadataSyncData.addCall(call);
|
||||||
|
final CrossDeviceSyncController.CallManager callManager =
|
||||||
|
new CrossDeviceSyncController.CallManager(mMockContext,
|
||||||
|
new CrossDeviceSyncController.PhoneAccountManager(mMockContext));
|
||||||
|
callManager.updateCalls(/* associationId= */ 0, callMetadataSyncData);
|
||||||
|
verify(mMockTelecomManager, times(1)).addNewIncomingCall(any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateCalls_newCall_noFacilitator() {
|
||||||
|
final CallMetadataSyncData.Call call = new CallMetadataSyncData.Call();
|
||||||
|
call.setId("123abc");
|
||||||
|
final CallMetadataSyncData callMetadataSyncData = new CallMetadataSyncData();
|
||||||
|
callMetadataSyncData.addCall(call);
|
||||||
|
final CrossDeviceSyncController.CallManager callManager =
|
||||||
|
new CrossDeviceSyncController.CallManager(mMockContext,
|
||||||
|
new CrossDeviceSyncController.PhoneAccountManager(mMockContext));
|
||||||
|
callManager.updateCalls(/* associationId= */ 0, callMetadataSyncData);
|
||||||
|
verify(mMockTelecomManager, times(0)).addNewIncomingCall(any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateCalls_existingCall() {
|
||||||
|
final CallMetadataSyncData.Call call = new CallMetadataSyncData.Call();
|
||||||
|
call.setId("123abc");
|
||||||
|
final CallMetadataSyncData callMetadataSyncData = new CallMetadataSyncData();
|
||||||
|
callMetadataSyncData.addCall(call);
|
||||||
|
final CrossDeviceSyncController.CallManager callManager =
|
||||||
|
new CrossDeviceSyncController.CallManager(mMockContext,
|
||||||
|
new CrossDeviceSyncController.PhoneAccountManager(mMockContext));
|
||||||
|
callManager.mCallIds.put(/* associationId= */ 0, Set.of(call.getId()));
|
||||||
|
callManager.updateCalls(/* associationId= */ 0, callMetadataSyncData);
|
||||||
|
verify(mMockTelecomManager, never()).addNewIncomingCall(any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateCalls_removedCall() {
|
||||||
|
final CallMetadataSyncData.Call call = new CallMetadataSyncData.Call();
|
||||||
|
call.setId("123abc");
|
||||||
|
final CallMetadataSyncData callMetadataSyncData = new CallMetadataSyncData();
|
||||||
|
callMetadataSyncData.addCall(call);
|
||||||
|
final CrossDeviceSyncController.CallManager callManager =
|
||||||
|
new CrossDeviceSyncController.CallManager(mMockContext,
|
||||||
|
new CrossDeviceSyncController.PhoneAccountManager(mMockContext));
|
||||||
|
callManager.mCallIds.put(/* associationId= */ 0, Set.of(call.getId(), "fakeCallId"));
|
||||||
|
callManager.updateCalls(/* associationId= */ 0, callMetadataSyncData);
|
||||||
|
verify(mMockTelecomManager, never()).addNewIncomingCall(any(), any());
|
||||||
|
assertWithMessage("Hasn't removed the id of the removed call")
|
||||||
|
.that(callManager.mCallIds)
|
||||||
|
.containsExactly(/* associationId= */ 0, Set.of(call.getId()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user