FileDocCategorySizeDatePackage
WifiDisplayAdapter.javaAPI DocAndroid 5.1 API24468Thu Mar 12 22:22:42 GMT 2015com.android.server.display

WifiDisplayAdapter

public final class WifiDisplayAdapter extends DisplayAdapter
Connects to Wifi displays that implement the Miracast protocol.

The Wifi display protocol relies on Wifi direct for discovering and pairing with the display. Once connected, the Media Server opens an RTSP socket and accepts a connection from the display. After session negotiation, the Media Server streams encoded buffers to the display.

This class is responsible for connecting to Wifi displays and mediating the interactions between Media Server, Surface Flinger and the Display Manager Service.

Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.

Fields Summary
private static final String
TAG
private static final boolean
DEBUG
private static final int
MSG_SEND_STATUS_CHANGE_BROADCAST
private static final String
ACTION_DISCONNECT
private static final String
DISPLAY_NAME_PREFIX
private final WifiDisplayHandler
mHandler
private final PersistentDataStore
mPersistentDataStore
private final boolean
mSupportsProtectedBuffers
private WifiDisplayController
mDisplayController
private WifiDisplayDevice
mDisplayDevice
private android.hardware.display.WifiDisplayStatus
mCurrentStatus
private int
mFeatureState
private int
mScanState
private int
mActiveDisplayState
private android.hardware.display.WifiDisplay
mActiveDisplay
private android.hardware.display.WifiDisplay[]
mDisplays
private android.hardware.display.WifiDisplay[]
mAvailableDisplays
private android.hardware.display.WifiDisplay[]
mRememberedDisplays
private android.hardware.display.WifiDisplaySessionInfo
mSessionInfo
private boolean
mPendingStatusChangeBroadcast
private final android.content.BroadcastReceiver
mBroadcastReceiver
private final WifiDisplayController.Listener
mWifiDisplayListener
Constructors Summary
public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, android.content.Context context, android.os.Handler handler, Listener listener, PersistentDataStore persistentDataStore)


    // Called with SyncRoot lock held.
      
                 
              
        super(syncRoot, context, handler, listener, TAG);
        mHandler = new WifiDisplayHandler(handler.getLooper());
        mPersistentDataStore = persistentDataStore;
        mSupportsProtectedBuffers = context.getResources().getBoolean(
                com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);
    
Methods Summary
private voidaddDisplayDeviceLocked(android.hardware.display.WifiDisplay display, android.view.Surface surface, int width, int height, int flags)

        removeDisplayDeviceLocked();

        if (mPersistentDataStore.rememberWifiDisplay(display)) {
            mPersistentDataStore.saveIfNeeded();
            updateRememberedDisplaysLocked();
            scheduleStatusChangedBroadcastLocked();
        }

        boolean secure = (flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0;
        int deviceFlags = DisplayDeviceInfo.FLAG_PRESENTATION;
        if (secure) {
            deviceFlags |= DisplayDeviceInfo.FLAG_SECURE;
            if (mSupportsProtectedBuffers) {
                deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
            }
        }

        float refreshRate = 60.0f; // TODO: get this for real

        String name = display.getFriendlyDisplayName();
        String address = display.getDeviceAddress();
        IBinder displayToken = SurfaceControl.createDisplay(name, secure);
        mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
                refreshRate, deviceFlags, address, surface);
        sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
    
public voiddumpLocked(java.io.PrintWriter pw)

        super.dumpLocked(pw);

        pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked());
        pw.println("mFeatureState=" + mFeatureState);
        pw.println("mScanState=" + mScanState);
        pw.println("mActiveDisplayState=" + mActiveDisplayState);
        pw.println("mActiveDisplay=" + mActiveDisplay);
        pw.println("mDisplays=" + Arrays.toString(mDisplays));
        pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
        pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
        pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
        pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers);

        // Try to dump the controller state.
        if (mDisplayController == null) {
            pw.println("mDisplayController=null");
        } else {
            pw.println("mDisplayController:");
            final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
            ipw.increaseIndent();
            DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200);
        }
    
private android.hardware.display.WifiDisplayfindAvailableDisplayLocked(java.lang.String address)

        for (WifiDisplay display : mAvailableDisplays) {
            if (display.getDeviceAddress().equals(address)) {
                return display;
            }
        }
        return null;
    
private voidfixRememberedDisplayNamesFromAvailableDisplaysLocked()

        // It may happen that a display name has changed since it was remembered.
        // Consult the list of available displays and update the name if needed.
        // We don't do anything special for the active display here.  The display
        // controller will send a separate event when it needs to be updates.
        boolean changed = false;
        for (int i = 0; i < mRememberedDisplays.length; i++) {
            WifiDisplay rememberedDisplay = mRememberedDisplays[i];
            WifiDisplay availableDisplay = findAvailableDisplayLocked(
                    rememberedDisplay.getDeviceAddress());
            if (availableDisplay != null && !rememberedDisplay.equals(availableDisplay)) {
                if (DEBUG) {
                    Slog.d(TAG, "fixRememberedDisplayNamesFromAvailableDisplaysLocked: "
                            + "updating remembered display to " + availableDisplay);
                }
                mRememberedDisplays[i] = availableDisplay;
                changed |= mPersistentDataStore.rememberWifiDisplay(availableDisplay);
            }
        }
        if (changed) {
            mPersistentDataStore.saveIfNeeded();
        }
    
public android.hardware.display.WifiDisplayStatusgetWifiDisplayStatusLocked()

        if (mCurrentStatus == null) {
            mCurrentStatus = new WifiDisplayStatus(
                    mFeatureState, mScanState, mActiveDisplayState,
                    mActiveDisplay, mDisplays, mSessionInfo);
        }

        if (DEBUG) {
            Slog.d(TAG, "getWifiDisplayStatusLocked: result=" + mCurrentStatus);
        }
        return mCurrentStatus;
    
private voidhandleSendStatusChangeBroadcast()

        final Intent intent;
        synchronized (getSyncRoot()) {
            if (!mPendingStatusChangeBroadcast) {
                return;
            }

            mPendingStatusChangeBroadcast = false;
            intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
            intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS,
                    getWifiDisplayStatusLocked());
        }

        // Send protected broadcast about wifi display status to registered receivers.
        getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
    
public voidregisterLocked()

        super.registerLocked();

        updateRememberedDisplaysLocked();

        getHandler().post(new Runnable() {
            @Override
            public void run() {
                mDisplayController = new WifiDisplayController(
                        getContext(), getHandler(), mWifiDisplayListener);

                getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
                        new IntentFilter(ACTION_DISCONNECT), null, mHandler);
            }
        });
    
private voidremoveDisplayDeviceLocked()

        if (mDisplayDevice != null) {
            mDisplayDevice.destroyLocked();
            sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
            mDisplayDevice = null;
        }
    
private voidrenameDisplayDeviceLocked(java.lang.String name)

        if (mDisplayDevice != null && !mDisplayDevice.getNameLocked().equals(name)) {
            mDisplayDevice.setNameLocked(name);
            sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
        }
    
public voidrequestConnectLocked(java.lang.String address)

        if (DEBUG) {
            Slog.d(TAG, "requestConnectLocked: address=" + address);
        }

        getHandler().post(new Runnable() {
            @Override
            public void run() {
                if (mDisplayController != null) {
                    mDisplayController.requestConnect(address);
                }
            }
        });
    
public voidrequestDisconnectLocked()

        if (DEBUG) {
            Slog.d(TAG, "requestDisconnectedLocked");
        }

        getHandler().post(new Runnable() {
            @Override
            public void run() {
                if (mDisplayController != null) {
                    mDisplayController.requestDisconnect();
                }
            }
        });
    
public voidrequestForgetLocked(java.lang.String address)

        if (DEBUG) {
            Slog.d(TAG, "requestForgetLocked: address=" + address);
        }

        if (mPersistentDataStore.forgetWifiDisplay(address)) {
            mPersistentDataStore.saveIfNeeded();
            updateRememberedDisplaysLocked();
            scheduleStatusChangedBroadcastLocked();
        }

        if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) {
            requestDisconnectLocked();
        }
    
public voidrequestPauseLocked()

        if (DEBUG) {
            Slog.d(TAG, "requestPauseLocked");
        }

        getHandler().post(new Runnable() {
            @Override
            public void run() {
                if (mDisplayController != null) {
                    mDisplayController.requestPause();
                }
            }
        });
      
public voidrequestRenameLocked(java.lang.String address, java.lang.String alias)

        if (DEBUG) {
            Slog.d(TAG, "requestRenameLocked: address=" + address + ", alias=" + alias);
        }

        if (alias != null) {
            alias = alias.trim();
            if (alias.isEmpty() || alias.equals(address)) {
                alias = null;
            }
        }

        WifiDisplay display = mPersistentDataStore.getRememberedWifiDisplay(address);
        if (display != null && !Objects.equal(display.getDeviceAlias(), alias)) {
            display = new WifiDisplay(address, display.getDeviceName(), alias,
                    false, false, false);
            if (mPersistentDataStore.rememberWifiDisplay(display)) {
                mPersistentDataStore.saveIfNeeded();
                updateRememberedDisplaysLocked();
                scheduleStatusChangedBroadcastLocked();
            }
        }

        if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) {
            renameDisplayDeviceLocked(mActiveDisplay.getFriendlyDisplayName());
        }
    
public voidrequestResumeLocked()

        if (DEBUG) {
            Slog.d(TAG, "requestResumeLocked");
        }

        getHandler().post(new Runnable() {
            @Override
            public void run() {
                if (mDisplayController != null) {
                    mDisplayController.requestResume();
                }
            }
        });
    
public voidrequestStartScanLocked()

        if (DEBUG) {
            Slog.d(TAG, "requestStartScanLocked");
        }

        getHandler().post(new Runnable() {
            @Override
            public void run() {
                if (mDisplayController != null) {
                    mDisplayController.requestStartScan();
                }
            }
        });
    
public voidrequestStopScanLocked()

        if (DEBUG) {
            Slog.d(TAG, "requestStopScanLocked");
        }

        getHandler().post(new Runnable() {
            @Override
            public void run() {
                if (mDisplayController != null) {
                    mDisplayController.requestStopScan();
                }
            }
        });
    
private voidscheduleStatusChangedBroadcastLocked()

        mCurrentStatus = null;
        if (!mPendingStatusChangeBroadcast) {
            mPendingStatusChangeBroadcast = true;
            mHandler.sendEmptyMessage(MSG_SEND_STATUS_CHANGE_BROADCAST);
        }
    
private voidupdateDisplaysLocked()

        List<WifiDisplay> displays = new ArrayList<WifiDisplay>(
                mAvailableDisplays.length + mRememberedDisplays.length);
        boolean[] remembered = new boolean[mAvailableDisplays.length];
        for (WifiDisplay d : mRememberedDisplays) {
            boolean available = false;
            for (int i = 0; i < mAvailableDisplays.length; i++) {
                if (d.equals(mAvailableDisplays[i])) {
                    remembered[i] = available = true;
                    break;
                }
            }
            if (!available) {
                displays.add(new WifiDisplay(d.getDeviceAddress(), d.getDeviceName(),
                        d.getDeviceAlias(), false, false, true));
            }
        }
        for (int i = 0; i < mAvailableDisplays.length; i++) {
            WifiDisplay d = mAvailableDisplays[i];
            displays.add(new WifiDisplay(d.getDeviceAddress(), d.getDeviceName(),
                    d.getDeviceAlias(), true, d.canConnect(), remembered[i]));
        }
        mDisplays = displays.toArray(WifiDisplay.EMPTY_ARRAY);
    
private voidupdateRememberedDisplaysLocked()

        mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays();
        mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay);
        mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays);
        updateDisplaysLocked();