Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 635e9152 authored by Jeff Brown's avatar Jeff Brown
Browse files

Integrate remote display providers into Quick Settings.

This is a first pass at integrating new remote display functionality
into Quick Settings.  The Wireless Display card which previously
only supported Wifi Display is reimplemented to use the media router
to enumerate available remote display routes.  This ensures that the
user is presented with a consistent state regarding the currently
selected display route.

In this patch, the Wireless Display card still launches the old
Settings preference page for Wifi Display when clicked.  This will be
addressed in future patches.

As part of this change, it was necessary to derive some new lifecycle
information regarding the visibility of the Quick Settings model.
When Quick Settings is shown, an onPrepare event is delivered to
give the model a chance to update its state.  Likewise when Quick
Settings is hidden, an onUnprepare event is delivered.

These events allow the system to determine precisely when remote
display discovery is required to update the UI so as not to waste
power performing discovery in the background all of the time.

Bug: 11257292
Change-Id: Id802aa0983b625aeb972b5d123e4cc080dd6705f
parent 69b07161
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -490,10 +490,8 @@
    <string name="quick_settings_wifi_no_network">No Network</string>
    <!-- QuickSettings: Wifi (Off) [CHAR LIMIT=NONE] -->
    <string name="quick_settings_wifi_off_label">Wi-Fi Off</string>
    <!-- QuickSettings: Wifi display [CHAR LIMIT=NONE] -->
    <string name="quick_settings_wifi_display_label">Wi-Fi Display</string>
    <!-- QuickSettings: Wifi display [CHAR LIMIT=NONE] -->
    <string name="quick_settings_wifi_display_no_connection_label">Wireless Display</string>
    <!-- QuickSettings: Remote display [CHAR LIMIT=NONE] -->
    <string name="quick_settings_remote_display_no_connection_label">Cast Screen</string>
    <!-- QuickSettings: Brightness dialog title [CHAR LIMIT=NONE] -->
    <string name="quick_settings_brightness_dialog_title">Brightness</string>
    <!-- QuickSettings: Brightness dialog auto brightness button [CHAR LIMIT=NONE] -->
+8 −28
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LevelListDrawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.WifiDisplayStatus;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Handler;
@@ -92,9 +91,7 @@ class QuickSettings {
    private QuickSettingsModel mModel;
    private ViewGroup mContainerView;

    private DisplayManager mDisplayManager;
    private DevicePolicyManager mDevicePolicyManager;
    private WifiDisplayStatus mWifiDisplayStatus;
    private PhoneStatusBar mStatusBarService;
    private BluetoothState mBluetoothState;
    private BluetoothAdapter mBluetoothAdapter;
@@ -118,13 +115,11 @@ class QuickSettings {
            new ArrayList<QuickSettingsTileView>();

    public QuickSettings(Context context, QuickSettingsContainerView container) {
        mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
        mDevicePolicyManager
            = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
        mContext = context;
        mContainerView = container;
        mModel = new QuickSettingsModel(context);
        mWifiDisplayStatus = new WifiDisplayStatus();
        mBluetoothState = new QuickSettingsModel.BluetoothState();
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -171,7 +166,6 @@ class QuickSettings {
        mLocationController = locationController;

        setupQuickSettings();
        updateWifiDisplayStatus();
        updateResources();
        applyLocationEnabledStatus();

@@ -668,20 +662,20 @@ class QuickSettings {
        });
        parent.addView(alarmTile);

        // Wifi Display
        QuickSettingsBasicTile wifiDisplayTile
        // Remote Display
        QuickSettingsBasicTile remoteDisplayTile
                = new QuickSettingsBasicTile(mContext);
        wifiDisplayTile.setImageResource(R.drawable.ic_qs_remote_display);
        wifiDisplayTile.setOnClickListener(new View.OnClickListener() {
        remoteDisplayTile.setImageResource(R.drawable.ic_qs_remote_display);
        remoteDisplayTile.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startSettingsActivity(android.provider.Settings.ACTION_WIFI_DISPLAY_SETTINGS);
            }
        });
        mModel.addWifiDisplayTile(wifiDisplayTile,
                new QuickSettingsModel.BasicRefreshCallback(wifiDisplayTile)
        mModel.addRemoteDisplayTile(remoteDisplayTile,
                new QuickSettingsModel.BasicRefreshCallback(remoteDisplayTile)
                        .setShowWhenEnabled(true));
        parent.addView(wifiDisplayTile);
        parent.addView(remoteDisplayTile);

        if (SHOW_IME_TILE || DEBUG_GONE_TILES) {
            // IME
@@ -816,15 +810,6 @@ class QuickSettings {
        dialog.show();
    }

    private void updateWifiDisplayStatus() {
        mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
        applyWifiDisplayStatus();
    }

    private void applyWifiDisplayStatus() {
        mModel.onWifiDisplayStateChanged(mWifiDisplayStatus);
    }

    private void applyBluetoothStatus() {
        mModel.onBluetoothStateChange(mBluetoothState);
    }
@@ -848,12 +833,7 @@ class QuickSettings {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED.equals(action)) {
                WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra(
                        DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
                mWifiDisplayStatus = status;
                applyWifiDisplayStatus();
            } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
            if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
                        BluetoothAdapter.ERROR);
                mBluetoothState.enabled = (state == BluetoothAdapter.STATE_ON);
+89 −20
Original line number Diff line number Diff line
@@ -27,7 +27,8 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
import android.hardware.display.WifiDisplayStatus;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteInfo;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.UserHandle;
@@ -57,7 +58,6 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
        BrightnessStateChangeCallback,
        RotationLockControllerCallback,
        LocationSettingsChangeCallback {

    // Sett InputMethoManagerService
    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";

@@ -199,6 +199,30 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
        }
    }

    /** Callback for changes to remote display routes. */
    private class RemoteDisplayRouteCallback extends MediaRouter.SimpleCallback {
        @Override
        public void onRouteAdded(MediaRouter router, RouteInfo route) {
            updateRemoteDisplays();
        }
        @Override
        public void onRouteChanged(MediaRouter router, RouteInfo route) {
            updateRemoteDisplays();
        }
        @Override
        public void onRouteRemoved(MediaRouter router, RouteInfo route) {
            updateRemoteDisplays();
        }
        @Override
        public void onRouteSelected(MediaRouter router, int type, RouteInfo route) {
            updateRemoteDisplays();
        }
        @Override
        public void onRouteUnselected(MediaRouter router, int type, RouteInfo route) {
            updateRemoteDisplays();
        }
    }

    private final Context mContext;
    private final Handler mHandler;
    private final CurrentUserTracker mUserTracker;
@@ -206,6 +230,9 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
    private final BugreportObserver mBugreportObserver;
    private final BrightnessObserver mBrightnessObserver;

    private final MediaRouter mMediaRouter;
    private final RemoteDisplayRouteCallback mRemoteDisplayRouteCallback;

    private final boolean mHasMobileData;

    private QuickSettingsTileView mUserTile;
@@ -228,9 +255,9 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
    private RefreshCallback mWifiCallback;
    private WifiState mWifiState = new WifiState();

    private QuickSettingsTileView mWifiDisplayTile;
    private RefreshCallback mWifiDisplayCallback;
    private State mWifiDisplayState = new State();
    private QuickSettingsTileView mRemoteDisplayTile;
    private RefreshCallback mRemoteDisplayCallback;
    private State mRemoteDisplayState = new State();

    private QuickSettingsTileView mRSSITile;
    private RefreshCallback mRSSICallback;
@@ -278,12 +305,14 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
        mContext = context;
        mHandler = new Handler();
        mUserTracker = new CurrentUserTracker(mContext) {
            @Override
            public void onUserSwitched(int newUserId) {
                mBrightnessObserver.startObserving();
                refreshRotationLockTile();
                onBrightnessLevelChanged();
                onNextAlarmChanged();
                onBugreportChanged();
                rebindMediaRouterAsCurrentUser();
            }
        };

@@ -294,6 +323,11 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
        mBrightnessObserver = new BrightnessObserver(mHandler);
        mBrightnessObserver.startObserving();

        mMediaRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
        rebindMediaRouterAsCurrentUser();

        mRemoteDisplayRouteCallback = new RemoteDisplayRouteCallback();

        ConnectivityManager cm = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        mHasMobileData = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
@@ -621,24 +655,59 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
        mBugreportCallback.refreshView(mBugreportTile, mBugreportState);
    }

    // Wifi Display
    void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) {
        mWifiDisplayTile = view;
        mWifiDisplayCallback = cb;
    // Remote Display
    void addRemoteDisplayTile(QuickSettingsTileView view, RefreshCallback cb) {
        mRemoteDisplayTile = view;
        mRemoteDisplayCallback = cb;
        final int[] count = new int[1];
        mRemoteDisplayTile.setOnPrepareListener(new QuickSettingsTileView.OnPrepareListener() {
            @Override
            public void onPrepare() {
                mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
                        mRemoteDisplayRouteCallback,
                        MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
                updateRemoteDisplays();
            }
    public void onWifiDisplayStateChanged(WifiDisplayStatus status) {
        mWifiDisplayState.enabled =
                (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON);
        if (status.getActiveDisplay() != null) {
            mWifiDisplayState.label = status.getActiveDisplay().getFriendlyDisplayName();
            mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display_connected;
        } else {
            mWifiDisplayState.label = mContext.getString(
                    R.string.quick_settings_wifi_display_no_connection_label);
            mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display;
            @Override
            public void onUnprepare() {
                mMediaRouter.removeCallback(mRemoteDisplayRouteCallback);
            }
        });

        updateRemoteDisplays();
    }
        mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState);

    private void rebindMediaRouterAsCurrentUser() {
        mMediaRouter.rebindAsUser(mUserTracker.getCurrentUserId());
    }

    private void updateRemoteDisplays() {
        MediaRouter.RouteInfo connectedRoute = mMediaRouter.getSelectedRoute(
                MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
        boolean enabled = connectedRoute != null && (connectedRoute.getSupportedTypes()
                & MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY) != 0;
        if (!enabled) {
            connectedRoute = null;
            final int count = mMediaRouter.getRouteCount();
            for (int i = 0; i < count; i++) {
                MediaRouter.RouteInfo route = mMediaRouter.getRouteAt(i);
                if ((route.getSupportedTypes() & MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY) != 0) {
                    enabled = true;
                    break;
                }
            }
        }

        mRemoteDisplayState.enabled = enabled;
        if (connectedRoute != null) {
            mRemoteDisplayState.label = connectedRoute.getName().toString();
            mRemoteDisplayState.iconId = R.drawable.ic_qs_remote_display_connected;
        } else {
            mRemoteDisplayState.label = mContext.getString(
                    R.string.quick_settings_remote_display_no_connection_label);
            mRemoteDisplayState.iconId = R.drawable.ic_qs_remote_display;
        }
        mRemoteDisplayCallback.refreshView(mRemoteDisplayTile, mRemoteDisplayState);
    }

    // IME
+71 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewParent;
import android.widget.FrameLayout;

/**
@@ -31,14 +32,14 @@ class QuickSettingsTileView extends FrameLayout {

    private int mContentLayoutId;
    private int mColSpan;
    private int mRowSpan;
    private boolean mPrepared;
    private OnPrepareListener mOnPrepareListener;

    public QuickSettingsTileView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mContentLayoutId = -1;
        mColSpan = 1;
        mRowSpan = 1;
    }

    void setColumnSpan(int span) {
@@ -77,4 +78,72 @@ class QuickSettingsTileView extends FrameLayout {
        }
        super.setVisibility(vis);
    }

    public void setOnPrepareListener(OnPrepareListener listener) {
        if (mOnPrepareListener != listener) {
            mOnPrepareListener = listener;
            mPrepared = false;
            post(new Runnable() {
                @Override
                public void run() {
                    updatePreparedState();
                }
            });
        }
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        updatePreparedState();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        updatePreparedState();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        updatePreparedState();
    }

    private void updatePreparedState() {
        if (mOnPrepareListener != null) {
            if (isParentVisible()) {
                if (!mPrepared) {
                    mPrepared = true;
                    mOnPrepareListener.onPrepare();
                }
            } else if (mPrepared) {
                mPrepared = false;
                mOnPrepareListener.onUnprepare();
            }
        }
    }

    private boolean isParentVisible() {
        if (!isAttachedToWindow()) {
            return false;
        }
        for (ViewParent current = getParent(); current instanceof View;
                current = current.getParent()) {
            View view = (View)current;
            if (view.getVisibility() != VISIBLE) {
                return false;
            }
        }
        return true;
    }

    /**
     * Called when the view's parent becomes visible or invisible to provide
     * an opportunity for the client to provide new content.
     */
    public interface OnPrepareListener {
        void onPrepare();
        void onUnprepare();
    }
}
 No newline at end of file