Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c877042f authored by Christine Franks's avatar Christine Franks Committed by Android (Google) Code Review
Browse files

Merge "Fix outgoing synced calls" into udc-dev

parents d731927c ebaeb8b4
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -45,10 +45,18 @@ message Telecom {
      AUDIO_PROCESSING = 5;
      RINGING_SIMULATED = 6;
      DISCONNECTED = 7;
      DIALING = 8;
    }
    Status status = 3;

    repeated Control controls = 4;

    enum Direction {
      UNKNOWN_DIRECTION = 0;
      INCOMING = 1;
      OUTGOING = 2;
    }
    Direction direction = 5;
  }

  message Request {
+24 −0
Original line number Diff line number Diff line
@@ -1415,6 +1415,30 @@ public class CompanionDeviceManagerService extends SystemService {
                mCrossDeviceSyncController.syncMessageToDevice(associationId, message);
            }
        }

        @Override
        public void sendCrossDeviceSyncMessageToAllDevices(int userId, byte[] message) {
            if (CompanionDeviceConfig.isEnabled(
                    CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
                mCrossDeviceSyncController.syncMessageToAllDevicesForUserId(userId, message);
            }
        }

        @Override
        public void addSelfOwnedCallId(String callId) {
            if (CompanionDeviceConfig.isEnabled(
                    CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
                mCrossDeviceSyncController.addSelfOwnedCallId(callId);
            }
        }

        @Override
        public void removeSelfOwnedCallId(String callId) {
            if (CompanionDeviceConfig.isEnabled(
                    CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
                mCrossDeviceSyncController.removeSelfOwnedCallId(callId);
            }
        }
    }

    /**
+9 −0
Original line number Diff line number Diff line
@@ -45,6 +45,15 @@ public interface CompanionDeviceManagerServiceInternal {
     */
    void sendCrossDeviceSyncMessage(int associationId, byte[] message);

    /** Sends the provided message to all active associations for the specified user. */
    void sendCrossDeviceSyncMessageToAllDevices(int userId, byte[] message);

    /** Mark a call id as "self owned" (i.e. this device owns the canonical call). */
    void addSelfOwnedCallId(String callId);

    /** Unmark a call id as "self owned" (i.e. this device no longer owns the canonical call). */
    void removeSelfOwnedCallId(String callId);

    /**
     * Requests a sync from an InCallService to CDM, for the given user and call metadata.
     */
+67 −13
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ import com.android.server.companion.CompanionDeviceManagerServiceInternal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.Set;

/** Service for Telecom to bind to when call metadata is synced between devices. */
public class CallMetadataSyncConnectionService extends ConnectionService {
@@ -65,11 +65,32 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
                                        associationId, call.getId()));
                        if (existingConnection != null) {
                            existingConnection.update(call);
                        } else {
                            // Check if this is an in-progress id being finalized.
                            CallMetadataSyncConnectionIdentifier key = null;
                            for (Map.Entry<CallMetadataSyncConnectionIdentifier,
                                    CallMetadataSyncConnection> e : mActiveConnections.entrySet()) {
                                if (e.getValue().getAssociationId() == associationId
                                        && !e.getValue().isIdFinalized()
                                        && call.getId().endsWith(e.getValue().getCallId())) {
                                    key = e.getKey();
                                    break;
                                }
                            }
                            if (key != null) {
                                final CallMetadataSyncConnection connection =
                                        mActiveConnections.remove(key);
                                connection.update(call);
                                mActiveConnections.put(
                                        new CallMetadataSyncConnectionIdentifier(associationId,
                                                call.getId()), connection);
                            }
                        }
                    }
                    // Remove obsolete calls.
                    mActiveConnections.values().removeIf(connection -> {
                        if (associationId == connection.getAssociationId()
                        if (connection.isIdFinalized()
                                && associationId == connection.getAssociationId()
                                && !callMetadataSyncData.hasCall(connection.getCallId())) {
                            connection.setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
                            return true;
@@ -77,6 +98,17 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
                        return false;
                    });
                }

                @Override
                void cleanUpCallIds(Set<String> callIds) {
                    mActiveConnections.values().removeIf(connection -> {
                        if (callIds.contains(connection.getCallId())) {
                            connection.setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
                            return true;
                        }
                        return false;
                    });
                }
            };

    @Override
@@ -95,10 +127,9 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
            ConnectionRequest connectionRequest) {
        final int associationId = connectionRequest.getExtras().getInt(
                CrossDeviceSyncController.EXTRA_ASSOCIATION_ID);
        final CallMetadataSyncData.Call call = connectionRequest.getExtras().getParcelable(
                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.
        final CallMetadataSyncData.Call call = CallMetadataSyncData.Call.fromBundle(
                connectionRequest.getExtras().getBundle(CrossDeviceSyncController.EXTRA_CALL));
        call.setDirection(android.companion.Telecom.Call.INCOMING);
        connectionRequest.getExtras().remove(CrossDeviceSyncController.EXTRA_CALL);
        connectionRequest.getExtras().remove(CrossDeviceSyncController.EXTRA_CALL_FACILITATOR_ID);
        connectionRequest.getExtras().remove(CrossDeviceSyncController.EXTRA_ASSOCIATION_ID);
@@ -130,18 +161,26 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
    @Override
    public Connection onCreateOutgoingConnection(PhoneAccountHandle phoneAccountHandle,
            ConnectionRequest connectionRequest) {
        final PhoneAccount phoneAccount = mTelecomManager.getPhoneAccount(phoneAccountHandle);
        final PhoneAccountHandle handle = phoneAccountHandle != null ? phoneAccountHandle
                : connectionRequest.getAccountHandle();
        final PhoneAccount phoneAccount = mTelecomManager.getPhoneAccount(handle);

        final CallMetadataSyncData.Call call = new CallMetadataSyncData.Call();
        call.setId(UUID.randomUUID().toString());
        call.setId(
                connectionRequest.getExtras().getString(CrossDeviceSyncController.EXTRA_CALL_ID));
        call.setStatus(android.companion.Telecom.Call.UNKNOWN_STATUS);
        final CallMetadataSyncData.CallFacilitator callFacilitator =
                new CallMetadataSyncData.CallFacilitator(phoneAccount.getLabel().toString(),
                        phoneAccount.getExtras().getString(
                                CrossDeviceSyncController.EXTRA_CALL_FACILITATOR_ID));
                new CallMetadataSyncData.CallFacilitator(phoneAccount != null
                        ? phoneAccount.getLabel().toString()
                        : handle.getComponentName().getShortClassName(),
                        phoneAccount != null ? phoneAccount.getExtras().getString(
                                CrossDeviceSyncController.EXTRA_CALL_FACILITATOR_ID)
                                : handle.getComponentName().getPackageName());
        call.setFacilitator(callFacilitator);
        call.setDirection(android.companion.Telecom.Call.OUTGOING);
        call.setCallerId(connectionRequest.getAddress().getSchemeSpecificPart());

        final int associationId = connectionRequest.getExtras().getInt(
        final int associationId = phoneAccount.getExtras().getInt(
                CrossDeviceSyncController.EXTRA_ASSOCIATION_ID);

        connectionRequest.getExtras().remove(CrossDeviceSyncController.EXTRA_CALL);
@@ -160,13 +199,15 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
                                CrossDeviceSyncController.createCallControlMessage(callId, action));
                    }
                });
        connection.setConnectionProperties(Connection.PROPERTY_IS_EXTERNAL_CALL);
        connection.setCallerDisplayName(call.getCallerId(), TelecomManager.PRESENTATION_ALLOWED);

        mCdmsi.addSelfOwnedCallId(call.getId());
        mCdmsi.sendCrossDeviceSyncMessage(associationId,
                CrossDeviceSyncController.createCallCreateMessage(call.getId(),
                        connectionRequest.getAddress().toString(),
                        call.getFacilitator().getIdentifier()));

        connection.setInitializing();
        return connection;
    }

@@ -240,6 +281,7 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
        private final int mAssociationId;
        private final CallMetadataSyncData.Call mCall;
        private final CallMetadataSyncConnectionCallback mCallback;
        private boolean mIsIdFinalized;

        CallMetadataSyncConnection(TelecomManager telecomManager, AudioManager audioManager,
                int associationId, CallMetadataSyncData.Call call,
@@ -259,6 +301,10 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
            return mAssociationId;
        }

        public boolean isIdFinalized() {
            return mIsIdFinalized;
        }

        private void initialize() {
            final int status = mCall.getStatus();
            if (status == android.companion.Telecom.Call.RINGING_SILENCED) {
@@ -273,6 +319,8 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
                setOnHold();
            } else if (state == Call.STATE_DISCONNECTED) {
                setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
            } else if (state == Call.STATE_DIALING) {
                setDialing();
            } else {
                setInitialized();
            }
@@ -307,6 +355,10 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
        }

        private void update(CallMetadataSyncData.Call call) {
            if (!mIsIdFinalized) {
                mCall.setId(call.getId());
                mIsIdFinalized = true;
            }
            final int status = call.getStatus();
            if (status == android.companion.Telecom.Call.RINGING_SILENCED
                    && mCall.getStatus() != android.companion.Telecom.Call.RINGING_SILENCED) {
@@ -323,6 +375,8 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
                    setOnHold();
                } else if (state == Call.STATE_DISCONNECTED) {
                    setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
                } else if (state == Call.STATE_DIALING) {
                    setDialing();
                } else {
                    Slog.e(TAG, "Could not update call to unknown state");
                }
+56 −72
Original line number Diff line number Diff line
@@ -16,10 +16,8 @@

package com.android.server.companion.datatransfer.contextsync;

import android.annotation.NonNull;
import android.companion.ContextSyncMessage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Bundle;

import java.util.ArrayList;
import java.util.Collection;
@@ -74,9 +72,10 @@ class CallMetadataSyncData {
        return mCallFacilitators;
    }

    public static class CallFacilitator implements Parcelable {
    public static class CallFacilitator {
        private String mName;
        private String mIdentifier;
        private boolean mIsTel;

        CallFacilitator() {}

@@ -85,16 +84,6 @@ class CallMetadataSyncData {
            mIdentifier = identifier;
        }

        CallFacilitator(Parcel parcel) {
            this(parcel.readString(), parcel.readString());
        }

        @Override
        public void writeToParcel(Parcel parcel, int parcelableFlags) {
            parcel.writeString(mName);
            parcel.writeString(mIdentifier);
        }

        public String getName() {
            return mName;
        }
@@ -103,6 +92,10 @@ class CallMetadataSyncData {
            return mIdentifier;
        }

        public boolean isTel() {
            return mIsTel;
        }

        public void setName(String name) {
            mName = name;
        }
@@ -111,25 +104,9 @@ class CallMetadataSyncData {
            mIdentifier = identifier;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @NonNull
        public static final Parcelable.Creator<CallFacilitator> CREATOR =
                new Parcelable.Creator<>() {

                    @Override
                    public CallFacilitator createFromParcel(Parcel source) {
                        return new CallFacilitator(source);
                    }

                    @Override
                    public CallFacilitator[] newArray(int size) {
                        return new CallFacilitator[size];
        public void setIsTel(boolean isTel) {
            mIsTel = isTel;
        }
                };
    }

    public static class CallControlRequest {
@@ -183,40 +160,57 @@ class CallMetadataSyncData {
        }
    }

    public static class Call implements Parcelable {
    public static class Call {

        private static final String EXTRA_CALLER_ID =
                "com.android.server.companion.datatransfer.contextsync.extra.CALLER_ID";
        private static final String EXTRA_APP_ICON =
                "com.android.server.companion.datatransfer.contextsync.extra.APP_ICON";
        private static final String EXTRA_FACILITATOR_NAME =
                "com.android.server.companion.datatransfer.contextsync.extra.FACILITATOR_NAME";
        private static final String EXTRA_FACILITATOR_ID =
                "com.android.server.companion.datatransfer.contextsync.extra.FACILITATOR_ID";
        private static final String EXTRA_STATUS =
                "com.android.server.companion.datatransfer.contextsync.extra.STATUS";
        private static final String EXTRA_DIRECTION =
                "com.android.server.companion.datatransfer.contextsync.extra.DIRECTION";
        private static final String EXTRA_CONTROLS =
                "com.android.server.companion.datatransfer.contextsync.extra.CONTROLS";
        private String mId;
        private String mCallerId;
        private byte[] mAppIcon;
        private CallFacilitator mFacilitator;
        private int mStatus;
        private int mDirection;
        private final Set<Integer> mControls = new HashSet<>();

        public static Call fromParcel(Parcel parcel) {
        public static Call fromBundle(Bundle bundle) {
            final Call call = new Call();
            call.setId(parcel.readString());
            call.setCallerId(parcel.readString());
            call.setAppIcon(parcel.readBlob());
            call.setFacilitator(parcel.readParcelable(CallFacilitator.class.getClassLoader(),
                    CallFacilitator.class));
            call.setStatus(parcel.readInt());
            final int numberOfControls = parcel.readInt();
            for (int i = 0; i < numberOfControls; i++) {
                call.addControl(parcel.readInt());
            if (bundle != null) {
                call.setId(bundle.getString(CrossDeviceSyncController.EXTRA_CALL_ID));
                call.setCallerId(bundle.getString(EXTRA_CALLER_ID));
                call.setAppIcon(bundle.getByteArray(EXTRA_APP_ICON));
                final String facilitatorName = bundle.getString(EXTRA_FACILITATOR_NAME);
                final String facilitatorIdentifier = bundle.getString(EXTRA_FACILITATOR_ID);
                call.setFacilitator(new CallFacilitator(facilitatorName, facilitatorIdentifier));
                call.setStatus(bundle.getInt(EXTRA_STATUS));
                call.setDirection(bundle.getInt(EXTRA_DIRECTION));
                call.setControls(new HashSet<>(bundle.getIntegerArrayList(EXTRA_CONTROLS)));
            }
            return call;
        }

        @Override
        public void writeToParcel(Parcel parcel, int parcelableFlags) {
            parcel.writeString(mId);
            parcel.writeString(mCallerId);
            parcel.writeBlob(mAppIcon);
            parcel.writeParcelable(mFacilitator, parcelableFlags);
            parcel.writeInt(mStatus);
            parcel.writeInt(mControls.size());
            for (int control : mControls) {
                parcel.writeInt(control);
            }
        public Bundle writeToBundle() {
            final Bundle bundle = new Bundle();
            bundle.putString(CrossDeviceSyncController.EXTRA_CALL_ID, mId);
            bundle.putString(EXTRA_CALLER_ID, mCallerId);
            bundle.putByteArray(EXTRA_APP_ICON, mAppIcon);
            bundle.putString(EXTRA_FACILITATOR_NAME, mFacilitator.getName());
            bundle.putString(EXTRA_FACILITATOR_ID, mFacilitator.getIdentifier());
            bundle.putInt(EXTRA_STATUS, mStatus);
            bundle.putInt(EXTRA_DIRECTION, mDirection);
            bundle.putIntegerArrayList(EXTRA_CONTROLS, new ArrayList<>(mControls));
            return bundle;
        }

        void setId(String id) {
@@ -239,6 +233,10 @@ class CallMetadataSyncData {
            mStatus = status;
        }

        void setDirection(int direction) {
            mDirection = direction;
        }

        void addControl(int control) {
            mControls.add(control);
        }
@@ -268,6 +266,10 @@ class CallMetadataSyncData {
            return mStatus;
        }

        int getDirection() {
            return mDirection;
        }

        Set<Integer> getControls() {
            return mControls;
        }
@@ -288,23 +290,5 @@ class CallMetadataSyncData {
        public int hashCode() {
            return Objects.hashCode(mId);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @NonNull public static final Parcelable.Creator<Call> CREATOR = new Parcelable.Creator<>() {

            @Override
            public Call createFromParcel(Parcel source) {
                return Call.fromParcel(source);
            }

            @Override
            public Call[] newArray(int size) {
                return new Call[size];
            }
        };
    }
}
Loading