/* * 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. */ package com.android.systemui.statusbar; import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.RippleDrawable; import android.service.notification.StatusBarNotification; import android.util.FeatureFlagUtils; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.InfoMediaManager; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.settingslib.media.MediaOutputSliceConstants; import com.android.settingslib.widget.AdaptiveIcon; import com.android.systemui.Dependency; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import java.util.ArrayList; import java.util.List; /** * Class for handling MediaTransfer state over a set of notifications. */ public class MediaTransferManager { private final Context mContext; private final ActivityStarter mActivityStarter; private MediaDevice mDevice; private List mViews = new ArrayList<>(); private LocalMediaManager mLocalMediaManager; private static final String TAG = "MediaTransferManager"; private final View.OnClickListener mOnClickHandler = new View.OnClickListener() { @Override public void onClick(View view) { if (handleMediaTransfer(view)) { return; } } private boolean handleMediaTransfer(View view) { if (view.findViewById(com.android.internal.R.id.media_seamless) == null) { return false; } ViewParent parent = view.getParent(); StatusBarNotification statusBarNotification = getRowForParent(parent).getEntry().getSbn(); final Intent intent = new Intent() .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT) .putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME, statusBarNotification.getPackageName()); mActivityStarter.startActivity(intent, false, true /* dismissShade */, Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); return true; } }; private final LocalMediaManager.DeviceCallback mMediaDeviceCallback = new LocalMediaManager.DeviceCallback() { @Override public void onDeviceListUpdate(List devices) { MediaDevice currentDevice = mLocalMediaManager.getCurrentConnectedDevice(); // Check because this can be called several times while changing devices if (mDevice == null || !mDevice.equals(currentDevice)) { mDevice = currentDevice; updateAllChips(); } } @Override public void onSelectedDeviceStateChanged(MediaDevice device, int state) { if (mDevice == null || !mDevice.equals(device)) { mDevice = device; updateAllChips(); } } }; public MediaTransferManager(Context context) { mContext = context; mActivityStarter = Dependency.get(ActivityStarter.class); LocalBluetoothManager lbm = Dependency.get(LocalBluetoothManager.class); InfoMediaManager imm = new InfoMediaManager(mContext, null, null, lbm); mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, null); } /** * Mark a view as removed. If no views remain the media device listener will be unregistered. * @param root */ public void setRemoved(View root) { if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SEAMLESS_TRANSFER) || mLocalMediaManager == null || root == null) { return; } View view = root.findViewById(com.android.internal.R.id.media_seamless); if (mViews.remove(view)) { if (mViews.size() == 0) { mLocalMediaManager.unregisterCallback(mMediaDeviceCallback); } } else { Log.e(TAG, "Tried to remove unknown view " + view); } } private ExpandableNotificationRow getRowForParent(ViewParent parent) { while (parent != null) { if (parent instanceof ExpandableNotificationRow) { return ((ExpandableNotificationRow) parent); } parent = parent.getParent(); } return null; } /** * apply the action button for MediaTransfer * * @param root The parent container of the view. * @param entry The entry of MediaTransfer action button. */ public void applyMediaTransferView(ViewGroup root, NotificationEntry entry) { if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SEAMLESS_TRANSFER) || mLocalMediaManager == null || root == null) { return; } View view = root.findViewById(com.android.internal.R.id.media_seamless); if (view == null) { return; } view.setVisibility(View.VISIBLE); view.setOnClickListener(mOnClickHandler); if (!mViews.contains(view)) { mViews.add(view); if (mViews.size() == 1) { mLocalMediaManager.registerCallback(mMediaDeviceCallback); } } // Initial update mLocalMediaManager.startScan(); mDevice = mLocalMediaManager.getCurrentConnectedDevice(); updateChip(view); } private void updateAllChips() { for (View view : mViews) { updateChip(view); } } private void updateChip(View view) { ExpandableNotificationRow enr = getRowForParent(view.getParent()); int fgColor = enr.getNotificationHeader().getOriginalIconColor(); ColorStateList fgTintList = ColorStateList.valueOf(fgColor); int bgColor = enr.getCurrentBackgroundTint(); // Update outline color LinearLayout viewLayout = (LinearLayout) view; RippleDrawable bkgDrawable = (RippleDrawable) viewLayout.getBackground(); GradientDrawable rect = (GradientDrawable) bkgDrawable.getDrawable(0); rect.setStroke(2, fgColor); rect.setColor(bgColor); ImageView iconView = view.findViewById(com.android.internal.R.id.media_seamless_image); TextView deviceName = view.findViewById(com.android.internal.R.id.media_seamless_text); deviceName.setTextColor(fgTintList); if (mDevice != null) { Drawable icon = mDevice.getIcon(); iconView.setVisibility(View.VISIBLE); iconView.setImageTintList(fgTintList); if (icon instanceof AdaptiveIcon) { AdaptiveIcon aIcon = (AdaptiveIcon) icon; aIcon.setBackgroundColor(bgColor); iconView.setImageDrawable(aIcon); } else { iconView.setImageDrawable(icon); } deviceName.setText(mDevice.getName()); } else { // Reset to default iconView.setVisibility(View.GONE); deviceName.setText(com.android.internal.R.string.ext_media_seamless_action); } } }