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