diff --git a/res/drawable/icon_mute.xml b/res/drawable/icon_mute.xml
new file mode 100644
index 0000000..20cf37b
--- /dev/null
+++ b/res/drawable/icon_mute.xml
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/res/layout/window_mute_prompt.xml b/res/layout/window_mute_prompt.xml
new file mode 100644
index 0000000..2af0064
--- /dev/null
+++ b/res/layout/window_mute_prompt.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/src/com/android/systemui/SystemUIApplication.java b/src/com/android/systemui/SystemUIApplication.java
index 191ac76..924b287 100644
--- a/src/com/android/systemui/SystemUIApplication.java
+++ b/src/com/android/systemui/SystemUIApplication.java
@@ -79,6 +79,11 @@ public class SystemUIApplication extends Application implements
private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback;
private SysUIComponent mSysUIComponent;
private SystemUIInitializer mInitializer;
+ private static SystemUIApplication sSystemUIApplication = null;
+
+ public static SystemUIApplication getInstance(){
+ return sSystemUIApplication;
+ }
public SystemUIApplication() {
super();
@@ -94,6 +99,7 @@ public class SystemUIApplication extends Application implements
@Override
public void onCreate() {
super.onCreate();
+ sSystemUIApplication = this;
Log.v(TAG, "SystemUIApplication created.");
// This line is used to setup Dagger's dependency injection and should be kept at the
// top of this method.
diff --git a/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 98d904e..3b6b750 100644
--- a/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -81,6 +81,10 @@ import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
+import android.media.AudioDeviceCallback;
+import android.media.AudioDeviceInfo;
+import com.zeasn.whaleos.view.MutePromptFloatWindow;
+
import javax.inject.Inject;
/**
@@ -147,7 +151,9 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
private VolumePolicy mVolumePolicy;
@GuardedBy("this")
private UserActivityListener mUserActivityListener;
-
+ private MutePromptFloatWindow mutePromptFloatWindow;
+ private boolean mIsShowMuteIcon = true;
+
protected final VC mVolumeController = new VC();
protected final BroadcastDispatcher mBroadcastDispatcher;
@@ -218,6 +224,12 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
mWakefulnessLifecycle.addObserver(mWakefullnessLifecycleObserver);
+ //add zeasn regster code
+ if (null == mutePromptFloatWindow) {
+ mutePromptFloatWindow = new MutePromptFloatWindow();
+ mutePromptFloatWindow.hide();
+ }
+ mAudio.registerAudioDeviceCallback(callback, new Handler());
}
public AudioManager getAudioManager() {
@@ -1119,6 +1131,17 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
}
if (changed) {
mCallbacks.onStateChanged(mState);
+ new Handler(Looper.getMainLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ updateState();
+ }
+ });
+ //********************* add zeasn audio receiver start
+ Intent zeasnIntent = new Intent("com.zeasn.action.DEVICE_AUDIO_CHANGED");
+ zeasnIntent.setComponent(new ComponentName("com.zeasn.whaleos.launcher3","com.zeasn.whaleos.launcher.receiver.VolumeChangeReceiver"));
+ context.sendBroadcast(zeasnIntent);
+ //********************* add zeasn audio receiver end
}
}
}
@@ -1274,4 +1297,66 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
public interface UserActivityListener {
void onUserActivity();
}
+
+ //****************************** add zeasn audio code start ************************************
+
+ private AudioDeviceCallback callback = new AudioDeviceCallback() {
+ private void updateNrdpProfile(AudioDeviceInfo[] devices, boolean state) {
+ for (AudioDeviceInfo deviceInfo : devices) {
+ Log.d(TAG, "isSink = " + deviceInfo.isSink() + ", " + (state ? "connect" : "disconnect") + " Audio device: " + deviceInfo.getType());
+ if (deviceInfo.isSink() && (deviceInfo.getType() == AudioDeviceInfo.TYPE_HDMI_ARC)) {
+ Log.d(TAG, (state ? "connect" : "disconnect") + " Audio device: " + deviceInfo.getType());
+ if (state) {
+ Log.d(TAG, "arc device added ");
+ mIsShowMuteIcon = false;
+ updateState();
+ } else {
+ Log.d(TAG, "arc device removed ");
+ mIsShowMuteIcon = true;
+ updateState();
+ }
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
+ super.onAudioDevicesAdded(addedDevices);
+ Log.d(TAG, "audio device added ");
+ updateNrdpProfile(addedDevices, true);
+ }
+
+ @Override
+ public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
+ Log.d(TAG, "audio device removed ");
+ updateNrdpProfile(removedDevices, false);
+ }
+ };
+
+ private void updateState() {
+ Log.d(TAG, "updateState: mIsShowMuteIcon -> " + mIsShowMuteIcon);
+ if (mIsShowMuteIcon) {
+ boolean isMute = getSystemVolume();
+ Log.d(TAG, "updateState: isMute -> " + isMute);
+ if (isMute) {
+ if (!mutePromptFloatWindow.isShown()) {
+ mutePromptFloatWindow.show();
+ }
+ } else {
+ if (mutePromptFloatWindow.isShown()) {
+ mutePromptFloatWindow.hide();
+ }
+ }
+ } else {
+ if (mutePromptFloatWindow.isShown()) {
+ mutePromptFloatWindow.hide();
+ }
+ }
+ }
+
+ private boolean getSystemVolume() {
+ return mAudio.isStreamMute(AudioManager.STREAM_MUSIC);
+ }
+ // *********************************** add zeasn audio code end ****************************
}
diff --git a/src/com/lib/common/base/window/DisplayType.java b/src/com/lib/common/base/window/DisplayType.java
new file mode 100644
index 0000000..6e1d02b
--- /dev/null
+++ b/src/com/lib/common/base/window/DisplayType.java
@@ -0,0 +1,27 @@
+package com.lib.common.base.window;
+
+/**
+ * ===================================================
+ * Created by MackWu on 2021/7/27 14:55
+ * Contact me
+ * Follow me
+ * ===================================================
+ */
+public enum DisplayType {
+
+ /**
+ * 显示和隐藏
+ */
+ SHOW_AND_HIDE,
+
+ /**
+ * 1px和全屏
+ */
+ @Deprecated
+ ONE_PX_AND_MATCH_PARENT,
+
+ /**
+ * 移到屏幕外
+ */
+ OUT_OF_SCREEN,
+}
diff --git a/src/com/lib/common/base/window/IWindow.java b/src/com/lib/common/base/window/IWindow.java
new file mode 100644
index 0000000..29561c4
--- /dev/null
+++ b/src/com/lib/common/base/window/IWindow.java
@@ -0,0 +1,74 @@
+package com.lib.common.base.window;
+
+/**
+ * ===================================================
+ * Created by MackWu on 2020/8/3 19:24
+ * Contact me
+ * Follow me
+ * ===================================================
+ */
+public interface IWindow {
+
+ /**
+ * 获取布局id
+ */
+ int getLayoutId();
+
+ /**
+ * 类型
+ * See {@link android.view.WindowManager.LayoutParams}
+ */
+ int getType();
+
+ /**
+ * 位置
+ */
+ int getGravity();
+
+ /**
+ * flag
+ *
+ * @param isFocusable 是否有焦点
+ */
+ int getFlag(boolean isFocusable);
+
+ /**
+ * 宽
+ */
+ int getWidth();
+
+ /**
+ * 高
+ */
+ int getHeight();
+
+ /**
+ * 在屏幕外时的X坐标
+ */
+ int getOutOfScreenX();
+
+ /**
+ * 在屏幕外时的Y坐标
+ */
+ int getOutOfScreenY();
+
+ /**
+ * 显示类型。
+ */
+ DisplayType getDisplayType();
+
+ /**
+ * 显示弹窗。
+ */
+ void show();
+
+ /**
+ * 隐藏弹窗。
+ */
+ void hide();
+
+ /**
+ * 是否显示
+ */
+ boolean isShown();
+}
diff --git a/src/com/lib/common/base/window/base/BaseWindow.java b/src/com/lib/common/base/window/base/BaseWindow.java
new file mode 100644
index 0000000..faf4e85
--- /dev/null
+++ b/src/com/lib/common/base/window/base/BaseWindow.java
@@ -0,0 +1,161 @@
+package com.lib.common.base.window.base;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+
+import com.lib.common.base.window.DisplayType;
+import com.lib.common.base.window.IWindow;
+import com.android.systemui.SystemUIApplication;
+
+/**
+ * ===================================================
+ * Created by MackWu on 2020/8/3 19:23
+ * Contact me
+ * Follow me
+ * ===================================================
+ */
+public abstract class BaseWindow implements IWindow {
+
+ private boolean inited;
+ protected Context context;
+ protected WindowManager windowManager;
+ protected WindowManager.LayoutParams windowLayoutParams;
+ protected View view;
+ protected boolean isShown;
+ protected final Handler handler = new Handler(Looper.getMainLooper());
+
+ public BaseWindow() {
+ this(SystemUIApplication.getInstance());
+ }
+
+ public BaseWindow(Context context){
+ this.context = context;
+ }
+
+ public BaseWindow init(){
+ if(!inited){
+ inited=true;
+ this.windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ this.windowLayoutParams = new WindowManager.LayoutParams();
+ initView();
+ initWindow();
+ }
+ return this;
+ }
+
+ protected abstract void onConfig(WindowManager.LayoutParams windowLayoutParams);
+
+ protected void initView() {
+ this.view = LayoutInflater.from(context).inflate(getLayoutId(), null);
+ }
+
+ protected void initWindow() {
+ windowLayoutParams.type = getType();
+ windowLayoutParams.format = PixelFormat.TRANSLUCENT;
+ windowLayoutParams.gravity = getGravity();
+ windowLayoutParams.flags = getFlag(true);
+ windowLayoutParams.width = getWidth();
+ windowLayoutParams.height = getHeight();
+ onConfig(this.windowLayoutParams);
+ windowManager.addView(view, windowLayoutParams);
+ hide();
+ }
+
+ @Override
+ public int getType() {
+ return WindowManager.LayoutParams.TYPE_APPLICATION;
+ }
+
+ @Override
+ public int getGravity() {
+ return Gravity.BOTTOM | Gravity.END;
+ }
+
+ @Override
+ public int getFlag(boolean isFocusable) {
+ return isFocusable
+ ? WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
+ WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
+ WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+ : WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
+ WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
+ WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+ }
+
+ @Override
+ public int getWidth() {
+ return WindowManager.LayoutParams.MATCH_PARENT;
+ }
+
+ @Override
+ public int getHeight() {
+ return WindowManager.LayoutParams.MATCH_PARENT;
+ }
+
+ @Override
+ public int getOutOfScreenX() {
+ return -2000;
+ }
+
+ @Override
+ public int getOutOfScreenY() {
+ return -2000;
+ }
+
+ @Override
+ public DisplayType getDisplayType() {
+ return DisplayType.SHOW_AND_HIDE;
+ }
+
+ @Override
+ public void show() {
+ isShown = true;
+ if (getDisplayType() == DisplayType.SHOW_AND_HIDE) {
+ view.setVisibility(View.VISIBLE);
+ }
+ if (getDisplayType() == DisplayType.OUT_OF_SCREEN) {
+ updateWindowPosition(0, 0, true);
+ }
+ }
+
+ @Override
+ public void hide() {
+ isShown = false;
+ if (getDisplayType() == DisplayType.SHOW_AND_HIDE) {
+ view.setVisibility(View.GONE);
+ }
+ if (getDisplayType() == DisplayType.OUT_OF_SCREEN) {
+ updateWindowPosition(getOutOfScreenX(), getOutOfScreenY(), false);
+ }
+ }
+
+ @Override
+ public boolean isShown() {
+ return isShown;
+ }
+
+ protected void updateWindowPosition(int x, int y, boolean isFocusable) {
+ windowLayoutParams = new WindowManager.LayoutParams();
+ windowLayoutParams.type = getType();
+ windowLayoutParams.format = PixelFormat.TRANSLUCENT;
+ windowLayoutParams.gravity = getGravity();
+ windowLayoutParams.flags = getFlag(isFocusable);
+ windowLayoutParams.x = x;
+ windowLayoutParams.y = y;
+ windowLayoutParams.width = getWidth();
+ windowLayoutParams.height = getHeight();
+ windowManager.updateViewLayout(view, windowLayoutParams);
+ }
+
+ public void remove(){
+ windowManager.removeView(view);
+ }
+
+}
diff --git a/src/com/lib/common/base/window/base/FloatView.java b/src/com/lib/common/base/window/base/FloatView.java
new file mode 100644
index 0000000..3f327f3
--- /dev/null
+++ b/src/com/lib/common/base/window/base/FloatView.java
@@ -0,0 +1,43 @@
+package com.lib.common.base.window.base;
+
+import android.view.View;
+import android.view.WindowManager;
+
+/**
+ */
+
+public abstract class FloatView {
+
+ abstract void setSize(int width, int height);
+
+ abstract void setView(View view);
+
+ abstract void setGravity(int gravity, int xOffset, int yOffset);
+
+ public abstract FloatView init();
+
+ public abstract FloatView setFlag(int flag);
+
+ abstract void dismiss();
+
+ public void updateXY(int x, int y) {
+ }
+
+ void updateX(int x) {
+ }
+
+ void updateY(int y) {
+ }
+
+ public int getX() {
+ return 0;
+ }
+
+ public int getY() {
+ return 0;
+ }
+
+ public void updateViewLayout(WindowManager.LayoutParams windowLayoutParams) {
+
+ }
+}
\ No newline at end of file
diff --git a/src/com/lib/common/base/window/base/FloatWindow.java b/src/com/lib/common/base/window/base/FloatWindow.java
new file mode 100644
index 0000000..61f3b3f
--- /dev/null
+++ b/src/com/lib/common/base/window/base/FloatWindow.java
@@ -0,0 +1,107 @@
+package com.lib.common.base.window.base;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.view.View;
+import android.view.WindowManager;
+
+/**
+ */
+
+public class FloatWindow extends FloatView {
+
+ private final Context mContext;
+
+ private final WindowManager mWindowManager;
+ private final WindowManager.LayoutParams mLayoutParams;
+ private View mView;
+ private int mX, mY;
+ private boolean isRemove = false;
+
+ public FloatWindow(Context applicationContext, int windowType) {
+ mContext = applicationContext;
+ mWindowManager = (WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE);
+ mLayoutParams = new WindowManager.LayoutParams();
+ mLayoutParams.type = windowType;
+ mLayoutParams.format = PixelFormat.TRANSLUCENT;
+ mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
+ mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
+ WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
+ WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+ }
+
+ @Override
+ public void setSize(int width, int height) {
+
+ }
+
+ @Override
+ public void setView(View view) {
+ mView = view;
+ }
+
+
+ @Override
+ public void setGravity(int gravity, int xOffset, int yOffset) {
+ mLayoutParams.gravity = gravity;
+ mLayoutParams.x = mX = xOffset;
+ mLayoutParams.y = mY = yOffset;
+ }
+
+ @Override
+ public FloatView init() {
+ try {
+ mWindowManager.addView(mView, mLayoutParams);
+ } catch (Exception ignored) {
+ }
+ return this;
+ }
+
+ @Override
+ public FloatView setFlag(int flag){
+ mLayoutParams.flags = flag;
+ return this;
+ }
+
+ @Override
+ public void dismiss() {
+ isRemove = true;
+ mWindowManager.removeView(mView);
+ }
+
+ @Override
+ public void updateXY(int x, int y) {
+ if (isRemove) return;
+ mLayoutParams.x = mX = x;
+ mLayoutParams.y = mY = y;
+ mWindowManager.updateViewLayout(mView, mLayoutParams);
+ }
+
+ @Override
+ void updateX(int x) {
+ if (isRemove) return;
+ mLayoutParams.x = mX = x;
+ mWindowManager.updateViewLayout(mView, mLayoutParams);
+ }
+
+ @Override
+ void updateY(int y) {
+ if (isRemove) return;
+ mLayoutParams.y = mY = y;
+ mWindowManager.updateViewLayout(mView, mLayoutParams);
+ }
+
+ @Override
+ public int getX() {
+ return mX;
+ }
+
+ @Override
+ public int getY() {
+ return mY;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/com/zeasn/whaleos/view/MutePromptFloatWindow.java b/src/com/zeasn/whaleos/view/MutePromptFloatWindow.java
new file mode 100644
index 0000000..91b7d9c
--- /dev/null
+++ b/src/com/zeasn/whaleos/view/MutePromptFloatWindow.java
@@ -0,0 +1,50 @@
+package com.zeasn.whaleos.view;
+
+import android.view.Gravity;
+import android.view.WindowManager;
+
+import com.lib.common.base.window.base.BaseWindow;
+import com.android.systemui.R;
+
+public class MutePromptFloatWindow extends BaseWindow {
+
+ public MutePromptFloatWindow() {
+ super();
+ init();
+ }
+
+ @Override
+ protected void onConfig(WindowManager.LayoutParams windowLayoutParams) {
+ windowLayoutParams.flags = getFlag(false);
+ }
+
+ @Override
+ public int getLayoutId() {
+ return R.layout.window_mute_prompt;
+ }
+
+ @Override
+ public int getType() {
+ return WindowManager.LayoutParams.TYPE_SEARCH_BAR;
+ }
+
+ @Override
+ public int getGravity() {
+ return Gravity.TOP | Gravity.END;
+ }
+
+ @Override
+ public int getWidth() {
+ return WindowManager.LayoutParams.WRAP_CONTENT;
+ }
+
+ @Override
+ public int getHeight() {
+ return WindowManager.LayoutParams.WRAP_CONTENT;
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ }
+}