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

Commit 49727b3b authored by Thomas Stuart's avatar Thomas Stuart Committed by Android (Google) Code Review
Browse files

Merge "impl transactional video API methods" into main

parents 945b738d 3a863ee7
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -29,6 +29,13 @@ flag{
  bug: "310669304"
}

flag{
  name: "transactional_video_state"
  namespace: "telecom"
  description: "when set, clients using transactional implementations will be able to set & get the video state"
  bug: "311265260"
}

flag{
  name: "business_call_composer"
  namespace: "telecom"
+47 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.server.telecom;
import static android.provider.CallLog.Calls.MISSED_REASON_NOT_MISSED;
import static android.telephony.TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE;

import static com.android.server.telecom.voip.VideoStateTranslation.VideoProfileStateToTransactionalVideoState;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -651,6 +653,36 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
     */
    private boolean mIsVideoCallingSupportedByPhoneAccount = false;

    /**
     * Indicates whether this individual calls video state can be changed as opposed to be gated
     * by the {@link PhoneAccount}.
     *
     * {@code True} if the call is Transactional && has the CallAttributes.SUPPORTS_VIDEO_CALLING
     * capability {@code false} otherwise.
     */
    private boolean mTransactionalCallSupportsVideoCalling = false;

    public void setTransactionalCallSupportsVideoCalling(CallAttributes callAttributes) {
        if (!mIsTransactionalCall) {
            Log.i(this, "setTransactionalCallSupportsVideoCalling: call is not transactional");
            return;
        }
        if (callAttributes == null) {
            Log.i(this, "setTransactionalCallSupportsVideoCalling: callAttributes is null");
            return;
        }
        if ((callAttributes.getCallCapabilities() & CallAttributes.SUPPORTS_VIDEO_CALLING)
                == CallAttributes.SUPPORTS_VIDEO_CALLING) {
            mTransactionalCallSupportsVideoCalling = true;
        } else {
            mTransactionalCallSupportsVideoCalling = false;
        }
    }

    public boolean isTransactionalCallSupportsVideoCalling() {
        return mTransactionalCallSupportsVideoCalling;
    }

    /**
     * Indicates whether or not this call can be pulled if it is an external call. If true, respect
     * the Connection Capability set by the ConnectionService. If false, override the capability
@@ -4022,6 +4054,15 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
            videoState = VideoProfile.STATE_AUDIO_ONLY;
        }

        // Transactional calls have the ability to change video calling capabilities on a per-call
        // basis as opposed to ConnectionService calls which are only based on the PhoneAccount.
        if (mFlags.transactionalVideoState()
                && mIsTransactionalCall && !mTransactionalCallSupportsVideoCalling) {
            Log.i(this, "setVideoState: The transactional does NOT support video calling."
                    + " defaulted to audio (video not supported)");
            videoState = VideoProfile.STATE_AUDIO_ONLY;
        }

        // Track Video State history during the duration of the call.
        // Only update the history when the call is active or disconnected. This ensures we do
        // not include the video state history when:
@@ -4044,6 +4085,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
            }
        }

        if (mFlags.transactionalVideoState()
                && mIsTransactionalCall && mTransactionalService != null) {
            int transactionalVS = VideoProfileStateToTransactionalVideoState(mVideoState);
            mTransactionalService.onVideoStateChanged(this, transactionalVS);
        }

        if (VideoProfile.isVideo(videoState)) {
            mAnalytics.setCallIsVideo(true);
        }
+3 −0
Original line number Diff line number Diff line
@@ -239,6 +239,9 @@ public class TelecomServiceImpl {
                                                callEventCallback, mCallsManager, call);

                        call.setTransactionServiceWrapper(serviceWrapper);
                        if (mFeatureFlags.transactionalVideoState()) {
                            call.setTransactionalCallSupportsVideoCalling(callAttributes);
                        }
                        ICallControl clientCallControl = serviceWrapper.getICallControl();

                        if (clientCallControl == null) {
+27 −1
Original line number Diff line number Diff line
@@ -43,10 +43,10 @@ import com.android.server.telecom.voip.EndpointChangeTransaction;
import com.android.server.telecom.voip.HoldCallTransaction;
import com.android.server.telecom.voip.EndCallTransaction;
import com.android.server.telecom.voip.MaybeHoldCallForNewCallTransaction;
import com.android.server.telecom.voip.ParallelTransaction;
import com.android.server.telecom.voip.RequestNewActiveCallTransaction;
import com.android.server.telecom.voip.SerialTransaction;
import com.android.server.telecom.voip.SetMuteStateTransaction;
import com.android.server.telecom.voip.RequestVideoStateTransaction;
import com.android.server.telecom.voip.TransactionManager;
import com.android.server.telecom.voip.VoipCallTransaction;
import com.android.server.telecom.voip.VoipCallTransactionResult;
@@ -71,6 +71,7 @@ public class TransactionalServiceWrapper implements
    public static final String ANSWER = "Answer";
    public static final String DISCONNECT = "Disconnect";
    public static final String START_STREAMING = "StartStreaming";
    public static final String REQUEST_VIDEO_STATE = "RequestVideoState";

    // CallEventCallback : Telecom --> Client (ex. voip app)
    public static final String ON_SET_ACTIVE = "onSetActive";
@@ -248,6 +249,17 @@ public class TransactionalServiceWrapper implements
            }
        }

        @Override
        public void requestVideoState(int videoState, String callId, ResultReceiver callback)
                throws RemoteException {
            try {
                Log.startSession("TSW.rVS");
                createTransactions(callId, callback, REQUEST_VIDEO_STATE, videoState);
            } finally {
                Log.endSession();
            }
        }

        private void createTransactions(String callId, ResultReceiver callback, String action,
                Object... objects) {
            Log.d(TAG, "createTransactions: callId=" + callId);
@@ -274,6 +286,11 @@ public class TransactionalServiceWrapper implements
                        addTransactionsToManager(mStreamingController.getStartStreamingTransaction(mCallsManager,
                                TransactionalServiceWrapper.this, call, mLock), callback);
                        break;
                    case REQUEST_VIDEO_STATE:
                        addTransactionsToManager(
                                new RequestVideoStateTransaction(mCallsManager, call,
                                        (int) objects[0]), callback);
                        break;
                }
            } else {
                Bundle exceptionBundle = new Bundle();
@@ -562,6 +579,15 @@ public class TransactionalServiceWrapper implements
        }
    }

    public void onVideoStateChanged(Call call, int videoState) {
        if (call != null) {
            try {
                mICallEventCallback.onVideoStateChanged(call.getId(), videoState);
            } catch (RemoteException e) {
            }
        }
    }

    public void removeCallFromWrappers(Call call) {
        if (call != null) {
            try {
+70 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.telecom.voip;

import static com.android.server.telecom.voip.VideoStateTranslation.TransactionalVideoStateToVideoProfileState;

import android.telecom.VideoProfile;
import android.util.Log;

import com.android.server.telecom.CallsManager;
import com.android.server.telecom.Call;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

public class RequestVideoStateTransaction extends VoipCallTransaction {

    private static final String TAG = RequestVideoStateTransaction.class.getSimpleName();
    private final Call mCall;
    private final int mVideoProfileState;

    public RequestVideoStateTransaction(CallsManager callsManager, Call call,
            int transactionalVideoState) {
        super(callsManager.getLock());
        mCall = call;
        mVideoProfileState = TransactionalVideoStateToVideoProfileState(transactionalVideoState);
    }

    @Override
    public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) {
        Log.d(TAG, "processTransaction");
        CompletableFuture<VoipCallTransactionResult> future = new CompletableFuture<>();

        if (isRequestingVideoTransmission(mVideoProfileState) &&
                !mCall.isVideoCallingSupportedByPhoneAccount()) {
            future.complete(new VoipCallTransactionResult(
                    VoipCallTransactionResult.RESULT_FAILED,
                    "Video calling is not supported by the target account"));
        } else if (isRequestingVideoTransmission(mVideoProfileState) &&
                !mCall.isTransactionalCallSupportsVideoCalling()) {
            future.complete(new VoipCallTransactionResult(
                    VoipCallTransactionResult.RESULT_FAILED,
                    "Video calling is not supported according to the callAttributes"));
        } else {
            mCall.setVideoState(mVideoProfileState);
            future.complete(new VoipCallTransactionResult(
                    VoipCallTransactionResult.RESULT_SUCCEED,
                    "The Video State was changed successfully"));
        }
        return future;
    }

    private boolean isRequestingVideoTransmission(int targetVideoState) {
        return targetVideoState != VideoProfile.STATE_AUDIO_ONLY;
    }
}
 No newline at end of file
Loading