am 0ae6ee5c: am f6a07ca1: am a60bba8d: Merge "QS: Wire up screen casting to tile/panel." into lmp-dev

* commit '0ae6ee5cd214b8211a8c6a2cc06fa41c0487d62e':
  QS: Wire up screen casting to tile/panel.
This commit is contained in:
John Spurlock
2014-08-26 10:09:07 +00:00
committed by Android Git Automerger
5 changed files with 113 additions and 7 deletions

View File

@@ -20,6 +20,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import java.util.Objects;
/** @hide */
public final class MediaProjectionInfo implements Parcelable {
private final String mPackageName;
@@ -43,6 +45,21 @@ public final class MediaProjectionInfo implements Parcelable {
return mUserHandle;
}
@Override
public boolean equals(Object o) {
if (o instanceof MediaProjectionInfo) {
final MediaProjectionInfo other = (MediaProjectionInfo) o;
return Objects.equals(other.mPackageName, mPackageName)
&& Objects.equals(other.mUserHandle, mUserHandle);
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(mPackageName, mUserHandle);
}
@Override
public String toString() {
return "MediaProjectionInfo{mPackageName="

View File

@@ -239,7 +239,8 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
@Override
public void onDetailItemDisconnect(Item item) {
if (item == null || item.tag == null) return;
mController.stopCasting();
final CastDevice device = (CastDevice) item.tag;
mController.stopCasting(device);
}
}
}

View File

@@ -25,7 +25,7 @@ public interface CastController {
void setCurrentUserId(int currentUserId);
Set<CastDevice> getCastDevices();
void startCasting(CastDevice device);
void stopCasting();
void stopCasting(CastDevice device);
public interface Callback {
void onCastDevicesChanged();

View File

@@ -19,15 +19,25 @@ package com.android.systemui.statusbar.policy;
import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteInfo;
import android.media.projection.MediaProjectionInfo;
import android.media.projection.MediaProjectionManager;
import android.os.Handler;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import com.android.systemui.R;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
@@ -41,12 +51,19 @@ public class CastControllerImpl implements CastController {
private final MediaRouter mMediaRouter;
private final ArrayMap<String, RouteInfo> mRoutes = new ArrayMap<>();
private final Object mDiscoveringLock = new Object();
private final MediaProjectionManager mProjectionManager;
private final Object mProjectionLock = new Object();
private boolean mDiscovering;
private MediaProjectionInfo mProjection;
public CastControllerImpl(Context context) {
mContext = context;
mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
mProjectionManager = (MediaProjectionManager)
context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
mProjection = mProjectionManager.getActiveProjectionInfo();
mProjectionManager.addCallback(mProjectionCallback, new Handler());
if (DEBUG) Log.d(TAG, "new CastController()");
}
@@ -59,6 +76,7 @@ public class CastControllerImpl implements CastController {
final RouteInfo route = mRoutes.valueAt(i);
pw.print(" "); pw.println(routeToString(route));
}
pw.print(" mProjection="); pw.println(mProjection);
}
@Override
@@ -95,6 +113,18 @@ public class CastControllerImpl implements CastController {
@Override
public Set<CastDevice> getCastDevices() {
final ArraySet<CastDevice> devices = new ArraySet<CastDevice>();
synchronized (mProjectionLock) {
if (mProjection != null) {
final CastDevice device = new CastDevice();
device.id = mProjection.getPackageName();
device.name = getAppName(mProjection.getPackageName());
device.description = mContext.getString(R.string.quick_settings_casting);
device.state = CastDevice.STATE_CONNECTED;
device.tag = mProjection;
devices.add(device);
return devices;
}
}
synchronized(mRoutes) {
for (RouteInfo route : mRoutes.values()) {
final CastDevice device = new CastDevice();
@@ -122,9 +152,55 @@ public class CastControllerImpl implements CastController {
}
@Override
public void stopCasting() {
if (DEBUG) Log.d(TAG, "stopCasting");
mMediaRouter.getDefaultRoute().select();
public void stopCasting(CastDevice device) {
final boolean isProjection = device.tag instanceof MediaProjectionInfo;
if (DEBUG) Log.d(TAG, "stopCasting isProjection=" + isProjection);
if (isProjection) {
final MediaProjectionInfo projection = (MediaProjectionInfo) device.tag;
if (Objects.equals(mProjectionManager.getActiveProjectionInfo(), projection)) {
mProjectionManager.stopActiveProjection();
} else {
Log.w(TAG, "Projection is no longer active: " + projection);
}
} else {
mMediaRouter.getDefaultRoute().select();
}
}
private void setProjection(MediaProjectionInfo projection, boolean started) {
boolean changed = false;
final MediaProjectionInfo oldProjection = mProjection;
synchronized (mProjectionLock) {
final boolean isCurrent = Objects.equals(projection, mProjection);
if (started && !isCurrent) {
mProjection = projection;
changed = true;
} else if (!started && isCurrent) {
mProjection = null;
changed = true;
}
}
if (changed) {
if (DEBUG) Log.d(TAG, "setProjection: " + oldProjection + " -> " + mProjection);
fireOnCastDevicesChanged();
}
}
private String getAppName(String packageName) {
final PackageManager pm = mContext.getPackageManager();
try {
final ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
if (appInfo != null) {
final CharSequence label = appInfo.loadLabel(pm);
if (!TextUtils.isEmpty(label)) {
return label.toString();
}
}
Log.w(TAG, "No label found for package: " + packageName);
} catch (NameNotFoundException e) {
Log.w(TAG, "Error getting appName for package: " + packageName, e);
}
return packageName;
}
private void updateRemoteDisplays() {
@@ -202,4 +278,17 @@ public class CastControllerImpl implements CastController {
updateRemoteDisplays();
}
};
private final MediaProjectionManager.Callback mProjectionCallback
= new MediaProjectionManager.Callback() {
@Override
public void onStart(MediaProjectionInfo info) {
setProjection(info, true);
}
@Override
public void onStop(MediaProjectionInfo info) {
setProjection(info, false);
}
};
}

View File

@@ -111,7 +111,6 @@ public final class MediaProjectionManagerService extends SystemService
@Override
public void binderDied() {
synchronized (mLock) {
unlinkDeathRecipientLocked(callback);
removeCallback(callback);
}
}
@@ -125,7 +124,7 @@ public final class MediaProjectionManagerService extends SystemService
private void removeCallback(IMediaProjectionWatcherCallback callback) {
synchronized (mLock) {
unlinkDeathRecipientLocked(callback);
removeCallback(callback);
mCallbackDelegate.remove(callback);
}
}