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

Commit 58ea0c96 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Handle destroyed sessions and fix color issues"

parents b69d57c6 fd51bb2d
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2019 The Android Open Source Project
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License
  -->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/qs_media_controls_options"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:gravity="center"
    android:layout_gravity="center"
    android:padding="10dp"
    >
    <ImageButton
        android:id="@+id/remove"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@android:drawable/ic_menu_delete"
        android:padding="8dp"
    />
    <ImageButton
        android:id="@+id/cancel"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@android:drawable/ic_menu_revert"
        android:padding="8dp"
    />
</LinearLayout>
+1 −0
Original line number Diff line number Diff line
@@ -1179,4 +1179,5 @@
    <dimen name="qs_media_height">150dp</dimen>
    <dimen name="qs_media_width">350dp</dimen>
    <dimen name="qs_media_padding">8dp</dimen>
    <dimen name="qs_media_corner_radius">10dp</dimen>
</resources>
+112 −8
Original line number Diff line number Diff line
@@ -18,8 +18,11 @@ package com.android.systemui.qs;

import android.app.Notification;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -35,6 +38,7 @@ import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -54,6 +58,8 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;

import java.util.List;

/**
 * Single media player for carousel in QSPanel
 */
@@ -70,6 +76,83 @@ public class QSMediaPlayer {
    private int mHeight;
    private int mForegroundColor;
    private int mBackgroundColor;
    private ComponentName mRecvComponent;
    private QSPanel mParent;

    private MediaController.Callback mSessionCallback = new MediaController.Callback() {
        @Override
        public void onSessionDestroyed() {
            Log.d(TAG, "session destroyed");
            mController.unregisterCallback(mSessionCallback);

            // Hide all the old buttons
            final int[] actionIds = {
                    R.id.action0,
                    R.id.action1,
                    R.id.action2,
                    R.id.action3,
                    R.id.action4
            };
            for (int i = 0; i < actionIds.length; i++) {
                ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]);
                if (thisBtn != null) {
                    thisBtn.setVisibility(View.GONE);
                }
            }

            // Add a restart button
            ImageButton btn = mMediaNotifView.findViewById(actionIds[0]);
            btn.setOnClickListener(v -> {
                Log.d(TAG, "Attempting to restart session");
                // Send a media button event to previously found receiver
                if (mRecvComponent != null) {
                    Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
                    intent.setComponent(mRecvComponent);
                    int keyCode = KeyEvent.KEYCODE_MEDIA_PLAY;
                    intent.putExtra(
                            Intent.EXTRA_KEY_EVENT,
                            new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
                    mContext.sendBroadcast(intent);
                } else {
                    Log.d(TAG, "No receiver to restart");
                    // If we don't have a receiver, try relaunching the activity instead
                    try {
                        mController.getSessionActivity().send();
                    } catch (PendingIntent.CanceledException e) {
                        Log.e(TAG, "Pending intent was canceled");
                        e.printStackTrace();
                    }
                }
            });
            btn.setImageDrawable(mContext.getResources().getDrawable(R.drawable.lb_ic_replay));
            btn.setImageTintList(ColorStateList.valueOf(mForegroundColor));
            btn.setVisibility(View.VISIBLE);

            // Add long-click option to remove the player
            ViewGroup mMediaCarousel = (ViewGroup) mMediaNotifView.getParent();
            mMediaNotifView.setOnLongClickListener(v -> {
                // Replace player view with delete/cancel view
                v.setVisibility(View.GONE);

                View options = LayoutInflater.from(mContext).inflate(
                        R.layout.qs_media_panel_options, null, false);
                ImageButton btnDelete = options.findViewById(R.id.remove);
                btnDelete.setOnClickListener(b -> {
                    mMediaCarousel.removeView(options);
                    mParent.removeMediaPlayer(QSMediaPlayer.this);
                });
                ImageButton btnCancel = options.findViewById(R.id.cancel);
                btnCancel.setOnClickListener(b -> {
                    mMediaCarousel.removeView(options);
                    v.setVisibility(View.VISIBLE);
                });

                int pos = mMediaCarousel.indexOfChild(v);
                mMediaCarousel.addView(options, pos, v.getLayoutParams());
                return true; // consumed click
            });
        }
    };

    /**
     *
@@ -92,7 +175,8 @@ public class QSMediaPlayer {
    }

    /**
     *
     * Create or update the player view for the given media session
     * @param parent the parent QSPanel
     * @param token token for this media session
     * @param icon app notification icon
     * @param iconColor foreground color (for text, icons)
@@ -101,13 +185,30 @@ public class QSMediaPlayer {
     * @param notif reference to original notification
     * @param device current playback device
     */
    public void setMediaSession(MediaSession.Token token, Icon icon, int iconColor, int bgColor,
            View actionsContainer, Notification notif, MediaDevice device) {
        Log.d(TAG, "got media session: " + token);
    public void setMediaSession(QSPanel parent, MediaSession.Token token, Icon icon, int iconColor,
            int bgColor, View actionsContainer, Notification notif, MediaDevice device) {
        mParent = parent;
        mToken = token;
        mForegroundColor = iconColor;
        mBackgroundColor = bgColor;
        mController = new MediaController(mContext, token);

        // Try to find a receiver for the media button that matches this app
        PackageManager pm = mContext.getPackageManager();
        Intent it = new Intent(Intent.ACTION_MEDIA_BUTTON);
        List<ResolveInfo> info = pm.queryBroadcastReceiversAsUser(it, 0, mContext.getUser());
        if (info != null) {
            for (ResolveInfo inf : info) {
                if (inf.activityInfo.packageName.equals(notif.contentIntent.getCreatorPackage())) {
                    Log.d(TAG, "Found receiver for package: " + inf);
                    mRecvComponent = inf.getComponentInfo().getComponentName();
                }
            }
        }

        // reset in case we had previously restarted the stream
        mMediaNotifView.setOnLongClickListener(null);
        mController.registerCallback(mSessionCallback);
        MediaMetadata mMediaMetadata = mController.getMetadata();
        if (mMediaMetadata == null) {
            Log.e(TAG, "Media metadata was null");
@@ -235,7 +336,6 @@ public class QSMediaPlayer {
        for (; i < actionIds.length; i++) {
            ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]);
            thisBtn.setVisibility(View.GONE);
            Log.d(TAG, "hid a button");
        }
    }

@@ -266,8 +366,9 @@ public class QSMediaPlayer {

    private void addAlbumArtBackground(MediaMetadata metadata, int bgColor, int width, int height) {
        Bitmap albumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
        float radius = mContext.getResources().getDimension(R.dimen.qs_media_corner_radius);
        if (albumArt != null) {

            Log.d(TAG, "updating album art");
            Bitmap original = albumArt.copy(Bitmap.Config.ARGB_8888, true);
            Bitmap scaled = scaleBitmap(original, width, height);
            Canvas canvas = new Canvas(scaled);
@@ -281,12 +382,15 @@ public class QSMediaPlayer {

            RoundedBitmapDrawable roundedDrawable = RoundedBitmapDrawableFactory.create(
                    mContext.getResources(), scaled);
            roundedDrawable.setCornerRadius(20);
            roundedDrawable.setCornerRadius(radius);

            mMediaNotifView.setBackground(roundedDrawable);
        } else {
            Log.e(TAG, "No album art available");
            mMediaNotifView.setBackground(null);
            GradientDrawable rect = new GradientDrawable();
            rect.setCornerRadius(radius);
            rect.setColor(bgColor);
            mMediaNotifView.setBackground(rect);
        }
    }

+22 −1
Original line number Diff line number Diff line
@@ -284,7 +284,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
        }

        Log.d(TAG, "setting player session");
        player.setMediaSession(token, icon, iconColor, bgColor, actionsContainer,
        player.setMediaSession(this, token, icon, iconColor, bgColor, actionsContainer,
                notif.getNotification(), mDevice);

        if (mMediaPlayers.size() > 0) {
@@ -303,6 +303,27 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
        return mMediaCarousel;
    }

    /**
     * Remove the media player from the carousel
     * @param player Player to remove
     * @return true if removed, false if player was not found
     */
    protected boolean removeMediaPlayer(QSMediaPlayer player) {
        // Remove from list
        if (!mMediaPlayers.remove(player)) {
            return false;
        }

        // Check if we need to collapse the carousel now
        mMediaCarousel.removeView(player.getView());
        if (mMediaPlayers.size() == 0) {
            ((View) mMediaCarousel.getParent()).setVisibility(View.GONE);
            mLocalMediaManager.stopScan();
            mLocalMediaManager.unregisterCallback(mDeviceCallback);
        }
        return true;
    }

    protected void addDivider() {
        mDivider = LayoutInflater.from(mContext).inflate(R.layout.qs_divider, this, false);
        mDivider.setBackgroundColor(Utils.applyAlpha(mDivider.getAlpha(),
+84 −6
Original line number Diff line number Diff line
@@ -16,19 +16,27 @@

package com.android.systemui.qs;

import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.Icon;
import android.media.MediaMetadata;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -42,6 +50,8 @@ import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;

import com.android.systemui.R;

import java.util.List;

/**
 * QQS mini media player
 */
@@ -53,6 +63,54 @@ public class QuickQSMediaPlayer {
    private LinearLayout mMediaNotifView;
    private MediaSession.Token mToken;
    private MediaController mController;
    private int mBackgroundColor;
    private int mForegroundColor;
    private ComponentName mRecvComponent;

    private MediaController.Callback mSessionCallback = new MediaController.Callback() {
        @Override
        public void onSessionDestroyed() {
            Log.d(TAG, "session destroyed");
            mController.unregisterCallback(mSessionCallback);

            // Hide all the old buttons
            final int[] actionIds = {R.id.action0, R.id.action1, R.id.action2};
            for (int i = 0; i < actionIds.length; i++) {
                ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]);
                if (thisBtn != null) {
                    thisBtn.setVisibility(View.GONE);
                }
            }

            // Add a restart button
            ImageButton btn = mMediaNotifView.findViewById(actionIds[0]);
            btn.setOnClickListener(v -> {
                Log.d(TAG, "Attempting to restart session");
                // Send a media button event to previously found receiver
                if (mRecvComponent != null) {
                    Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
                    intent.setComponent(mRecvComponent);
                    int keyCode = KeyEvent.KEYCODE_MEDIA_PLAY;
                    intent.putExtra(
                            Intent.EXTRA_KEY_EVENT,
                            new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
                    mContext.sendBroadcast(intent);
                } else {
                    Log.d(TAG, "No receiver to restart");
                    // If we don't have a receiver, try relaunching the activity instead
                    try {
                        mController.getSessionActivity().send();
                    } catch (PendingIntent.CanceledException e) {
                        Log.e(TAG, "Pending intent was canceled");
                        e.printStackTrace();
                    }
                }
            });
            btn.setImageDrawable(mContext.getResources().getDrawable(R.drawable.lb_ic_replay));
            btn.setImageTintList(ColorStateList.valueOf(mForegroundColor));
            btn.setVisibility(View.VISIBLE);
        }
    };

    /**
     *
@@ -83,34 +141,50 @@ public class QuickQSMediaPlayer {
            View actionsContainer, int[] actionsToShow) {
        Log.d(TAG, "Setting media session: " + token);
        mToken = token;
        mForegroundColor = iconColor;
        mBackgroundColor = bgColor;
        mController = new MediaController(mContext, token);
        MediaMetadata mMediaMetadata = mController.getMetadata();

        // Try to find a receiver for the media button that matches this app
        PackageManager pm = mContext.getPackageManager();
        Intent it = new Intent(Intent.ACTION_MEDIA_BUTTON);
        List<ResolveInfo> info = pm.queryBroadcastReceiversAsUser(it, 0, mContext.getUser());
        if (info != null) {
            for (ResolveInfo inf : info) {
                if (inf.activityInfo.packageName.equals(mController.getPackageName())) {
                    Log.d(TAG, "Found receiver for package: " + inf);
                    mRecvComponent = inf.getComponentInfo().getComponentName();
                }
            }
        }
        mController.registerCallback(mSessionCallback);

        if (mMediaMetadata == null) {
            Log.e(TAG, "Media metadata was null");
            return;
        }

        // Album art
        addAlbumArtBackground(mMediaMetadata, bgColor);
        addAlbumArtBackground(mMediaMetadata, mBackgroundColor);

        // App icon
        ImageView appIcon = mMediaNotifView.findViewById(R.id.icon);
        Drawable iconDrawable = icon.loadDrawable(mContext);
        iconDrawable.setTint(iconColor);
        iconDrawable.setTint(mForegroundColor);
        appIcon.setImageDrawable(iconDrawable);

        // Artist name
        TextView appText = mMediaNotifView.findViewById(R.id.header_title);
        String artistName = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
        appText.setText(artistName);
        appText.setTextColor(iconColor);
        appText.setTextColor(mForegroundColor);

        // Song name
        TextView titleText = mMediaNotifView.findViewById(R.id.header_text);
        String songName = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_TITLE);
        titleText.setText(songName);
        titleText.setTextColor(iconColor);
        titleText.setTextColor(mForegroundColor);

        // Buttons we can display
        final int[] actionIds = {R.id.action0, R.id.action1, R.id.action2};
@@ -178,6 +252,7 @@ public class QuickQSMediaPlayer {

    private void addAlbumArtBackground(MediaMetadata metadata, int bgColor) {
        Bitmap albumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
        float radius = mContext.getResources().getDimension(R.dimen.qs_media_corner_radius);
        if (albumArt != null) {
            Rect bounds = new Rect();
            mMediaNotifView.getBoundsOnScreen(bounds);
@@ -197,12 +272,15 @@ public class QuickQSMediaPlayer {

            RoundedBitmapDrawable roundedDrawable = RoundedBitmapDrawableFactory.create(
                    mContext.getResources(), scaled);
            roundedDrawable.setCornerRadius(20);
            roundedDrawable.setCornerRadius(radius);

            mMediaNotifView.setBackground(roundedDrawable);
        } else {
            Log.e(TAG, "No album art available");
            mMediaNotifView.setBackground(null);
            GradientDrawable rect = new GradientDrawable();
            rect.setCornerRadius(radius);
            rect.setColor(bgColor);
            mMediaNotifView.setBackground(rect);
        }
    }

Loading