diff options
| author | spkal01 <kalligeross@gmail.com> | 2021-06-13 17:48:12 +0530 |
|---|---|---|
| committer | Semavi Ulusoy <doc.divxm@gmail.com> | 2021-09-08 09:30:27 +0300 |
| commit | 9874e2a3b4b4e93871f1521522dc02e96e995082 (patch) | |
| tree | ea3570578422589eab5ab805c628fa3b2e6d5efc | |
| parent | f632843222317ddcc0029c4ba8f1c72928dc88e8 (diff) | |
Plugins: Add per app volume to plugins
Signed-off-by: Stallix <joey@evolution-x.org>
14 files changed, 515 insertions, 16 deletions
diff --git a/AospPanel/res/layout/volume_dialog_aosp_row.xml b/AospPanel/res/layout/volume_dialog_aosp_row.xml index e5511ef..5cc1c1a 100644 --- a/AospPanel/res/layout/volume_dialog_aosp_row.xml +++ b/AospPanel/res/layout/volume_dialog_aosp_row.xml @@ -59,12 +59,25 @@ <com.android.plugin.volume.common.AlphaOptimizedImageButton android:id="@+id/volume_row_icon" style="@style/VolumeButtons" + android:visibility="gone" android:layout_width="@dimen/volume_dialog_tap_target_size" android:layout_height="@dimen/volume_dialog_tap_target_size" android:background="@drawable/ripple_drawable_20dp" android:layout_marginBottom="@dimen/volume_dialog_row_margin_bottom" android:tint="?android:attr/colorAccent" android:soundEffectsEnabled="false" /> + + <co.potatoproject.plugin.volume.common.AlphaOptimizedImageButton + android:id="@+id/volume_row_app_icon" + style="@style/VolumeButtons" + android:visibility="gone" + android:layout_width="@dimen/volume_dialog_tap_target_app_size" + android:layout_height="@dimen/volume_dialog_tap_target_app_size" + android:background="@drawable/ripple_drawable_20dp" + android:layout_marginBottom="@dimen/volume_dialog_row_margin_bottom" + android:padding="@dimen/volume_row_app_icon_padding" + android:soundEffectsEnabled="false" + android:scaleType="centerInside" /> </LinearLayout> <include layout="@layout/volume_dnd_icon"/> diff --git a/AospPanel/res/values/dimens.xml b/AospPanel/res/values/dimens.xml new file mode 100644 index 0000000..7b5c5de --- /dev/null +++ b/AospPanel/res/values/dimens.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2020 The Potato Open Sauce 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. +--> +<resources> + <dimen name="volume_dialog_row_margin_bottom">8dp</dimen> + <dimen name="volume_row_app_icon_padding">8dp</dimen> + <dimen name="volume_dialog_tap_target_app_size">43dp</dimen> +</resources> diff --git a/AospPanel/src/com/android/plugin/volume/aosp/VolumeDialogImpl.java b/AospPanel/src/com/android/plugin/volume/aosp/VolumeDialogImpl.java index 7a875dd..4df89a5 100644 --- a/AospPanel/src/com/android/plugin/volume/aosp/VolumeDialogImpl.java +++ b/AospPanel/src/com/android/plugin/volume/aosp/VolumeDialogImpl.java @@ -18,6 +18,9 @@ package com.android.plugin.volume.aosp; +import android.media.AppTrackData; +import android.database.ContentObserver; +import android.os.UserHandle; import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; import static android.media.AudioManager.RINGER_MODE_NORMAL; import static android.media.AudioManager.RINGER_MODE_SILENT; @@ -61,6 +64,7 @@ import android.graphics.drawable.Drawable; import android.graphics.PorterDuff; import android.media.AudioManager; import android.media.AudioSystem; +import android.media.AppTrackData; import android.os.Debug; import android.os.Handler; import android.os.Looper; @@ -169,7 +173,7 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { private AccessibilityManager mAccessibilityMgr; private final Object mSafetyWarningLock = new Object(); private final Accessibility mAccessibility = new Accessibility(); - + private final List<VolumeRow> mAppRows = new ArrayList<>(); private boolean mShowing; private boolean mShowA11yStream; @@ -187,7 +191,9 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { private ViewStub mODICaptionsTooltipViewStub; private View mODICaptionsTooltipView = null; + private SettingsObserver settingsObserver; private boolean mExpanded; + private boolean mAppVolume; public VolumeDialogImpl() {} @@ -204,6 +210,8 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { mShowActiveStreamOnly = showActiveStreamOnly(); mHasSeenODICaptionsTooltip = true; initObserver(pluginContext, sysuiContext); + settingsObserver = new SettingsObserver(mHandler); + settingsObserver.observe(); } public void init(int windowType, Callback callback) { @@ -224,6 +232,7 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { public void destroy() { mController.removeCallback(mControllerCallbackH); mHandler.removeCallbacksAndMessages(null); + settingsObserver.unobserve(); } private void initDialog() { @@ -376,6 +385,33 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { initODICaptionsH(); } + private class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + void unobserve() { + mContext.getContentResolver().unregisterContentObserver(this); + } + + void observe() { + mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor(Settings.System.SHOW_APP_VOLUME), false, this, UserHandle.USER_ALL); + update(); + } + + + @Override + public void onChange(boolean selfChange) { + update(); + initDialog(); + } + + + public void update() { + mAppVolume = Settings.System.getIntForUser(mContext.getContentResolver(), Settings.System.SHOW_APP_VOLUME, 0, UserHandle.USER_CURRENT) == 1; + } + + } private final OnComputeInternalInsetsListener mInsetsListener = internalInsetsInfo -> { internalInsetsInfo.touchableRegion.setEmpty(); internalInsetsInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION); @@ -442,6 +478,41 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { mRows.add(row); } + private void addAppRow(AppTrackData data) { + VolumeRow row = new VolumeRow(); + initAppRow(row, data); + mDialogRowsView.addView(row.view); + mAppRows.add(row); + } + + @SuppressLint("InflateParams") + private void initAppRow(final VolumeRow row, final AppTrackData data) { + row.view = LayoutInflater.from(mContext).inflate(R.layout.volume_dialog_aosp_row, null); + + row.packageName = data.getPackageName(); + row.isAppVolumeRow = true; + + row.view.setTag(row); + row.slider = row.view.findViewById(R.id.volume_row_slider); + row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row)); + + row.appMuted = data.isMuted(); + row.slider.setProgress((int) (data.getVolume() * 100)); + + row.dndIcon = row.view.findViewById(R.id.dnd_icon); + row.dndIcon.setVisibility(View.GONE); + + row.icon = row.view.findViewById(R.id.volume_row_app_icon); + row.icon.setVisibility(View.VISIBLE); + PackageManager pm = mContext.getPackageManager(); + try { + row.icon.setImageDrawable(pm.getApplicationIcon(row.packageName)); + } catch (PackageManager.NameNotFoundException e) { + row.icon.setImageDrawable(pm.getDefaultActivityIcon()); + Log.e(TAG, "Failed to get icon of " + row.packageName, e); + } + } + private void addExistingRows() { int N = mRows.size(); for (int i = 0; i < N; i++) { @@ -539,6 +610,7 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { row.icon = row.view.findViewById(R.id.volume_row_icon); Drawable iconResDrawable = mSysUIContext.getDrawable(iconRes); + row.icon.setVisibility(View.VISIBLE); row.icon.setImageDrawable(iconResDrawable); if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) { row.icon.setOnClickListener(v -> { @@ -627,10 +699,30 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { mExpanded = false; updateOutputSwitcherVisibility(); } + if (mAppVolume) { + updateAppRows(); + } mExpandRows.setExpanded(mExpanded); }); } } + private void updateAppRows() { + for (int i = mAppRows.size() - 1; i >= 0; i--) { + final VolumeRow row = mAppRows.get(i); + removeAppRow(row); + } + List<AppTrackData> trackDatas = mController.getAudioManager().listAppTrackDatas(); + for (AppTrackData data : trackDatas) { + if (data.isActive()) { + addAppRow(data); + } + } + } + + private void removeAppRow(VolumeRow volumeRow) { + mAppRows.remove(volumeRow); + mDialogRowsView.removeView(volumeRow.view); + } public void initRingerH() { if (mRingerIcon != null) { @@ -1579,9 +1671,13 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { rescheduleTimeoutH(); - if (mRow.ss == null) return; if (D.BUG) Log.d(TAG, AudioSystem.streamToString(mRow.stream) + " onProgressChanged " + progress + " fromUser=" + fromUser); + if (mRow.isAppVolumeRow) { + mController.getAudioManager().setAppVolume(mRow.packageName, progress * 0.01f); + return; + } + if (mRow.ss == null) return; if (!fromUser) return; if (mRow.ss.levelMin > 0) { final int minProgress = mRow.ss.levelMin * 100; @@ -1605,15 +1701,17 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { @Override public void onStartTrackingTouch(SeekBar seekBar) { + mRow.tracking = true; + if (mRow.isAppVolumeRow) return; if (D.BUG) Log.d(TAG, "onStartTrackingTouch"+ " " + mRow.stream); mController.setActiveStream(mRow.stream); - mRow.tracking = true; } @Override public void onStopTrackingTouch(SeekBar seekBar) { if (D.BUG) Log.d(TAG, "onStopTrackingTouch"+ " " + mRow.stream); mRow.tracking = false; + if (mRow.isAppVolumeRow) return; mRow.userAttempt = SystemClock.uptimeMillis(); final int userLevel = getImpliedLevel(seekBar, seekBar.getProgress()); Events.writeEvent(Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel); @@ -1668,5 +1766,9 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { private int animTargetProgress; private int lastAudibleLevel = 2; private FrameLayout dndIcon; + /* for change app's volume */ + private String packageName; + private boolean isAppVolumeRow = false; + private boolean appMuted; } } diff --git a/CompactPanel/res/layout/volume_dialog_compact_row.xml b/CompactPanel/res/layout/volume_dialog_compact_row.xml index 4832c9b..cd9f88f 100644 --- a/CompactPanel/res/layout/volume_dialog_compact_row.xml +++ b/CompactPanel/res/layout/volume_dialog_compact_row.xml @@ -41,6 +41,17 @@ android:visibility="gone" android:soundEffectsEnabled="false" /> + <co.potatoproject.plugin.volume.common.AlphaOptimizedImageButton + android:id="@+id/volume_row_app_icon" + style="@style/VolumeButtons" + android:visibility="gone" + android:layout_width="@dimen/volume_dialog_tap_target_app_size" + android:layout_height="@dimen/volume_dialog_tap_target_app_size" + android:background="@drawable/ripple_drawable_20dp" + android:layout_marginTop="@dimen/volume_dialog_row_margin_bottom" + android:soundEffectsEnabled="false" + android:scaleType="centerInside" /> + <TextView android:id="@+id/volume_row_header" android:layout_width="wrap_content" @@ -51,6 +62,7 @@ android:visibility="gone" android:textColor="?android:attr/colorControlNormal" android:textAppearance="@style/TextAppearance.Volume.Header" /> + <FrameLayout android:id="@+id/volume_row_slider_frame" android:layout_width="@dimen/volume_dialog_panel_mini_width" diff --git a/CompactPanel/res/values/dimens.xml b/CompactPanel/res/values/dimens.xml index 1363dea..01d7a38 100644 --- a/CompactPanel/res/values/dimens.xml +++ b/CompactPanel/res/values/dimens.xml @@ -25,4 +25,8 @@ <dimen name="volume_dialog_row_width">48dp</dimen> <dimen name="volume_dialog_row_side_padding">8dp</dimen> + + <dimen name="volume_row_app_icon_padding">8dp</dimen> + <dimen name="volume_dialog_row_margin_bottom">8dp</dimen> + <dimen name="volume_dialog_tap_target_app_size">36dp</dimen> </resources> diff --git a/CompactPanel/src/com/android/plugin/volume/compact/VolumeDialogImpl.java b/CompactPanel/src/com/android/plugin/volume/compact/VolumeDialogImpl.java index 578db2a..fb25762 100644 --- a/CompactPanel/src/com/android/plugin/volume/compact/VolumeDialogImpl.java +++ b/CompactPanel/src/com/android/plugin/volume/compact/VolumeDialogImpl.java @@ -35,6 +35,8 @@ import static android.view.View.VISIBLE; import static com.android.plugin.volume.common.Events.DISMISS_REASON_SETTINGS_CLICKED; +import android.database.ContentObserver; +import android.os.UserHandle; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.app.ActivityManager; @@ -60,6 +62,7 @@ import android.graphics.drawable.Drawable; import android.graphics.PorterDuff; import android.media.AudioManager; import android.media.AudioSystem; +import android.media.AppTrackData; import android.os.Debug; import android.os.Handler; import android.os.Looper; @@ -164,6 +167,7 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { private ExpandableIndicator mExpandRows; private FrameLayout mZenIcon; private final List<VolumeRow> mRows = new ArrayList<>(); + private final List<VolumeRow> mAppRows = new ArrayList<>(); private ConfigurableTexts mConfigurableTexts; private final SparseBooleanArray mDynamic = new SparseBooleanArray(); private KeyguardManager mKeyguard; @@ -192,6 +196,9 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { private PanelMode mPanelMode = PanelMode.MINI; + + private SettingsObserver settingsObserver; + private boolean mAppVolume; public VolumeDialogImpl() {} @Override @@ -207,6 +214,8 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { mShowActiveStreamOnly = showActiveStreamOnly(); mHasSeenODICaptionsTooltip = true; initObserver(pluginContext, sysuiContext); + settingsObserver = new SettingsObserver(mHandler); + settingsObserver.observe(); } @Override @@ -224,6 +233,7 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { public void destroy() { mController.removeCallback(mControllerCallbackH); mHandler.removeCallbacksAndMessages(null); + settingsObserver.unobserve(); } @Override @@ -373,6 +383,32 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { initODICaptionsH(); } + private class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + void unobserve() { + mContext.getContentResolver().unregisterContentObserver(this); + } + + void observe() { + mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor(Settings.System.SHOW_APP_VOLUME), false, this, UserHandle.USER_ALL); + update(); + } + + @Override + public void onChange(boolean selfChange) { + update(); + initDialog(); + } + + public void update() { + mAppVolume = Settings.System.getIntForUser(mContext.getContentResolver(), Settings.System.SHOW_APP_VOLUME, 0, UserHandle.USER_CURRENT) == 1; + // updateRowsH(getActiveRow()); + } + } + private final OnComputeInternalInsetsListener mInsetsListener = internalInsetsInfo -> { internalInsetsInfo.touchableRegion.setEmpty(); internalInsetsInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION); @@ -439,6 +475,41 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { mRows.add(0, row); } + private void addAppRow(AppTrackData data) { + VolumeRow row = new VolumeRow(); + initAppRow(row, data); + mDialogRowsView.addView(row.view); + mAppRows.add(row); + } + + @SuppressLint("InflateParams") + private void initAppRow(final VolumeRow row, final AppTrackData data) { + row.view = LayoutInflater.from(mContext).inflate(R.layout.volume_dialog_compact_row, null); + + row.packageName = data.getPackageName(); + row.isAppVolumeRow = true; + + row.view.setTag(row); + row.slider = row.view.findViewById(R.id.volume_row_slider); + row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row)); + + row.appMuted = data.isMuted(); + row.slider.setProgress((int) (data.getVolume() * 100)); + + row.dndIcon = row.view.findViewById(R.id.dnd_icon); + row.dndIcon.setVisibility(View.GONE); + + row.icon = row.view.findViewById(R.id.volume_row_app_icon); + row.icon.setVisibility(View.VISIBLE); + PackageManager pm = mContext.getPackageManager(); + try { + row.icon.setImageDrawable(pm.getApplicationIcon(row.packageName)); + } catch (PackageManager.NameNotFoundException e) { + row.icon.setImageDrawable(pm.getDefaultActivityIcon()); + Log.e(TAG, "Failed to get icon of " + row.packageName, e); + } + } + private void addExistingRows() { int N = mRows.size(); for (int i = 0; i < N; i++) { @@ -537,6 +608,7 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { row.icon = row.view.findViewById(R.id.volume_row_icon); Drawable iconResDrawable = mSysUIContext.getDrawable(iconRes); row.icon.setImageDrawable(iconResDrawable); + row.icon.setVisibility(View.VISIBLE); if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) { row.icon.setOnClickListener(v -> { Events.writeEvent(Events.EVENT_ICON_CLICK, row.stream, row.iconState); @@ -617,6 +689,9 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { mPanelMode = PanelMode.COLLAPSED; updatePanelOnMode(); } + if (mAppVolume) { + updateAppRows(); + } mExpandRows.setExpanded(mPanelMode == PanelMode.EXPANDED); }); } @@ -638,6 +713,24 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { } } + private void removeAppRow(VolumeRow volumeRow) { + mAppRows.remove(volumeRow); + mDialogRowsView.removeView(volumeRow.view); + } + + private void updateAppRows() { + for (int i = mAppRows.size() - 1; i >= 0; i--) { + final VolumeRow row = mAppRows.get(i); + removeAppRow(row); + } + List<AppTrackData> trackDatas = mController.getAudioManager().listAppTrackDatas(); + for (AppTrackData data : trackDatas) { + if (data.isActive()) { + addAppRow(data); + } + } + } + public void initRingerH() { if (mRingerIcon != null) { mRingerIcon.setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE); @@ -1641,10 +1734,14 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (mRow.ss == null) return; if (D.BUG) Log.d(TAG, AudioSystem.streamToString(mRow.stream) + " onProgressChanged " + progress + " fromUser=" + fromUser); rescheduleTimeoutH(); + if (mRow.isAppVolumeRow) { + mController.getAudioManager().setAppVolume(mRow.packageName, progress * 0.01f); + return; + } + if (mRow.ss == null) return; if (!fromUser) return; if (mRow.ss.levelMin > 0) { final int minProgress = mRow.ss.levelMin * 100; @@ -1668,9 +1765,10 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { @Override public void onStartTrackingTouch(SeekBar seekBar) { + mRow.tracking = true; + if (mRow.isAppVolumeRow) return; if (D.BUG) Log.d(TAG, "onStartTrackingTouch"+ " " + mRow.stream); mController.setActiveStream(mRow.stream); - mRow.tracking = true; if(mPanelMode == PanelMode.MINI) { mPanelMode = PanelMode.COLLAPSED; updatePanelOnMode(); @@ -1681,6 +1779,7 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { public void onStopTrackingTouch(SeekBar seekBar) { if (D.BUG) Log.d(TAG, "onStopTrackingTouch"+ " " + mRow.stream); mRow.tracking = false; + if (mRow.isAppVolumeRow) return; mRow.userAttempt = SystemClock.uptimeMillis(); final int userLevel = getImpliedLevel(seekBar, seekBar.getProgress()); Events.writeEvent(Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel); @@ -1735,6 +1834,10 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { private int animTargetProgress; private int lastAudibleLevel = 2; private FrameLayout dndIcon; + /* for change app's volume */ + private String packageName; + private boolean isAppVolumeRow = false; + private boolean appMuted; } private enum PanelMode { diff --git a/MiuiCompactPanel/res/layout/volume_dialog_miui_row.xml b/MiuiCompactPanel/res/layout/volume_dialog_miui_row.xml index fc00a3d..fdfb1e9 100644 --- a/MiuiCompactPanel/res/layout/volume_dialog_miui_row.xml +++ b/MiuiCompactPanel/res/layout/volume_dialog_miui_row.xml @@ -63,6 +63,7 @@ <co.potatoproject.plugin.volume.common.AlphaOptimizedImageButton android:id="@+id/volume_row_icon" style="@style/VolumeButtons" + android:visibility="gone" android:layout_width="@dimen/volume_dialog_miui_tap_target_size" android:layout_height="@dimen/volume_dialog_miui_tap_target_size" android:background="@drawable/ripple_drawable_20dp" @@ -70,6 +71,17 @@ android:tint="@android:color/white" android:clickable="false" android:soundEffectsEnabled="false" /> + + <co.potatoproject.plugin.volume.common.AlphaOptimizedImageButton + android:id="@+id/volume_row_app_icon" + style="@style/VolumeButtons" + android:visibility="gone" + android:layout_width="@dimen/volume_dialog_miui_tap_target_size" + android:layout_height="@dimen/volume_dialog_miui_tap_target_size" + android:background="@drawable/ripple_drawable_20dp" + android:layout_marginTop="@dimen/volume_dialog_miui_row_icon_margintop" + android:soundEffectsEnabled="false" + android:scaleType="centerInside" /> </LinearLayout> <include layout="@layout/volume_dnd_icon_miui"/> diff --git a/MiuiCompactPanel/res/values/dimens.xml b/MiuiCompactPanel/res/values/dimens.xml index 68c2bca..5bf5e24 100644 --- a/MiuiCompactPanel/res/values/dimens.xml +++ b/MiuiCompactPanel/res/values/dimens.xml @@ -40,7 +40,5 @@ <dimen name="volume_row_slider_padding_start">12dp</dimen> <dimen name="volume_tool_tip_bottom_margin">32dp</dimen> <dimen name="volume_tool_tip_right_margin">76dp</dimen> - <dimen name="volume_row_app_icon_padding">1dp</dimen> - <dimen name="volume_dialog_tap_target_app_size">38dip</dimen> - <dimen name="volume_dialog_app_row_icon_margintop">-50dp</dimen> + <dimen name="volume_row_app_icon_padding">8dp</dimen> </resources> diff --git a/MiuiCompactPanel/src/co/potatoproject/plugin/volume/miui/VolumeDialogImpl.java b/MiuiCompactPanel/src/co/potatoproject/plugin/volume/miui/VolumeDialogImpl.java index 2c33b1b..807e458 100644 --- a/MiuiCompactPanel/src/co/potatoproject/plugin/volume/miui/VolumeDialogImpl.java +++ b/MiuiCompactPanel/src/co/potatoproject/plugin/volume/miui/VolumeDialogImpl.java @@ -17,6 +17,10 @@ package co.potatoproject.plugin.volume.miui; + +import android.media.AppTrackData; +import android.database.ContentObserver; +import android.os.UserHandle; import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; import static android.media.AudioManager.RINGER_MODE_NORMAL; import static android.media.AudioManager.RINGER_MODE_SILENT; @@ -191,7 +195,10 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { private ViewStub mODICaptionsTooltipViewStub; private View mODICaptionsTooltipView = null; + private SettingsObserver settingsObserver; private boolean mExpanded; + private final List<VolumeRow> mAppRows = new ArrayList<>(); + private boolean mAppVolume; private View[] views; private Drawable[] defaultDrawables; @@ -212,6 +219,8 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { mShowActiveStreamOnly = showActiveStreamOnly(); mHasSeenODICaptionsTooltip = true; initObserver(pluginContext, sysuiContext); + settingsObserver = new SettingsObserver(mHandler); + settingsObserver.observe(); } public void init(int windowType, Callback callback) { @@ -232,6 +241,7 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { public void destroy() { mController.removeCallback(mControllerCallbackH); mHandler.removeCallbacksAndMessages(null); + settingsObserver.unobserve(); } private void initDialog() { @@ -369,6 +379,35 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { initODICaptionsH(); } + + private class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + void unobserve() { + mContext.getContentResolver().unregisterContentObserver(this); + } + + void observe() { + mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor(Settings.System.SHOW_APP_VOLUME), false, this, UserHandle.USER_ALL); + update(); + } + + + @Override + public void onChange(boolean selfChange) { + update(); + initDialog(); + } + + + public void update() { + mAppVolume = Settings.System.getIntForUser(mContext.getContentResolver(), Settings.System.SHOW_APP_VOLUME, 0, UserHandle.USER_CURRENT) == 1; + + } + } + private final OnComputeInternalInsetsListener mInsetsListener = internalInsetsInfo -> { internalInsetsInfo.touchableRegion.setEmpty(); internalInsetsInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION); @@ -435,6 +474,41 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { mRows.add(row); } + private void addAppRow(AppTrackData data) { + VolumeRow row = new VolumeRow(); + initAppRow(row, data); + mDialogRowsView.addView(row.view); + mAppRows.add(row); + } + + @SuppressLint("InflateParams") + private void initAppRow(final VolumeRow row, final AppTrackData data) { + row.view = LayoutInflater.from(mContext).inflate(R.layout.volume_dialog_miui_row, null); + + row.packageName = data.getPackageName(); + row.isAppVolumeRow = true; + + row.view.setTag(row); + row.slider = row.view.findViewById(R.id.volume_row_slider); + row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row)); + + row.appMuted = data.isMuted(); + row.slider.setProgress((int) (data.getVolume() * 100)); + + row.dndIcon = row.view.findViewById(R.id.dnd_icon); + row.dndIcon.setVisibility(View.GONE); + + row.icon = row.view.findViewById(R.id.volume_row_app_icon); + row.icon.setVisibility(View.VISIBLE); + PackageManager pm = mContext.getPackageManager(); + try { + row.icon.setImageDrawable(pm.getApplicationIcon(row.packageName)); + } catch (PackageManager.NameNotFoundException e) { + row.icon.setImageDrawable(pm.getDefaultActivityIcon()); + Log.e(TAG, "Failed to get icon of " + row.packageName, e); + } + } + private void addExistingRows() { int N = mRows.size(); for (int i = 0; i < N; i++) { @@ -530,6 +604,7 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { row.icon = row.view.findViewById(R.id.volume_row_icon); Drawable iconResDrawable = mSysUIContext.getDrawable(iconRes); + row.icon.setVisibility(View.VISIBLE); row.icon.setImageDrawable(iconResDrawable); row.icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); row.icon.setClickable(false); @@ -613,11 +688,32 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { mExpanded = false; updateOutputSwitcherVisibility(); } + if (mAppVolume) { + updateAppRows(); + } mExpandRows.setExpanded(mExpanded); }); } } + private void updateAppRows() { + for (int i = mAppRows.size() - 1; i >= 0; i--) { + final VolumeRow row = mAppRows.get(i); + removeAppRow(row); + } + List<AppTrackData> trackDatas = mController.getAudioManager().listAppTrackDatas(); + for (AppTrackData data : trackDatas) { + if (data.isActive()) { + addAppRow(data); + } + } + } + + private void removeAppRow(VolumeRow volumeRow) { + mAppRows.remove(volumeRow); + mDialogRowsView.removeView(volumeRow.view); + } + public void initRingerH() { if (mRingerIcon != null) { mRingerIcon.setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE); @@ -1577,9 +1673,13 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { rescheduleTimeoutH(); - if (mRow.ss == null) return; if (D.BUG) Log.d(TAG, AudioSystem.streamToString(mRow.stream) + " onProgressChanged " + progress + " fromUser=" + fromUser); + if (mRow.isAppVolumeRow) { + mController.getAudioManager().setAppVolume(mRow.packageName, progress * 0.01f); + return; + } + if (mRow.ss == null) return; if (!fromUser) return; if (mRow.ss.levelMin > 0) { final int minProgress = mRow.ss.levelMin * 100; @@ -1610,6 +1710,8 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { @Override public void onStartTrackingTouch(SeekBar seekBar) { + mRow.tracking = true; + if (mRow.isAppVolumeRow) return; if (D.BUG) Log.d(TAG, "onStartTrackingTouch"+ " " + mRow.stream); mController.setActiveStream(mRow.stream); mRow.tracking = true; @@ -1619,6 +1721,7 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { public void onStopTrackingTouch(SeekBar seekBar) { if (D.BUG) Log.d(TAG, "onStopTrackingTouch"+ " " + mRow.stream); mRow.tracking = false; + if (mRow.isAppVolumeRow) return; mRow.userAttempt = SystemClock.uptimeMillis(); final int userLevel = getImpliedLevel(seekBar, seekBar.getProgress()); Events.writeEvent(Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel); @@ -1673,5 +1776,9 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { private int animTargetProgress; private int lastAudibleLevel = 2; private FrameLayout dndIcon; + /* for change app's volume */ + private String packageName; + private boolean isAppVolumeRow = false; + private boolean appMuted; } } diff --git a/OreoPanel/res/layout/volume_dialog_oreo_row.xml b/OreoPanel/res/layout/volume_dialog_oreo_row.xml index 0cbb524..22003ec 100644 --- a/OreoPanel/res/layout/volume_dialog_oreo_row.xml +++ b/OreoPanel/res/layout/volume_dialog_oreo_row.xml @@ -39,9 +39,21 @@ android:id="@+id/volume_row_icon" style="@style/VolumeButtons" android:layout_width="@dimen/volume_button_size" + android:visibility="gone" android:layout_height="@dimen/volume_button_size" android:soundEffectsEnabled="false" /> + <co.potatoproject.plugin.volume.common.AlphaOptimizedImageButton + android:id="@+id/volume_row_app_icon" + style="@style/VolumeButtons" + android:visibility="gone" + android:layout_width="@dimen/volume_dialog_app_size" + android:layout_height="@dimen/volume_dialog_app_size" + android:paddingStart="@dimen/volume_row_app_icon_padding" + android:background="@drawable/ripple_drawable_20dp" + android:soundEffectsEnabled="false" + android:scaleType="centerInside" /> + <SeekBar android:id="@+id/volume_row_slider" android:layout_width="match_parent" @@ -52,4 +64,4 @@ android:paddingStart="@dimen/volume_row_slider_padding_start"/> </LinearLayout> -</LinearLayout>
\ No newline at end of file +</LinearLayout> diff --git a/OreoPanel/res/values/dimens.xml b/OreoPanel/res/values/dimens.xml index bd89584..f81227e 100644 --- a/OreoPanel/res/values/dimens.xml +++ b/OreoPanel/res/values/dimens.xml @@ -14,4 +14,8 @@ <resources> <dimen name="volume_oreo_row_slider_height">48dp</dimen> <dimen name="volume_dialog_oreo_panel_width">416dp</dimen> + + <dimen name="volume_row_app_icon_padding">13dp</dimen> + <dimen name="volume_dialog_row_margin_bottom">8dp</dimen> + <dimen name="volume_dialog_app_size">40dp</dimen> </resources> diff --git a/OreoPanel/src/com/android/plugin/volume/oreo/VolumeDialogImpl.java b/OreoPanel/src/com/android/plugin/volume/oreo/VolumeDialogImpl.java index ba897a6..c9c2b31 100644 --- a/OreoPanel/src/com/android/plugin/volume/oreo/VolumeDialogImpl.java +++ b/OreoPanel/src/com/android/plugin/volume/oreo/VolumeDialogImpl.java @@ -18,6 +18,8 @@ package com.android.plugin.volume.oreo; +import android.database.ContentObserver; +import android.os.UserHandle; import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK; import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_GENERIC; import static android.media.AudioManager.RINGER_MODE_NORMAL; @@ -38,7 +40,10 @@ import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Color; +import android.graphics.ColorFilter; import android.graphics.PixelFormat; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; import android.graphics.Rect; import android.graphics.Region; import android.graphics.drawable.AnimatedVectorDrawable; @@ -47,6 +52,7 @@ import android.graphics.drawable.Drawable; import android.graphics.PorterDuff; import android.media.AudioManager; import android.media.AudioSystem; +import android.media.AppTrackData; import android.os.Debug; import android.os.Handler; import android.os.Looper; @@ -140,6 +146,7 @@ public class VolumeDialogImpl implements VolumeDialog { private ViewGroup mDialogContentView; private ExpandableIndicator mExpandButton; private final List<VolumeRow> mRows = new ArrayList<>(); + private final List<VolumeRow> mAppRows = new ArrayList<>(); private ConfigurableTexts mConfigurableTexts; private final SparseBooleanArray mDynamic = new SparseBooleanArray(); private KeyguardManager mKeyguard; @@ -156,7 +163,7 @@ public class VolumeDialogImpl implements VolumeDialog { private boolean mShowing; private boolean mExpanded; private boolean mShowA11yStream; - + private ColorFilter mAppIconMuteColorFilter; private int mActiveStream; private int mPrevActiveStream; private boolean mAutomute = VolumePrefs.DEFAULT_ENABLE_AUTOMUTE; @@ -171,6 +178,9 @@ public class VolumeDialogImpl implements VolumeDialog { private boolean mHovering = false; private int mDensity; + private SettingsObserver settingsObserver; + private boolean mAppVolume; + public VolumeDialogImpl() {} @Override @@ -184,6 +194,8 @@ public class VolumeDialogImpl implements VolumeDialog { mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mAccessibilityMgr = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); + settingsObserver = new SettingsObserver(mHandler); + settingsObserver.observe(); } public void init(int windowType, Callback callback) { @@ -206,6 +218,7 @@ public class VolumeDialogImpl implements VolumeDialog { mAccessibility.destroy(); mController.removeCallback(mControllerCallbackH); mHandler.removeCallbacksAndMessages(null); + settingsObserver.unobserve(); } private void initDialog() { @@ -313,6 +326,32 @@ public class VolumeDialogImpl implements VolumeDialog { mExpandButtonAnimationDuration = 300; initRingerH(); } + + private class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + void unobserve() { + mContext.getContentResolver().unregisterContentObserver(this); + } + + void observe() { + mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor(Settings.System.SHOW_APP_VOLUME), false, this, UserHandle.USER_ALL); + update(); + } + + @Override + public void onChange(boolean selfChange) { + update(); + initDialog(); + } + + public void update() { + mAppVolume = Settings.System.getIntForUser(mContext.getContentResolver(), Settings.System.SHOW_APP_VOLUME, 0, UserHandle.USER_CURRENT) == 1; + // updateRowsH(getActiveRow()); + } + } private final OnComputeInternalInsetsListener mInsetsListener = internalInsetsInfo -> { internalInsetsInfo.touchableRegion.setEmpty(); @@ -383,6 +422,40 @@ public class VolumeDialogImpl implements VolumeDialog { } } + private void addAppRow(AppTrackData data) { + VolumeRow row = new VolumeRow(); + initAppRow(row, data); + mDialogRowsView.addView(row.view); + mAppRows.add(row); + } + + @SuppressLint("InflateParams") + private void initAppRow(final VolumeRow row, final AppTrackData data) { + row.view = LayoutInflater.from(mContext).inflate(R.layout.volume_dialog_oreo_row, null); + + row.packageName = data.getPackageName(); + row.isAppVolumeRow = true; + + row.view.setTag(row); + row.slider = row.view.findViewById(R.id.volume_row_slider); + row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row)); + + row.appMuted = data.isMuted(); + row.slider.setProgress((int) (data.getVolume() * 100)); + + row.icon = row.view.findViewById(R.id.volume_row_app_icon); + row.icon.setVisibility(View.VISIBLE); + PackageManager pm = mContext.getPackageManager(); + try { + row.icon.setImageDrawable(pm.getApplicationIcon(row.packageName)); + } catch (PackageManager.NameNotFoundException e) { + row.icon.setImageDrawable(pm.getDefaultActivityIcon()); + Log.e(TAG, "Failed to get icon of " + row.packageName, e); + } + } + + + private void addExistingRows() { int N = mRows.size(); for (int i = 0; i < N; i++) { @@ -482,6 +555,7 @@ public class VolumeDialogImpl implements VolumeDialog { row.icon = row.view.findViewById(R.id.volume_row_icon); Drawable iconResDrawable = mSysUIContext.getDrawable(iconRes); row.icon.setImageDrawable(iconResDrawable); + row.icon.setVisibility(View.VISIBLE); if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) { row.icon.setOnClickListener(new OnClickListener() { @Override @@ -846,6 +920,9 @@ public class VolumeDialogImpl implements VolumeDialog { final boolean shouldBeVisible = shouldBeVisibleH(row, activeRow); Utils.setVisOrGone(row.view, shouldBeVisible); Utils.setVisOrGone(row.header, false); + if (mAppVolume) { + updateAppRows(); + } if (row.view.isShown()) { updateVolumeRowSliderTintH(row, isActive); } @@ -869,6 +946,24 @@ public class VolumeDialogImpl implements VolumeDialog { mDialogRowsView.removeView(volumeRow.view); } + private void removeAppRow(VolumeRow volumeRow) { + mAppRows.remove(volumeRow); + mDialogRowsView.removeView(volumeRow.view); + } + + private void updateAppRows() { + for (int i = mAppRows.size() - 1; i >= 0; i--) { + final VolumeRow row = mAppRows.get(i); + removeAppRow(row); + } + List<AppTrackData> trackDatas = mController.getAudioManager().listAppTrackDatas(); + for (AppTrackData data : trackDatas) { + if (data.isActive()) { + addAppRow(data); + } + } + } + private void onStateChangedH(State state) { if (D.BUG) Log.d(TAG, "onStateChangedH() state: " + state.toString()); if (mShowing && mState != null && state != null @@ -1336,9 +1431,13 @@ public class VolumeDialogImpl implements VolumeDialog { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { rescheduleTimeoutH(); - if (mRow.ss == null) return; if (D.BUG) Log.d(TAG, AudioSystem.streamToString(mRow.stream) + " onProgressChanged " + progress + " fromUser=" + fromUser); + if (mRow.isAppVolumeRow) { + mController.getAudioManager().setAppVolume(mRow.packageName, progress * 0.01f); + return; + } + if (mRow.ss == null) return; if (!fromUser) return; if (mRow.ss.levelMin > 0) { final int minProgress = mRow.ss.levelMin * 100; @@ -1361,15 +1460,16 @@ public class VolumeDialogImpl implements VolumeDialog { @Override public void onStartTrackingTouch(SeekBar seekBar) { + mRow.tracking = true; if (D.BUG) Log.d(TAG, "onStartTrackingTouch"+ " " + mRow.stream); mController.setActiveStream(mRow.stream); - mRow.tracking = true; } @Override public void onStopTrackingTouch(SeekBar seekBar) { if (D.BUG) Log.d(TAG, "onStopTrackingTouch"+ " " + mRow.stream); mRow.tracking = false; + if (mRow.isAppVolumeRow) return; mRow.userAttempt = SystemClock.uptimeMillis(); final int userLevel = getImpliedLevel(seekBar, seekBar.getProgress()); Events.writeEvent(Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel); @@ -1451,5 +1551,9 @@ public class VolumeDialogImpl implements VolumeDialog { private ObjectAnimator anim; // slider progress animation for non-touch-related updates private int animTargetProgress; private int lastAudibleLevel = 1; + /* for change app's volume */ + private String packageName; + private boolean isAppVolumeRow = false; + private boolean appMuted; } } diff --git a/TiledPanel/src/com/android/plugin/volume/tiled/VolumeDialogImpl.java b/TiledPanel/src/com/android/plugin/volume/tiled/VolumeDialogImpl.java index d400eda..92ad489 100644 --- a/TiledPanel/src/com/android/plugin/volume/tiled/VolumeDialogImpl.java +++ b/TiledPanel/src/com/android/plugin/volume/tiled/VolumeDialogImpl.java @@ -1643,9 +1643,13 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (mRow.ss == null) return; if (D.BUG) Log.d(TAG, AudioSystem.streamToString(mRow.stream) + " onProgressChanged " + progress + " fromUser=" + fromUser); + if (mRow.isAppVolumeRow) { + mController.getAudioManager().setAppVolume(mRow.packageName, progress * 0.01f); + return; + } + if (mRow.ss == null) return; if (!fromUser) return; if (mRow.ss.levelMin > 0) { final int minProgress = mRow.ss.levelMin * 100; @@ -1669,15 +1673,17 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { @Override public void onStartTrackingTouch(SeekBar seekBar) { + mRow.tracking = true; + if (mRow.isAppVolumeRow) return; if (D.BUG) Log.d(TAG, "onStartTrackingTouch"+ " " + mRow.stream); mController.setActiveStream(mRow.stream); - mRow.tracking = true; } @Override public void onStopTrackingTouch(SeekBar seekBar) { if (D.BUG) Log.d(TAG, "onStopTrackingTouch"+ " " + mRow.stream); mRow.tracking = false; + if (mRow.isAppVolumeRow) return; mRow.userAttempt = SystemClock.uptimeMillis(); final int userLevel = getImpliedLevel(seekBar, seekBar.getProgress()); Events.writeEvent(Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel); @@ -1734,5 +1740,9 @@ public class VolumeDialogImpl extends PanelSideAware implements VolumeDialog { private FrameLayout dndIcon; private View buttonView; private ImageButton buttonIcon; + /* for change app's volume */ + private String packageName; + private boolean isAppVolumeRow = false; + private boolean appMuted; } } diff --git a/VolumePluginCommon/res/values/dimens.xml b/VolumePluginCommon/res/values/dimens.xml index 938e58f..34404a4 100644 --- a/VolumePluginCommon/res/values/dimens.xml +++ b/VolumePluginCommon/res/values/dimens.xml @@ -50,7 +50,7 @@ <dimen name="volume_dialog_miui_row_height">252dp</dimen> <dimen name="volume_dialog_miui_ringer_size">46dip</dimen> <dimen name="volume_dialog_miui_ringer_icon_padding">8dp</dimen> - <dimen name="volume_dialog_miui_tap_target_size">46dip</dimen> + <dimen name="volume_dialog_miui_tap_target_size">42dip</dimen> <dimen name="volume_dialog_miui_spacer">9dip</dimen> <dimen name="volume_dialog_miui_slider_margin_top">-12.5dp</dimen> <dimen name="volume_dialog_miui_slider_margin_bottom">-12.5dp</dimen> |
