1/*
2 * Copyright (C) 2014 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 R* limitations under the License.
15 */
16
17package android.telecom;
18
19import android.net.Uri;
20import android.os.Bundle;
21import android.os.Handler;
22import android.os.Message;
23import android.os.RemoteException;
24import android.telecom.Logging.Session;
25
26import com.android.internal.os.SomeArgs;
27import com.android.internal.telecom.IConnectionServiceAdapter;
28import com.android.internal.telecom.IVideoProvider;
29import com.android.internal.telecom.RemoteServiceCallback;
30
31import java.util.List;
32
33/**
34 * A component that provides an RPC servant implementation of {@link IConnectionServiceAdapter},
35 * posting incoming messages on the main thread on a client-supplied delegate object.
36 *
37 * TODO: Generate this and similar classes using a compiler starting from AIDL interfaces.
38 *
39 * @hide
40 */
41final class ConnectionServiceAdapterServant {
42    private static final int MSG_HANDLE_CREATE_CONNECTION_COMPLETE = 1;
43    private static final int MSG_SET_ACTIVE = 2;
44    private static final int MSG_SET_RINGING = 3;
45    private static final int MSG_SET_DIALING = 4;
46    private static final int MSG_SET_DISCONNECTED = 5;
47    private static final int MSG_SET_ON_HOLD = 6;
48    private static final int MSG_SET_RINGBACK_REQUESTED = 7;
49    private static final int MSG_SET_CONNECTION_CAPABILITIES = 8;
50    private static final int MSG_SET_IS_CONFERENCED = 9;
51    private static final int MSG_ADD_CONFERENCE_CALL = 10;
52    private static final int MSG_REMOVE_CALL = 11;
53    private static final int MSG_ON_POST_DIAL_WAIT = 12;
54    private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 13;
55    private static final int MSG_SET_VIDEO_STATE = 14;
56    private static final int MSG_SET_VIDEO_CALL_PROVIDER = 15;
57    private static final int MSG_SET_IS_VOIP_AUDIO_MODE = 16;
58    private static final int MSG_SET_STATUS_HINTS = 17;
59    private static final int MSG_SET_ADDRESS = 18;
60    private static final int MSG_SET_CALLER_DISPLAY_NAME = 19;
61    private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20;
62    private static final int MSG_ADD_EXISTING_CONNECTION = 21;
63    private static final int MSG_ON_POST_DIAL_CHAR = 22;
64    private static final int MSG_SET_CONFERENCE_MERGE_FAILED = 23;
65    private static final int MSG_PUT_EXTRAS = 24;
66    private static final int MSG_REMOVE_EXTRAS = 25;
67    private static final int MSG_ON_CONNECTION_EVENT = 26;
68    private static final int MSG_SET_CONNECTION_PROPERTIES = 27;
69    private static final int MSG_SET_PULLING = 28;
70    private static final int MSG_SET_AUDIO_ROUTE = 29;
71    private static final int MSG_ON_RTT_INITIATION_SUCCESS = 30;
72    private static final int MSG_ON_RTT_INITIATION_FAILURE = 31;
73    private static final int MSG_ON_RTT_REMOTELY_TERMINATED = 32;
74    private static final int MSG_ON_RTT_UPGRADE_REQUEST = 33;
75
76    private final IConnectionServiceAdapter mDelegate;
77
78    private final Handler mHandler = new Handler() {
79        @Override
80        public void handleMessage(Message msg) {
81            try {
82                internalHandleMessage(msg);
83            } catch (RemoteException e) {
84            }
85        }
86
87        // Internal method defined to centralize handling of RemoteException
88        private void internalHandleMessage(Message msg) throws RemoteException {
89            switch (msg.what) {
90                case MSG_HANDLE_CREATE_CONNECTION_COMPLETE: {
91                    SomeArgs args = (SomeArgs) msg.obj;
92                    try {
93                        mDelegate.handleCreateConnectionComplete(
94                                (String) args.arg1,
95                                (ConnectionRequest) args.arg2,
96                                (ParcelableConnection) args.arg3,
97                                null /*Session.Info*/);
98                    } finally {
99                        args.recycle();
100                    }
101                    break;
102                }
103                case MSG_SET_ACTIVE:
104                    mDelegate.setActive((String) msg.obj, null /*Session.Info*/);
105                    break;
106                case MSG_SET_RINGING:
107                    mDelegate.setRinging((String) msg.obj, null /*Session.Info*/);
108                    break;
109                case MSG_SET_DIALING:
110                    mDelegate.setDialing((String) msg.obj, null /*Session.Info*/);
111                    break;
112                case MSG_SET_PULLING:
113                    mDelegate.setPulling((String) msg.obj, null /*Session.Info*/);
114                    break;
115                case MSG_SET_DISCONNECTED: {
116                    SomeArgs args = (SomeArgs) msg.obj;
117                    try {
118                        mDelegate.setDisconnected((String) args.arg1, (DisconnectCause) args.arg2,
119                                null /*Session.Info*/);
120                    } finally {
121                        args.recycle();
122                    }
123                    break;
124                }
125                case MSG_SET_ON_HOLD:
126                    mDelegate.setOnHold((String) msg.obj, null /*Session.Info*/);
127                    break;
128                case MSG_SET_RINGBACK_REQUESTED:
129                    mDelegate.setRingbackRequested((String) msg.obj, msg.arg1 == 1,
130                            null /*Session.Info*/);
131                    break;
132                case MSG_SET_CONNECTION_CAPABILITIES:
133                    mDelegate.setConnectionCapabilities((String) msg.obj, msg.arg1,
134                            null /*Session.Info*/);
135                    break;
136                case MSG_SET_CONNECTION_PROPERTIES:
137                    mDelegate.setConnectionProperties((String) msg.obj, msg.arg1,
138                            null /*Session.Info*/);
139                    break;
140                case MSG_SET_IS_CONFERENCED: {
141                    SomeArgs args = (SomeArgs) msg.obj;
142                    try {
143                        mDelegate.setIsConferenced((String) args.arg1, (String) args.arg2,
144                                null /*Session.Info*/);
145                    } finally {
146                        args.recycle();
147                    }
148                    break;
149                }
150                case MSG_ADD_CONFERENCE_CALL: {
151                    SomeArgs args = (SomeArgs) msg.obj;
152                    try {
153                        mDelegate.addConferenceCall(
154                                (String) args.arg1, (ParcelableConference) args.arg2,
155                                null /*Session.Info*/);
156                    } finally {
157                        args.recycle();
158                    }
159                    break;
160                }
161                case MSG_REMOVE_CALL:
162                    mDelegate.removeCall((String) msg.obj,
163                            null /*Session.Info*/);
164                    break;
165                case MSG_ON_POST_DIAL_WAIT: {
166                    SomeArgs args = (SomeArgs) msg.obj;
167                    try {
168                        mDelegate.onPostDialWait((String) args.arg1, (String) args.arg2,
169                                null /*Session.Info*/);
170                    } finally {
171                        args.recycle();
172                    }
173                    break;
174                }
175                case MSG_ON_POST_DIAL_CHAR: {
176                    SomeArgs args = (SomeArgs) msg.obj;
177                    try {
178                        mDelegate.onPostDialChar((String) args.arg1, (char) args.argi1,
179                                null /*Session.Info*/);
180                    } finally {
181                        args.recycle();
182                    }
183                    break;
184                }
185                case MSG_QUERY_REMOTE_CALL_SERVICES:
186                    mDelegate.queryRemoteConnectionServices((RemoteServiceCallback) msg.obj,
187                            null /*Session.Info*/);
188                    break;
189                case MSG_SET_VIDEO_STATE:
190                    mDelegate.setVideoState((String) msg.obj, msg.arg1, null /*Session.Info*/);
191                    break;
192                case MSG_SET_VIDEO_CALL_PROVIDER: {
193                    SomeArgs args = (SomeArgs) msg.obj;
194                    try {
195                        mDelegate.setVideoProvider((String) args.arg1,
196                                (IVideoProvider) args.arg2, null /*Session.Info*/);
197                    } finally {
198                        args.recycle();
199                    }
200                    break;
201                }
202                case MSG_SET_IS_VOIP_AUDIO_MODE:
203                    mDelegate.setIsVoipAudioMode((String) msg.obj, msg.arg1 == 1,
204                            null /*Session.Info*/);
205                    break;
206                case MSG_SET_STATUS_HINTS: {
207                    SomeArgs args = (SomeArgs) msg.obj;
208                    try {
209                        mDelegate.setStatusHints((String) args.arg1, (StatusHints) args.arg2,
210                                null /*Session.Info*/);
211                    } finally {
212                        args.recycle();
213                    }
214                    break;
215                }
216                case MSG_SET_ADDRESS: {
217                    SomeArgs args = (SomeArgs) msg.obj;
218                    try {
219                        mDelegate.setAddress((String) args.arg1, (Uri) args.arg2, args.argi1,
220                                null /*Session.Info*/);
221                    } finally {
222                        args.recycle();
223                    }
224                    break;
225                }
226                case MSG_SET_CALLER_DISPLAY_NAME: {
227                    SomeArgs args = (SomeArgs) msg.obj;
228                    try {
229                        mDelegate.setCallerDisplayName(
230                                (String) args.arg1, (String) args.arg2, args.argi1,
231                                null /*Session.Info*/);
232                    } finally {
233                        args.recycle();
234                    }
235                    break;
236                }
237                case MSG_SET_CONFERENCEABLE_CONNECTIONS: {
238                    SomeArgs args = (SomeArgs) msg.obj;
239                    try {
240                        mDelegate.setConferenceableConnections((String) args.arg1,
241                                (List<String>) args.arg2, null /*Session.Info*/);
242                    } finally {
243                        args.recycle();
244                    }
245                    break;
246                }
247                case MSG_ADD_EXISTING_CONNECTION: {
248                    SomeArgs args = (SomeArgs) msg.obj;
249                    try {
250                        mDelegate.addExistingConnection((String) args.arg1,
251                                (ParcelableConnection) args.arg2, null /*Session.Info*/);
252                    } finally {
253                        args.recycle();
254                    }
255                    break;
256                }
257                case MSG_SET_CONFERENCE_MERGE_FAILED: {
258                    SomeArgs args = (SomeArgs) msg.obj;
259                    try {
260                        mDelegate.setConferenceMergeFailed((String) args.arg1,
261                                null /*Session.Info*/);
262                    } finally {
263                        args.recycle();
264                    }
265                    break;
266                }
267                case MSG_PUT_EXTRAS: {
268                    SomeArgs args = (SomeArgs) msg.obj;
269                    try {
270                        mDelegate.putExtras((String) args.arg1, (Bundle) args.arg2,
271                                null /*Session.Info*/);
272                    } finally {
273                        args.recycle();
274                    }
275                    break;
276                }
277                case MSG_REMOVE_EXTRAS: {
278                    SomeArgs args = (SomeArgs) msg.obj;
279                    try {
280                        mDelegate.removeExtras((String) args.arg1, (List<String>) args.arg2,
281                                null /*Session.Info*/);
282                    } finally {
283                        args.recycle();
284                    }
285                    break;
286                }
287                case MSG_ON_CONNECTION_EVENT: {
288                    SomeArgs args = (SomeArgs) msg.obj;
289                    try {
290                        mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2,
291                                (Bundle) args.arg3, null /*Session.Info*/);
292                    } finally {
293                        args.recycle();
294                    }
295                    break;
296                }
297                case MSG_SET_AUDIO_ROUTE: {
298                    SomeArgs args = (SomeArgs) msg.obj;
299                    try {
300                        mDelegate.setAudioRoute((String) args.arg1, args.argi1,
301                                (Session.Info) args.arg2);
302                    } finally {
303                        args.recycle();
304                    }
305                    break;
306                }
307                case MSG_ON_RTT_INITIATION_SUCCESS:
308                    mDelegate.onRttInitiationSuccess((String) msg.obj, null /*Session.Info*/);
309                    break;
310                case MSG_ON_RTT_INITIATION_FAILURE:
311                    mDelegate.onRttInitiationFailure((String) msg.obj, msg.arg1,
312                            null /*Session.Info*/);
313                    break;
314                case MSG_ON_RTT_REMOTELY_TERMINATED:
315                    mDelegate.onRttSessionRemotelyTerminated((String) msg.obj,
316                            null /*Session.Info*/);
317                    break;
318                case MSG_ON_RTT_UPGRADE_REQUEST:
319                    mDelegate.onRemoteRttRequest((String) msg.obj, null /*Session.Info*/);
320                    break;
321            }
322        }
323    };
324
325    private final IConnectionServiceAdapter mStub = new IConnectionServiceAdapter.Stub() {
326        @Override
327        public void handleCreateConnectionComplete(
328                String id,
329                ConnectionRequest request,
330                ParcelableConnection connection,
331                Session.Info sessionInfo) {
332            SomeArgs args = SomeArgs.obtain();
333            args.arg1 = id;
334            args.arg2 = request;
335            args.arg3 = connection;
336            mHandler.obtainMessage(MSG_HANDLE_CREATE_CONNECTION_COMPLETE, args).sendToTarget();
337        }
338
339        @Override
340        public void setActive(String connectionId, Session.Info sessionInfo) {
341            mHandler.obtainMessage(MSG_SET_ACTIVE, connectionId).sendToTarget();
342        }
343
344        @Override
345        public void setRinging(String connectionId, Session.Info sessionInfo) {
346            mHandler.obtainMessage(MSG_SET_RINGING, connectionId).sendToTarget();
347        }
348
349        @Override
350        public void setDialing(String connectionId, Session.Info sessionInfo) {
351            mHandler.obtainMessage(MSG_SET_DIALING, connectionId).sendToTarget();
352        }
353
354        @Override
355        public void setPulling(String connectionId, Session.Info sessionInfo) {
356            mHandler.obtainMessage(MSG_SET_PULLING, connectionId).sendToTarget();
357        }
358
359        @Override
360        public void setDisconnected(String connectionId, DisconnectCause disconnectCause,
361                Session.Info sessionInfo) {
362            SomeArgs args = SomeArgs.obtain();
363            args.arg1 = connectionId;
364            args.arg2 = disconnectCause;
365            mHandler.obtainMessage(MSG_SET_DISCONNECTED, args).sendToTarget();
366        }
367
368        @Override
369        public void setOnHold(String connectionId, Session.Info sessionInfo) {
370            mHandler.obtainMessage(MSG_SET_ON_HOLD, connectionId).sendToTarget();
371        }
372
373        @Override
374        public void setRingbackRequested(String connectionId, boolean ringback,
375                Session.Info sessionInfo) {
376            mHandler.obtainMessage(MSG_SET_RINGBACK_REQUESTED, ringback ? 1 : 0, 0, connectionId)
377                    .sendToTarget();
378        }
379
380        @Override
381        public void setConnectionCapabilities(String connectionId, int connectionCapabilities,
382                Session.Info sessionInfo) {
383            mHandler.obtainMessage(
384                    MSG_SET_CONNECTION_CAPABILITIES, connectionCapabilities, 0, connectionId)
385                    .sendToTarget();
386        }
387
388        @Override
389        public void setConnectionProperties(String connectionId, int connectionProperties,
390                Session.Info sessionInfo) {
391            mHandler.obtainMessage(
392                    MSG_SET_CONNECTION_PROPERTIES, connectionProperties, 0, connectionId)
393                    .sendToTarget();
394        }
395
396        @Override
397        public void setConferenceMergeFailed(String callId, Session.Info sessionInfo) {
398            SomeArgs args = SomeArgs.obtain();
399            args.arg1 = callId;
400            mHandler.obtainMessage(MSG_SET_CONFERENCE_MERGE_FAILED, args).sendToTarget();
401        }
402
403        @Override
404        public void setIsConferenced(String callId, String conferenceCallId,
405                Session.Info sessionInfo) {
406            SomeArgs args = SomeArgs.obtain();
407            args.arg1 = callId;
408            args.arg2 = conferenceCallId;
409            mHandler.obtainMessage(MSG_SET_IS_CONFERENCED, args).sendToTarget();
410        }
411
412        @Override
413        public void addConferenceCall(String callId, ParcelableConference parcelableConference,
414                Session.Info sessionInfo) {
415            SomeArgs args = SomeArgs.obtain();
416            args.arg1 = callId;
417            args.arg2 = parcelableConference;
418            mHandler.obtainMessage(MSG_ADD_CONFERENCE_CALL, args).sendToTarget();
419        }
420
421        @Override
422        public void removeCall(String connectionId,
423                Session.Info sessionInfo) {
424            mHandler.obtainMessage(MSG_REMOVE_CALL, connectionId).sendToTarget();
425        }
426
427        @Override
428        public void onPostDialWait(String connectionId, String remainingDigits,
429                Session.Info sessionInfo) {
430            SomeArgs args = SomeArgs.obtain();
431            args.arg1 = connectionId;
432            args.arg2 = remainingDigits;
433            mHandler.obtainMessage(MSG_ON_POST_DIAL_WAIT, args).sendToTarget();
434        }
435
436        @Override
437        public void onPostDialChar(String connectionId, char nextChar,
438                Session.Info sessionInfo) {
439            SomeArgs args = SomeArgs.obtain();
440            args.arg1 = connectionId;
441            args.argi1 = nextChar;
442            mHandler.obtainMessage(MSG_ON_POST_DIAL_CHAR, args).sendToTarget();
443        }
444
445        @Override
446        public void queryRemoteConnectionServices(RemoteServiceCallback callback,
447                Session.Info sessionInfo) {
448            mHandler.obtainMessage(MSG_QUERY_REMOTE_CALL_SERVICES, callback).sendToTarget();
449        }
450
451        @Override
452        public void setVideoState(String connectionId, int videoState,
453                Session.Info sessionInfo) {
454            mHandler.obtainMessage(MSG_SET_VIDEO_STATE, videoState, 0, connectionId).sendToTarget();
455        }
456
457        @Override
458        public void setVideoProvider(String connectionId, IVideoProvider videoProvider,
459                Session.Info sessionInfo) {
460            SomeArgs args = SomeArgs.obtain();
461            args.arg1 = connectionId;
462            args.arg2 = videoProvider;
463            mHandler.obtainMessage(MSG_SET_VIDEO_CALL_PROVIDER, args).sendToTarget();
464        }
465
466        @Override
467        public final void setIsVoipAudioMode(String connectionId, boolean isVoip,
468                Session.Info sessionInfo) {
469            mHandler.obtainMessage(MSG_SET_IS_VOIP_AUDIO_MODE, isVoip ? 1 : 0, 0,
470                    connectionId).sendToTarget();
471        }
472
473        @Override
474        public final void setStatusHints(String connectionId, StatusHints statusHints,
475                Session.Info sessionInfo) {
476            SomeArgs args = SomeArgs.obtain();
477            args.arg1 = connectionId;
478            args.arg2 = statusHints;
479            mHandler.obtainMessage(MSG_SET_STATUS_HINTS, args).sendToTarget();
480        }
481
482        @Override
483        public final void setAddress(String connectionId, Uri address, int presentation,
484                Session.Info sessionInfo) {
485            SomeArgs args = SomeArgs.obtain();
486            args.arg1 = connectionId;
487            args.arg2 = address;
488            args.argi1 = presentation;
489            mHandler.obtainMessage(MSG_SET_ADDRESS, args).sendToTarget();
490        }
491
492        @Override
493        public final void setCallerDisplayName(
494                String connectionId, String callerDisplayName, int presentation,
495                Session.Info sessionInfo) {
496            SomeArgs args = SomeArgs.obtain();
497            args.arg1 = connectionId;
498            args.arg2 = callerDisplayName;
499            args.argi1 = presentation;
500            mHandler.obtainMessage(MSG_SET_CALLER_DISPLAY_NAME, args).sendToTarget();
501        }
502
503        @Override
504        public final void setConferenceableConnections(String connectionId,
505                List<String> conferenceableConnectionIds, Session.Info sessionInfo) {
506            SomeArgs args = SomeArgs.obtain();
507            args.arg1 = connectionId;
508            args.arg2 = conferenceableConnectionIds;
509            mHandler.obtainMessage(MSG_SET_CONFERENCEABLE_CONNECTIONS, args).sendToTarget();
510        }
511
512        @Override
513        public final void addExistingConnection(String connectionId,
514                ParcelableConnection connection, Session.Info sessionInfo) {
515            SomeArgs args = SomeArgs.obtain();
516            args.arg1 = connectionId;
517            args.arg2 = connection;
518            mHandler.obtainMessage(MSG_ADD_EXISTING_CONNECTION, args).sendToTarget();
519        }
520
521        @Override
522        public final void putExtras(String connectionId, Bundle extras, Session.Info sessionInfo) {
523            SomeArgs args = SomeArgs.obtain();
524            args.arg1 = connectionId;
525            args.arg2 = extras;
526            mHandler.obtainMessage(MSG_PUT_EXTRAS, args).sendToTarget();
527        }
528
529        @Override
530        public final void removeExtras(String connectionId, List<String> keys,
531                Session.Info sessionInfo) {
532            SomeArgs args = SomeArgs.obtain();
533            args.arg1 = connectionId;
534            args.arg2 = keys;
535            mHandler.obtainMessage(MSG_REMOVE_EXTRAS, args).sendToTarget();
536        }
537
538        @Override
539        public final void setAudioRoute(String connectionId, int audioRoute,
540                Session.Info sessionInfo) {
541
542            SomeArgs args = SomeArgs.obtain();
543            args.arg1 = connectionId;
544            args.argi1 = audioRoute;
545            args.arg2 = sessionInfo;
546            mHandler.obtainMessage(MSG_SET_AUDIO_ROUTE, args).sendToTarget();
547        }
548
549        @Override
550        public final void onConnectionEvent(String connectionId, String event, Bundle extras,
551                Session.Info sessionInfo) {
552            SomeArgs args = SomeArgs.obtain();
553            args.arg1 = connectionId;
554            args.arg2 = event;
555            args.arg3 = extras;
556            mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
557        }
558
559        @Override
560        public void onRttInitiationSuccess(String connectionId, Session.Info sessionInfo)
561                throws RemoteException {
562            mHandler.obtainMessage(MSG_ON_RTT_INITIATION_SUCCESS, connectionId).sendToTarget();
563        }
564
565        @Override
566        public void onRttInitiationFailure(String connectionId, int reason,
567                Session.Info sessionInfo)
568                throws RemoteException {
569            mHandler.obtainMessage(MSG_ON_RTT_INITIATION_FAILURE, reason, 0, connectionId)
570                    .sendToTarget();
571        }
572
573        @Override
574        public void onRttSessionRemotelyTerminated(String connectionId, Session.Info sessionInfo)
575                throws RemoteException {
576            mHandler.obtainMessage(MSG_ON_RTT_REMOTELY_TERMINATED, connectionId).sendToTarget();
577        }
578
579        @Override
580        public void onRemoteRttRequest(String connectionId, Session.Info sessionInfo)
581                throws RemoteException {
582            mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, connectionId).sendToTarget();
583        }
584    };
585
586    public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
587        mDelegate = delegate;
588    }
589
590    public IConnectionServiceAdapter getStub() {
591        return mStub;
592    }
593}
594