/*
* 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 com.android.media.remotedisplay.test;
import com.android.media.remotedisplay.RemoteDisplay;
import com.android.media.remotedisplay.RemoteDisplayProvider;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
/**
* Remote display provider implementation that publishes working routes.
*/
public class RemoteDisplayProviderService extends Service {
private static final String TAG = "RemoteDisplayProviderTest";
private Provider mProvider;
@Override
public IBinder onBind(Intent intent) {
if (intent.getAction().equals(RemoteDisplayProvider.SERVICE_INTERFACE)) {
if (mProvider == null) {
mProvider = new Provider();
return mProvider.getBinder();
}
}
return null;
}
final class Provider extends RemoteDisplayProvider {
private RemoteDisplay mTestDisplay1; // variable volume
private RemoteDisplay mTestDisplay2; // fixed volume
private RemoteDisplay mTestDisplay3; // not available
private RemoteDisplay mTestDisplay4; // in use
private RemoteDisplay mTestDisplay5; // available but ignores request to connect
private RemoteDisplay mTestDisplay6; // available but never finishes connecting
private RemoteDisplay mTestDisplay7; // blinks in and out of existence
private RemoteDisplay mTestDisplay8; // available but connecting attempt flakes out
private RemoteDisplay mTestDisplay9; // available but connection flakes out
private RemoteDisplay mTestDisplay10; // available and reconnects periodically
private final Handler mHandler;
private boolean mBlinking;
public Provider() {
super(RemoteDisplayProviderService.this);
mHandler = new Handler(getMainLooper());
}
@Override
public void onDiscoveryModeChanged(int mode) {
Log.d(TAG, "onDiscoveryModeChanged: mode=" + mode);
if (mode != DISCOVERY_MODE_NONE) {
// When discovery begins, go find all of the routes.
if (mTestDisplay1 == null) {
mTestDisplay1 = new RemoteDisplay("testDisplay1",
"Test Display 1 (variable)");
mTestDisplay1.setDescription("Variable volume");
mTestDisplay1.setStatus(RemoteDisplay.STATUS_AVAILABLE);
mTestDisplay1.setVolume(10);
mTestDisplay1.setVolumeHandling(RemoteDisplay.PLAYBACK_VOLUME_VARIABLE);
mTestDisplay1.setVolumeMax(15);
addDisplay(mTestDisplay1);
}
if (mTestDisplay2 == null) {
mTestDisplay2 = new RemoteDisplay("testDisplay2",
"Test Display 2 (fixed)");
mTestDisplay2.setDescription("Fixed volume");
mTestDisplay2.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay2);
}
if (mTestDisplay3 == null) {
mTestDisplay3 = new RemoteDisplay("testDisplay3",
"Test Display 3 (unavailable)");
mTestDisplay3.setDescription("Always unavailable");
mTestDisplay3.setStatus(RemoteDisplay.STATUS_NOT_AVAILABLE);
addDisplay(mTestDisplay3);
}
if (mTestDisplay4 == null) {
mTestDisplay4 = new RemoteDisplay("testDisplay4",
"Test Display 4 (in-use)");
mTestDisplay4.setDescription("Always in-use");
mTestDisplay4.setStatus(RemoteDisplay.STATUS_IN_USE);
addDisplay(mTestDisplay4);
}
if (mTestDisplay5 == null) {
mTestDisplay5 = new RemoteDisplay("testDisplay5",
"Test Display 5 (connect ignored)");
mTestDisplay5.setDescription("Ignores connect");
mTestDisplay5.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay5);
}
if (mTestDisplay6 == null) {
mTestDisplay6 = new RemoteDisplay("testDisplay6",
"Test Display 6 (connect hangs)");
mTestDisplay6.setDescription("Never finishes connecting");
mTestDisplay6.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay6);
}
if (mTestDisplay8 == null) {
mTestDisplay8 = new RemoteDisplay("testDisplay8",
"Test Display 8 (flaky when connecting)");
mTestDisplay8.setDescription("Aborts spontaneously while connecting");
mTestDisplay8.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay8);
}
if (mTestDisplay9 == null) {
mTestDisplay9 = new RemoteDisplay("testDisplay9",
"Test Display 9 (flaky when connected)");
mTestDisplay9.setDescription("Aborts spontaneously while connected");
mTestDisplay9.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay9);
}
if (mTestDisplay10 == null) {
mTestDisplay10 = new RemoteDisplay("testDisplay10",
"Test Display 10 (reconnects periodically)");
mTestDisplay10.setDescription("Reconnects spontaneously");
mTestDisplay10.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay10);
}
} else {
// When discovery ends, go hide some of the routes we can't actually use.
// This isn't something a normal route provider would do though.
// The routes will usually stay published.
if (mTestDisplay3 != null) {
removeDisplay(mTestDisplay3);
mTestDisplay3 = null;
}
if (mTestDisplay4 != null) {
removeDisplay(mTestDisplay4);
mTestDisplay4 = null;
}
}
// When active discovery is on, pretend there's a route that we can't quite
// reach that blinks in and out of existence.
if (mode == DISCOVERY_MODE_ACTIVE) {
if (!mBlinking) {
mBlinking = true;
mHandler.post(mBlink);
}
} else {
mBlinking = false;
}
}
@Override
public void onConnect(final RemoteDisplay display) {
Log.d(TAG, "onConnect: display.getId()=" + display.getId());
if (display == mTestDisplay1 || display == mTestDisplay2) {
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if ((display == mTestDisplay1 || display == mTestDisplay2)
&& display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
display.setStatus(RemoteDisplay.STATUS_CONNECTED);
updateDisplay(display);
}
}
}, 2000);
} else if (display == mTestDisplay6 || display == mTestDisplay7) {
// never finishes connecting
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
} else if (display == mTestDisplay8) {
// flakes out while connecting
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if ((display == mTestDisplay8)
&& display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
updateDisplay(display);
}
}
}, 2000);
} else if (display == mTestDisplay9) {
// flakes out when connected
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if ((display == mTestDisplay9)
&& display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
display.setStatus(RemoteDisplay.STATUS_CONNECTED);
updateDisplay(display);
}
}
}, 2000);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if ((display == mTestDisplay9)
&& display.getStatus() == RemoteDisplay.STATUS_CONNECTED) {
display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
updateDisplay(display);
}
}
}, 5000);
} else if (display == mTestDisplay10) {
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (display == mTestDisplay10) {
if (display.getStatus() == RemoteDisplay.STATUS_CONNECTING) {
display.setStatus(RemoteDisplay.STATUS_CONNECTED);
updateDisplay(display);
mHandler.postDelayed(this, 7000);
} else if (display.getStatus() == RemoteDisplay.STATUS_CONNECTED) {
display.setStatus(RemoteDisplay.STATUS_CONNECTING);
updateDisplay(display);
mHandler.postDelayed(this, 2000);
}
}
}
}, 2000);
}
}
@Override
public void onDisconnect(RemoteDisplay display) {
Log.d(TAG, "onDisconnect: display.getId()=" + display.getId());
if (display == mTestDisplay1 || display == mTestDisplay2
|| display == mTestDisplay6 || display == mTestDisplay8
|| display == mTestDisplay9 || display == mTestDisplay10) {
display.setStatus(RemoteDisplay.STATUS_AVAILABLE);
updateDisplay(display);
}
}
@Override
public void onSetVolume(RemoteDisplay display, int volume) {
Log.d(TAG, "onSetVolume: display.getId()=" + display.getId()
+ ", volume=" + volume);
if (display == mTestDisplay1) {
display.setVolume(Math.max(0, Math.min(display.getVolumeMax(), volume)));
updateDisplay(display);
}
}
@Override
public void onAdjustVolume(RemoteDisplay display, int delta) {
Log.d(TAG, "onAdjustVolume: display.getId()=" + display.getId()
+ ", delta=" + delta);
if (display == mTestDisplay1) {
display.setVolume(Math.max(0, Math.min(display.getVolumeMax(),
display .getVolume() + delta)));
updateDisplay(display);
}
}
@Override
public void addDisplay(RemoteDisplay display) {
Log.d(TAG, "addDisplay: display=" + display);
super.addDisplay(display);
}
@Override
public void removeDisplay(RemoteDisplay display) {
Log.d(TAG, "removeDisplay: display=" + display);
super.removeDisplay(display);
}
@Override
public void updateDisplay(RemoteDisplay display) {
Log.d(TAG, "updateDisplay: display=" + display);
super.updateDisplay(display);
}
private final Runnable mBlink = new Runnable() {
@Override
public void run() {
if (mTestDisplay7 == null) {
if (mBlinking) {
mTestDisplay7 = new RemoteDisplay("testDisplay7",
"Test Display 7 (blinky)");
mTestDisplay7.setDescription("Comes and goes but can't connect");
mTestDisplay7.setStatus(RemoteDisplay.STATUS_AVAILABLE);
addDisplay(mTestDisplay7);
mHandler.postDelayed(this, 7000);
}
} else {
removeDisplay(mTestDisplay7);
mTestDisplay7 = null;
if (mBlinking) {
mHandler.postDelayed(this, 4000);
}
}
}
};
}
}