InCallService.java revision 1cf9b6bec12c027a0d551540a6e01f3ac2d0a9d4
1/*
2 * Copyright (C) 2013 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 android.telecom;
18
19import android.annotation.SdkConstant;
20import android.app.Service;
21import android.content.Intent;
22import android.os.Handler;
23import android.os.IBinder;
24import android.os.Looper;
25import android.os.Message;
26import android.view.Surface;
27
28import com.android.internal.os.SomeArgs;
29import com.android.internal.telecom.IInCallAdapter;
30import com.android.internal.telecom.IInCallService;
31
32import java.lang.String;
33
34/**
35 * This service is implemented by any app that wishes to provide the user-interface for managing
36 * phone calls. Telecom binds to this service while there exists a live (active or incoming) call,
37 * and uses it to notify the in-call app of any live and and recently disconnected calls.
38 */
39public abstract class InCallService extends Service {
40
41    /**
42     * The {@link Intent} that must be declared as handled by the service.
43     */
44    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
45    public static final String SERVICE_INTERFACE = "android.telecom.InCallService";
46
47    private static final int MSG_SET_IN_CALL_ADAPTER = 1;
48    private static final int MSG_ADD_CALL = 2;
49    private static final int MSG_UPDATE_CALL = 3;
50    private static final int MSG_SET_POST_DIAL_WAIT = 4;
51    private static final int MSG_ON_AUDIO_STATE_CHANGED = 5;
52    private static final int MSG_BRING_TO_FOREGROUND = 6;
53    private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7;
54
55    /** Default Handler used to consolidate binder method calls onto a single thread. */
56    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
57        @Override
58        public void handleMessage(Message msg) {
59            if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) {
60                return;
61            }
62
63            switch (msg.what) {
64                case MSG_SET_IN_CALL_ADAPTER:
65                    mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));
66                    onPhoneCreated(mPhone);
67                    break;
68                case MSG_ADD_CALL:
69                    mPhone.internalAddCall((ParcelableCall) msg.obj);
70                    break;
71                case MSG_UPDATE_CALL:
72                    mPhone.internalUpdateCall((ParcelableCall) msg.obj);
73                    break;
74                case MSG_SET_POST_DIAL_WAIT: {
75                    SomeArgs args = (SomeArgs) msg.obj;
76                    try {
77                        String callId = (String) args.arg1;
78                        String remaining = (String) args.arg2;
79                        mPhone.internalSetPostDialWait(callId, remaining);
80                    } finally {
81                        args.recycle();
82                    }
83                    break;
84                }
85                case MSG_ON_AUDIO_STATE_CHANGED:
86                    mPhone.internalAudioStateChanged((AudioState) msg.obj);
87                    break;
88                case MSG_BRING_TO_FOREGROUND:
89                    mPhone.internalBringToForeground(msg.arg1 == 1);
90                    break;
91                case MSG_ON_CAN_ADD_CALL_CHANGED:
92                    mPhone.internalSetCanAddCall(msg.arg1 == 1);
93                    break;
94                default:
95                    break;
96            }
97        }
98    };
99
100    /** Manages the binder calls so that the implementor does not need to deal with it. */
101    private final class InCallServiceBinder extends IInCallService.Stub {
102        @Override
103        public void setInCallAdapter(IInCallAdapter inCallAdapter) {
104            mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
105        }
106
107        @Override
108        public void addCall(ParcelableCall call) {
109            mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
110        }
111
112        @Override
113        public void updateCall(ParcelableCall call) {
114            mHandler.obtainMessage(MSG_UPDATE_CALL, call).sendToTarget();
115        }
116
117        @Override
118        public void setPostDial(String callId, String remaining) {
119            // TODO: Unused
120        }
121
122        @Override
123        public void setPostDialWait(String callId, String remaining) {
124            SomeArgs args = SomeArgs.obtain();
125            args.arg1 = callId;
126            args.arg2 = remaining;
127            mHandler.obtainMessage(MSG_SET_POST_DIAL_WAIT, args).sendToTarget();
128        }
129
130        @Override
131        public void onAudioStateChanged(AudioState audioState) {
132            mHandler.obtainMessage(MSG_ON_AUDIO_STATE_CHANGED, audioState).sendToTarget();
133        }
134
135        @Override
136        public void bringToForeground(boolean showDialpad) {
137            mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget();
138        }
139
140        @Override
141        public void onCanAddCallChanged(boolean canAddCall) {
142            mHandler.obtainMessage(MSG_ON_CAN_ADD_CALL_CHANGED, canAddCall ? 1 : 0, 0)
143                    .sendToTarget();
144        }
145    }
146
147    private Phone mPhone;
148
149    public InCallService() {
150    }
151
152    @Override
153    public IBinder onBind(Intent intent) {
154        return new InCallServiceBinder();
155    }
156
157    @Override
158    public boolean onUnbind(Intent intent) {
159        if (mPhone != null) {
160            Phone oldPhone = mPhone;
161            mPhone = null;
162
163            oldPhone.destroy();
164            onPhoneDestroyed(oldPhone);
165        }
166        return false;
167    }
168
169    /**
170     * Obtain the {@code Phone} associated with this {@code InCallService}.
171     *
172     * @return The {@code Phone} object associated with this {@code InCallService}, or {@code null}
173     *         if the {@code InCallService} is not in a state where it has an associated
174     *         {@code Phone}.
175     */
176    public final Phone getPhone() {
177        return mPhone;
178    }
179
180    /**
181     * Invoked when the {@code Phone} has been created. This is a signal to the in-call experience
182     * to start displaying in-call information to the user. Each instance of {@code InCallService}
183     * will have only one {@code Phone}, and this method will be called exactly once in the lifetime
184     * of the {@code InCallService}.
185     *
186     * @param phone The {@code Phone} object associated with this {@code InCallService}.
187     */
188    public void onPhoneCreated(Phone phone) {
189    }
190
191    /**
192     * Invoked when a {@code Phone} has been destroyed. This is a signal to the in-call experience
193     * to stop displaying in-call information to the user. This method will be called exactly once
194     * in the lifetime of the {@code InCallService}, and it will always be called after a previous
195     * call to {@link #onPhoneCreated(Phone)}.
196     *
197     * @param phone The {@code Phone} object associated with this {@code InCallService}.
198     */
199    public void onPhoneDestroyed(Phone phone) {
200    }
201
202    /**
203     * Class to invoke functionality related to video calls.
204     */
205    public static abstract class VideoCall {
206
207        /**
208         * Sets a listener to invoke callback methods in the InCallUI after performing video
209         * telephony actions.
210         *
211         * @param videoCallListener The call video client.
212         */
213        public abstract void setVideoCallListener(VideoCall.Listener videoCallListener);
214
215        /**
216         * Sets the camera to be used for video recording in a video call.
217         *
218         * @param cameraId The id of the camera.
219         */
220        public abstract void setCamera(String cameraId);
221
222        /**
223         * Sets the surface to be used for displaying a preview of what the user's camera is
224         * currently capturing.  When video transmission is enabled, this is the video signal which
225         * is sent to the remote device.
226         *
227         * @param surface The surface.
228         */
229        public abstract void setPreviewSurface(Surface surface);
230
231        /**
232         * Sets the surface to be used for displaying the video received from the remote device.
233         *
234         * @param surface The surface.
235         */
236        public abstract void setDisplaySurface(Surface surface);
237
238        /**
239         * Sets the device orientation, in degrees.  Assumes that a standard portrait orientation of
240         * the device is 0 degrees.
241         *
242         * @param rotation The device orientation, in degrees.
243         */
244        public abstract void setDeviceOrientation(int rotation);
245
246        /**
247         * Sets camera zoom ratio.
248         *
249         * @param value The camera zoom ratio.
250         */
251        public abstract void setZoom(float value);
252
253        /**
254         * Issues a request to modify the properties of the current session.  The request is sent to
255         * the remote device where it it handled by
256         * {@link VideoCall.Listener#onSessionModifyRequestReceived}.
257         * Some examples of session modification requests: upgrade call from audio to video,
258         * downgrade call from video to audio, pause video.
259         *
260         * @param requestProfile The requested call video properties.
261         */
262        public abstract void sendSessionModifyRequest(VideoProfile requestProfile);
263
264        /**
265         * Provides a response to a request to change the current call session video
266         * properties.
267         * This is in response to a request the InCall UI has received via
268         * {@link VideoCall.Listener#onSessionModifyRequestReceived}.
269         * The response is handled on the remove device by
270         * {@link VideoCall.Listener#onSessionModifyResponseReceived}.
271         *
272         * @param responseProfile The response call video properties.
273         */
274        public abstract void sendSessionModifyResponse(VideoProfile responseProfile);
275
276        /**
277         * Issues a request to the video provider to retrieve the camera capabilities.
278         * Camera capabilities are reported back to the caller via
279         * {@link VideoCall.Listener#onCameraCapabilitiesChanged(CameraCapabilities)}.
280         */
281        public abstract void requestCameraCapabilities();
282
283        /**
284         * Issues a request to the video telephony framework to retrieve the cumulative data usage for
285         * the current call.  Data usage is reported back to the caller via
286         * {@link VideoCall.Listener#onCallDataUsageChanged}.
287         */
288        public abstract void requestCallDataUsage();
289
290        /**
291         * Provides the video telephony framework with the URI of an image to be displayed to remote
292         * devices when the video signal is paused.
293         *
294         * @param uri URI of image to display.
295         */
296        public abstract void setPauseImage(String uri);
297
298        /**
299         * Listener class which invokes callbacks after video call actions occur.
300         */
301        public static abstract class Listener {
302            /**
303             * Called when a session modification request is received from the remote device.
304             * The remote request is sent via
305             * {@link Connection.VideoProvider#onSendSessionModifyRequest}. The InCall UI
306             * is responsible for potentially prompting the user whether they wish to accept the new
307             * call profile (e.g. prompt user if they wish to accept an upgrade from an audio to a
308             * video call) and should call
309             * {@link Connection.VideoProvider#onSendSessionModifyResponse} to indicate
310             * the video settings the user has agreed to.
311             *
312             * @param videoProfile The requested video call profile.
313             */
314            public abstract void onSessionModifyRequestReceived(VideoProfile videoProfile);
315
316            /**
317             * Called when a response to a session modification request is received from the remote
318             * device. The remote InCall UI sends the response using
319             * {@link Connection.VideoProvider#onSendSessionModifyResponse}.
320             *
321             * @param status Status of the session modify request.  Valid values are
322             *               {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS},
323             *               {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_FAIL},
324             *               {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_INVALID}
325             * @param requestedProfile The original request which was sent to the remote device.
326             * @param responseProfile The actual profile changes made by the remote device.
327             */
328            public abstract void onSessionModifyResponseReceived(int status,
329                    VideoProfile requestedProfile, VideoProfile responseProfile);
330
331            /**
332             * Handles events related to the current session which the client may wish to handle.
333             * These are separate from requested changes to the session due to the underlying
334             * protocol or connection.
335             *
336             * Valid values are:
337             * {@link Connection.VideoProvider#SESSION_EVENT_RX_PAUSE},
338             * {@link Connection.VideoProvider#SESSION_EVENT_RX_RESUME},
339             * {@link Connection.VideoProvider#SESSION_EVENT_TX_START},
340             * {@link Connection.VideoProvider#SESSION_EVENT_TX_STOP},
341             * {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_FAILURE},
342             * {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_READY}
343             *
344             * @param event The event.
345             */
346            public abstract void onCallSessionEvent(int event);
347
348            /**
349             * Handles a change to the video dimensions from the remote caller (peer). This could
350             * happen if, for example, the peer changes orientation of their device.
351             *
352             * @param width  The updated peer video width.
353             * @param height The updated peer video height.
354             */
355            public abstract void onPeerDimensionsChanged(int width, int height);
356
357            /**
358             * Handles a change to the video quality.
359             *
360             * @param videoQuality  The updated peer video quality.
361             */
362            public abstract void onVideoQualityChanged(int videoQuality);
363
364            /**
365             * Handles an update to the total data used for the current session.
366             *
367             * @param dataUsage The updated data usage.
368             */
369            public abstract void onCallDataUsageChanged(long dataUsage);
370
371            /**
372             * Handles a change in camera capabilities.
373             *
374             * @param cameraCapabilities The changed camera capabilities.
375             */
376            public abstract void onCameraCapabilitiesChanged(
377                    CameraCapabilities cameraCapabilities);
378        }
379    }
380}
381