Merge "[Output Switcher] Update Volume control in Output Switcher" into tm-qpr-dev
This commit is contained in:
@@ -17,7 +17,10 @@
|
|||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:id="@android:id/background">
|
<item android:id="@android:id/background">
|
||||||
<shape>
|
<shape>
|
||||||
<corners android:radius="28dp" />
|
<corners
|
||||||
|
android:bottomRightRadius="28dp"
|
||||||
|
android:topRightRadius="28dp"
|
||||||
|
/>
|
||||||
<solid android:color="@android:color/transparent" />
|
<solid android:color="@android:color/transparent" />
|
||||||
<size
|
<size
|
||||||
android:height="64dp"/>
|
android:height="64dp"/>
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportWidth="48"
|
||||||
|
android:viewportHeight="48"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:autoMirrored="true">
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/media_dialog_item_main_content"
|
||||||
|
android:pathData="M40.65,45.2 L34.05,38.6Q32.65,39.6 31.025,40.325Q29.4,41.05 27.65,41.45V38.35Q28.8,38 29.875,37.575Q30.95,37.15 31.9,36.45L23.65,28.15V40L13.65,30H5.65V18H13.45L2.45,7L4.6,4.85L42.8,43ZM38.85,33.6 L36.7,31.45Q37.7,29.75 38.175,27.85Q38.65,25.95 38.65,23.95Q38.65,18.8 35.65,14.725Q32.65,10.65 27.65,9.55V6.45Q33.85,7.85 37.75,12.725Q41.65,17.6 41.65,23.95Q41.65,26.5 40.95,28.95Q40.25,31.4 38.85,33.6ZM32.15,26.9 L27.65,22.4V15.9Q30,17 31.325,19.2Q32.65,21.4 32.65,24Q32.65,24.75 32.525,25.475Q32.4,26.2 32.15,26.9ZM23.65,18.4 L18.45,13.2 23.65,8ZM20.65,32.7V25.2L16.45,21H8.65V27H14.95ZM18.55,23.1Z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners
|
||||||
|
android:bottomLeftRadius="28dp"
|
||||||
|
android:topLeftRadius="28dp"
|
||||||
|
android:bottomRightRadius="0dp"
|
||||||
|
android:topRightRadius="0dp"/>
|
||||||
|
<solid android:color="@color/media_dialog_item_background" />
|
||||||
|
</shape>
|
||||||
158
packages/SystemUI/res/layout/media_output_list_item_advanced.xml
Normal file
158
packages/SystemUI/res/layout/media_output_list_item_advanced.xml
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2022 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/device_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginBottom="12dp">
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/item_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/media_output_item_background"
|
||||||
|
android:layout_gravity="center_vertical|start">
|
||||||
|
<com.android.systemui.media.dialog.MediaOutputSeekbar
|
||||||
|
android:id="@+id/volume_seekbar"
|
||||||
|
android:splitTrack="false"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:paddingStart="64dp"
|
||||||
|
android:paddingEnd="0dp"
|
||||||
|
android:background="@null"
|
||||||
|
android:contentDescription="@string/media_output_dialog_accessibility_seekbar"
|
||||||
|
android:progressDrawable="@drawable/media_output_dialog_seekbar_background"
|
||||||
|
android:thumb="@null"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/icon_area"
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:background="@drawable/media_output_title_icon_area"
|
||||||
|
android:layout_gravity="center_vertical|start">
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/title_icon"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:animateLayoutChanges="true"
|
||||||
|
android:layout_gravity="center"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/volume_value"
|
||||||
|
android:animateLayoutChanges="true"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|start"
|
||||||
|
android:layout_marginStart="72dp"
|
||||||
|
android:layout_marginEnd="56dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
|
||||||
|
android:textSize="16sp"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/two_line_layout"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|start"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginEnd="56dp"
|
||||||
|
android:layout_marginStart="72dp">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/two_line_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
|
||||||
|
android:textColor="@color/media_dialog_item_main_content"
|
||||||
|
android:textSize="16sp"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/subtitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="@color/media_dialog_item_main_content"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:fontFamily="@*android:string/config_bodyFontFamily"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/volume_indeterminate_progress"
|
||||||
|
style="?android:attr/progressBarStyleSmallTitle"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:layout_gravity="end|center"
|
||||||
|
android:indeterminateOnly="true"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/media_output_item_status"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:layout_gravity="end|center"
|
||||||
|
android:indeterminateOnly="true"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/end_action_area"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:layout_gravity="end|center"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/check_box"
|
||||||
|
android:focusable="false"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:button="@drawable/ic_circle_check_box"
|
||||||
|
android:visibility="gone"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
||||||
@@ -2377,7 +2377,7 @@
|
|||||||
<!-- Controls menu, edit [CHAR_LIMIT=30] -->
|
<!-- Controls menu, edit [CHAR_LIMIT=30] -->
|
||||||
<string name="controls_menu_edit">Edit controls</string>
|
<string name="controls_menu_edit">Edit controls</string>
|
||||||
|
|
||||||
<!-- Title for the media output group dialog with media related devices [CHAR LIMIT=50] -->
|
<!-- Title for the media output dialog with media related devices [CHAR LIMIT=50] -->
|
||||||
<string name="media_output_dialog_add_output">Add outputs</string>
|
<string name="media_output_dialog_add_output">Add outputs</string>
|
||||||
<!-- Title for the media output slice with group devices [CHAR LIMIT=50] -->
|
<!-- Title for the media output slice with group devices [CHAR LIMIT=50] -->
|
||||||
<string name="media_output_dialog_group">Group</string>
|
<string name="media_output_dialog_group">Group</string>
|
||||||
@@ -2401,6 +2401,8 @@
|
|||||||
<string name="media_output_dialog_accessibility_title">Available devices for audio output.</string>
|
<string name="media_output_dialog_accessibility_title">Available devices for audio output.</string>
|
||||||
<!-- Accessibility text describing purpose of seekbar in media output dialog. [CHAR LIMIT=NONE] -->
|
<!-- Accessibility text describing purpose of seekbar in media output dialog. [CHAR LIMIT=NONE] -->
|
||||||
<string name="media_output_dialog_accessibility_seekbar">Volume</string>
|
<string name="media_output_dialog_accessibility_seekbar">Volume</string>
|
||||||
|
<!-- Summary for media output volume of a device in percentage [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="media_output_dialog_volume_percentage"><xliff:g id="percentage" example="10">%1$d</xliff:g>%%</string>
|
||||||
|
|
||||||
<!-- Media Output Broadcast Dialog -->
|
<!-- Media Output Broadcast Dialog -->
|
||||||
<!-- Title for Broadcast First Notify Dialog [CHAR LIMIT=60] -->
|
<!-- Title for Broadcast First Notify Dialog [CHAR LIMIT=60] -->
|
||||||
|
|||||||
@@ -437,6 +437,11 @@ object Flags {
|
|||||||
val WARN_ON_BLOCKING_BINDER_TRANSACTIONS =
|
val WARN_ON_BLOCKING_BINDER_TRANSACTIONS =
|
||||||
unreleasedFlag(2400, "warn_on_blocking_binder_transactions")
|
unreleasedFlag(2400, "warn_on_blocking_binder_transactions")
|
||||||
|
|
||||||
|
// 2500 - output switcher
|
||||||
|
// TODO(b/261538825): Tracking Bug
|
||||||
|
@JvmField
|
||||||
|
val OUTPUT_SWITCHER_ADVANCED_LAYOUT = unreleasedFlag(2500, "output_switcher_advanced_layout")
|
||||||
|
|
||||||
// TODO(b259590361): Tracking bug
|
// TODO(b259590361): Tracking bug
|
||||||
val EXPERIMENTAL_FLAG = unreleasedFlag(2, "exp_flag_release")
|
val EXPERIMENTAL_FLAG = unreleasedFlag(2, "exp_flag_release")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.android.systemui.media.dialog;
|
package com.android.systemui.media.dialog;
|
||||||
|
|
||||||
import android.annotation.DrawableRes;
|
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.PorterDuffColorFilter;
|
import android.graphics.PorterDuffColorFilter;
|
||||||
@@ -122,17 +121,19 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
// Set different layout for each device
|
// Set different layout for each device
|
||||||
if (device.isMutingExpectedDevice()
|
if (device.isMutingExpectedDevice()
|
||||||
&& !mController.isCurrentConnectedDeviceRemote()) {
|
&& !mController.isCurrentConnectedDeviceRemote()) {
|
||||||
|
if (!mController.isAdvancedLayoutSupported()) {
|
||||||
updateTitleIcon(R.drawable.media_output_icon_volume,
|
updateTitleIcon(R.drawable.media_output_icon_volume,
|
||||||
mController.getColorItemContent());
|
mController.getColorItemContent());
|
||||||
|
}
|
||||||
initMutingExpectedDevice();
|
initMutingExpectedDevice();
|
||||||
mCurrentActivePosition = position;
|
mCurrentActivePosition = position;
|
||||||
updateContainerClickListener(v -> onItemClick(v, device));
|
updateFullItemClickListener(v -> onItemClick(v, device));
|
||||||
setSingleLineLayout(getItemTitle(device));
|
setSingleLineLayout(getItemTitle(device));
|
||||||
} else if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
|
} else if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
|
||||||
setUpDeviceIcon(device);
|
setUpDeviceIcon(device);
|
||||||
updateConnectionFailedStatusIcon();
|
updateConnectionFailedStatusIcon();
|
||||||
mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
|
mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
|
||||||
updateContainerClickListener(v -> onItemClick(v, device));
|
updateFullItemClickListener(v -> onItemClick(v, device));
|
||||||
setTwoLineLayout(device, false /* bFocused */, false /* showSeekBar */,
|
setTwoLineLayout(device, false /* bFocused */, false /* showSeekBar */,
|
||||||
false /* showProgressBar */, true /* showSubtitle */,
|
false /* showProgressBar */, true /* showSubtitle */,
|
||||||
true /* showStatus */);
|
true /* showStatus */);
|
||||||
@@ -146,8 +147,10 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
&& isDeviceIncluded(mController.getSelectedMediaDevice(), device)) {
|
&& isDeviceIncluded(mController.getSelectedMediaDevice(), device)) {
|
||||||
boolean isDeviceDeselectable = isDeviceIncluded(
|
boolean isDeviceDeselectable = isDeviceIncluded(
|
||||||
mController.getDeselectableMediaDevice(), device);
|
mController.getDeselectableMediaDevice(), device);
|
||||||
|
if (!mController.isAdvancedLayoutSupported()) {
|
||||||
updateTitleIcon(R.drawable.media_output_icon_volume,
|
updateTitleIcon(R.drawable.media_output_icon_volume,
|
||||||
mController.getColorItemContent());
|
mController.getColorItemContent());
|
||||||
|
}
|
||||||
updateGroupableCheckBox(true, isDeviceDeselectable, device);
|
updateGroupableCheckBox(true, isDeviceDeselectable, device);
|
||||||
updateEndClickArea(device, isDeviceDeselectable);
|
updateEndClickArea(device, isDeviceDeselectable);
|
||||||
setUpContentDescriptionForView(mContainerLayout, false, device);
|
setUpContentDescriptionForView(mContainerLayout, false, device);
|
||||||
@@ -161,7 +164,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
&& !mController.isCurrentConnectedDeviceRemote()) {
|
&& !mController.isCurrentConnectedDeviceRemote()) {
|
||||||
// mark as disconnected and set special click listener
|
// mark as disconnected and set special click listener
|
||||||
setUpDeviceIcon(device);
|
setUpDeviceIcon(device);
|
||||||
updateContainerClickListener(v -> cancelMuteAwaitConnection());
|
updateFullItemClickListener(v -> cancelMuteAwaitConnection());
|
||||||
setSingleLineLayout(getItemTitle(device));
|
setSingleLineLayout(getItemTitle(device));
|
||||||
} else {
|
} else {
|
||||||
updateTitleIcon(R.drawable.media_output_icon_volume,
|
updateTitleIcon(R.drawable.media_output_icon_volume,
|
||||||
@@ -176,14 +179,14 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
} else if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
|
} else if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
|
||||||
setUpDeviceIcon(device);
|
setUpDeviceIcon(device);
|
||||||
updateGroupableCheckBox(false, true, device);
|
updateGroupableCheckBox(false, true, device);
|
||||||
updateContainerClickListener(v -> onGroupActionTriggered(true, device));
|
updateFullItemClickListener(v -> onGroupActionTriggered(true, device));
|
||||||
setSingleLineLayout(getItemTitle(device), false /* showSeekBar */,
|
setSingleLineLayout(getItemTitle(device), false /* showSeekBar */,
|
||||||
false /* showProgressBar */, true /* showCheckBox */,
|
false /* showProgressBar */, true /* showCheckBox */,
|
||||||
true /* showEndTouchArea */);
|
true /* showEndTouchArea */);
|
||||||
} else {
|
} else {
|
||||||
setUpDeviceIcon(device);
|
setUpDeviceIcon(device);
|
||||||
setSingleLineLayout(getItemTitle(device));
|
setSingleLineLayout(getItemTitle(device));
|
||||||
updateContainerClickListener(v -> onItemClick(v, device));
|
updateFullItemClickListener(v -> onItemClick(v, device));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -228,13 +231,9 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
setCheckBoxColor(mCheckBox, mController.getColorItemContent());
|
setCheckBoxColor(mCheckBox, mController.getColorItemContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTitleIcon(@DrawableRes int id, int color) {
|
private void updateFullItemClickListener(View.OnClickListener listener) {
|
||||||
mTitleIcon.setImageDrawable(mContext.getDrawable(id));
|
|
||||||
mTitleIcon.setColorFilter(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateContainerClickListener(View.OnClickListener listener) {
|
|
||||||
mContainerLayout.setOnClickListener(listener);
|
mContainerLayout.setOnClickListener(listener);
|
||||||
|
updateIconAreaClickListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -246,6 +245,11 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
|
|||||||
final Drawable addDrawable = mContext.getDrawable(R.drawable.ic_add);
|
final Drawable addDrawable = mContext.getDrawable(R.drawable.ic_add);
|
||||||
mTitleIcon.setImageDrawable(addDrawable);
|
mTitleIcon.setImageDrawable(addDrawable);
|
||||||
mTitleIcon.setColorFilter(mController.getColorItemContent());
|
mTitleIcon.setColorFilter(mController.getColorItemContent());
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
mIconAreaLayout.getBackground().setColorFilter(
|
||||||
|
new PorterDuffColorFilter(mController.getColorItemBackground(),
|
||||||
|
PorterDuff.Mode.SRC_IN));
|
||||||
|
}
|
||||||
mContainerLayout.setOnClickListener(mController::launchBluetoothPairing);
|
mContainerLayout.setOnClickListener(mController::launchBluetoothPairing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.android.systemui.media.dialog;
|
package com.android.systemui.media.dialog;
|
||||||
|
|
||||||
|
import static com.android.systemui.media.dialog.MediaOutputSeekbar.VOLUME_PERCENTAGE_SCALE_SIZE;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
|
import android.annotation.DrawableRes;
|
||||||
import android.app.WallpaperColors;
|
import android.app.WallpaperColors;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
@@ -80,8 +83,9 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
public MediaDeviceBaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
|
public MediaDeviceBaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
|
||||||
int viewType) {
|
int viewType) {
|
||||||
mContext = viewGroup.getContext();
|
mContext = viewGroup.getContext();
|
||||||
mHolderView = LayoutInflater.from(mContext).inflate(R.layout.media_output_list_item,
|
mHolderView = LayoutInflater.from(mContext).inflate(
|
||||||
viewGroup, false);
|
mController.isAdvancedLayoutSupported() ? R.layout.media_output_list_item_advanced
|
||||||
|
: R.layout.media_output_list_item, viewGroup, false);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -131,9 +135,11 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
|
|
||||||
final LinearLayout mContainerLayout;
|
final LinearLayout mContainerLayout;
|
||||||
final FrameLayout mItemLayout;
|
final FrameLayout mItemLayout;
|
||||||
|
final FrameLayout mIconAreaLayout;
|
||||||
final TextView mTitleText;
|
final TextView mTitleText;
|
||||||
final TextView mTwoLineTitleText;
|
final TextView mTwoLineTitleText;
|
||||||
final TextView mSubTitleText;
|
final TextView mSubTitleText;
|
||||||
|
final TextView mVolumeValueText;
|
||||||
final ImageView mTitleIcon;
|
final ImageView mTitleIcon;
|
||||||
final ProgressBar mProgressBar;
|
final ProgressBar mProgressBar;
|
||||||
final MediaOutputSeekbar mSeekBar;
|
final MediaOutputSeekbar mSeekBar;
|
||||||
@@ -159,6 +165,13 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
mStatusIcon = view.requireViewById(R.id.media_output_item_status);
|
mStatusIcon = view.requireViewById(R.id.media_output_item_status);
|
||||||
mCheckBox = view.requireViewById(R.id.check_box);
|
mCheckBox = view.requireViewById(R.id.check_box);
|
||||||
mEndTouchArea = view.requireViewById(R.id.end_action_area);
|
mEndTouchArea = view.requireViewById(R.id.end_action_area);
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
mVolumeValueText = view.requireViewById(R.id.volume_value);
|
||||||
|
mIconAreaLayout = view.requireViewById(R.id.icon_area);
|
||||||
|
} else {
|
||||||
|
mVolumeValueText = null;
|
||||||
|
mIconAreaLayout = null;
|
||||||
|
}
|
||||||
initAnimator();
|
initAnimator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,9 +183,14 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
mEndTouchArea.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
mEndTouchArea.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||||
mContainerLayout.setOnClickListener(null);
|
mContainerLayout.setOnClickListener(null);
|
||||||
mContainerLayout.setContentDescription(null);
|
mContainerLayout.setContentDescription(null);
|
||||||
|
mTitleIcon.setOnClickListener(null);
|
||||||
mTitleText.setTextColor(mController.getColorItemContent());
|
mTitleText.setTextColor(mController.getColorItemContent());
|
||||||
mSubTitleText.setTextColor(mController.getColorItemContent());
|
mSubTitleText.setTextColor(mController.getColorItemContent());
|
||||||
mTwoLineTitleText.setTextColor(mController.getColorItemContent());
|
mTwoLineTitleText.setTextColor(mController.getColorItemContent());
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
mIconAreaLayout.setOnClickListener(null);
|
||||||
|
mVolumeValueText.setTextColor(mController.getColorItemContent());
|
||||||
|
}
|
||||||
mSeekBar.getProgressDrawable().setColorFilter(
|
mSeekBar.getProgressDrawable().setColorFilter(
|
||||||
new PorterDuffColorFilter(mController.getColorSeekbarProgress(),
|
new PorterDuffColorFilter(mController.getColorSeekbarProgress(),
|
||||||
PorterDuff.Mode.SRC_IN));
|
PorterDuff.Mode.SRC_IN));
|
||||||
@@ -203,13 +221,28 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
.findDrawableByLayerId(android.R.id.progress);
|
.findDrawableByLayerId(android.R.id.progress);
|
||||||
final GradientDrawable progressDrawable =
|
final GradientDrawable progressDrawable =
|
||||||
(GradientDrawable) clipDrawable.getDrawable();
|
(GradientDrawable) clipDrawable.getDrawable();
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
progressDrawable.setCornerRadii(
|
||||||
|
new float[]{0, 0, mController.getActiveRadius(),
|
||||||
|
mController.getActiveRadius(),
|
||||||
|
mController.getActiveRadius(),
|
||||||
|
mController.getActiveRadius(), 0, 0});
|
||||||
|
} else {
|
||||||
progressDrawable.setCornerRadius(mController.getActiveRadius());
|
progressDrawable.setCornerRadius(mController.getActiveRadius());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
mItemLayout.getBackground().setColorFilter(new PorterDuffColorFilter(
|
mItemLayout.getBackground().setColorFilter(new PorterDuffColorFilter(
|
||||||
isActive ? mController.getColorConnectedItemBackground()
|
isActive ? mController.getColorConnectedItemBackground()
|
||||||
: mController.getColorItemBackground(),
|
: mController.getColorItemBackground(),
|
||||||
PorterDuff.Mode.SRC_IN));
|
PorterDuff.Mode.SRC_IN));
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
mIconAreaLayout.getBackground().setColorFilter(new PorterDuffColorFilter(
|
||||||
|
showSeekBar ? mController.getColorSeekbarProgress()
|
||||||
|
: showProgressBar ? mController.getColorConnectedItemBackground()
|
||||||
|
: mController.getColorItemBackground(),
|
||||||
|
PorterDuff.Mode.SRC_IN));
|
||||||
|
}
|
||||||
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
|
mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
|
||||||
mSeekBar.setAlpha(1);
|
mSeekBar.setAlpha(1);
|
||||||
mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
|
mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
|
||||||
@@ -263,42 +296,134 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
final int currentVolume = device.getCurrentVolume();
|
final int currentVolume = device.getCurrentVolume();
|
||||||
if (mSeekBar.getVolume() != currentVolume) {
|
if (mSeekBar.getVolume() != currentVolume) {
|
||||||
if (isCurrentSeekbarInvisible && !mIsInitVolumeFirstTime) {
|
if (isCurrentSeekbarInvisible && !mIsInitVolumeFirstTime) {
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
updateTitleIcon(currentVolume == 0 ? R.drawable.media_output_icon_volume_off
|
||||||
|
: R.drawable.media_output_icon_volume,
|
||||||
|
mController.getColorItemContent());
|
||||||
|
}
|
||||||
animateCornerAndVolume(mSeekBar.getProgress(),
|
animateCornerAndVolume(mSeekBar.getProgress(),
|
||||||
MediaOutputSeekbar.scaleVolumeToProgress(currentVolume));
|
MediaOutputSeekbar.scaleVolumeToProgress(currentVolume));
|
||||||
} else {
|
} else {
|
||||||
if (!mVolumeAnimator.isStarted()) {
|
if (!mVolumeAnimator.isStarted()) {
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
int percentage =
|
||||||
|
(int) ((double) currentVolume * VOLUME_PERCENTAGE_SCALE_SIZE
|
||||||
|
/ (double) mSeekBar.getMax());
|
||||||
|
if (percentage == 0) {
|
||||||
|
updateMutedVolumeIcon();
|
||||||
|
} else {
|
||||||
|
updateUnmutedVolumeIcon();
|
||||||
|
}
|
||||||
|
}
|
||||||
mSeekBar.setVolume(currentVolume);
|
mSeekBar.setVolume(currentVolume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (mController.isAdvancedLayoutSupported() && currentVolume == 0) {
|
||||||
|
mSeekBar.resetVolume();
|
||||||
|
updateMutedVolumeIcon();
|
||||||
}
|
}
|
||||||
if (mIsInitVolumeFirstTime) {
|
if (mIsInitVolumeFirstTime) {
|
||||||
mIsInitVolumeFirstTime = false;
|
mIsInitVolumeFirstTime = false;
|
||||||
}
|
}
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
updateIconAreaClickListener((v) -> {
|
||||||
|
mSeekBar.resetVolume();
|
||||||
|
mController.adjustVolume(device, 0);
|
||||||
|
updateMutedVolumeIcon();
|
||||||
|
});
|
||||||
|
}
|
||||||
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
if (device == null || !fromUser) {
|
if (device == null || !fromUser) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int currentVolume = MediaOutputSeekbar.scaleProgressToVolume(progress);
|
int progressToVolume = MediaOutputSeekbar.scaleProgressToVolume(progress);
|
||||||
int deviceVolume = device.getCurrentVolume();
|
int deviceVolume = device.getCurrentVolume();
|
||||||
if (currentVolume != deviceVolume) {
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
mController.adjustVolume(device, currentVolume);
|
int percentage =
|
||||||
|
(int) ((double) progressToVolume * VOLUME_PERCENTAGE_SCALE_SIZE
|
||||||
|
/ (double) seekBar.getMax());
|
||||||
|
mVolumeValueText.setText(mContext.getResources().getString(
|
||||||
|
R.string.media_output_dialog_volume_percentage, percentage));
|
||||||
|
mVolumeValueText.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
if (progressToVolume != deviceVolume) {
|
||||||
|
mController.adjustVolume(device, progressToVolume);
|
||||||
|
if (mController.isAdvancedLayoutSupported() && deviceVolume == 0) {
|
||||||
|
updateUnmutedVolumeIcon();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
mTitleIcon.setVisibility(View.INVISIBLE);
|
||||||
|
mVolumeValueText.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
mIsDragging = true;
|
mIsDragging = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
int currentVolume = MediaOutputSeekbar.scaleProgressToVolume(
|
||||||
|
seekBar.getProgress());
|
||||||
|
int percentage =
|
||||||
|
(int) ((double) currentVolume * VOLUME_PERCENTAGE_SCALE_SIZE
|
||||||
|
/ (double) seekBar.getMax());
|
||||||
|
if (percentage == 0) {
|
||||||
|
seekBar.setProgress(0);
|
||||||
|
updateMutedVolumeIcon();
|
||||||
|
} else {
|
||||||
|
updateUnmutedVolumeIcon();
|
||||||
|
}
|
||||||
|
mTitleIcon.setVisibility(View.VISIBLE);
|
||||||
|
mVolumeValueText.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
mIsDragging = false;
|
mIsDragging = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateMutedVolumeIcon() {
|
||||||
|
updateTitleIcon(R.drawable.media_output_icon_volume_off,
|
||||||
|
mController.getColorItemContent());
|
||||||
|
final GradientDrawable iconAreaBackgroundDrawable =
|
||||||
|
(GradientDrawable) mIconAreaLayout.getBackground();
|
||||||
|
iconAreaBackgroundDrawable.setCornerRadius(mController.getActiveRadius());
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateUnmutedVolumeIcon() {
|
||||||
|
updateTitleIcon(R.drawable.media_output_icon_volume,
|
||||||
|
mController.getColorItemContent());
|
||||||
|
final GradientDrawable iconAreaBackgroundDrawable =
|
||||||
|
(GradientDrawable) mIconAreaLayout.getBackground();
|
||||||
|
iconAreaBackgroundDrawable.setCornerRadii(new float[]{
|
||||||
|
mController.getActiveRadius(),
|
||||||
|
mController.getActiveRadius(),
|
||||||
|
0, 0, 0, 0, mController.getActiveRadius(), mController.getActiveRadius()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTitleIcon(@DrawableRes int id, int color) {
|
||||||
|
mTitleIcon.setImageDrawable(mContext.getDrawable(id));
|
||||||
|
mTitleIcon.setColorFilter(color);
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
mIconAreaLayout.getBackground().setColorFilter(
|
||||||
|
new PorterDuffColorFilter(mController.getColorSeekbarProgress(),
|
||||||
|
PorterDuff.Mode.SRC_IN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateIconAreaClickListener(View.OnClickListener listener) {
|
||||||
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
mIconAreaLayout.setOnClickListener(listener);
|
||||||
|
}
|
||||||
|
mTitleIcon.setOnClickListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
void initMutingExpectedDevice() {
|
void initMutingExpectedDevice() {
|
||||||
disableSeekBar();
|
disableSeekBar();
|
||||||
final Drawable backgroundDrawable = mContext.getDrawable(
|
final Drawable backgroundDrawable = mContext.getDrawable(
|
||||||
@@ -316,11 +441,26 @@ public abstract class MediaOutputBaseAdapter extends
|
|||||||
final ClipDrawable clipDrawable =
|
final ClipDrawable clipDrawable =
|
||||||
(ClipDrawable) ((LayerDrawable) mSeekBar.getProgressDrawable())
|
(ClipDrawable) ((LayerDrawable) mSeekBar.getProgressDrawable())
|
||||||
.findDrawableByLayerId(android.R.id.progress);
|
.findDrawableByLayerId(android.R.id.progress);
|
||||||
final GradientDrawable progressDrawable = (GradientDrawable) clipDrawable.getDrawable();
|
final GradientDrawable targetBackgroundDrawable =
|
||||||
|
(GradientDrawable) (mController.isAdvancedLayoutSupported()
|
||||||
|
? mIconAreaLayout.getBackground()
|
||||||
|
: clipDrawable.getDrawable());
|
||||||
mCornerAnimator.addUpdateListener(animation -> {
|
mCornerAnimator.addUpdateListener(animation -> {
|
||||||
float value = (float) animation.getAnimatedValue();
|
float value = (float) animation.getAnimatedValue();
|
||||||
layoutBackgroundDrawable.setCornerRadius(value);
|
layoutBackgroundDrawable.setCornerRadius(value);
|
||||||
progressDrawable.setCornerRadius(value);
|
if (mController.isAdvancedLayoutSupported()) {
|
||||||
|
if (toProgress == 0) {
|
||||||
|
targetBackgroundDrawable.setCornerRadius(value);
|
||||||
|
} else {
|
||||||
|
targetBackgroundDrawable.setCornerRadii(new float[]{
|
||||||
|
value,
|
||||||
|
value,
|
||||||
|
0, 0, 0, 0, value, value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
targetBackgroundDrawable.setCornerRadius(value);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
mVolumeAnimator.setIntValues(fromProgress, toProgress);
|
mVolumeAnimator.setIntValues(fromProgress, toProgress);
|
||||||
mVolumeAnimator.start();
|
mVolumeAnimator.start();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import com.android.internal.logging.UiEventLogger
|
|||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager
|
import com.android.settingslib.bluetooth.LocalBluetoothManager
|
||||||
import com.android.systemui.animation.DialogLaunchAnimator
|
import com.android.systemui.animation.DialogLaunchAnimator
|
||||||
import com.android.systemui.broadcast.BroadcastSender
|
import com.android.systemui.broadcast.BroadcastSender
|
||||||
|
import com.android.systemui.flags.FeatureFlags
|
||||||
import com.android.systemui.media.nearby.NearbyMediaDevicesManager
|
import com.android.systemui.media.nearby.NearbyMediaDevicesManager
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
||||||
@@ -47,7 +48,8 @@ class MediaOutputBroadcastDialogFactory @Inject constructor(
|
|||||||
private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>,
|
private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>,
|
||||||
private val audioManager: AudioManager,
|
private val audioManager: AudioManager,
|
||||||
private val powerExemptionManager: PowerExemptionManager,
|
private val powerExemptionManager: PowerExemptionManager,
|
||||||
private val keyGuardManager: KeyguardManager
|
private val keyGuardManager: KeyguardManager,
|
||||||
|
private val featureFlags: FeatureFlags
|
||||||
) {
|
) {
|
||||||
var mediaOutputBroadcastDialog: MediaOutputBroadcastDialog? = null
|
var mediaOutputBroadcastDialog: MediaOutputBroadcastDialog? = null
|
||||||
|
|
||||||
@@ -59,7 +61,7 @@ class MediaOutputBroadcastDialogFactory @Inject constructor(
|
|||||||
val controller = MediaOutputController(context, packageName,
|
val controller = MediaOutputController(context, packageName,
|
||||||
mediaSessionManager, lbm, starter, notifCollection,
|
mediaSessionManager, lbm, starter, notifCollection,
|
||||||
dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager,
|
dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager,
|
||||||
powerExemptionManager, keyGuardManager)
|
powerExemptionManager, keyGuardManager, featureFlags)
|
||||||
val dialog =
|
val dialog =
|
||||||
MediaOutputBroadcastDialog(context, aboveStatusBar, broadcastSender, controller)
|
MediaOutputBroadcastDialog(context, aboveStatusBar, broadcastSender, controller)
|
||||||
mediaOutputBroadcastDialog = dialog
|
mediaOutputBroadcastDialog = dialog
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ import com.android.systemui.R;
|
|||||||
import com.android.systemui.animation.ActivityLaunchAnimator;
|
import com.android.systemui.animation.ActivityLaunchAnimator;
|
||||||
import com.android.systemui.animation.DialogLaunchAnimator;
|
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||||
import com.android.systemui.broadcast.BroadcastSender;
|
import com.android.systemui.broadcast.BroadcastSender;
|
||||||
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
|
import com.android.systemui.flags.Flags;
|
||||||
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
|
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
|
||||||
import com.android.systemui.monet.ColorScheme;
|
import com.android.systemui.monet.ColorScheme;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
@@ -147,6 +149,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
|||||||
private int mColorDialogBackground;
|
private int mColorDialogBackground;
|
||||||
private float mInactiveRadius;
|
private float mInactiveRadius;
|
||||||
private float mActiveRadius;
|
private float mActiveRadius;
|
||||||
|
private FeatureFlags mFeatureFlags;
|
||||||
|
|
||||||
public enum BroadcastNotifyDialog {
|
public enum BroadcastNotifyDialog {
|
||||||
ACTION_FIRST_LAUNCH,
|
ACTION_FIRST_LAUNCH,
|
||||||
@@ -162,7 +165,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
|||||||
Optional<NearbyMediaDevicesManager> nearbyMediaDevicesManagerOptional,
|
Optional<NearbyMediaDevicesManager> nearbyMediaDevicesManagerOptional,
|
||||||
AudioManager audioManager,
|
AudioManager audioManager,
|
||||||
PowerExemptionManager powerExemptionManager,
|
PowerExemptionManager powerExemptionManager,
|
||||||
KeyguardManager keyGuardManager) {
|
KeyguardManager keyGuardManager,
|
||||||
|
FeatureFlags featureFlags) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mPackageName = packageName;
|
mPackageName = packageName;
|
||||||
mMediaSessionManager = mediaSessionManager;
|
mMediaSessionManager = mediaSessionManager;
|
||||||
@@ -172,6 +176,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
|||||||
mAudioManager = audioManager;
|
mAudioManager = audioManager;
|
||||||
mPowerExemptionManager = powerExemptionManager;
|
mPowerExemptionManager = powerExemptionManager;
|
||||||
mKeyGuardManager = keyGuardManager;
|
mKeyGuardManager = keyGuardManager;
|
||||||
|
mFeatureFlags = featureFlags;
|
||||||
InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm);
|
InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm);
|
||||||
mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
|
mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
|
||||||
mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
|
mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
|
||||||
@@ -599,6 +604,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
|||||||
currentConnectedMediaDevice);
|
currentConnectedMediaDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAdvancedLayoutSupported() {
|
||||||
|
return mFeatureFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT);
|
||||||
|
}
|
||||||
|
|
||||||
List<MediaDevice> getGroupMediaDevices() {
|
List<MediaDevice> getGroupMediaDevices() {
|
||||||
final List<MediaDevice> selectedDevices = getSelectedMediaDevice();
|
final List<MediaDevice> selectedDevices = getSelectedMediaDevice();
|
||||||
final List<MediaDevice> selectableDevices = getSelectableMediaDevice();
|
final List<MediaDevice> selectableDevices = getSelectableMediaDevice();
|
||||||
@@ -792,7 +801,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
|
|||||||
MediaOutputController controller = new MediaOutputController(mContext, mPackageName,
|
MediaOutputController controller = new MediaOutputController(mContext, mPackageName,
|
||||||
mMediaSessionManager, mLocalBluetoothManager, mActivityStarter,
|
mMediaSessionManager, mLocalBluetoothManager, mActivityStarter,
|
||||||
mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager),
|
mNotifCollection, mDialogLaunchAnimator, Optional.of(mNearbyMediaDevicesManager),
|
||||||
mAudioManager, mPowerExemptionManager, mKeyGuardManager);
|
mAudioManager, mPowerExemptionManager, mKeyGuardManager, mFeatureFlags);
|
||||||
MediaOutputBroadcastDialog dialog = new MediaOutputBroadcastDialog(mContext, true,
|
MediaOutputBroadcastDialog dialog = new MediaOutputBroadcastDialog(mContext, true,
|
||||||
broadcastSender, controller);
|
broadcastSender, controller);
|
||||||
mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog);
|
mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import com.android.systemui.broadcast.BroadcastSender
|
|||||||
import com.android.systemui.media.nearby.NearbyMediaDevicesManager
|
import com.android.systemui.media.nearby.NearbyMediaDevicesManager
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
||||||
|
import com.android.systemui.flags.FeatureFlags
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -49,7 +50,8 @@ class MediaOutputDialogFactory @Inject constructor(
|
|||||||
private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>,
|
private val nearbyMediaDevicesManagerOptional: Optional<NearbyMediaDevicesManager>,
|
||||||
private val audioManager: AudioManager,
|
private val audioManager: AudioManager,
|
||||||
private val powerExemptionManager: PowerExemptionManager,
|
private val powerExemptionManager: PowerExemptionManager,
|
||||||
private val keyGuardManager: KeyguardManager
|
private val keyGuardManager: KeyguardManager,
|
||||||
|
private val featureFlags: FeatureFlags
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val INTERACTION_JANK_TAG = "media_output"
|
private const val INTERACTION_JANK_TAG = "media_output"
|
||||||
@@ -65,7 +67,7 @@ class MediaOutputDialogFactory @Inject constructor(
|
|||||||
context, packageName,
|
context, packageName,
|
||||||
mediaSessionManager, lbm, starter, notifCollection,
|
mediaSessionManager, lbm, starter, notifCollection,
|
||||||
dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager,
|
dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager,
|
||||||
powerExemptionManager, keyGuardManager)
|
powerExemptionManager, keyGuardManager, featureFlags)
|
||||||
val dialog =
|
val dialog =
|
||||||
MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller, uiEventLogger)
|
MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller, uiEventLogger)
|
||||||
mediaOutputDialog = dialog
|
mediaOutputDialog = dialog
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import android.widget.SeekBar;
|
|||||||
*/
|
*/
|
||||||
public class MediaOutputSeekbar extends SeekBar {
|
public class MediaOutputSeekbar extends SeekBar {
|
||||||
private static final int SCALE_SIZE = 1000;
|
private static final int SCALE_SIZE = 1000;
|
||||||
|
public static final int VOLUME_PERCENTAGE_SCALE_SIZE = 100000;
|
||||||
|
|
||||||
public MediaOutputSeekbar(Context context, AttributeSet attrs) {
|
public MediaOutputSeekbar(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import com.android.systemui.R;
|
|||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.animation.DialogLaunchAnimator;
|
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||||
import com.android.systemui.broadcast.BroadcastSender;
|
import com.android.systemui.broadcast.BroadcastSender;
|
||||||
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
|
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
|
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
|
||||||
@@ -89,6 +90,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
|
|||||||
private final AudioManager mAudioManager = mock(AudioManager.class);
|
private final AudioManager mAudioManager = mock(AudioManager.class);
|
||||||
private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class);
|
private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class);
|
||||||
private KeyguardManager mKeyguardManager = mock(KeyguardManager.class);
|
private KeyguardManager mKeyguardManager = mock(KeyguardManager.class);
|
||||||
|
private FeatureFlags mFlags = mock(FeatureFlags.class);
|
||||||
|
|
||||||
private List<MediaController> mMediaControllers = new ArrayList<>();
|
private List<MediaController> mMediaControllers = new ArrayList<>();
|
||||||
private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl;
|
private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl;
|
||||||
@@ -121,7 +123,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
|
|||||||
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
||||||
mNotifCollection, mDialogLaunchAnimator,
|
mNotifCollection, mDialogLaunchAnimator,
|
||||||
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
||||||
mKeyguardManager);
|
mKeyguardManager, mFlags);
|
||||||
mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender,
|
mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext, mBroadcastSender,
|
||||||
mMediaOutputController);
|
mMediaOutputController);
|
||||||
mMediaOutputBaseDialogImpl.onCreate(new Bundle());
|
mMediaOutputBaseDialogImpl.onCreate(new Bundle());
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ import com.android.systemui.R;
|
|||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.animation.ActivityLaunchAnimator;
|
import com.android.systemui.animation.ActivityLaunchAnimator;
|
||||||
import com.android.systemui.animation.DialogLaunchAnimator;
|
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||||
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
|
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
@@ -110,6 +111,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
|||||||
private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class);
|
private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class);
|
||||||
private CommonNotifCollection mNotifCollection = mock(CommonNotifCollection.class);
|
private CommonNotifCollection mNotifCollection = mock(CommonNotifCollection.class);
|
||||||
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
|
private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
|
||||||
|
private FeatureFlags mFlags = mock(FeatureFlags.class);
|
||||||
private final ActivityLaunchAnimator.Controller mActivityLaunchAnimatorController = mock(
|
private final ActivityLaunchAnimator.Controller mActivityLaunchAnimatorController = mock(
|
||||||
ActivityLaunchAnimator.Controller.class);
|
ActivityLaunchAnimator.Controller.class);
|
||||||
private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
|
private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
|
||||||
@@ -141,7 +143,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
|||||||
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
||||||
mNotifCollection, mDialogLaunchAnimator,
|
mNotifCollection, mDialogLaunchAnimator,
|
||||||
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
||||||
mKeyguardManager);
|
mKeyguardManager, mFlags);
|
||||||
mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
|
mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
|
||||||
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
|
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
|
||||||
MediaDescription.Builder builder = new MediaDescription.Builder();
|
MediaDescription.Builder builder = new MediaDescription.Builder();
|
||||||
@@ -194,7 +196,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
|||||||
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
||||||
mNotifCollection, mDialogLaunchAnimator,
|
mNotifCollection, mDialogLaunchAnimator,
|
||||||
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
||||||
mKeyguardManager);
|
mKeyguardManager, mFlags);
|
||||||
|
|
||||||
mMediaOutputController.start(mCb);
|
mMediaOutputController.start(mCb);
|
||||||
|
|
||||||
@@ -224,7 +226,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
|||||||
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
||||||
mNotifCollection, mDialogLaunchAnimator,
|
mNotifCollection, mDialogLaunchAnimator,
|
||||||
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
||||||
mKeyguardManager);
|
mKeyguardManager, mFlags);
|
||||||
|
|
||||||
mMediaOutputController.start(mCb);
|
mMediaOutputController.start(mCb);
|
||||||
|
|
||||||
@@ -318,7 +320,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
|||||||
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
||||||
mNotifCollection, mDialogLaunchAnimator,
|
mNotifCollection, mDialogLaunchAnimator,
|
||||||
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
||||||
mKeyguardManager);
|
mKeyguardManager, mFlags);
|
||||||
testMediaOutputController.start(mCb);
|
testMediaOutputController.start(mCb);
|
||||||
reset(mCb);
|
reset(mCb);
|
||||||
|
|
||||||
@@ -341,7 +343,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
|||||||
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
||||||
mNotifCollection, mDialogLaunchAnimator,
|
mNotifCollection, mDialogLaunchAnimator,
|
||||||
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
||||||
mKeyguardManager);
|
mKeyguardManager, mFlags);
|
||||||
testMediaOutputController.start(mCb);
|
testMediaOutputController.start(mCb);
|
||||||
reset(mCb);
|
reset(mCb);
|
||||||
|
|
||||||
@@ -377,7 +379,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
|||||||
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
||||||
mNotifCollection, mDialogLaunchAnimator,
|
mNotifCollection, mDialogLaunchAnimator,
|
||||||
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
||||||
mKeyguardManager);
|
mKeyguardManager, mFlags);
|
||||||
|
|
||||||
LocalMediaManager testLocalMediaManager = spy(testMediaOutputController.mLocalMediaManager);
|
LocalMediaManager testLocalMediaManager = spy(testMediaOutputController.mLocalMediaManager);
|
||||||
testMediaOutputController.mLocalMediaManager = testLocalMediaManager;
|
testMediaOutputController.mLocalMediaManager = testLocalMediaManager;
|
||||||
@@ -394,7 +396,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
|||||||
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
||||||
mNotifCollection, mDialogLaunchAnimator,
|
mNotifCollection, mDialogLaunchAnimator,
|
||||||
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
||||||
mKeyguardManager);
|
mKeyguardManager, mFlags);
|
||||||
|
|
||||||
LocalMediaManager testLocalMediaManager = spy(testMediaOutputController.mLocalMediaManager);
|
LocalMediaManager testLocalMediaManager = spy(testMediaOutputController.mLocalMediaManager);
|
||||||
testMediaOutputController.mLocalMediaManager = testLocalMediaManager;
|
testMediaOutputController.mLocalMediaManager = testLocalMediaManager;
|
||||||
@@ -671,7 +673,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
|
|||||||
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
||||||
mNotifCollection, mDialogLaunchAnimator,
|
mNotifCollection, mDialogLaunchAnimator,
|
||||||
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
||||||
mKeyguardManager);
|
mKeyguardManager, mFlags);
|
||||||
|
|
||||||
assertThat(mMediaOutputController.getNotificationIcon()).isNull();
|
assertThat(mMediaOutputController.getNotificationIcon()).isNull();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import com.android.systemui.R;
|
|||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.animation.DialogLaunchAnimator;
|
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||||
import com.android.systemui.broadcast.BroadcastSender;
|
import com.android.systemui.broadcast.BroadcastSender;
|
||||||
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
|
import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
|
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
|
||||||
@@ -93,6 +94,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
|
|||||||
private final AudioManager mAudioManager = mock(AudioManager.class);
|
private final AudioManager mAudioManager = mock(AudioManager.class);
|
||||||
private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class);
|
private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class);
|
||||||
private KeyguardManager mKeyguardManager = mock(KeyguardManager.class);
|
private KeyguardManager mKeyguardManager = mock(KeyguardManager.class);
|
||||||
|
private FeatureFlags mFlags = mock(FeatureFlags.class);
|
||||||
|
|
||||||
private List<MediaController> mMediaControllers = new ArrayList<>();
|
private List<MediaController> mMediaControllers = new ArrayList<>();
|
||||||
private MediaOutputDialog mMediaOutputDialog;
|
private MediaOutputDialog mMediaOutputDialog;
|
||||||
@@ -115,7 +117,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
|
|||||||
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
mMediaSessionManager, mLocalBluetoothManager, mStarter,
|
||||||
mNotifCollection, mDialogLaunchAnimator,
|
mNotifCollection, mDialogLaunchAnimator,
|
||||||
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
|
||||||
mKeyguardManager);
|
mKeyguardManager, mFlags);
|
||||||
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
|
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
|
||||||
mMediaOutputDialog = new MediaOutputDialog(mContext, false, mBroadcastSender,
|
mMediaOutputDialog = new MediaOutputDialog(mContext, false, mBroadcastSender,
|
||||||
mMediaOutputController, mUiEventLogger);
|
mMediaOutputController, mUiEventLogger);
|
||||||
|
|||||||
Reference in New Issue
Block a user