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