1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import com.android.internal.telephony.ICallService;
import com.android.internal.telephony.ICallServiceAdapter;
/**
* Base implementation of CallService which can be used to provide calls for the system
* in-call UI. CallService is a one-way service from the framework's CallsManager to any app
* that would like to provide calls managed by the default system in-call user interface.
* When the service is bound by the framework, CallsManager will call setCallServiceAdapter
* which will provide CallService with an instance of {@link CallServiceAdapter} to be used
* for communicating back to CallsManager. Subsequently, more specific methods of the service
* will be called to perform various call actions including making an outgoing call and
* disconnected existing calls.
* TODO(santoscordon): Needs more about AndroidManifest.xml service registrations before
* we can unhide this API.
*
* Most public methods of this function are backed by a one-way AIDL interface which precludes
* syncronous responses. As a result, most responses are handled by (or have TODOs to handle)
* response objects instead of return values.
* TODO(santoscordon): Improve paragraph above once the final design is in place.
* @hide
*/
public abstract class CallService extends Service {
/**
* Default Handler used to consolidate binder method calls onto a single thread.
*/
private final class CallServiceMessageHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SET_CALL_SERVICE_ADAPTER:
setCallServiceAdapter((ICallServiceAdapter) msg.obj);
break;
case MSG_IS_COMPATIBLE_WITH:
isCompatibleWith((String) msg.obj);
break;
case MSG_CALL:
call((String) msg.obj);
break;
case MSG_DISCONNECT:
disconnect((String) msg.obj);
break;
default:
break;
}
}
}
/**
* Default ICallService implementation provided to CallsManager via {@link #onBind}.
*/
private final class CallServiceWrapper extends ICallService.Stub {
@Override
public void setCallServiceAdapter(ICallServiceAdapter callServiceAdapter) {
mMessageHandler.obtainMessage(MSG_SET_CALL_SERVICE_ADAPTER, callServiceAdapter)
.sendToTarget();
}
@Override
public void isCompatibleWith(String handle) {
mMessageHandler.obtainMessage(MSG_IS_COMPATIBLE_WITH, handle).sendToTarget();
}
@Override
public void call(String handle) {
mMessageHandler.obtainMessage(MSG_CALL, handle).sendToTarget();
}
@Override
public void disconnect(String callId) {
mMessageHandler.obtainMessage(MSG_DISCONNECT, callId).sendToTarget();
}
}
// Only used internally by this class.
// Binder method calls on this service can occur on multiple threads. These messages are used
// in conjunction with {@link #mMessageHandler} to ensure that all callbacks are handled on a
// single thread. Keeping it on a single thread allows CallService implementations to avoid
// needing multi-threaded code in their own callback routines.
private static final int
MSG_SET_CALL_SERVICE_ADAPTER = 1,
MSG_IS_COMPATIBLE_WITH = 2,
MSG_CALL = 3,
MSG_DISCONNECT = 4;
/**
* Message handler for consolidating binder callbacks onto a single thread.
* See {@link #CallServiceMessageHandler}.
*/
private final CallServiceMessageHandler mMessageHandler;
/**
* Default binder implementation of {@link ICallService} interface.
*/
private final CallServiceWrapper mBinder;
/**
* Protected constructor called only by subclasses creates the binder interface and
* single-threaded message handler.
*/
protected CallService() {
mMessageHandler = new CallServiceMessageHandler();
mBinder = new CallServiceWrapper();
}
/** {@inheritDoc} */
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Sets an implementation of ICallServiceAdapter for adding new calls and communicating state
* changes of existing calls.
* @param callServiceAdapter Adapter object for communicating call to CallsManager
* TODO(santoscordon): Should we not reference ICallServiceAdapter directly from here? Should we
* wrap that in a wrapper like we do for CallService/ICallService?
* TODO(santoscordon): Consider rename of CallServiceAdapter to CallsManager.
*/
public abstract void setCallServiceAdapter(ICallServiceAdapter callServiceAdapter);
/**
* Determines if the CallService can make calls to the handle.
* @param handle The handle to test for compatibility.
* TODO(santoscordon): Need response parameter.
*/
public abstract void isCompatibleWith(String handle);
/**
* Calls the specified handle. Handle type is dynamically extensible and can be a phone number,
* a SIP address, or other types. Only called if {@link #isCompatibleWith} returns true for the
* same handle and this service is selected by the switchboard to handle the call.
* @param handle The handle to call.
*/
public abstract void call(String handle);
/**
* Disconnects the specified call.
* @param callId The ID of the call to disconnect.
*/
public abstract void disconnect(String callId);
}
|