From 2bcd40352628fead2ab7c35e3420cc284835eddd Mon Sep 17 00:00:00 2001 From: linanson Date: Mon, 14 Jan 2019 15:22:04 +0800 Subject: [PATCH] SeamlessMedia button as one of media action button - Implement the mechanism for Seamless button in the group of media action button. - Have a fake Seamless icon in the right of media action button group. - Need to bind with MediaOutputSlice that are implementing. Bug: 118428931 Test: Build pass Change-Id: Idc51d416cc1fc85babdc83d138c8558db5ed5d8e --- core/java/android/app/Notification.java | 4 + core/res/res/drawable/ic_media_seamless.xml | 25 +++++ ...tification_template_material_big_media.xml | 4 + core/res/res/values/strings.xml | 3 + core/res/res/values/symbols.xml | 3 + .../systemui/plugins/ActivityStarter.java | 7 +- .../systemui/ActivityStarterDelegate.java | 9 ++ .../statusbar/MediaTransferManager.java | 99 +++++++++++++++++++ .../row/NotificationContentView.java | 20 ++++ .../systemui/statusbar/phone/StatusBar.java | 1 + 10 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 core/res/res/drawable/ic_media_seamless.xml create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 7c550d4332fe7..028e3efc9fb83 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -8122,6 +8122,10 @@ public class Notification implements Parcelable big.setViewVisibility(MEDIA_BUTTON_IDS[i], View.GONE); } } + bindMediaActionButton(big, R.id.media_seamless, new Action(R.drawable.ic_media_seamless, + mBuilder.mContext.getString( + com.android.internal.R.string.ext_media_seamless_action), null), p); + big.setViewVisibility(R.id.media_seamless, View.GONE); handleImage(big); return big; } diff --git a/core/res/res/drawable/ic_media_seamless.xml b/core/res/res/drawable/ic_media_seamless.xml new file mode 100644 index 0000000000000..122e9c586095a --- /dev/null +++ b/core/res/res/drawable/ic_media_seamless.xml @@ -0,0 +1,25 @@ + + + + diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml index 5cb93eb9319a9..56f7a593cc439 100644 --- a/core/res/res/layout/notification_template_material_big_media.xml +++ b/core/res/res/layout/notification_template_material_big_media.xml @@ -79,6 +79,10 @@ layout="@layout/notification_material_media_action" android:id="@+id/action4" /> + diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 6adb4a7118578..04df97c455a86 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3692,6 +3692,9 @@ Explore + + Seamless transfer + %s missing diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 5400d94ed033c..52400de3fe2bf 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -191,6 +191,7 @@ + @@ -2237,6 +2238,7 @@ + @@ -3098,6 +3100,7 @@ + diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java index 5317a6df53e86..66d5d1160bf64 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java @@ -27,7 +27,7 @@ import com.android.systemui.plugins.annotations.ProvidesInterface; */ @ProvidesInterface(version = ActivityStarter.VERSION) public interface ActivityStarter { - int VERSION = 1; + int VERSION = 2; void startPendingIntentDismissingKeyguard(PendingIntent intent); @@ -37,6 +37,11 @@ public interface ActivityStarter { */ void startPendingIntentDismissingKeyguard(PendingIntent intent, Runnable intentSentUiThreadCallback); + + /** + * The intent flag can be specified in startActivity(). + */ + void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, int flags); void startActivity(Intent intent, boolean dismissShade); void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade); void startActivity(Intent intent, boolean dismissShade, Callback callback); diff --git a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java index b461f69f10d6f..04f887bb6b2f1 100644 --- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java @@ -52,6 +52,15 @@ public class ActivityStarterDelegate implements ActivityStarter { mActualStarter.startPendingIntentDismissingKeyguard(intent, intentSentCallback); } + @Override + public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, + int flags) { + if (mActualStarter == null) { + return; + } + mActualStarter.startActivity(intent, onlyProvisioned, dismissShade, flags); + } + @Override public void startActivity(Intent intent, boolean dismissShade) { if (mActualStarter == null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java new file mode 100644 index 0000000000000..752b6a80f93df --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java @@ -0,0 +1,99 @@ +/* + * 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.service.notification.StatusBarNotification; +import android.util.FeatureFlagUtils; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; + +import com.android.settingslib.media.MediaOutputSliceConstants; +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; + +/** + * Class for handling MediaTransfer state over a set of notifications. + */ +public class MediaTransferManager { + private final Context mContext; + private final ActivityStarter mActivityStarter; + + 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 = getNotificationForParent(parent); + 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 StatusBarNotification getNotificationForParent(ViewParent parent) { + while (parent != null) { + if (parent instanceof ExpandableNotificationRow) { + return ((ExpandableNotificationRow) parent).getStatusBarNotification(); + } + parent = parent.getParent(); + } + return null; + } + }; + + public MediaTransferManager(Context context) { + mContext = context; + mActivityStarter = Dependency.get(ActivityStarter.class); + } + + /** + * 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)) { + return; + } + + View view = root.findViewById(com.android.internal.R.id.media_seamless); + if (view == null) { + return; + } + + view.setVisibility(View.VISIBLE); + view.setOnClickListener(mOnClickHandler); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index c161da348c28f..77cdbb9212739 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -43,6 +43,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.ContrastColorUtil; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.statusbar.MediaTransferManager; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.TransformableView; @@ -163,11 +164,13 @@ public class NotificationContentView extends FrameLayout { private boolean mIsContentExpandable; private boolean mRemoteInputVisible; private int mUnrestrictedContentHeight; + private MediaTransferManager mMediaTransferManager; public NotificationContentView(Context context, AttributeSet attrs) { super(context, attrs); mHybridGroupManager = new HybridGroupManager(getContext(), this); + mMediaTransferManager = new MediaTransferManager(getContext()); mSmartReplyConstants = Dependency.get(SmartReplyConstants.class); mSmartReplyController = Dependency.get(SmartReplyController.class); initView(); @@ -1250,6 +1253,7 @@ public class NotificationContentView extends FrameLayout { mAmbientWrapper.onContentUpdated(row); } applyRemoteInputAndSmartReply(entry); + applyMediaTransfer(entry); updateLegacy(); mForceSelectNextLayout = true; setDark(mDark, false /* animate */, 0 /* delay */); @@ -1292,6 +1296,22 @@ public class NotificationContentView extends FrameLayout { } } + private void applyMediaTransfer(final NotificationEntry entry) { + View bigContentView = mExpandedChild; + if (bigContentView == null || !entry.isMediaNotification()) { + return; + } + + View mediaActionContainer = bigContentView.findViewById( + com.android.internal.R.id.media_actions); + if (!(mediaActionContainer instanceof LinearLayout)) { + return; + } + + mMediaTransferManager.applyMediaTransferView((ViewGroup) mediaActionContainer, + entry); + } + private void applyRemoteInputAndSmartReply(final NotificationEntry entry) { if (mRemoteInputController == null) { return; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index dd231821ef2bd..2413268500906 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1444,6 +1444,7 @@ public class StatusBar extends SystemUI implements DemoMode, return new StatusBar.H(); } + @Override public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, int flags) { startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, flags);