1 /*
2  * Copyright (C) 2018 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 android.telephony.ims;
18 
19 import android.annotation.SystemApi;
20 import android.annotation.UnsupportedAppUsage;
21 import android.net.Uri;
22 import android.os.Handler;
23 import android.os.Looper;
24 import android.os.Message;
25 import android.os.RemoteException;
26 import android.telecom.Connection;
27 import android.telecom.VideoProfile;
28 import android.telecom.VideoProfile.CameraCapabilities;
29 import android.view.Surface;
30 
31 import com.android.ims.internal.IImsVideoCallCallback;
32 import com.android.ims.internal.IImsVideoCallProvider;
33 import com.android.internal.os.SomeArgs;
34 
35 /**
36  * @hide
37  */
38 @SystemApi
39 public abstract class ImsVideoCallProvider {
40     private static final int MSG_SET_CALLBACK = 1;
41     private static final int MSG_SET_CAMERA = 2;
42     private static final int MSG_SET_PREVIEW_SURFACE = 3;
43     private static final int MSG_SET_DISPLAY_SURFACE = 4;
44     private static final int MSG_SET_DEVICE_ORIENTATION = 5;
45     private static final int MSG_SET_ZOOM = 6;
46     private static final int MSG_SEND_SESSION_MODIFY_REQUEST = 7;
47     private static final int MSG_SEND_SESSION_MODIFY_RESPONSE = 8;
48     private static final int MSG_REQUEST_CAMERA_CAPABILITIES = 9;
49     private static final int MSG_REQUEST_CALL_DATA_USAGE = 10;
50     private static final int MSG_SET_PAUSE_IMAGE = 11;
51 
52     private final ImsVideoCallProviderBinder mBinder;
53 
54     private IImsVideoCallCallback mCallback;
55 
56     /**
57      * Default handler used to consolidate binder method calls onto a single thread.
58      */
59     private final Handler mProviderHandler = new Handler(Looper.getMainLooper()) {
60         @Override
61         public void handleMessage(Message msg) {
62             switch (msg.what) {
63                 case MSG_SET_CALLBACK:
64                     mCallback = (IImsVideoCallCallback) msg.obj;
65                     break;
66                 case MSG_SET_CAMERA:
67                 {
68                     SomeArgs args = (SomeArgs) msg.obj;
69                     try {
70                         onSetCamera((String) args.arg1);
71                         onSetCamera((String) args.arg1, args.argi1);
72                     } finally {
73                         args.recycle();
74                     }
75                     break;
76                 }
77                 case MSG_SET_PREVIEW_SURFACE:
78                     onSetPreviewSurface((Surface) msg.obj);
79                     break;
80                 case MSG_SET_DISPLAY_SURFACE:
81                     onSetDisplaySurface((Surface) msg.obj);
82                     break;
83                 case MSG_SET_DEVICE_ORIENTATION:
84                     onSetDeviceOrientation(msg.arg1);
85                     break;
86                 case MSG_SET_ZOOM:
87                     onSetZoom((Float) msg.obj);
88                     break;
89                 case MSG_SEND_SESSION_MODIFY_REQUEST: {
90                     SomeArgs args = (SomeArgs) msg.obj;
91                     try {
92                         VideoProfile fromProfile = (VideoProfile) args.arg1;
93                         VideoProfile toProfile = (VideoProfile) args.arg2;
94 
95                         onSendSessionModifyRequest(fromProfile, toProfile);
96                     } finally {
97                         args.recycle();
98                     }
99                     break;
100                 }
101                 case MSG_SEND_SESSION_MODIFY_RESPONSE:
102                     onSendSessionModifyResponse((VideoProfile) msg.obj);
103                     break;
104                 case MSG_REQUEST_CAMERA_CAPABILITIES:
105                     onRequestCameraCapabilities();
106                     break;
107                 case MSG_REQUEST_CALL_DATA_USAGE:
108                     onRequestCallDataUsage();
109                     break;
110                 case MSG_SET_PAUSE_IMAGE:
111                     onSetPauseImage((Uri) msg.obj);
112                     break;
113                 default:
114                     break;
115             }
116         }
117     };
118 
119     /**
120      * IImsVideoCallProvider stub implementation.
121      */
122     private final class ImsVideoCallProviderBinder extends IImsVideoCallProvider.Stub {
setCallback(IImsVideoCallCallback callback)123         public void setCallback(IImsVideoCallCallback callback) {
124             mProviderHandler.obtainMessage(MSG_SET_CALLBACK, callback).sendToTarget();
125         }
126 
setCamera(String cameraId, int uid)127         public void setCamera(String cameraId, int uid) {
128             SomeArgs args = SomeArgs.obtain();
129             args.arg1 = cameraId;
130             args.argi1 = uid;
131             mProviderHandler.obtainMessage(MSG_SET_CAMERA, args).sendToTarget();
132         }
133 
setPreviewSurface(Surface surface)134         public void setPreviewSurface(Surface surface) {
135             mProviderHandler.obtainMessage(MSG_SET_PREVIEW_SURFACE, surface).sendToTarget();
136         }
137 
setDisplaySurface(Surface surface)138         public void setDisplaySurface(Surface surface) {
139             mProviderHandler.obtainMessage(MSG_SET_DISPLAY_SURFACE, surface).sendToTarget();
140         }
141 
setDeviceOrientation(int rotation)142         public void setDeviceOrientation(int rotation) {
143             mProviderHandler.obtainMessage(MSG_SET_DEVICE_ORIENTATION, rotation, 0).sendToTarget();
144         }
145 
setZoom(float value)146         public void setZoom(float value) {
147             mProviderHandler.obtainMessage(MSG_SET_ZOOM, value).sendToTarget();
148         }
149 
sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile)150         public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
151             SomeArgs args = SomeArgs.obtain();
152             args.arg1 = fromProfile;
153             args.arg2 = toProfile;
154             mProviderHandler.obtainMessage(MSG_SEND_SESSION_MODIFY_REQUEST, args).sendToTarget();
155         }
156 
sendSessionModifyResponse(VideoProfile responseProfile)157         public void sendSessionModifyResponse(VideoProfile responseProfile) {
158             mProviderHandler.obtainMessage(
159                     MSG_SEND_SESSION_MODIFY_RESPONSE, responseProfile).sendToTarget();
160         }
161 
requestCameraCapabilities()162         public void requestCameraCapabilities() {
163             mProviderHandler.obtainMessage(MSG_REQUEST_CAMERA_CAPABILITIES).sendToTarget();
164         }
165 
requestCallDataUsage()166         public void requestCallDataUsage() {
167             mProviderHandler.obtainMessage(MSG_REQUEST_CALL_DATA_USAGE).sendToTarget();
168         }
169 
setPauseImage(Uri uri)170         public void setPauseImage(Uri uri) {
171             mProviderHandler.obtainMessage(MSG_SET_PAUSE_IMAGE, uri).sendToTarget();
172         }
173     }
174 
ImsVideoCallProvider()175     public ImsVideoCallProvider() {
176         mBinder = new ImsVideoCallProviderBinder();
177     }
178 
179     /**
180      * Returns binder object which can be used across IPC methods.
181      * @hide
182      */
183     @UnsupportedAppUsage
getInterface()184     public final IImsVideoCallProvider getInterface() {
185         return mBinder;
186     }
187 
188     /** @see Connection.VideoProvider#onSetCamera */
onSetCamera(String cameraId)189     public abstract void onSetCamera(String cameraId);
190 
191     /**
192      * Similar to {@link #onSetCamera(String)}, except includes the UID of the calling process which
193      * the IMS service uses when opening the camera.  This ensures camera permissions are verified
194      * by the camera service.
195      *
196      * @param cameraId The id of the camera to be opened.
197      * @param uid The uid of the caller, used when opening the camera for permission verification.
198      * @see Connection.VideoProvider#onSetCamera
199      */
onSetCamera(String cameraId, int uid)200     public void onSetCamera(String cameraId, int uid) {
201     }
202 
203     /** @see Connection.VideoProvider#onSetPreviewSurface */
onSetPreviewSurface(Surface surface)204     public abstract void onSetPreviewSurface(Surface surface);
205 
206     /** @see Connection.VideoProvider#onSetDisplaySurface */
onSetDisplaySurface(Surface surface)207     public abstract void onSetDisplaySurface(Surface surface);
208 
209     /** @see Connection.VideoProvider#onSetDeviceOrientation */
onSetDeviceOrientation(int rotation)210     public abstract void onSetDeviceOrientation(int rotation);
211 
212     /** @see Connection.VideoProvider#onSetZoom */
onSetZoom(float value)213     public abstract void onSetZoom(float value);
214 
215     /** @see Connection.VideoProvider#onSendSessionModifyRequest */
onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile)216     public abstract void onSendSessionModifyRequest(VideoProfile fromProfile,
217             VideoProfile toProfile);
218 
219     /** @see Connection.VideoProvider#onSendSessionModifyResponse */
onSendSessionModifyResponse(VideoProfile responseProfile)220     public abstract void onSendSessionModifyResponse(VideoProfile responseProfile);
221 
222     /** @see Connection.VideoProvider#onRequestCameraCapabilities */
onRequestCameraCapabilities()223     public abstract void onRequestCameraCapabilities();
224 
225     /** @see Connection.VideoProvider#onRequestCallDataUsage */
onRequestCallDataUsage()226     public abstract void onRequestCallDataUsage();
227 
228     /** @see Connection.VideoProvider#onSetPauseImage */
onSetPauseImage(Uri uri)229     public abstract void onSetPauseImage(Uri uri);
230 
231     /** @see Connection.VideoProvider#receiveSessionModifyRequest */
receiveSessionModifyRequest(VideoProfile VideoProfile)232     public void receiveSessionModifyRequest(VideoProfile VideoProfile) {
233         if (mCallback != null) {
234             try {
235                 mCallback.receiveSessionModifyRequest(VideoProfile);
236             } catch (RemoteException ignored) {
237             }
238         }
239     }
240 
241     /** @see Connection.VideoProvider#receiveSessionModifyResponse */
receiveSessionModifyResponse( int status, VideoProfile requestedProfile, VideoProfile responseProfile)242     public void receiveSessionModifyResponse(
243             int status, VideoProfile requestedProfile, VideoProfile responseProfile) {
244         if (mCallback != null) {
245             try {
246                 mCallback.receiveSessionModifyResponse(status, requestedProfile, responseProfile);
247             } catch (RemoteException ignored) {
248             }
249         }
250     }
251 
252     /** @see Connection.VideoProvider#handleCallSessionEvent */
handleCallSessionEvent(int event)253     public void handleCallSessionEvent(int event) {
254         if (mCallback != null) {
255             try {
256                 mCallback.handleCallSessionEvent(event);
257             } catch (RemoteException ignored) {
258             }
259         }
260     }
261 
262     /** @see Connection.VideoProvider#changePeerDimensions */
changePeerDimensions(int width, int height)263     public void changePeerDimensions(int width, int height) {
264         if (mCallback != null) {
265             try {
266                 mCallback.changePeerDimensions(width, height);
267             } catch (RemoteException ignored) {
268             }
269         }
270     }
271 
272     /** @see Connection.VideoProvider#changeCallDataUsage */
changeCallDataUsage(long dataUsage)273     public void changeCallDataUsage(long dataUsage) {
274         if (mCallback != null) {
275             try {
276                 mCallback.changeCallDataUsage(dataUsage);
277             } catch (RemoteException ignored) {
278             }
279         }
280     }
281 
282     /** @see Connection.VideoProvider#changeCameraCapabilities */
changeCameraCapabilities(CameraCapabilities CameraCapabilities)283     public void changeCameraCapabilities(CameraCapabilities CameraCapabilities) {
284         if (mCallback != null) {
285             try {
286                 mCallback.changeCameraCapabilities(CameraCapabilities);
287             } catch (RemoteException ignored) {
288             }
289         }
290     }
291 
292     /** @see Connection.VideoProvider#changeVideoQuality */
changeVideoQuality(int videoQuality)293     public void changeVideoQuality(int videoQuality) {
294         if (mCallback != null) {
295             try {
296                 mCallback.changeVideoQuality(videoQuality);
297             } catch (RemoteException ignored) {
298             }
299         }
300     }
301 }
302