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 
17 package com.android.media.remotedisplay.test;
18 
19 import com.android.media.remotedisplay.RemoteDisplay;
20 import com.android.media.remotedisplay.RemoteDisplayProvider;
21 
22 import android.app.Service;
23 import android.content.Intent;
24 import android.os.Handler;
25 import android.os.IBinder;
26 import android.util.Log;
27 
28 /**
29  * Remote display provider implementation that publishes working routes.
30  */
31 public class RemoteDisplayProviderService extends Service {
32     private static final String TAG = "RemoteDisplayProviderTest";
33 
34     private Provider mProvider;
35 
36     @Override
onBind(Intent intent)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 
Provider()62         public Provider() {
63             super(RemoteDisplayProviderService.this);
64             mHandler = new Handler(getMainLooper());
65         }
66 
67         @Override
onDiscoveryModeChanged(int mode)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
onConnect(final RemoteDisplay display)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
onDisconnect(RemoteDisplay display)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
onSetVolume(RemoteDisplay display, int volume)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
onAdjustVolume(RemoteDisplay display, int delta)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
addDisplay(RemoteDisplay display)282         public void addDisplay(RemoteDisplay display) {
283             Log.d(TAG, "addDisplay: display=" + display);
284             super.addDisplay(display);
285         }
286 
287         @Override
removeDisplay(RemoteDisplay display)288         public void removeDisplay(RemoteDisplay display) {
289             Log.d(TAG, "removeDisplay: display=" + display);
290             super.removeDisplay(display);
291         }
292 
293         @Override
updateDisplay(RemoteDisplay display)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