186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn/* 286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Copyright (C) 2015 The Android Open Source Project 386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Licensed under the Apache License, Version 2.0 (the "License"); 586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * you may not use this file except in compliance with the License. 686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * You may obtain a copy of the License at 786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * http://www.apache.org/licenses/LICENSE-2.0 986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 1086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Unless required by applicable law or agreed to in writing, software 1186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * distributed under the License is distributed on an "AS IS" BASIS, 1286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * See the License for the specific language governing permissions and 1486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * limitations under the License 1586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 1686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 1786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnpackage com.android.server.telecom; 1886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 19a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunnimport android.Manifest; 20a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunnimport android.app.AppOpsManager; 21a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunnimport android.content.Context; 2286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport android.net.Uri; 23a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunnimport android.os.Binder; 24115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunnimport android.os.Build; 2586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport android.os.IBinder; 2686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport android.os.Looper; 2786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport android.os.RemoteException; 281bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunnimport android.os.UserHandle; 2986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport android.telecom.Connection; 3086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport android.telecom.InCallService; 31a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Log; 3286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport android.telecom.VideoProfile; 33a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunnimport android.text.TextUtils; 3486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport android.view.Surface; 3586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 3686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport com.android.internal.telecom.IVideoCallback; 3786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport com.android.internal.telecom.IVideoProvider; 3886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 3986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport java.util.Collections; 4086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport java.util.Set; 4186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnimport java.util.concurrent.ConcurrentHashMap; 4286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 43a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunnimport static android.Manifest.permission.CALL_PHONE; 44a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn 4586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn/** 4686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies video provider messages from {@link InCallService.VideoCall} 4786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * implementations to the underlying {@link Connection.VideoProvider} implementation. Also proxies 4886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * callbacks from the {@link Connection.VideoProvider} to {@link InCallService.VideoCall} 4986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * implementations. 5086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 5186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Also provides a means for Telecom to send and receive these messages. 5286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 5386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunnpublic class VideoProviderProxy extends Connection.VideoProvider { 5486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 5586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 5686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Listener for Telecom components interested in callbacks from the video provider. 5786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 5886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn interface Listener { 5986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn void onSessionModifyRequestReceived(Call call, VideoProfile videoProfile); 6086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 6186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 6286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 6386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Set of listeners on this VideoProviderProxy. 6486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 6586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 6686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * load factor before resizing, 1 means we only expect a single thread to 6786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * access the map so make only a single shard 6886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 6986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn private final Set<Listener> mListeners = Collections.newSetFromMap( 7086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); 7186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 7286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** The TelecomSystem SyncRoot used for synchronized operations. */ 7386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn private final TelecomSystem.SyncRoot mLock; 7486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 7586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 7686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * The {@link android.telecom.Connection.VideoProvider} implementation residing with the 7786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link android.telecom.ConnectionService} which is being wrapped by this 7886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link VideoProviderProxy}. 7986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 8086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn private final IVideoProvider mConectionServiceVideoProvider; 8186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 8286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 8386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Binder used to bind to the {@link android.telecom.ConnectionService}'s 8486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link com.android.internal.telecom.IVideoCallback}. 8586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 8686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn private final VideoCallListenerBinder mVideoCallListenerBinder; 8786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 8886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 8986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * The Telecom {@link Call} this {@link VideoProviderProxy} is associated with. 9086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 9186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn private Call mCall; 9286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 931bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn /** 941bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn * Interface providing access to the currently logged in user. 951bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn */ 961bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn private CurrentUserProxy mCurrentUserProxy; 971bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn 9886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { 9986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 10086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void binderDied() { 10186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.asBinder().unlinkToDeath(this, 0); 10286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 10386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn }; 10486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 10586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 10686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Creates a new instance of the {@link VideoProviderProxy}, binding it to the passed in 10786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@code videoProvider} residing with the {@link android.telecom.ConnectionService}. 10886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 10986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 11086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param lock 11186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param videoProvider The {@link android.telecom.ConnectionService}'s video provider. 11286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param call The current call. 11386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @throws RemoteException Remote exception. 11486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 11586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn VideoProviderProxy(TelecomSystem.SyncRoot lock, 1161bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn IVideoProvider videoProvider, Call call, CurrentUserProxy currentUserProxy) 1171bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn throws RemoteException { 11886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 11986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn super(Looper.getMainLooper()); 12086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 12186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mLock = lock; 12286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 12386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider = videoProvider; 12486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0); 12586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 12686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mVideoCallListenerBinder = new VideoCallListenerBinder(); 12786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.addVideoCallback(mVideoCallListenerBinder); 12886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mCall = call; 1291bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn mCurrentUserProxy = currentUserProxy; 13086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 13186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 13286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 13386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * IVideoCallback stub implementation. An instance of this class receives callbacks from the 13486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@code ConnectionService}'s video provider. 13586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 13686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn private final class VideoCallListenerBinder extends IVideoCallback.Stub { 13786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 13886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link #mConectionServiceVideoProvider} to the 13986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link InCallService} when a session modification request is received. 14086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 14186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param videoProfile The requested video profile. 14286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 14386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 14486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void receiveSessionModifyRequest(VideoProfile videoProfile) { 1453165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger try { 1463165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger Log.startSession("VPP.rSMR"); 1473165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger synchronized (mLock) { 1483165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger logFromVideoProvider("receiveSessionModifyRequest: " + videoProfile); 149a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger Log.addEvent(mCall, LogUtils.Events.RECEIVE_VIDEO_REQUEST, 15070d6f858f10a77277c63aafcaa1f113f647117a6Tyler Gunn VideoProfile.videoStateToString(videoProfile.getVideoState())); 15186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 1524640c4fc55ca4118351330d68684ca9989661ccdHall Liu mCall.getAnalytics().addVideoEvent( 1534640c4fc55ca4118351330d68684ca9989661ccdHall Liu Analytics.RECEIVE_REMOTE_SESSION_MODIFY_REQUEST, 1544640c4fc55ca4118351330d68684ca9989661ccdHall Liu videoProfile.getVideoState()); 15513e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn 15613e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn if (!mCall.isVideoCallingSupported() && 15713e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn VideoProfile.isVideo(videoProfile.getVideoState())) { 15813e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn // If video calling is not supported by the phone account, and we receive 15913e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn // a request to upgrade to video, automatically reject it without informing 16013e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn // the InCallService. 16113e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn 162a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_RESPONSE, "video not supported"); 16313e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn VideoProfile responseProfile = new VideoProfile( 16413e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn VideoProfile.STATE_AUDIO_ONLY); 16513e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn try { 16613e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn mConectionServiceVideoProvider.sendSessionModifyResponse( 16713e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn responseProfile); 16813e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn } catch (RemoteException e) { 16913e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn } 17013e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn 17113e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn // Don't want to inform listeners of the request as we've just rejected it. 17213e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn return; 17313e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn } 17413e8a6938eb5db779ea41f82f00916363ad09aa6Tyler Gunn 1753165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger // Inform other Telecom components of the session modification request. 1763165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger for (Listener listener : mListeners) { 1773165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger listener.onSessionModifyRequestReceived(mCall, videoProfile); 1783165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger } 17986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 1803165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger VideoProviderProxy.this.receiveSessionModifyRequest(videoProfile); 1813165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger } 1823165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger } finally { 1833165d50d3fc688d632faecfae9c2f987e537941fBrad Ebinger Log.endSession(); 18486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 18586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 18686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 18786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 18886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link #mConectionServiceVideoProvider} to the 18986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link InCallService} when a session modification response is received. 19086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 19186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param status The status of the response. 19286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param requestProfile The requested video profile. 19386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param responseProfile The response video profile. 19486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 19586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 19686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void receiveSessionModifyResponse(int status, VideoProfile requestProfile, 19786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn VideoProfile responseProfile) { 19810f8cd2c3f51b2fb3dc1d70ceac6bd6127f860d5Brad Ebinger logFromVideoProvider("receiveSessionModifyResponse: status=" + status + 19910f8cd2c3f51b2fb3dc1d70ceac6bd6127f860d5Brad Ebinger " requestProfile=" + requestProfile + " responseProfile=" + responseProfile); 20010f8cd2c3f51b2fb3dc1d70ceac6bd6127f860d5Brad Ebinger String eventMessage = "Status Code : " + status + " Video State: " + 20110f8cd2c3f51b2fb3dc1d70ceac6bd6127f860d5Brad Ebinger (responseProfile != null ? responseProfile.getVideoState() : "null"); 202a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger Log.addEvent(mCall, LogUtils.Events.RECEIVE_VIDEO_RESPONSE, eventMessage); 20386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 20410f8cd2c3f51b2fb3dc1d70ceac6bd6127f860d5Brad Ebinger if (status == Connection.VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS) { 20510f8cd2c3f51b2fb3dc1d70ceac6bd6127f860d5Brad Ebinger mCall.getAnalytics().addVideoEvent( 20610f8cd2c3f51b2fb3dc1d70ceac6bd6127f860d5Brad Ebinger Analytics.RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE, 2072f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu responseProfile == null ? 2082f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu VideoProfile.STATE_AUDIO_ONLY : 2092f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu responseProfile.getVideoState()); 21010f8cd2c3f51b2fb3dc1d70ceac6bd6127f860d5Brad Ebinger } 21186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn VideoProviderProxy.this.receiveSessionModifyResponse(status, requestProfile, 21286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn responseProfile); 21386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 21486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 21586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 21686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 21786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link #mConectionServiceVideoProvider} to the 21886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link InCallService} when a call session event occurs. 21986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 22086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param event The call session event. 22186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 22286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 22386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void handleCallSessionEvent(int event) { 22486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 22533e453811b7dc0af47301d1aa22384de3d464da4Tyler Gunn logFromVideoProvider("handleCallSessionEvent: " + 22633e453811b7dc0af47301d1aa22384de3d464da4Tyler Gunn Connection.VideoProvider.sessionEventToString(event)); 22786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn VideoProviderProxy.this.handleCallSessionEvent(event); 22886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 22986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 23086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 23186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 23286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link #mConectionServiceVideoProvider} to the 23386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link InCallService} when the peer dimensions change. 23486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 23586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param width The width of the peer's video. 23686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param height The height of the peer's video. 23786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 23886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 23986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void changePeerDimensions(int width, int height) { 24086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 24186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromVideoProvider("changePeerDimensions: width=" + width + " height=" + 24286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn height); 24386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn VideoProviderProxy.this.changePeerDimensions(width, height); 24486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 24586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 24686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 24786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 24886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link #mConectionServiceVideoProvider} to the 24986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link InCallService} when the video quality changes. 25086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 25186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param videoQuality The video quality. 25286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 25386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 25486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void changeVideoQuality(int videoQuality) { 25586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 25686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromVideoProvider("changeVideoQuality: " + videoQuality); 25786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn VideoProviderProxy.this.changeVideoQuality(videoQuality); 25886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 25986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 26086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 26186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 26286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link #mConectionServiceVideoProvider} to the 26386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link InCallService} when the call data usage changes. 26486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 2657a1f8239f7d22faef49c1f89de522e908e2e43f8Tyler Gunn * Also tracks the current call data usage on the {@link Call} for use when writing to the 2667a1f8239f7d22faef49c1f89de522e908e2e43f8Tyler Gunn * call log. 2677a1f8239f7d22faef49c1f89de522e908e2e43f8Tyler Gunn * 26886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param dataUsage The data usage. 26986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 27086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 27186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void changeCallDataUsage(long dataUsage) { 27286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 27386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromVideoProvider("changeCallDataUsage: " + dataUsage); 27486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn VideoProviderProxy.this.setCallDataUsage(dataUsage); 2757a1f8239f7d22faef49c1f89de522e908e2e43f8Tyler Gunn mCall.setCallDataUsage(dataUsage); 27686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 27786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 27886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 27986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 28086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link #mConectionServiceVideoProvider} to the 28186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link InCallService} when the camera capabilities change. 28286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 28386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param cameraCapabilities The camera capabilities. 28486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 28586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 28686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) { 28786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 28886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromVideoProvider("changeCameraCapabilities: " + cameraCapabilities); 28986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn VideoProviderProxy.this.changeCameraCapabilities(cameraCapabilities); 29086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 29186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 29286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 29386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 294a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn @Override 295a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn public void onSetCamera(String cameraId) { 296a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn // No-op. We implement the other prototype of onSetCamera so that we can use the calling 297a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn // package, uid and pid to verify permission. 298a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn } 299a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn 30086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 30186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link InCallService} to the 30286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link #mConectionServiceVideoProvider} to change the camera. 30386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 30486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param cameraId The id of the camera. 305a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn * @param callingPackage The package calling in. 306a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn * @param callingUid The UID of the caller. 307a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn * @param callingPid The PID of the caller. 308115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn * @param targetSdkVersion The target SDK version of the calling InCallService where the camera 309115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn * request originated. 31086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 31186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 312a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn public void onSetCamera(String cameraId, String callingPackage, int callingUid, 313115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn int callingPid, int targetSdkVersion) { 31486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 3151bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn logFromInCall("setCamera: " + cameraId + " callingPackage=" + callingPackage + 3161bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn "; callingUid=" + callingUid); 317a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn 318a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn if (!TextUtils.isEmpty(cameraId)) { 319a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn if (!canUseCamera(mCall.getContext(), callingPackage, callingUid, callingPid)) { 320a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn // Calling app is not permitted to use the camera. Ignore the request and send 321a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn // back a call session event indicating the error. 322772fdf6e57e44ced7d969eccedfe8cab2713e0d6Garik Badalyan Log.i(this, "onSetCamera: camera permission denied; package=%s, uid=%d, " 323115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn + "pid=%d, targetSdkVersion=%d", 324115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn callingPackage, callingUid, callingPid, targetSdkVersion); 325115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn 326115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn // API 26 introduces a new camera permission error we can use here since the 327115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn // caller supports that API version. 328115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn if (targetSdkVersion > Build.VERSION_CODES.N_MR1) { 329115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn VideoProviderProxy.this.handleCallSessionEvent( 330115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn Connection.VideoProvider.SESSION_EVENT_CAMERA_PERMISSION_ERROR); 331115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn } else { 332115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn VideoProviderProxy.this.handleCallSessionEvent( 333115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn Connection.VideoProvider.SESSION_EVENT_CAMERA_FAILURE); 334115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn } 335a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn return; 336a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn } 337a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn } 33886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn try { 339115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn mConectionServiceVideoProvider.setCamera(cameraId, callingPackage, 340115c06ee64e209cda99abdc1fbd23fd65aa6da47Tyler Gunn targetSdkVersion); 34186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } catch (RemoteException e) { 342a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn VideoProviderProxy.this.handleCallSessionEvent( 343a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn Connection.VideoProvider.SESSION_EVENT_CAMERA_FAILURE); 34486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 34586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 34686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 34786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 34886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 34986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link InCallService} to the 35086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link #mConectionServiceVideoProvider} to set the preview surface. 35186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 35286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param surface The surface. 35386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 35486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 35586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void onSetPreviewSurface(Surface surface) { 35686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 35786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromInCall("setPreviewSurface"); 35886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn try { 35986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.setPreviewSurface(surface); 36086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } catch (RemoteException e) { 36186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 36286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 36386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 36486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 36586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 36686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link InCallService} to the 36786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link #mConectionServiceVideoProvider} to change the display surface. 36886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 36986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param surface The surface. 37086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 37186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 37286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void onSetDisplaySurface(Surface surface) { 37386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 37486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromInCall("setDisplaySurface"); 37586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn try { 37686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.setDisplaySurface(surface); 37786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } catch (RemoteException e) { 37886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 37986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 38086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 38186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 38286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 38386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link InCallService} to the 38486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link #mConectionServiceVideoProvider} to change the device orientation. 38586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 38686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param rotation The device orientation, in degrees. 38786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 38886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 38986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void onSetDeviceOrientation(int rotation) { 39086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 39186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromInCall("setDeviceOrientation: " + rotation); 39286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn try { 39386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.setDeviceOrientation(rotation); 39486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } catch (RemoteException e) { 39586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 39686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 39786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 39886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 39986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 40086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link InCallService} to the 40186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link #mConectionServiceVideoProvider} to change the camera zoom ratio. 40286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 40386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param value The camera zoom ratio. 40486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 40586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 40686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void onSetZoom(float value) { 40786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 40886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromInCall("setZoom: " + value); 40986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn try { 41086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.setZoom(value); 41186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } catch (RemoteException e) { 41286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 41386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 41486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 41586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 41686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 41786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link InCallService} to the 41886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link #mConectionServiceVideoProvider} to provide a response to a session modification 41986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * request. 42086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 42186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param fromProfile The video properties prior to the request. 42286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param toProfile The video properties with the requested changes made. 42386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 42486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 42586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) { 42686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 42786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromInCall("sendSessionModifyRequest: from=" + fromProfile + " to=" + toProfile); 428a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_REQUEST, 42970d6f858f10a77277c63aafcaa1f113f647117a6Tyler Gunn VideoProfile.videoStateToString(toProfile.getVideoState())); 4304640c4fc55ca4118351330d68684ca9989661ccdHall Liu mCall.getAnalytics().addVideoEvent( 4314640c4fc55ca4118351330d68684ca9989661ccdHall Liu Analytics.SEND_LOCAL_SESSION_MODIFY_REQUEST, 4324640c4fc55ca4118351330d68684ca9989661ccdHall Liu toProfile.getVideoState()); 43386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn try { 43486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.sendSessionModifyRequest(fromProfile, toProfile); 43586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } catch (RemoteException e) { 43686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 43786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 43886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 43986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 44086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 44186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link InCallService} to the 44286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link #mConectionServiceVideoProvider} to send a session modification request. 44386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 44486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param responseProfile The response connection video properties. 44586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 44686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 44786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void onSendSessionModifyResponse(VideoProfile responseProfile) { 44886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 44986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromInCall("sendSessionModifyResponse: " + responseProfile); 450a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_RESPONSE, 45170d6f858f10a77277c63aafcaa1f113f647117a6Tyler Gunn VideoProfile.videoStateToString(responseProfile.getVideoState())); 4524640c4fc55ca4118351330d68684ca9989661ccdHall Liu mCall.getAnalytics().addVideoEvent( 4534640c4fc55ca4118351330d68684ca9989661ccdHall Liu Analytics.SEND_LOCAL_SESSION_MODIFY_RESPONSE, 4544640c4fc55ca4118351330d68684ca9989661ccdHall Liu responseProfile.getVideoState()); 45586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn try { 45686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.sendSessionModifyResponse(responseProfile); 45786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } catch (RemoteException e) { 45886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 45986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 46086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 46186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 46286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 46386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link InCallService} to the 46486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link #mConectionServiceVideoProvider} to request the camera capabilities. 46586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 46686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 46786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void onRequestCameraCapabilities() { 46886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 46986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromInCall("requestCameraCapabilities"); 47086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn try { 47186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.requestCameraCapabilities(); 47286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } catch (RemoteException e) { 47386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 47486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 47586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 47686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 47786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 47886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link InCallService} to the 47986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link #mConectionServiceVideoProvider} to request the connection data usage. 48086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 48186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 48286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void onRequestConnectionDataUsage() { 48386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 48486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromInCall("requestCallDataUsage"); 48586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn try { 48686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.requestCallDataUsage(); 48786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } catch (RemoteException e) { 48886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 48986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 49086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 49186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 49286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 49386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Proxies a request from the {@link InCallService} to the 49486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link #mConectionServiceVideoProvider} to set the pause image. 49586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 49686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param uri URI of image to display. 49786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 49886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn @Override 49986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void onSetPauseImage(Uri uri) { 50086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn synchronized (mLock) { 50186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn logFromInCall("setPauseImage: " + uri); 50286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn try { 50386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mConectionServiceVideoProvider.setPauseImage(uri); 50486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } catch (RemoteException e) { 50586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 50686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 50786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 50886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 50986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 51086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Add a listener to this {@link VideoProviderProxy}. 51186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 51286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param listener The listener. 51386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 51486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void addListener(Listener listener) { 51586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mListeners.add(listener); 51686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 51786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 51886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 51986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Remove a listener from this {@link VideoProviderProxy}. 52086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 52186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param listener The listener. 52286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 52386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public void removeListener(Listener listener) { 52486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn if (listener != null) { 52586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn mListeners.remove(listener); 52686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 52786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 52886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 52986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 53086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Logs a message originating from the {@link InCallService}. 53186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 53286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param toLog The message to log. 53386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 53486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn private void logFromInCall(String toLog) { 53533e453811b7dc0af47301d1aa22384de3d464da4Tyler Gunn Log.i(this, "IC->VP (callId=" + (mCall == null ? "?" : mCall.getId()) + "): " + toLog); 53686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 53786014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn 53886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn /** 53986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * Logs a message originating from the {@link android.telecom.ConnectionService}'s 54086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * {@link Connection.VideoProvider}. 54186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * 54286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn * @param toLog The message to log. 54386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn */ 54486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn private void logFromVideoProvider(String toLog) { 54533e453811b7dc0af47301d1aa22384de3d464da4Tyler Gunn Log.i(this, "VP->IC (callId=" + (mCall == null ? "?" : mCall.getId()) + "): " + toLog); 54686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn } 547a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn 548a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn /** 549a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn * Determines if the caller has permission to use the camera. 550a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn * 551a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn * @param context The context. 552a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn * @param callingPackage The package name of the caller (i.e. Dialer). 553a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn * @param callingUid The UID of the caller. 5541bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn * @param callingPid The PID of the caller. 555a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn * @return {@code true} if the calling uid and package can use the camera, {@code false} 556a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn * otherwise. 557a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn */ 558a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn private boolean canUseCamera(Context context, String callingPackage, int callingUid, 559a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn int callingPid) { 5601bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn 5611bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid); 5621bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn UserHandle currentUserHandle = mCurrentUserProxy.getCurrentUserHandle(); 5631bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn if (currentUserHandle != null && !currentUserHandle.equals(callingUser)) { 5641bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn Log.w(this, "canUseCamera attempt to user camera by background user."); 5651bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn return false; 5661bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn } 5671bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn 568a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn try { 569a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn context.enforcePermission(Manifest.permission.CAMERA, callingPid, callingUid, 570a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn "Camera permission required."); 571a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn } catch (SecurityException se) { 572a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn return false; 573a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn } 574a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn 575a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService( 576a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn Context.APP_OPS_SERVICE); 577a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn 578a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn try { 579a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn // Some apps that have the permission can be restricted via app ops. 580a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn return appOpsManager != null && appOpsManager.noteOp(AppOpsManager.OP_CAMERA, 581a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn callingUid, callingPackage) == AppOpsManager.MODE_ALLOWED; 582a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn } catch (SecurityException se) { 5831bf0e6be00af0ca5731a52f0727c6d9a2f8b6944Tyler Gunn Log.w(this, "canUseCamera got appOpps Exception " + se.toString()); 584a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn return false; 585a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn } 586a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn } 587a0a43d51041c9efbe04f7c65236c9e90c3e79346Tyler Gunn 58886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn} 589