美文网首页
音量保护对话框显示层级过高

音量保护对话框显示层级过高

作者: Ed_Lannister | 来源:发表于2018-04-03 15:21 被阅读110次

    调节音量函数

    /frameworks/base/services/core/java/com/android/server/audio/AudioService.java
    private void adjustStreamVolume(int streamType, int direction, int flags,
                String callingPackage, String caller, int uid) {
    

    这里check是否音量超过安全音量

     else if ((direction == AudioManager.ADJUST_RAISE) &&
                       /* !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)*/false) {
                    Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
                    mVolumeController.postDisplaySafeVolumeWarning(flags);
                }
    

    音量控制UI

    /** The controller for the volume UI. */
        private final VolumeController mVolumeController = new VolumeController();
    

    VolumeController中的postDisplaySafeVolumeWarning方法

            public void postDisplaySafeVolumeWarning(int flags) {
                if (mController == null)
                    return;
                try {
                    mController.displaySafeVolumeWarning(flags);
                } catch (RemoteException e) {
                    Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
                }
            }
    
    private IVolumeController mController;
    

    提供给别的进程调用音量控制对话框的AIDL接口frameworks/base/media/java/android/media/IVolumeController.aidl

    oneway interface IVolumeController {
    
        void displaySafeVolumeWarning(int flags);
    
        void volumeChanged(int streamType, int flags);
    
        void masterMuteChanged(int flags);
    
        void setLayoutDirection(int layoutDirection);
    
        void dismiss();
    }
    

    实际调用到音量对话框控制器

    frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
    private final class VC extends IVolumeController.Stub {
            private final String TAG = VolumeDialogController.TAG + ".VC";
    ...
    @Override
            public void displaySafeVolumeWarning(int flags) throws RemoteException {
                if (D.BUG) Log.d(TAG, "displaySafeVolumeWarning "
                        + Util.audioManagerFlagsToString(flags));
                if (mDestroyed) return;
                mWorker.obtainMessage(W.SHOW_SAFETY_WARNING, flags, 0).sendToTarget();
            }
    

    这里的mworker是一个 handle thread拿到的looper

            mWorkerThread = new HandlerThread(VolumeDialogController.class.getSimpleName());
            mWorkerThread.start();
            mWorker = new W(mWorkerThread.getLooper());
    

    looper进行obtain message,带三个参数

    private final W mWorker;
    ...
    mWorker.obtainMessage(W.SHOW_SAFETY_WARNING, flags, 0).sendToTarget();
    ...
    case SHOW_SAFETY_WARNING: onShowSafetyWarningW(msg.arg1); break;
    

    looper进行on show safety warning

    private void onShowSafetyWarningW(int flags) {
            mCallbacks.onShowSafetyWarning(flags);
        }
    

    回调到下面的代码

    frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
    ...
            public void onShowSafetyWarning(int flags) {
                showSafetyWarningH(flags);
            }
    ...
    
        private void showSafetyWarningH(int flags) {
            if ((flags & (AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_SHOW_UI_WARNINGS)) != 0
                    || mShowing) {
                synchronized (mSafetyWarningLock) {
                    if (mSafetyWarning != null) {
                        return;
                    }
                    mSafetyWarning = new SafetyWarningDialog(mContext, mController.getAudioManager()) {
                        @Override
                        protected void cleanUp() {
                            synchronized (mSafetyWarningLock) {
                                mSafetyWarning = null;
                            }
                            recheckH(null);
                        }
                    };
                    mSafetyWarning.show();
                }
                recheckH(null);
            }
            rescheduleTimeoutH();
        }
    ...
    

    可以看到,这里新建了一个SafetyWarningDialog的对象,转到

    private SafetyWarningDialog mSafetyWarning;
    ...
    /frameworks/base/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
    ...
        public SafetyWarningDialog(Context context, AudioManager audioManager) {
            super(context);
            mContext = context;
            mAudioManager = audioManager;
    
            getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
            setShowForAllUsers(true);
            setMessage(mContext.getString(com.android.internal.R.string.safe_media_volume_warning));
            setButton(DialogInterface.BUTTON_POSITIVE,
                    mContext.getString(com.android.internal.R.string.yes), this);
            setButton(DialogInterface.BUTTON_NEGATIVE,
                    mContext.getString(com.android.internal.R.string.no), (OnClickListener) null);
            setOnDismissListener(this);
            setIsHasButtonForVR(true);
            setShouldDismissforVR(false);
            final IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
            context.registerReceiver(mReceiver, filter);
        }
    

    getWindow().setType,这里设置的窗口类型在windowmanager.java中都有定义,需要给什么样级别的type,修改后面type型的宏就可以了。理论上这里定义的级别就是window的token值,值越大,窗口的越在上面;调整这里的type类型就可以改变窗口的显示层级。当然,需要注意类似,指针、状态栏、导航栏是否有别的自定义级别,这个会影响对显示层级的理解。
    通过以下配置文件可以直接禁用掉音量过大保护框

    frameworks/base / core/res/res/values/config.xml
        <bool name="config_safe_media_volume_enabled">false</bool>
    

    相关文章

      网友评论

          本文标题:音量保护对话框显示层级过高

          本文链接:https://www.haomeiwen.com/subject/ibzrcftx.html