InCallService.java revision 159f35c8e4a2d5902cbbeb8d3b9a80bddf247de3
1f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes/*
2f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Copyright (C) 2013 The Android Open Source Project
3f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes *
4f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * you may not use this file except in compliance with the License.
6f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * You may obtain a copy of the License at
7f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes *
8f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes *
10f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Unless required by applicable law or agreed to in writing, software
11f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * See the License for the specific language governing permissions and
14f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * limitations under the License.
15f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes */
16f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
17277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampepackage android.telecom;
18277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe
1907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughesimport android.annotation.SdkConstant;
2076b6167407c2b6f5d40ad895b2793a6b037f54b2Elliott Hughesimport android.annotation.SystemApi;
21f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesimport android.app.Service;
22d49012909625c3bf87bf51138fe79315ce1b1bdcAndreas Gampeimport android.content.Intent;
23eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughesimport android.hardware.camera2.CameraManager;
2487583b3de6e811e141f8c97c1f796eb516e8a751Andreas Gampeimport android.net.Uri;
25e431e2758d62cf56f7f347f5a8c9d79e41b6dcd7Steven Morelandimport android.os.Bundle;
26e431e2758d62cf56f7f347f5a8c9d79e41b6dcd7Steven Morelandimport android.os.Handler;
27e431e2758d62cf56f7f347f5a8c9d79e41b6dcd7Steven Morelandimport android.os.IBinder;
280795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartierimport android.os.Looper;
29bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughesimport android.os.Message;
30f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesimport android.view.Surface;
31f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
32f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesimport com.android.internal.os.SomeArgs;
331bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesimport com.android.internal.telecom.IInCallAdapter;
34545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughesimport com.android.internal.telecom.IInCallService;
35f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
36f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesimport java.lang.String;
3700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersimport java.util.Collections;
3853b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogersimport java.util.List;
39545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes
40f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes/**
41f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * This service is implemented by any app that wishes to provide the user-interface for managing
421bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes * phone calls. Telecom binds to this service while there exists a live (active or incoming) call,
438c2ff641294715864013737fdec57cdfd410270cMan Cao * and uses it to notify the in-call app of any live and recently disconnected calls. An app must
44f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * first be set as the default phone app (See {@link TelecomManager#getDefaultDialerPackage()})
45f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * before the telecom service will bind to its {@code InCallService} implementation.
46f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * <p>
47f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Below is an example manifest registration for an {@code InCallService}. The meta-data
482cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier * ({@link TelecomManager#METADATA_IN_CALL_SERVICE_UI}) indicates that this particular
49f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * {@code InCallService} implementation intends to replace the built-in in-call UI.
50bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * <pre>
5153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers * {@code
52970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz * <service android:name="your.package.YourInCallServiceImplementation"
53970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz *          android:permission="android.permission.BIND_INCALL_SERVICE">
54970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz *      <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
55970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz *      <intent-filter>
56ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz *          <action android:name="android.telecom.InCallService"/>
57970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz *      </intent-filter>
5800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * </service>
59970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz * }
60970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz * </pre>
6114e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch */
6214e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birchpublic abstract class InCallService extends Service {
6314e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch
6414e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch    /**
6514e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch     * The {@link Intent} that must be declared as handled by the service.
6614e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch     */
6714e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
6846f9340f2a055a8fdfebbfbb739c697c20d83e7cAlex Light    public static final String SERVICE_INTERFACE = "android.telecom.InCallService";
6946f9340f2a055a8fdfebbfbb739c697c20d83e7cAlex Light
7046f9340f2a055a8fdfebbfbb739c697c20d83e7cAlex Light    private static final int MSG_SET_IN_CALL_ADAPTER = 1;
71970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz    private static final int MSG_ADD_CALL = 2;
72970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz    private static final int MSG_UPDATE_CALL = 3;
73970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz    private static final int MSG_SET_POST_DIAL_WAIT = 4;
74ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz    private static final int MSG_ON_CALL_AUDIO_STATE_CHANGED = 5;
75970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz    private static final int MSG_BRING_TO_FOREGROUND = 6;
76970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz    private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7;
77970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz    private static final int MSG_SILENCE_RINGER = 8;
7888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    private static final int MSG_ON_CONNECTION_EVENT = 9;
7988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light    private static final int MSG_ON_RTT_UPGRADE_REQUEST = 10;
80970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz
81970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz    /** Default Handler used to consolidate binder method calls onto a single thread. */
82970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
83970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz        @Override
84970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz        public void handleMessage(Message msg) {
8515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers            if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) {
86bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                return;
8753b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers            }
88bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
89bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes            switch (msg.what) {
90bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                case MSG_SET_IN_CALL_ADAPTER:
91bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    String callingPackage = getApplicationContext().getOpPackageName();
92bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage,
93bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                            getApplicationContext().getApplicationInfo().targetSdkVersion);
94bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    mPhone.addListener(mPhoneListener);
95bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    onPhoneCreated(mPhone);
96bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    break;
97bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                case MSG_ADD_CALL:
98bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    mPhone.internalAddCall((ParcelableCall) msg.obj);
99bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    break;
100bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                case MSG_UPDATE_CALL:
101bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    mPhone.internalUpdateCall((ParcelableCall) msg.obj);
102bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    break;
103bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                case MSG_SET_POST_DIAL_WAIT: {
104bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    SomeArgs args = (SomeArgs) msg.obj;
105bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    try {
106bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                        String callId = (String) args.arg1;
107bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                        String remaining = (String) args.arg2;
10821f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes                        mPhone.internalSetPostDialWait(callId, remaining);
109bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    } finally {
110bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                        args.recycle();
111bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    }
112bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    break;
113bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                }
114bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                case MSG_ON_CALL_AUDIO_STATE_CHANGED:
115bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    mPhone.internalCallAudioStateChanged((CallAudioState) msg.obj);
116bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    break;
117bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                case MSG_BRING_TO_FOREGROUND:
118bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    mPhone.internalBringToForeground(msg.arg1 == 1);
119bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    break;
120ba0b9c55adce3f533845ab1b25c552589e5b4118Elliott Hughes                case MSG_ON_CAN_ADD_CALL_CHANGED:
1212921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom                    mPhone.internalSetCanAddCall(msg.arg1 == 1);
1222921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom                    break;
1232921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom                case MSG_SILENCE_RINGER:
1242921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom                    mPhone.internalSilenceRinger();
125bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    break;
12621f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes                case MSG_ON_CONNECTION_EVENT: {
127d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers                    SomeArgs args = (SomeArgs) msg.obj;
128920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao                    try {
12921f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes                        String callId = (String) args.arg1;
13021f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes                        String event = (String) args.arg2;
13121f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes                        Bundle extras = (Bundle) args.arg3;
13221f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes                        mPhone.internalOnConnectionEvent(callId, event, extras);
133f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes                    } finally {
134f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes                        args.recycle();
135f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes                    }
136bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    break;
13750b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers                }
138bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                case MSG_ON_RTT_UPGRADE_REQUEST: {
13950b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers                    String callId = (String) msg.obj;
140bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    int requestId = msg.arg1;
141bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                    mPhone.internalOnRttUpgradeRequest(callId, requestId);
14221f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes                    break;
143bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                }
144bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes                default:
14521f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes                    break;
14621f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes            }
14721f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes        }
148bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes    };
14921f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes
150bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes    /** Manages the binder calls so that the implementor does not need to deal with it. */
151bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes    private final class InCallServiceBinder extends IInCallService.Stub {
152bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes        @Override
1532cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier        public void setInCallAdapter(IInCallAdapter inCallAdapter) {
154545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes            mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
155545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes        }
156bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes
157f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        @Override
158f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        public void addCall(ParcelableCall call) {
15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers            mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
16053b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers        }
161767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes
162f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        @Override
163f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        public void updateCall(ParcelableCall call) {
1641bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes            mHandler.obtainMessage(MSG_UPDATE_CALL, call).sendToTarget();
165767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes        }
166f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
167f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        @Override
1681bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes        public void setPostDial(String callId, String remaining) {
16947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes            // TODO: Unused
170f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        }
171f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
172f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        @Override
173f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        public void setPostDialWait(String callId, String remaining) {
1743b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin            SomeArgs args = SomeArgs.obtain();
1753b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin            args.arg1 = callId;
176f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes            args.arg2 = remaining;
177f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes            mHandler.obtainMessage(MSG_SET_POST_DIAL_WAIT, args).sendToTarget();
1783b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin        }
179f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes
180f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        @Override
181f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        public void onCallAudioStateChanged(CallAudioState callAudioState) {
182f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes            mHandler.obtainMessage(MSG_ON_CALL_AUDIO_STATE_CHANGED, callAudioState).sendToTarget();
183f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        }
184eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes
185f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        @Override
186f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes        public void bringToForeground(boolean showDialpad) {
187f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes            mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget();
188        }
189
190        @Override
191        public void onCanAddCallChanged(boolean canAddCall) {
192            mHandler.obtainMessage(MSG_ON_CAN_ADD_CALL_CHANGED, canAddCall ? 1 : 0, 0)
193                    .sendToTarget();
194        }
195
196        @Override
197        public void silenceRinger() {
198            mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget();
199        }
200
201        @Override
202        public void onConnectionEvent(String callId, String event, Bundle extras) {
203            SomeArgs args = SomeArgs.obtain();
204            args.arg1 = callId;
205            args.arg2 = event;
206            args.arg3 = extras;
207            mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
208        }
209
210        @Override
211        public void onRttUpgradeRequest(String callId, int id) {
212            mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, id, 0, callId).sendToTarget();
213        }
214    }
215
216    private Phone.Listener mPhoneListener = new Phone.Listener() {
217        /** ${inheritDoc} */
218        @Override
219        public void onAudioStateChanged(Phone phone, AudioState audioState) {
220            InCallService.this.onAudioStateChanged(audioState);
221        }
222
223        public void onCallAudioStateChanged(Phone phone, CallAudioState callAudioState) {
224            InCallService.this.onCallAudioStateChanged(callAudioState);
225        };
226
227        /** ${inheritDoc} */
228        @Override
229        public void onBringToForeground(Phone phone, boolean showDialpad) {
230            InCallService.this.onBringToForeground(showDialpad);
231        }
232
233        /** ${inheritDoc} */
234        @Override
235        public void onCallAdded(Phone phone, Call call) {
236            InCallService.this.onCallAdded(call);
237        }
238
239        /** ${inheritDoc} */
240        @Override
241        public void onCallRemoved(Phone phone, Call call) {
242            InCallService.this.onCallRemoved(call);
243        }
244
245        /** ${inheritDoc} */
246        @Override
247        public void onCanAddCallChanged(Phone phone, boolean canAddCall) {
248            InCallService.this.onCanAddCallChanged(canAddCall);
249        }
250
251        /** ${inheritDoc} */
252        @Override
253        public void onSilenceRinger(Phone phone) {
254            InCallService.this.onSilenceRinger();
255        }
256
257    };
258
259    private Phone mPhone;
260
261    public InCallService() {
262    }
263
264    @Override
265    public IBinder onBind(Intent intent) {
266        return new InCallServiceBinder();
267    }
268
269    @Override
270    public boolean onUnbind(Intent intent) {
271        if (mPhone != null) {
272            Phone oldPhone = mPhone;
273            mPhone = null;
274
275            oldPhone.destroy();
276            // destroy sets all the calls to disconnected if any live ones still exist. Therefore,
277            // it is important to remove the Listener *after* the call to destroy so that
278            // InCallService.on* callbacks are appropriately called.
279            oldPhone.removeListener(mPhoneListener);
280
281            onPhoneDestroyed(oldPhone);
282        }
283
284        return false;
285    }
286
287    /**
288     * Obtain the {@code Phone} associated with this {@code InCallService}.
289     *
290     * @return The {@code Phone} object associated with this {@code InCallService}, or {@code null}
291     *         if the {@code InCallService} is not in a state where it has an associated
292     *         {@code Phone}.
293     * @hide
294     * @deprecated Use direct methods on InCallService instead of {@link Phone}.
295     */
296    @SystemApi
297    @Deprecated
298    public Phone getPhone() {
299        return mPhone;
300    }
301
302    /**
303     * Obtains the current list of {@code Call}s to be displayed by this in-call service.
304     *
305     * @return A list of the relevant {@code Call}s.
306     */
307    public final List<Call> getCalls() {
308        return mPhone == null ? Collections.<Call>emptyList() : mPhone.getCalls();
309    }
310
311    /**
312     * Returns if the device can support additional calls.
313     *
314     * @return Whether the phone supports adding more calls.
315     */
316    public final boolean canAddCall() {
317        return mPhone == null ? false : mPhone.canAddCall();
318    }
319
320    /**
321     * Obtains the current phone call audio state.
322     *
323     * @return An object encapsulating the audio state. Returns null if the service is not
324     *         fully initialized.
325     * @deprecated Use {@link #getCallAudioState()} instead.
326     * @hide
327     */
328    @Deprecated
329    public final AudioState getAudioState() {
330        return mPhone == null ? null : mPhone.getAudioState();
331    }
332
333    /**
334     * Obtains the current phone call audio state.
335     *
336     * @return An object encapsulating the audio state. Returns null if the service is not
337     *         fully initialized.
338     */
339    public final CallAudioState getCallAudioState() {
340        return mPhone == null ? null : mPhone.getCallAudioState();
341    }
342
343    /**
344     * Sets the microphone mute state. When this request is honored, there will be change to
345     * the {@link #getCallAudioState()}.
346     *
347     * @param state {@code true} if the microphone should be muted; {@code false} otherwise.
348     */
349    public final void setMuted(boolean state) {
350        if (mPhone != null) {
351            mPhone.setMuted(state);
352        }
353    }
354
355    /**
356     * Sets the audio route (speaker, bluetooth, etc...).  When this request is honored, there will
357     * be change to the {@link #getCallAudioState()}.
358     *
359     * @param route The audio route to use.
360     */
361    public final void setAudioRoute(int route) {
362        if (mPhone != null) {
363            mPhone.setAudioRoute(route);
364        }
365    }
366
367    /**
368     * Invoked when the {@code Phone} has been created. This is a signal to the in-call experience
369     * to start displaying in-call information to the user. Each instance of {@code InCallService}
370     * will have only one {@code Phone}, and this method will be called exactly once in the lifetime
371     * of the {@code InCallService}.
372     *
373     * @param phone The {@code Phone} object associated with this {@code InCallService}.
374     * @hide
375     * @deprecated Use direct methods on InCallService instead of {@link Phone}.
376     */
377    @SystemApi
378    @Deprecated
379    public void onPhoneCreated(Phone phone) {
380    }
381
382    /**
383     * Invoked when a {@code Phone} has been destroyed. This is a signal to the in-call experience
384     * to stop displaying in-call information to the user. This method will be called exactly once
385     * in the lifetime of the {@code InCallService}, and it will always be called after a previous
386     * call to {@link #onPhoneCreated(Phone)}.
387     *
388     * @param phone The {@code Phone} object associated with this {@code InCallService}.
389     * @hide
390     * @deprecated Use direct methods on InCallService instead of {@link Phone}.
391     */
392    @SystemApi
393    @Deprecated
394    public void onPhoneDestroyed(Phone phone) {
395    }
396
397    /**
398     * Called when the audio state changes.
399     *
400     * @param audioState The new {@link AudioState}.
401     * @deprecated Use {@link #onCallAudioStateChanged(CallAudioState) instead}.
402     * @hide
403     */
404    @Deprecated
405    public void onAudioStateChanged(AudioState audioState) {
406    }
407
408    /**
409     * Called when the audio state changes.
410     *
411     * @param audioState The new {@link CallAudioState}.
412     */
413    public void onCallAudioStateChanged(CallAudioState audioState) {
414    }
415
416    /**
417     * Called to bring the in-call screen to the foreground. The in-call experience should
418     * respond immediately by coming to the foreground to inform the user of the state of
419     * ongoing {@code Call}s.
420     *
421     * @param showDialpad If true, put up the dialpad when the screen is shown.
422     */
423    public void onBringToForeground(boolean showDialpad) {
424    }
425
426    /**
427     * Called when a {@code Call} has been added to this in-call session. The in-call user
428     * experience should add necessary state listeners to the specified {@code Call} and
429     * immediately start to show the user information about the existence
430     * and nature of this {@code Call}. Subsequent invocations of {@link #getCalls()} will
431     * include this {@code Call}.
432     *
433     * @param call A newly added {@code Call}.
434     */
435    public void onCallAdded(Call call) {
436    }
437
438    /**
439     * Called when a {@code Call} has been removed from this in-call session. The in-call user
440     * experience should remove any state listeners from the specified {@code Call} and
441     * immediately stop displaying any information about this {@code Call}.
442     * Subsequent invocations of {@link #getCalls()} will no longer include this {@code Call}.
443     *
444     * @param call A newly removed {@code Call}.
445     */
446    public void onCallRemoved(Call call) {
447    }
448
449    /**
450     * Called when the ability to add more calls changes.  If the phone cannot
451     * support more calls then {@code canAddCall} is set to {@code false}.  If it can, then it
452     * is set to {@code true}. This can be used to control the visibility of UI to add more calls.
453     *
454     * @param canAddCall Indicates whether an additional call can be added.
455     */
456    public void onCanAddCallChanged(boolean canAddCall) {
457    }
458
459    /**
460     * Called to silence the ringer if a ringing call exists.
461     */
462    public void onSilenceRinger() {
463    }
464
465    /**
466     * Unused; to handle connection events issued by a {@link ConnectionService}, implement the
467     * {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)} callback.
468     * <p>
469     * See {@link Connection#sendConnectionEvent(String, Bundle)}.
470     *
471     * @param call The call the event is associated with.
472     * @param event The event.
473     * @param extras Any associated extras.
474     */
475    public void onConnectionEvent(Call call, String event, Bundle extras) {
476    }
477
478    /**
479     * Used to issue commands to the {@link Connection.VideoProvider} associated with a
480     * {@link Call}.
481     */
482    public static abstract class VideoCall {
483
484        /** @hide */
485        public abstract void destroy();
486
487        /**
488         * Registers a callback to receive commands and state changes for video calls.
489         *
490         * @param callback The video call callback.
491         */
492        public abstract void registerCallback(VideoCall.Callback callback);
493
494        /**
495         * Registers a callback to receive commands and state changes for video calls.
496         *
497         * @param callback The video call callback.
498         * @param handler A handler which commands and status changes will be delivered to.
499         */
500        public abstract void registerCallback(VideoCall.Callback callback, Handler handler);
501
502        /**
503         * Clears the video call callback set via {@link #registerCallback}.
504         *
505         * @param callback The video call callback to clear.
506         */
507        public abstract void unregisterCallback(VideoCall.Callback callback);
508
509        /**
510         * Sets the camera to be used for the outgoing video.
511         * <p>
512         * Handled by {@link Connection.VideoProvider#onSetCamera(String)}.
513         *
514         * @param cameraId The id of the camera (use ids as reported by
515         * {@link CameraManager#getCameraIdList()}).
516         */
517        public abstract void setCamera(String cameraId);
518
519        /**
520         * Sets the surface to be used for displaying a preview of what the user's camera is
521         * currently capturing.  When video transmission is enabled, this is the video signal which
522         * is sent to the remote device.
523         * <p>
524         * Handled by {@link Connection.VideoProvider#onSetPreviewSurface(Surface)}.
525         *
526         * @param surface The {@link Surface}.
527         */
528        public abstract void setPreviewSurface(Surface surface);
529
530        /**
531         * Sets the surface to be used for displaying the video received from the remote device.
532         * <p>
533         * Handled by {@link Connection.VideoProvider#onSetDisplaySurface(Surface)}.
534         *
535         * @param surface The {@link Surface}.
536         */
537        public abstract void setDisplaySurface(Surface surface);
538
539        /**
540         * Sets the device orientation, in degrees.  Assumes that a standard portrait orientation of
541         * the device is 0 degrees.
542         * <p>
543         * Handled by {@link Connection.VideoProvider#onSetDeviceOrientation(int)}.
544         *
545         * @param rotation The device orientation, in degrees.
546         */
547        public abstract void setDeviceOrientation(int rotation);
548
549        /**
550         * Sets camera zoom ratio.
551         * <p>
552         * Handled by {@link Connection.VideoProvider#onSetZoom(float)}.
553         *
554         * @param value The camera zoom ratio.
555         */
556        public abstract void setZoom(float value);
557
558        /**
559         * Issues a request to modify the properties of the current video session.
560         * <p>
561         * Example scenarios include: requesting an audio-only call to be upgraded to a
562         * bi-directional video call, turning on or off the user's camera, sending a pause signal
563         * when the {@link InCallService} is no longer the foreground application.
564         * <p>
565         * Handled by
566         * {@link Connection.VideoProvider#onSendSessionModifyRequest(VideoProfile, VideoProfile)}.
567         *
568         * @param requestProfile The requested call video properties.
569         */
570        public abstract void sendSessionModifyRequest(VideoProfile requestProfile);
571
572        /**
573         * Provides a response to a request to change the current call video session
574         * properties.  This should be called in response to a request the {@link InCallService} has
575         * received via {@link VideoCall.Callback#onSessionModifyRequestReceived}.
576         * <p>
577         * Handled by
578         * {@link Connection.VideoProvider#onSendSessionModifyResponse(VideoProfile)}.
579         *
580         * @param responseProfile The response call video properties.
581         */
582        public abstract void sendSessionModifyResponse(VideoProfile responseProfile);
583
584        /**
585         * Issues a request to the {@link Connection.VideoProvider} to retrieve the capabilities
586         * of the current camera.  The current camera is selected using
587         * {@link VideoCall#setCamera(String)}.
588         * <p>
589         * Camera capabilities are reported to the caller via
590         * {@link VideoCall.Callback#onCameraCapabilitiesChanged(VideoProfile.CameraCapabilities)}.
591         * <p>
592         * Handled by {@link Connection.VideoProvider#onRequestCameraCapabilities()}.
593         */
594        public abstract void requestCameraCapabilities();
595
596        /**
597         * Issues a request to the {@link Connection.VideoProvider} to retrieve the cumulative data
598         * usage for the video component of the current call (in bytes).  Data usage is reported
599         * to the caller via {@link VideoCall.Callback#onCallDataUsageChanged}.
600         * <p>
601         * Handled by {@link Connection.VideoProvider#onRequestConnectionDataUsage()}.
602         */
603        public abstract void requestCallDataUsage();
604
605        /**
606         * Provides the {@link Connection.VideoProvider} with the {@link Uri} of an image to be
607         * displayed to the peer device when the video signal is paused.
608         * <p>
609         * Handled by {@link Connection.VideoProvider#onSetPauseImage(Uri)}.
610         *
611         * @param uri URI of image to display.
612         */
613        public abstract void setPauseImage(Uri uri);
614
615        /**
616         * The {@link InCallService} extends this class to provide a means of receiving callbacks
617         * from the {@link Connection.VideoProvider}.
618         * <p>
619         * When the {@link InCallService} receives the
620         * {@link Call.Callback#onVideoCallChanged(Call, VideoCall)} callback, it should create an
621         * instance its {@link VideoCall.Callback} implementation and set it on the
622         * {@link VideoCall} using {@link VideoCall#registerCallback(Callback)}.
623         */
624        public static abstract class Callback {
625            /**
626             * Called when the {@link Connection.VideoProvider} receives a session modification
627             * request from the peer device.
628             * <p>
629             * The {@link InCallService} may potentially prompt the user to confirm whether they
630             * wish to accept the request, or decide to automatically accept the request.  In either
631             * case the {@link InCallService} should call
632             * {@link VideoCall#sendSessionModifyResponse(VideoProfile)} to indicate the video
633             * profile agreed upon.
634             * <p>
635             * Callback originates from
636             * {@link Connection.VideoProvider#receiveSessionModifyRequest(VideoProfile)}.
637             *
638             * @param videoProfile The requested video profile.
639             */
640            public abstract void onSessionModifyRequestReceived(VideoProfile videoProfile);
641
642            /**
643             * Called when the {@link Connection.VideoProvider} receives a response to a session
644             * modification request previously sent to the peer device.
645             * <p>
646             * The new video state should not be considered active by the {@link InCallService}
647             * until the {@link Call} video state changes (the
648             * {@link Call.Callback#onDetailsChanged(Call, Call.Details)} callback is triggered
649             * when the video state changes).
650             * <p>
651             * Callback originates from
652             * {@link Connection.VideoProvider#receiveSessionModifyResponse(int, VideoProfile,
653             *      VideoProfile)}.
654             *
655             * @param status Status of the session modify request.  Valid values are
656             *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS},
657             *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_FAIL},
658             *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_INVALID},
659             *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_TIMED_OUT},
660             *      {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE}.
661             * @param requestedProfile The original request which was sent to the peer device.
662             * @param responseProfile The actual profile changes made by the peer device.
663             */
664            public abstract void onSessionModifyResponseReceived(int status,
665                    VideoProfile requestedProfile, VideoProfile responseProfile);
666
667            /**
668             * Handles events related to the current video session which the {@link InCallService}
669             * may wish to handle. These are separate from requested changes to the session due to
670             * the underlying protocol or connection.
671             * <p>
672             * Callback originates from
673             * {@link Connection.VideoProvider#handleCallSessionEvent(int)}.
674             *
675             * @param event The event.  Valid values are:
676             *      {@link Connection.VideoProvider#SESSION_EVENT_RX_PAUSE},
677             *      {@link Connection.VideoProvider#SESSION_EVENT_RX_RESUME},
678             *      {@link Connection.VideoProvider#SESSION_EVENT_TX_START},
679             *      {@link Connection.VideoProvider#SESSION_EVENT_TX_STOP},
680             *      {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_FAILURE},
681             *      {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_READY},
682             *      {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_PERMISSION_ERROR}.
683             */
684            public abstract void onCallSessionEvent(int event);
685
686            /**
687             * Handles a change to the video dimensions from the peer device. This could happen if,
688             * for example, the peer changes orientation of their device, or switches cameras.
689             * <p>
690             * Callback originates from
691             * {@link Connection.VideoProvider#changePeerDimensions(int, int)}.
692             *
693             * @param width  The updated peer video width.
694             * @param height The updated peer video height.
695             */
696            public abstract void onPeerDimensionsChanged(int width, int height);
697
698            /**
699             * Handles a change to the video quality.
700             * <p>
701             * Callback originates from {@link Connection.VideoProvider#changeVideoQuality(int)}.
702             *
703             * @param videoQuality  The updated peer video quality.  Valid values:
704             *      {@link VideoProfile#QUALITY_HIGH},
705             *      {@link VideoProfile#QUALITY_MEDIUM},
706             *      {@link VideoProfile#QUALITY_LOW},
707             *      {@link VideoProfile#QUALITY_DEFAULT}.
708             */
709            public abstract void onVideoQualityChanged(int videoQuality);
710
711            /**
712             * Handles an update to the total data used for the current video session.
713             * <p>
714             * Used by the {@link Connection.VideoProvider} in response to
715             * {@link VideoCall#requestCallDataUsage()}.  May also be called periodically by the
716             * {@link Connection.VideoProvider}.
717             * <p>
718             * Callback originates from {@link Connection.VideoProvider#setCallDataUsage(long)}.
719             *
720             * @param dataUsage The updated data usage (in bytes).
721             */
722            public abstract void onCallDataUsageChanged(long dataUsage);
723
724            /**
725             * Handles a change in the capabilities of the currently selected camera.
726             * <p>
727             * Used by the {@link Connection.VideoProvider} in response to
728             * {@link VideoCall#requestCameraCapabilities()}.  The {@link Connection.VideoProvider}
729             * may also report the camera capabilities after a call to
730             * {@link VideoCall#setCamera(String)}.
731             * <p>
732             * Callback originates from
733             * {@link Connection.VideoProvider#changeCameraCapabilities(
734             *      VideoProfile.CameraCapabilities)}.
735             *
736             * @param cameraCapabilities The changed camera capabilities.
737             */
738            public abstract void onCameraCapabilitiesChanged(
739                    VideoProfile.CameraCapabilities cameraCapabilities);
740        }
741    }
742}
743