1/*
2 * Copyright (C) 2013 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.media.remotedisplay.test;
18
19import com.android.media.remotedisplay.RemoteDisplay;
20import com.android.media.remotedisplay.RemoteDisplayProvider;
21
22import android.app.Service;
23import android.content.Intent;
24import android.os.Handler;
25import android.os.IBinder;
26import android.util.Log;
27
28/**
29 * Remote display provider implementation that publishes working routes.
30 */
31public class RemoteDisplayProviderService extends Service {
32    private static final String TAG = "RemoteDisplayProviderTest";
33
34    private Provider mProvider;
35
36    @Override
37    public IBinder onBind(Intent intent) {
38        if (intent.getAction().equals(RemoteDisplayProvider.SERVICE_INTERFACE)) {
39            if (mProvider == null) {
40                mProvider = new Provider();
41                return mProvider.getBinder();
42            }
43        }
44        return null;
45    }
46
47    final class Provider extends RemoteDisplayProvider {
48        private RemoteDisplay mTestDisplay1; // variable volume
49        private RemoteDisplay mTestDisplay2; // fixed volume
50        private RemoteDisplay mTestDisplay3; // not available
51        private RemoteDisplay mTestDisplay4; // in use
52        private RemoteDisplay mTestDisplay5; // available but ignores request to connect
53        private RemoteDisplay mTestDisplay6; // available but never finishes connecting
54        private RemoteDisplay mTestDisplay7; // blinks in and out of existence
55        private RemoteDisplay mTestDisplay8; // available but connecting attempt flakes out
56        private RemoteDisplay mTestDisplay9; // available but connection flakes out
57        private RemoteDisplay mTestDisplay10; // available and reconnects periodically
58
59        private final Handler mHandler;
60        private boolean mBlinking;
61
62        public Provider() {
63            super(RemoteDisplayProviderService.this);
64            mHandler = new Handler(getMainLooper());
65        }
66
67        @Override
68        public void onDiscoveryModeChanged(int mode) {
69            Log.d(TAG, "onDiscoveryModeChanged: mode=" + mode);
70
71            if (mode != DISCOVERY_MODE_NONE) {
72                // When discovery begins, go find all of the routes.
73                if (mTestDisplay1 == null) {
74                    mTestDisplay1 = new RemoteDisplay("testDisplay1",
75                            "Test Display 1 (variable)");
76                    mTestDisplay1.setDescription("Variable volume");
77                    mTestDisplay1.setStatus(RemoteDisplay.STATUS_AVAILABLE);
78                    mTestDisplay1.setVolume(10);
79                    mTestDisplay1.setVolumeHandling(RemoteDisplay.PLAYBACK_VOLUME_VARIABLE);
80                    mTestDisplay1.setVolumeMax(15);
81                    addDisplay(mTestDisplay1);
82                }
83                if (mTestDisplay2 == null) {
84                    mTestDisplay2 = new RemoteDisplay("testDisplay2",
85                            "Test Display 2 (fixed)");
86                    mTestDisplay2.setDescription("Fixed volume");
87                    mTestDisplay2.setStatus(RemoteDisplay.STATUS_AVAILABLE);
88                    addDisplay(mTestDisplay2);
89                }
90                if (mTestDisplay3 == null) {
91                    mTestDisplay3 = new RemoteDisplay("testDisplay3",
92                            "Test Display 3 (unavailable)");
93                    mTestDisplay3.setDescription("Always unavailable");
94                    mTestDisplay3.setStatus(RemoteDisplay.STATUS_NOT_AVAILABLE);
95                    addDisplay(mTestDisplay3);
96                }
97                if (mTestDisplay4 == null) {
98                    mTestDisplay4 = new RemoteDisplay("testDisplay4",
99                            "Test Display 4 (in-use)");
100                    mTestDisplay4.setDescription("Always in-use");
101                    mTestDisplay4.setStatus(RemoteDisplay.STATUS_IN_USE);
102                    addDisplay(mTestDisplay4);
103                }
104                if (mTestDisplay5 == null) {
105                    mTestDisplay5 = new RemoteDisplay("testDisplay5",
106                            "Test Display 5 (connect ignored)");
107                    mTestDisplay5.setDescription("Ignores connect");
108                    mTestDisplay5.setStatus(RemoteDisplay.STATUS_AVAILABLE);
109                    addDisplay(mTestDisplay5);
110                }
111                if (mTestDisplay6 == null) {
112                    mTestDisplay6 = new RemoteDisplay("testDisplay6",
113                            "Test Display 6 (connect hangs)");
114                    mTestDisplay6.setDescription("Never finishes connecting");
115                    mTestDisplay6.setStatus(RemoteDisplay.STATUS_AVAILABLE);
116                    addDisplay(mTestDisplay6);
117                }
118                if (mTestDisplay8 == null) {
119                    mTestDisplay8 = new RemoteDisplay("testDisplay8",
120                            "Test Display 8 (flaky when connecting)");
121                    mTestDisplay8.setDescription("Aborts spontaneously while connecting");
122                    mTestDisplay8.setStatus(RemoteDisplay.STATUS_AVAILABLE);
123                    addDisplay(mTestDisplay8);
124                }
125                if (mTestDisplay9 == null) {
126                    mTestDisplay9 = new RemoteDisplay("testDisplay9",
127                            "Test Display 9 (flaky when connected)");
128                    mTestDisplay9.setDescription("Aborts spontaneously while connected");
129                    mTestDisplay9.setStatus(RemoteDisplay.STATUS_AVAILABLE);
130                    addDisplay(mTestDisplay9);
131                }
132                if (mTestDisplay10 == null) {
133                    mTestDisplay10 = new RemoteDisplay("testDisplay10",
134                            "Test Display 10 (reconnects periodically)");
135                    mTestDisplay10.setDescription("Reconnects spontaneously");
136                    mTestDisplay10.setStatus(RemoteDisplay.STATUS_AVAILABLE);
137                    addDisplay(mTestDisplay10);
138                }
139            } else {
140                // When discovery ends, go hide some of the routes we can't actually use.
141                // This isn't something a normal route provider would do though.
142                // The routes will usually stay published.
143                if (mTestDisplay3 != null) {
144                    removeDisplay(mTestDisplay3);
145                    mTestDisplay3 = null;
146                }
147                if (mTestDisplay4 != null) {
148                    removeDisplay(mTestDisplay4);
149                    mTestDisplay4 = null;
150                }
151            }
152
153            // When active discovery is on, pretend there's a route that we can't quite
154            // reach that blinks in and out of existence.
155            if (mode == DISCOVERY_MODE_ACTIVE) {
156                if (!mBlinking) {
157                    mBlinking = true;
158                    mHandler.post(mBlink);
159                }
160            } else {
161                mBlinking = false;
162            }
163        }
164
165        @Override
166        public void onConnect(final RemoteDisplay display) {
167            Log.d(TAG, "onConnect: display.getId()=" + display.getId());
168
169            if (display == mTestDisplay1 || display == mTestDisplay2) {
170                display.setStatus(RemoteDisplay.STATUS_CONNECTING);
171                updateDisplay(display);
172                mHandler.postDelayed(new Runnable() {
173                    @Override
174                    public void run() {
175                        if ((display == mTestDisplay1 || display == mTestDisplay2)
176                                && display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
177                            display.setStatus(RemoteDisplay.STATUS_CONNECTED);
178                            updateDisplay(display);
179                        }
180                    }
181                }, 2000);
182            } else if (display == mTestDisplay6 || display == mTestDisplay7) {
183                // never finishes connecting
184                display.setStatus(RemoteDisplay.STATUS_CONNECTING);
185                updateDisplay(display);
186            } else if (display == mTestDisplay8) {
187                // flakes out while connecting
188                display.setStatus(RemoteDisplay.STATUS_CONNECTING);
189                updateDisplay(display);
190                mHandler.postDelayed(new Runnable() {
191                    @Override
192                    public void run() {
193                        if ((display == mTestDisplay8)
194                                && display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
195                            display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
196                            updateDisplay(display);
197                        }
198                    }
199                }, 2000);
200            } else if (display == mTestDisplay9) {
201                // flakes out when connected
202                display.setStatus(RemoteDisplay.STATUS_CONNECTING);
203                updateDisplay(display);
204                mHandler.postDelayed(new Runnable() {
205                    @Override
206                    public void run() {
207                        if ((display == mTestDisplay9)
208                                && display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
209                            display.setStatus(RemoteDisplay.STATUS_CONNECTED);
210                            updateDisplay(display);
211                        }
212                    }
213                }, 2000);
214                mHandler.postDelayed(new Runnable() {
215                    @Override
216                    public void run() {
217                        if ((display == mTestDisplay9)
218                                && display.getStatus() == RemoteDisplay.STATUS_CONNECTED) {
219                            display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
220                            updateDisplay(display);
221                        }
222                    }
223                }, 5000);
224            } else if (display == mTestDisplay10) {
225                display.setStatus(RemoteDisplay.STATUS_CONNECTING);
226                updateDisplay(display);
227                mHandler.postDelayed(new Runnable() {
228                    @Override
229                    public void run() {
230                        if (display == mTestDisplay10) {
231                            if (display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
232                                display.setStatus(RemoteDisplay.STATUS_CONNECTED);
233                                updateDisplay(display);
234                                mHandler.postDelayed(this, 7000);
235                            } else if (display.getStatus() == RemoteDisplay.STATUS_CONNECTED) {
236                                display.setStatus(RemoteDisplay.STATUS_CONNECTING);
237                                updateDisplay(display);
238                                mHandler.postDelayed(this, 2000);
239                            }
240                        }
241                    }
242                }, 2000);
243            }
244        }
245
246        @Override
247        public void onDisconnect(RemoteDisplay display) {
248            Log.d(TAG, "onDisconnect: display.getId()=" + display.getId());
249
250            if (display == mTestDisplay1 || display == mTestDisplay2
251                    || display == mTestDisplay6 || display == mTestDisplay8
252                    || display == mTestDisplay9 || display == mTestDisplay10) {
253                display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
254                updateDisplay(display);
255            }
256        }
257
258        @Override
259        public void onSetVolume(RemoteDisplay display, int volume) {
260            Log.d(TAG, "onSetVolume: display.getId()=" + display.getId()
261                    + ", volume=" + volume);
262
263            if (display == mTestDisplay1) {
264                display.setVolume(Math.max(0, Math.min(display.getVolumeMax(), volume)));
265                updateDisplay(display);
266            }
267        }
268
269        @Override
270        public void onAdjustVolume(RemoteDisplay display, int delta) {
271            Log.d(TAG, "onAdjustVolume: display.getId()=" + display.getId()
272                    + ", delta=" + delta);
273
274            if (display == mTestDisplay1) {
275                display.setVolume(Math.max(0, Math.min(display.getVolumeMax(),
276                        display .getVolume() + delta)));
277                updateDisplay(display);
278            }
279        }
280
281        @Override
282        public void addDisplay(RemoteDisplay display) {
283            Log.d(TAG, "addDisplay: display=" + display);
284            super.addDisplay(display);
285        }
286
287        @Override
288        public void removeDisplay(RemoteDisplay display) {
289            Log.d(TAG, "removeDisplay: display=" + display);
290            super.removeDisplay(display);
291        }
292
293        @Override
294        public void updateDisplay(RemoteDisplay display) {
295            Log.d(TAG, "updateDisplay: display=" + display);
296            super.updateDisplay(display);
297        }
298
299        private final Runnable mBlink = new Runnable() {
300            @Override
301            public void run() {
302                if (mTestDisplay7 == null) {
303                    if (mBlinking) {
304                        mTestDisplay7 = new RemoteDisplay("testDisplay7",
305                                "Test Display 7 (blinky)");
306                        mTestDisplay7.setDescription("Comes and goes but can't connect");
307                        mTestDisplay7.setStatus(RemoteDisplay.STATUS_AVAILABLE);
308                        addDisplay(mTestDisplay7);
309                        mHandler.postDelayed(this, 7000);
310                    }
311                } else {
312                    removeDisplay(mTestDisplay7);
313                    mTestDisplay7 = null;
314                    if (mBlinking) {
315                        mHandler.postDelayed(this, 4000);
316                    }
317                }
318            }
319        };
320    }
321}
322