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
This commit is contained in:
linanson
2019-01-14 15:22:04 +08:00
parent 5fbcaf46c1
commit 2bcd403526
10 changed files with 174 additions and 1 deletions

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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] -->

View File

@@ -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" />

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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);