diff options
10 files changed, 174 insertions, 1 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 7c550d4332fe..028e3efc9fb8 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 000000000000..122e9c586095 --- /dev/null +++ b/core/res/res/drawable/ic_media_seamless.xml @@ -0,0 +1,25 @@ +<!-- + Copyright (C) 2017 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FF000000" + android:pathData="M12,3l0.01,10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55C7.79,13 6,14.79 6,17c0,2.21 1.79,4 4.01,4S14,19.21 14,17V7h4V3H12zM10.01,19c-1.1,0 -2,-0.9 -2,-2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2C12.01,18.1 11.11,19 10.01,19z"/> +</vector> 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 5cb93eb9319a..56f7a593cc43 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" /> + <include + layout="@layout/notification_material_media_action" + android:id="@+id/media_seamless" + /> </LinearLayout> </LinearLayout> </com.android.internal.widget.MediaNotificationView> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 6adb4a711857..04df97c455a8 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3692,6 +3692,9 @@ <!-- Notification action to browse external media [CHAR LIMIT=20] --> <string name="ext_media_browse_action">Explore</string> + <!-- Notification action to transfer media [CHAR LIMIT=40] --> + <string name="ext_media_seamless_action">Seamless transfer</string> + <!-- Notification title when external media is missing [CHAR LIMIT=30] --> <string name="ext_media_missing_title"><xliff:g id="name" example="SD card">%s</xliff:g> missing</string> <!-- Notification body when external media is missing [CHAR LIMIT=30] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 5400d94ed033..52400de3fe2b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -191,6 +191,7 @@ <java-symbol type="id" name="action2" /> <java-symbol type="id" name="action3" /> <java-symbol type="id" name="action4" /> + <java-symbol type="id" name="media_seamless" /> <java-symbol type="id" name="big_picture" /> <java-symbol type="id" name="big_text" /> <java-symbol type="id" name="chronometer" /> @@ -2237,6 +2238,7 @@ <java-symbol type="string" name="ext_media_init_action" /> <java-symbol type="string" name="ext_media_unmount_action" /> <java-symbol type="string" name="ext_media_browse_action" /> + <java-symbol type="string" name="ext_media_seamless_action" /> <java-symbol type="string" name="ext_media_missing_title" /> <java-symbol type="string" name="ext_media_missing_message" /> <java-symbol type="string" name="ext_media_move_specific_title" /> @@ -3098,6 +3100,7 @@ <java-symbol type="drawable" name="ic_restart" /> <java-symbol type="drawable" name="ic_screenshot" /> <java-symbol type="drawable" name="ic_faster_emergency" /> + <java-symbol type="drawable" name="ic_media_seamless" /> <java-symbol type="drawable" name="emergency_icon" /> <java-symbol type="array" name="config_convert_to_emergency_number_map" /> 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 5317a6df53e8..66d5d1160bf6 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 b461f69f10d6..04f887bb6b2f 100644 --- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java @@ -53,6 +53,15 @@ public class ActivityStarterDelegate implements ActivityStarter { } @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) { return; 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 000000000000..752b6a80f93d --- /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 c161da348c28..77cdbb921273 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 dd231821ef2b..241326850090 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); |