1/*
2 * Copyright (C) 2017 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 com.android.server.telecom.testapps;
18
19import android.app.Notification;
20import android.app.NotificationManager;
21import android.app.PendingIntent;
22import android.content.Context;
23import android.content.Intent;
24import android.graphics.drawable.Icon;
25import android.media.MediaPlayer;
26import android.os.Bundle;
27import android.telecom.Call;
28import android.telecom.CallAudioState;
29import android.telecom.Connection;
30import android.telecom.ConnectionService;
31import android.telecom.DisconnectCause;
32import android.telecom.VideoProfile;
33
34import com.android.server.telecom.testapps.R;
35
36/**
37 * Sample self-managed {@link Connection} for a self-managed {@link ConnectionService}.
38 * <p>
39 * See {@link android.telecom} for more information on self-managed {@link ConnectionService}s.
40 */
41public class SelfManagedConnection extends Connection {
42    public static class Listener {
43        public void onConnectionStateChanged(SelfManagedConnection connection) {}
44        public void onConnectionRemoved(SelfManagedConnection connection) {}
45    }
46
47    public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
48            "com.android.server.telecom.testapps.extra.PHONE_ACCOUNT_HANDLE";
49    public static final String CALL_NOTIFICATION = "com.android.server.telecom.testapps.CALL";
50
51    private static int sNextCallId = 1;
52
53    private final int mCallId;
54    private final Context mContext;
55    private final SelfManagedCallList mCallList;
56    private final MediaPlayer mMediaPlayer;
57    private final boolean mIsIncomingCall;
58    private boolean mIsIncomingCallUiShowing;
59    private Listener mListener;
60    private boolean mIsHandover;
61
62    SelfManagedConnection(SelfManagedCallList callList, Context context, boolean isIncoming) {
63        mCallList = callList;
64        mMediaPlayer = createMediaPlayer(context);
65        mIsIncomingCall = isIncoming;
66        mContext = context;
67        mCallId = sNextCallId++;
68    }
69
70    public void setListener(Listener listener) {
71        mListener = listener;
72    }
73
74    /**
75     * Handles updates to the audio state of the connection.
76     * @param state The new connection audio state.
77     */
78    @Override
79    public void onCallAudioStateChanged(CallAudioState state) {
80        mCallList.notifyCallModified();
81    }
82
83    @Override
84    public void onShowIncomingCallUi() {
85        if (isHandover()) {
86            return;
87        }
88        // Create the fullscreen intent used to show the fullscreen incoming call UX.
89        Intent intent = new Intent(Intent.ACTION_MAIN, null);
90        intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
91        intent.setClass(mContext, IncomingSelfManagedCallActivity.class);
92        intent.putExtra(IncomingSelfManagedCallActivity.EXTRA_CALL_ID, mCallId);
93        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 1, intent, 0);
94
95        // Build the notification as an ongoing high priority item.
96        final Notification.Builder builder = new Notification.Builder(mContext);
97        builder.setOngoing(true);
98        builder.setPriority(Notification.PRIORITY_HIGH);
99
100        // Set up the main intent to send the user to the incoming call screen.
101        builder.setContentIntent(pendingIntent);
102        builder.setFullScreenIntent(pendingIntent, true);
103
104        // Setup notification content.
105        builder.setSmallIcon(R.drawable.ic_android_black_24dp);
106        builder.setContentTitle("Incoming call...");
107        builder.setContentText("Incoming test call from " + getAddress());
108
109        // Setup answer and reject call button
110        final Intent answerIntent = new Intent(
111                SelfManagedCallNotificationReceiver.ACTION_ANSWER_CALL, null, mContext,
112                SelfManagedCallNotificationReceiver.class);
113        answerIntent.putExtra(IncomingSelfManagedCallActivity.EXTRA_CALL_ID, mCallId);
114        final Intent rejectIntent = new Intent(
115                SelfManagedCallNotificationReceiver.ACTION_REJECT_CALL, null, mContext,
116                SelfManagedCallNotificationReceiver.class);
117        rejectIntent.putExtra(IncomingSelfManagedCallActivity.EXTRA_CALL_ID, mCallId);
118
119        builder.addAction(
120                new Notification.Action.Builder(
121                        Icon.createWithResource(mContext, R.drawable.ic_android_black_24dp),
122                        "Answer",
123                        PendingIntent.getBroadcast(mContext, 0, answerIntent,
124                                PendingIntent.FLAG_UPDATE_CURRENT))
125                        .build());
126        builder.addAction(
127                new Notification.Action.Builder(
128                        Icon.createWithResource(mContext, R.drawable.ic_android_black_24dp),
129                        "Reject",
130                        PendingIntent.getBroadcast(mContext, 0, rejectIntent,
131                                PendingIntent.FLAG_UPDATE_CURRENT))
132                        .build());
133
134        NotificationManager notificationManager = mContext.getSystemService(
135                NotificationManager.class);
136        notificationManager.notify(CALL_NOTIFICATION, mCallId, builder.build());
137    }
138
139    @Override
140    public void onHold() {
141        setOnHold();
142    }
143
144    @Override
145    public void onUnhold() {
146        setActive();
147    }
148
149    @Override
150    public void onAnswer(int videoState) {
151        setConnectionActive();
152    }
153
154    @Override
155    public void onAnswer() {
156        onAnswer(VideoProfile.STATE_AUDIO_ONLY);
157    }
158
159    @Override
160    public void onReject() {
161        setConnectionDisconnected(DisconnectCause.REJECTED);
162    }
163
164    @Override
165    public void onDisconnect() {
166        setConnectionDisconnected(DisconnectCause.LOCAL);
167    }
168
169    public void setConnectionActive() {
170        mMediaPlayer.start();
171        setActive();
172        if (mListener != null ) {
173            mListener.onConnectionStateChanged(this);
174        }
175    }
176
177    public void setConnectionHeld() {
178        mMediaPlayer.pause();
179        setOnHold();
180        if (mListener != null ) {
181            mListener.onConnectionStateChanged(this);
182        }
183    }
184
185    public void setConnectionDisconnected(int cause) {
186        mMediaPlayer.stop();
187        setDisconnected(new DisconnectCause(cause));
188        destroy();
189        if (mListener != null ) {
190            mListener.onConnectionRemoved(this);
191        }
192    }
193
194    public void setIsIncomingCallUiShowing(boolean showing) {
195        mIsIncomingCallUiShowing = showing;
196    }
197
198    public boolean isIncomingCallUiShowing() {
199        return mIsIncomingCallUiShowing;
200    }
201
202    public boolean isIncomingCall() {
203        return mIsIncomingCall;
204    }
205
206    public int getCallId() {
207        return mCallId;
208    }
209
210    public void setIsHandover(boolean isHandover) {
211        mIsHandover = isHandover;
212    }
213
214    public boolean isHandover() {
215        return mIsHandover;
216    }
217
218    private MediaPlayer createMediaPlayer(Context context) {
219        int audioToPlay = (Math.random() > 0.5f) ? R.raw.sample_audio : R.raw.sample_audio2;
220        MediaPlayer mediaPlayer = MediaPlayer.create(context, audioToPlay);
221        mediaPlayer.setLooping(true);
222        return mediaPlayer;
223    }
224}
225