1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.telecom.voip; 18 19 import static android.Manifest.permission.CALL_PRIVILEGED; 20 import static android.telecom.CallAttributes.CALL_CAPABILITIES_KEY; 21 import static android.telecom.CallAttributes.DISPLAY_NAME_KEY; 22 import static android.telecom.CallException.CODE_CALL_NOT_PERMITTED_AT_PRESENT_TIME; 23 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.PackageManager; 27 import android.os.Bundle; 28 import android.telecom.CallAttributes; 29 import android.telecom.TelecomManager; 30 import android.util.Log; 31 32 import com.android.server.telecom.Call; 33 import com.android.server.telecom.CallsManager; 34 import com.android.server.telecom.LoggedHandlerExecutor; 35 36 import java.util.concurrent.CompletableFuture; 37 import java.util.concurrent.CompletionStage; 38 39 public class OutgoingCallTransaction extends VoipCallTransaction { 40 41 private static final String TAG = OutgoingCallTransaction.class.getSimpleName(); 42 private final String mCallId; 43 private final Context mContext; 44 private final String mCallingPackage; 45 private final CallAttributes mCallAttributes; 46 private final CallsManager mCallsManager; 47 private final Bundle mExtras; 48 OutgoingCallTransaction(String callId, Context context, CallAttributes callAttributes, CallsManager callsManager, Bundle extras)49 public OutgoingCallTransaction(String callId, Context context, CallAttributes callAttributes, 50 CallsManager callsManager, Bundle extras) { 51 super(callsManager.getLock()); 52 mCallId = callId; 53 mContext = context; 54 mCallAttributes = callAttributes; 55 mCallsManager = callsManager; 56 mExtras = extras; 57 mCallingPackage = mContext.getOpPackageName(); 58 } 59 OutgoingCallTransaction(String callId, Context context, CallAttributes callAttributes, CallsManager callsManager)60 public OutgoingCallTransaction(String callId, Context context, CallAttributes callAttributes, 61 CallsManager callsManager) { 62 this(callId, context, callAttributes, callsManager, new Bundle()); 63 } 64 65 @Override processTransaction(Void v)66 public CompletionStage<VoipCallTransactionResult> processTransaction(Void v) { 67 Log.d(TAG, "processTransaction"); 68 69 final boolean hasCallPrivilegedPermission = mContext.checkCallingPermission( 70 CALL_PRIVILEGED) == PackageManager.PERMISSION_GRANTED; 71 72 final Intent intent = new Intent(hasCallPrivilegedPermission ? 73 Intent.ACTION_CALL_PRIVILEGED : Intent.ACTION_CALL, mCallAttributes.getAddress()); 74 75 if (mCallsManager.isOutgoingCallPermitted(mCallAttributes.getPhoneAccountHandle())) { 76 Log.d(TAG, "processTransaction: outgoing call permitted"); 77 78 CompletableFuture<Call> callFuture = 79 mCallsManager.startOutgoingCall(mCallAttributes.getAddress(), 80 mCallAttributes.getPhoneAccountHandle(), 81 generateExtras(mCallAttributes), 82 mCallAttributes.getPhoneAccountHandle().getUserHandle(), 83 intent, 84 mCallingPackage); 85 86 if (callFuture == null) { 87 return CompletableFuture.completedFuture( 88 new VoipCallTransactionResult( 89 CODE_CALL_NOT_PERMITTED_AT_PRESENT_TIME, 90 "incoming call not permitted at the current time")); 91 } 92 CompletionStage<VoipCallTransactionResult> result = callFuture.thenComposeAsync( 93 (call) -> { 94 95 Log.d(TAG, "processTransaction: completing future"); 96 97 if (call == null) { 98 Log.d(TAG, "processTransaction: call is null"); 99 return CompletableFuture.completedFuture( 100 new VoipCallTransactionResult( 101 CODE_CALL_NOT_PERMITTED_AT_PRESENT_TIME, 102 "call could not be created at this time")); 103 } else { 104 Log.d(TAG, "processTransaction: call done. id=" + call.getId()); 105 } 106 107 return CompletableFuture.completedFuture( 108 new VoipCallTransactionResult( 109 VoipCallTransactionResult.RESULT_SUCCEED, 110 call, null)); 111 } 112 , new LoggedHandlerExecutor(mHandler, "OCT.pT", null)); 113 114 return result; 115 } else { 116 return CompletableFuture.completedFuture( 117 new VoipCallTransactionResult( 118 CODE_CALL_NOT_PERMITTED_AT_PRESENT_TIME, 119 "incoming call not permitted at the current time")); 120 121 } 122 } 123 generateExtras(CallAttributes callAttributes)124 private Bundle generateExtras(CallAttributes callAttributes) { 125 mExtras.setDefusable(true); 126 mExtras.putString(TelecomManager.TRANSACTION_CALL_ID_KEY, mCallId); 127 mExtras.putInt(CALL_CAPABILITIES_KEY, callAttributes.getCallCapabilities()); 128 mExtras.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, 129 callAttributes.getCallType()); 130 mExtras.putCharSequence(DISPLAY_NAME_KEY, callAttributes.getDisplayName()); 131 return mExtras; 132 } 133 } 134