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:
@@ -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="
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user