MTK Android12 关机界面全屏展示

时间:2024-11-16 22:50:54

需求:关机和重启按钮点击后,去掉正在关机的动画和tips,改为一张图片实现。

修改点

修改点如下:
涉及到的修改文件
修改:
\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\globalactionsGlobalActionsDialogLite.java

新增:
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\layout\dialog_fullscreen_tip.xml
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\layout-land\dialog_fullscreen_tip.xml
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\drawable-xxhdpi\reboot_fullscreen_port_bg.png
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\drawable-xxhdpi\reboot_fullscreen_land_bg.png

备注:drawable 中的reboot_fullscreen_port_bg.png  reboot_fullscreen_land_bg.png  图片以客户提供的横竖屏图片为准

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

实现效果如下

mtk Android12 关机、重启 全屏图片显示

代码分析

找到关机相关内容 ->->关机的实际操作位置:ShutDownAction

@VisibleForTesting
    final class ShutDownAction extends SinglePressAction implements LongPressAction {
        ShutDownAction() {
            super(R.drawable.ic_lock_power_off,
                    R.string.global_action_power_off);
        }

        @Override
        public boolean onLongPress() {
            mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_LONG_PRESS);
            if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
             //   (true);
                return true;
            }
            return false;
        }

        @Override
        public boolean showDuringKeyguard() {
            return true;
        }

        @Override
        public boolean showBeforeProvisioning() {
            return true;
        }

        @Override
        public void onPress() {
            mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_PRESS);
            // shutdown by making sure radio and power are handled accordingly.
            mWindowManagerFuncs.shutdown();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

往里层追代码,如下:

  • onLongPress()-》 (true); 暂不分析,安全模式逻辑去了
  • onPress()->()->
    GlobalActionsComponent shutdown() ->Service shutdown 关机流程
    -> -> reboot方法

retoot 相关源码如下:

 /**
     * Allows the status bar to reboot the device.
     */
    @Override
    public void reboot(boolean safeMode) {
        enforceStatusBarService();
        String reason = safeMode
                ? PowerManager.REBOOT_SAFE_MODE
                : PowerManager.SHUTDOWN_USER_REQUESTED;
        ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
        final long identity = Binder.clearCallingIdentity();
        try {
            mNotificationDelegate.prepareForPossibleShutdown();
            mHandler.post(() -> {
                // ShutdownThread displays UI, so give it a UI context.
                if (safeMode) {
                    ShutdownThread.rebootSafeMode(getUiContext(), true);
                } else {
                    ShutdownThread.reboot(getUiContext(), reason, false);
                }
            });
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

-> ->reboot方法

 /**
     * Request a clean shutdown, waiting for subsystems to clean up their
     * state etc.  Must be called from a Looper thread in which its UI
     * is shown.
     *
     * @param context Context used to display the shutdown progress dialog. This must be a context
     *                suitable for displaying UI (aka Themable).
     * @param reason code to pass to the kernel (. "recovery"), or null.
     * @param confirm true if user confirmation is needed before shutting down.
     */
    public static void reboot(final Context context, String reason, boolean confirm) {
        mReboot = true;
        mRebootSafeMode = false;
        mRebootHasProgressBar = false;
        mReason = reason;
        shutdownInner(context, confirm);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

往外层追

  • createActionItems() 方法
 mPowerItems.add(shutdownAction);
 mPowerItems.add(restartAction);
  • 1
  • 2
  • mPowerItems 对应的adapter MyPowerOptionsAdapter
MyPowerOptionsAdapter  对应item 点击事件:view.setOnClickListener(v ->   onClickItem(position));	   
		   private void onClickItem(int position) {
            Action item = getItem(position);
            if (!(item instanceof SilentModeTriStateAction)) {
                if (mDialog != null) {
                    mDialog.dismiss();
                } else {
                    Log.w(TAG, "Action clicked while mDialog is null.");
                }
                item.onPress();
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 分析2中的 (); 和 ();方法
对于:mDialog.dismiss()
		       @Override
               public void dismiss() {
                dismissWithAnimation(() -> {
                dismissInternal();
            });
            }
			
			
			protected void dismissInternal() {
            mContainer.setTranslationX(0);
            ObjectAnimator alphaAnimator =
                    ObjectAnimator.ofFloat(mContainer, "alpha", 1f, 0f);
            alphaAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
            alphaAnimator.setDuration(233);
            alphaAnimator.addUpdateListener((animation) -> {
                float animatedValue = 1f - animation.getAnimatedFraction();
                int alpha = (int) (animatedValue * mScrimAlpha * 255);
                mBackgroundDrawable.setAlpha(alpha);
            });

            float xOffset = mGlobalActionsLayout.getAnimationOffsetX();
            ObjectAnimator xAnimator =
                    ObjectAnimator.ofFloat(mContainer, "translationX", 0f, xOffset);
            xAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
            xAnimator.setDuration(350);

            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.playTogether(alphaAnimator, xAnimator);
            animatorSet.addListener(new AnimatorListenerAdapter() {
                public void onAnimationEnd(Animator animation) {
                    completeDismiss();
                }
            });

            animatorSet.start();

            // close first, as popup windows will not fade during the animation
            dismissOverflow(false);
            dismissPowerOptions(false);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

上面代码分析可以看出,关机其实就是执行了一个动画旋转进度条,如果弹出一个全屏界面,那么去掉这个动画,或者弹出一个全屏Dialog 出来,正好覆盖当前显示的进度条的dialog 。

();
item 就是上面分析的 view集合mPowerItems的子元素,这里是:shutdownAction
  • 1
  • 2
 final class ShutDownAction extends SinglePressAction implements LongPressAction {
        ShutDownAction() {
            super(R.drawable.ic_lock_power_off,
                    R.string.global_action_power_off);
        }

        @Override
        public boolean onLongPress() {
            mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_LONG_PRESS);
            if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
                mWindowManagerFuncs.reboot(true);
                return true;
            }
            return false;
        }

        @Override
        public boolean showDuringKeyguard() {
            return true;
        }

        @Override
        public boolean showBeforeProvisioning() {
            return true;
        }

        @Override
        public void onPress() {
            mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_PRESS);
            // shutdown by making sure radio and power are handled accordingly.
			Log.d(MYTAG,"ShutDownAction  onPress:");	

            mWindowManagerFuncs.shutdown();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

代码看出,这里 onPress 方法调用的是 ();-》回到了 前面往底层追的部分流程。

总结

总结:从上面分析流程可以看到,实现点击关机【重启一样的逻辑】,弹出一个界面的需求,实现方式:
1)去掉关机、重启的dialog的 dismiss方法,();【也可以不去,全屏界面会盖住】
2)在关闭实现全屏界面,这里用全屏dialog 实现。

//();
	Dialog fullScreenDialog = new Dialog(mContext); // context是你的Activity或者其他Context
  fullScreenDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置没有标题
  fullScreenDialog.setContentView(com.android.systemui.R.layout.dialog_fullscreen_tip); // 设置你的布局文件
  fullScreenDialog.setCancelable(false); // 设置是否可以通过点击背景取消Dialog
  // 设置全屏
   Window window = fullScreenDialog.getWindow();
   if (window != null) {
		  window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
		  //(.FLAG_ALT_FOCUSABLE_IM);
        window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); // 设置背景透明
   }
   fullScreenDialog.show(); // 显示Dialog	
	//wangfangchen end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

所有修改内容资源源码链接地址
Android CodeSearch
关机流程参考一
Android12 关机 重启参考流程二
Android关机流程参考三