summaryrefslogtreecommitdiffstats
path: root/telecomm/java/android/telecomm/InCallService.java
blob: 8f1add2b1e5a9df0443a3c1126c3448f214bc83b (plain)
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
166
167
168
169
170
171
172
173
/*
 * 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.telecomm;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;

import com.android.internal.telecomm.IInCallAdapter;
import com.android.internal.telecomm.IInCallService;

/**
 * This service is implemented by any app that wishes to provide the user-interface for managing
 * phone calls. Telecomm binds to this service while there exists a live (active or incoming)
 * call, and uses it to notify the in-call app of any live and and recently disconnected calls.
 * TODO(santoscordon): Needs more/better description of lifecycle once the interface is better
 * defined.
 * TODO(santoscordon): What happens if two or more apps on a given device implement this interface?
 */
public abstract class InCallService extends Service {
    private static final int MSG_SET_IN_CALL_ADAPTER = 1;
    private static final int MSG_ADD_CALL = 2;
    private static final int MSG_SET_ACTIVE = 3;
    private static final int MSG_SET_DISCONNECTED = 4;
    private static final int MSG_SET_HOLD = 5;
    private static final int MSG_ON_AUDIO_STATE_CHANGED = 6;

    /** Default Handler used to consolidate binder method calls onto a single thread. */
    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SET_IN_CALL_ADAPTER:
                    InCallAdapter adapter = new InCallAdapter((IInCallAdapter) msg.obj);
                    setInCallAdapter(adapter);
                    break;
                case MSG_ADD_CALL:
                    addCall((CallInfo) msg.obj);
                    break;
                case MSG_SET_ACTIVE:
                    setActive((String) msg.obj);
                    break;
                case MSG_SET_DISCONNECTED:
                    setDisconnected((String) msg.obj, msg.arg1);
                    break;
                case MSG_SET_HOLD:
                    setOnHold((String) msg.obj);
                    break;
                case MSG_ON_AUDIO_STATE_CHANGED:
                    onAudioStateChanged((CallAudioState) msg.obj);
                default:
                    break;
            }
        }
    };

    /** Manages the binder calls so that the implementor does not need to deal with it. */
    private final class InCallServiceBinder extends IInCallService.Stub {
        /** {@inheritDoc} */
        @Override
        public void setInCallAdapter(IInCallAdapter inCallAdapter) {
            mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
        }

        /** {@inheritDoc} */
        @Override
        public void addCall(CallInfo callInfo) {
            mHandler.obtainMessage(MSG_ADD_CALL, callInfo).sendToTarget();
        }

        /** {@inheritDoc} */
        @Override
        public void setActive(String callId) {
            mHandler.obtainMessage(MSG_SET_ACTIVE, callId).sendToTarget();
        }

        /** {@inheritDoc} */
        @Override
        public void setDisconnected(String callId, int disconnectCause) {
            mHandler.obtainMessage(MSG_SET_DISCONNECTED, disconnectCause, 0, callId).sendToTarget();
        }

        /** {@inheritDoc} */
        @Override
        public void setOnHold(String callId) {
            mHandler.obtainMessage(MSG_SET_HOLD, callId).sendToTarget();
        }

        /** {@inheritDoc} */
        @Override
        public void onAudioStateChanged(CallAudioState audioState) {
            mHandler.obtainMessage(MSG_ON_AUDIO_STATE_CHANGED, audioState).sendToTarget();
        }
    }

    private final InCallServiceBinder mBinder;

    protected InCallService() {
        mBinder = new InCallServiceBinder();
    }

    @Override
    public final IBinder onBind(Intent intent) {
        return mBinder;
    }

    /**
     * Provides the in-call app an adapter object through which to send call-commands such as
     * answering and rejecting incoming calls, disconnecting active calls, and putting calls in
     * special states (mute, hold, etc).
     *
     * @param inCallAdapter Adapter through which an in-call app can send call-commands to Telecomm.
     */
    protected abstract void setInCallAdapter(InCallAdapter inCallAdapter);

    /**
     * Indicates to the in-call app that a new call has been created and an appropriate
     * user-interface should be built and shown to notify the user. Information about the call
     * including its current state is passed in through the callInfo object.
     *
     * @param callInfo Information about the new call.
     */
     protected abstract void addCall(CallInfo callInfo);

    /**
     * Indicates to the in-call app that a call has moved to the {@link CallState#ACTIVE} state.
     *
     * @param callId The identifier of the call that became active.
     */
    protected abstract void setActive(String callId);

    /**
     * Indicates to the in-call app that a call has been moved to the
     * {@link CallState#DISCONNECTED} and the user should be notified.
     *
     * @param callId The identifier of the call that was disconnected.
     * @param disconnectCause The reason for the disconnection, any of
     *         {@link android.telephony.DisconnectCause}.
     */
    protected abstract void setDisconnected(String callId, int disconnectCause);

    /**
     * Indicates to the in-call app that a call has been moved to the
     * {@link android.telecomm.CallState#ON_HOLD} state and the user should be notified.
     *
     * @param callId The identifier of the call that was put on hold.
     */
    protected abstract void setOnHold(String callId);

    /**
     * Called when the audio state changes.
     *
     * @param audioState The new {@link CallAudioState}.
     */
    protected abstract void onAudioStateChanged(CallAudioState audioState);
}