package com.android.settings.wfd;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.hardware.display.DisplayManager;
import android.hardware.display.WifiDisplay;
import android.hardware.display.WifiDisplayStatus;
import android.provider.Settings;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteInfo;
import android.os.Handler;
import android.content.Context;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.content.BroadcastReceiver;
import android.view.Menu;
import android.net.Uri;
import android.net.wifi.WpsInfo;
import java.util.ArrayList;
import java.util.List;
public class WfdService extends Service {
private String TAG="WfdService";
private static final int MENU_ID_ENABLE_WIFI_DISPLAY = Menu.FIRST;
private static final int CHANGE_SETTINGS = 1 << 0;
private static final int CHANGE_ROUTES = 1 << 1;
private static final int CHANGE_WIFI_DISPLAY_STATUS = 1 << 2;
private static final int CHANGE_ALL = -1;
private static final int ORDER_CERTIFICATION = 1;
private static final int ORDER_CONNECTED = 2;
private static final int ORDER_AVAILABLE = 3;
private static final int ORDER_UNAVAILABLE = 4;
private int mWpsConfig = WpsInfo.INVALID;
private int mPendingChanges;
private boolean mWifiDisplayOnSetting;
private WifiDisplayStatus mWifiDisplayStatus;
private boolean mWifiDisplayCertificationOn;
private DisplayManager mDisplayManager;
private MediaRouter mRouter;
private Handler mHandler;
private boolean mStarted=true;
public WfdService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
Log.v(TAG,"onCreate");
final Context context = this;
mHandler = new Handler();
mRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
context.registerReceiver(mReceiver, filter);
getContentResolver().registerContentObserver(Settings.Global.getUriFor(
Settings.Global.WIFI_DISPLAY_ON), false, mSettingsObserver);
getContentResolver().registerContentObserver(Settings.Global.getUriFor(
Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON), false, mSettingsObserver);
getContentResolver().registerContentObserver(Settings.Global.getUriFor(
Settings.Global.WIFI_DISPLAY_WPS_CONFIG), false, mSettingsObserver);
mRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mRouterCallback,
MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.v(TAG,"onDestroy");
final Context context = this;
context.unregisterReceiver(mReceiver);
getContentResolver().unregisterContentObserver(mSettingsObserver);
mRouter.removeCallback(mRouterCallback);
unscheduleUpdate();
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED)) {
scheduleUpdate(CHANGE_WIFI_DISPLAY_STATUS);
}
}
};
private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange, Uri uri) {
scheduleUpdate(CHANGE_SETTINGS);
}
};
private final MediaRouter.Callback mRouterCallback = new MediaRouter.SimpleCallback() {
@Override
public void onRouteAdded(MediaRouter router, RouteInfo info) {
scheduleUpdate(CHANGE_ROUTES);
}
@Override
public void onRouteChanged(MediaRouter router, RouteInfo info) {
scheduleUpdate(CHANGE_ROUTES);
}
@Override
public void onRouteRemoved(MediaRouter router, RouteInfo info) {
scheduleUpdate(CHANGE_ROUTES);
}
@Override
public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
scheduleUpdate(CHANGE_ROUTES);
}
@Override
public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
scheduleUpdate(CHANGE_ROUTES);
}
};
private void scheduleUpdate(int changes) {
if (mStarted) {
if (mPendingChanges == 0) {
mHandler.post(mUpdateRunnable);
}
mPendingChanges |= changes;
}
}
private void unscheduleUpdate() {
if (mPendingChanges != 0) {
mPendingChanges = 0;
mHandler.removeCallbacks(mUpdateRunnable);
}
}
private final Runnable mUpdateRunnable = new Runnable() {
@Override
public void run() {
final int changes = mPendingChanges;
mPendingChanges = 0;
update(changes);
}
};
private List<WifiDisplay> devices=new ArrayList<>();
private void update(int changes) {
boolean invalidateOptions = false;
// Update settings.
if ((changes & CHANGE_SETTINGS) != 0) {
mWifiDisplayOnSetting = Settings.Global.getInt(getContentResolver(),
Settings.Global.WIFI_DISPLAY_ON, 0) != 0;
mWifiDisplayCertificationOn = Settings.Global.getInt(getContentResolver(),
Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON, 0) != 0;
mWpsConfig = Settings.Global.getInt(getContentResolver(),
Settings.Global.WIFI_DISPLAY_WPS_CONFIG, WpsInfo.INVALID);
// The wifi display enabled setting may have changed.
invalidateOptions = true;
}
// Update wifi display state.
if ((changes & CHANGE_WIFI_DISPLAY_STATUS) != 0) {
mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
// The wifi display feature state may have changed.
invalidateOptions = true;
}
// Add all known remote display routes.
final int routeCount = mRouter.getRouteCount();
for (int i = 0; i < routeCount; i++) {
MediaRouter.RouteInfo route = mRouter.getRouteAt(i);
//Log.v(TAG,"MediaRouter " +route.toString());
if (route.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY)) {
//preferenceScreen.addPreference(createRoutePreference(route));
}
}
// Additional features for wifi display routes.
if (mWifiDisplayStatus != null
&& mWifiDisplayStatus.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) {
// Add all unpaired wifi displays.
devices.clear();
for (WifiDisplay display : mWifiDisplayStatus.getDisplays()) {
Log.v(TAG,"WifiDisplay " +display.toString());
if (!display.isRemembered() && display.isAvailable()
&& !display.equals(mWifiDisplayStatus.getActiveDisplay())) {
//preferenceScreen.addPreference(new UnpairedWifiDisplayPreference(
// getPrefContext(), display));
devices.add(display);
}
}
// Add the certification menu if enabled in developer options.
if (mWifiDisplayCertificationOn) {
//buildCertificationMenu(preferenceScreen);
}
}
}
private void pairWifiDisplay(WifiDisplay display) {
if (display.canConnect()) {
Log.v(TAG,"pairWifiDisplay " +display.toString());
mDisplayManager.connectWifiDisplay(display.getDeviceAddress());
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent!=null){
String action=intent.getAction();
if(action!=null){
Log.v(TAG,"action = "+action);
switch (action){
case "WIFI_DISPLAY_ON":
Settings.Global.putInt(getContentResolver(),
Settings.Global.WIFI_DISPLAY_ON, 1);
break;
case "WIFI_DISPLAY_OFF":
Settings.Global.putInt(getContentResolver(),
Settings.Global.WIFI_DISPLAY_ON, 0);
break;
case "PAIR_WIFI_DISPLAY":
connectDevice();
break;
}
}
}
return super.onStartCommand(intent, flags, startId);
}
private void connectDevice(){
for(WifiDisplay display :devices){
pairWifiDisplay(display);
break;
}
}
}
来源:oschina
链接:https://my.oschina.net/wfy94/blog/4348807