美文网首页
StatusBar总结

StatusBar总结

作者: MickCaptain | 来源:发表于2019-07-19 11:57 被阅读0次

    简要说明:
    该分析基于android 8.1.0

    StatusBar的启动流程

    1. systemservice ->main -> run -> startotherservice ->startsystemui -> startServiceAsUser()
    // 启动systemService run方法
        public static void main(String[] args) {
            new SystemServer().run();
        }
    private void run ( ) { 
    ....
    // 启动服务
            try {
                traceBeginAndSlog("StartServices");
                startBootstrapServices();
                startCoreServices();
                startOtherServices();
                SystemServerInitThreadPool.shutdown();
            } catch (Throwable ex) {
                Slog.e("System", "******************************************");
                Slog.e("System", "************ Failure starting system services", ex);
                throw ex;
            } finally {
                traceEnd();
            }
    }
    private void startOtherService{
    ...
          traceBeginAndSlog("StartSystemUI");
                try {
                    startSystemUi(context, windowManagerF);
                } catch (Throwable e) {
                    reportWtf("starting System UI", e);
                }
                traceEnd();
    ...
    }
    
    static final void startSystemUi(Context context, WindowManagerService windowManager) {
            Intent intent = new Intent();
            intent.setComponent(new ComponentName("com.android.systemui",
                        "com.android.systemui.SystemUIService"));
            intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
            //Slog.d(TAG, "Starting service: " + intent);
            context.startServiceAsUser(intent, UserHandle.SYSTEM);
            windowManager.onSystemUiStarted();
        }
    
    
    
    1. 通过 startServiceAsUser 启动了SystemUIService
    2. SystemUIService -> onCreate -> ((SystemUIApplication) getApplication()).startServicesIfNeeded()
    public class SystemUIService extends Service {
    
        @Override
        public void onCreate() {
            super.onCreate();
            ((SystemUIApplication) getApplication()).startServicesIfNeeded();
    
            // For debugging RescueParty
            if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
                throw new RuntimeException();
            }
        }
    ...
      }
    
    1. 通过startServicesIfNeeded 启动SystemBars
        private final Class<?>[] SERVICES = new Class[] {
                Dependency.class,
                NotificationChannels.class,
                CommandQueue.CommandQueueStart.class,
                KeyguardViewMediator.class,
                Recents.class,
                VolumeUI.class,
                Divider.class,
                SystemBars.class,
                StorageNotification.class,
                PowerUI.class,
                RingtonePlayer.class,
                KeyboardUI.class,
                PipUI.class,
                ShortcutKeyDispatcher.class,
                VendorServices.class,
                GarbageMonitor.Service.class,
                LatencyTester.class,
                GlobalActionsComponent.class,
                RoundedCorners.class,
        };
    
    private void startServicesIfNeeded(Class<?>[] services) {
            if (mServicesStarted) {
                return;
            }
    
            if (!mBootCompleted) {
                // check to see if maybe it was already completed long before we began
                // see ActivityManagerService.finishBooting()
                if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
                    mBootCompleted = true;
                    if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
                }
            }
    
            Log.v(TAG, "Starting SystemUI services for user " +
                    Process.myUserHandle().getIdentifier() + ".");
            TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
                    Trace.TRACE_TAG_APP);
            log.traceBegin("StartServices");
            final int N = services.length;
            for (int i = 0; i < N; i++) {
                Class<?> cl = services[i];
                if (DEBUG) Log.d(TAG, "loading: " + cl);
                log.traceBegin("StartServices" + cl.getSimpleName());
                long ti = System.currentTimeMillis();
                try {
    
    ================================启动service=================================================
                    Object newService = SystemUIFactory.getInstance().createInstance(cl);
                    mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
                } catch (IllegalAccessException ex) {
                    throw new RuntimeException(ex);
                } catch (InstantiationException ex) {
                    throw new RuntimeException(ex);
                }
    
                mServices[i].mContext = this;
                mServices[i].mComponents = mComponents;
                if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
                mServices[i].start();
                log.traceEnd();
    ===========================end=====================================
                // Warn if initialization of component takes too long
                ti = System.currentTimeMillis() - ti;
                if (ti > 1000) {
                    Log.w(TAG, "Initialization of " + cl.getName() + " took " + ti + " ms");
                }
                if (mBootCompleted) {
                    mServices[i].onBootCompleted();
                }
            }
            log.traceEnd();
            Dependency.get(PluginManager.class).addPluginListener(
                    new PluginListener<OverlayPlugin>() {
                        private ArraySet<OverlayPlugin> mOverlays;
    
                        @Override
                        public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
                            StatusBar statusBar = getComponent(StatusBar.class);
                            if (statusBar != null) {
                                plugin.setup(statusBar.getStatusBarWindow(),
                                        statusBar.getNavigationBarView());
                            }
                            // Lazy init.
                            if (mOverlays == null) mOverlays = new ArraySet<>();
                            if (plugin.holdStatusBarOpen()) {
                                mOverlays.add(plugin);
                                Dependency.get(StatusBarWindowManager.class).setStateListener(b ->
                                        mOverlays.forEach(o -> o.setCollapseDesired(b)));
                                Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
                                        mOverlays.size() != 0);
    
                            }
                        }
    
                        @Override
                        public void onPluginDisconnected(OverlayPlugin plugin) {
                            mOverlays.remove(plugin);
                            Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
                                    mOverlays.size() != 0);
                        }
                    }, OverlayPlugin.class, true /* Allow multiple plugins */);
    
            mServicesStarted = true;
        }
    
    
    1. systembars -> start() -> createStatusBarFromConfig -> mStatusBar = (SystemUI) cls.newInstance()... mStatusBar.start();
    public class SystemBars extends SystemUI{
    ...
    private void createStatusBarFromConfig() {
            if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
            final String clsName = mContext.getString(R.string.config_statusBarComponent);
            if (clsName == null || clsName.length() == 0) {
                throw andLog("No status bar component configured", null);
            }
            Class<?> cls = null;
            try {
                cls = mContext.getClassLoader().loadClass(clsName);
            } catch (Throwable t) {
                throw andLog("Error loading status bar component: " + clsName, t);
            }
            try {
                mStatusBar = (SystemUI) cls.newInstance();
            } catch (Throwable t) {
                throw andLog("Error creating status bar component: " + clsName, t);
            }
            mStatusBar.mContext = mContext;
            mStatusBar.mComponents = mComponents;
            mStatusBar.start();
            if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
        }
    ...
    }
    
    1. StatusBar -> start() -> createAndAddWindows() - > addStatusBarWindow() ->makeStatusBarView()
    protected void makeStatusBarView() {
            final Context context = mContext;
            updateDisplaySize(); // populates mDisplayMetrics
            updateResources();
            updateTheme();
    
            inflateStatusBarWindow(context);
            mStatusBarWindow.setService(this);
            mStatusBarWindow.setOnTouchListener(getStatusBarWindowTouchListener());
    
            // TODO: Deal with the ugliness that comes from having some of the statusbar broken out
            // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
            mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
                    R.id.notification_panel);
            mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
                    R.id.notification_stack_scroller);
            mNotificationPanel.setStatusBar(this);
            mNotificationPanel.setGroupManager(mGroupManager);
            mAboveShelfObserver = new AboveShelfObserver(mStackScroller);
            mAboveShelfObserver.setListener(mStatusBarWindow.findViewById(
                    R.id.notification_container_parent));
            mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
    
            mNotificationIconAreaController = SystemUIFactory.getInstance()
                    .createNotificationIconAreaController(context, this);
            inflateShelf();
            mNotificationIconAreaController.setupShelf(mNotificationShelf);
            Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController);
            FragmentHostManager.get(mStatusBarWindow)
                    .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
                        CollapsedStatusBarFragment statusBarFragment =
                                (CollapsedStatusBarFragment) fragment;
                        statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
                        mStatusBarView = (PhoneStatusBarView) fragment.getView();
                        mStatusBarView.setBar(this);
                        mStatusBarView.setPanel(mNotificationPanel);
                        mStatusBarView.setScrimController(mScrimController);
                        mStatusBarView.setBouncerShowing(mBouncerShowing);
                        setAreThereNotifications();
                        checkBarModes();
                    }).getFragmentManager()
                    .beginTransaction()
                    .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
                            CollapsedStatusBarFragment.TAG)
                    .commit();
            mIconController = Dependency.get(StatusBarIconController.class);
    
            mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow, mGroupManager);
            mHeadsUpManager.setBar(this);
            mHeadsUpManager.addListener(this);
            mHeadsUpManager.addListener(mNotificationPanel);
            mHeadsUpManager.addListener(mGroupManager);
            mHeadsUpManager.addListener(mVisualStabilityManager);
            mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
            mNotificationData.setHeadsUpManager(mHeadsUpManager);
            mGroupManager.setHeadsUpManager(mHeadsUpManager);
            mHeadsUpManager.setVisualStabilityManager(mVisualStabilityManager);
    
            if (MULTIUSER_DEBUG) {
                mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
                        R.id.header_debug_info);
                mNotificationPanelDebugText.setVisibility(View.VISIBLE);
            }
    
            try {
                boolean showNav = mWindowManagerService.hasNavigationBar();
                if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
                if (showNav) {
                    createNavigationBar();
                }
            } catch (RemoteException ex) {
                // no window manager? good luck with that
            }
    
            // figure out which pixel-format to use for the status bar.
            mPixelFormat = PixelFormat.OPAQUE;
    
            mStackScroller.setLongPressListener(getNotificationLongClicker());
            mStackScroller.setStatusBar(this);
            mStackScroller.setGroupManager(mGroupManager);
            mStackScroller.setHeadsUpManager(mHeadsUpManager);
            mGroupManager.setOnGroupChangeListener(mStackScroller);
            mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller);
    
            inflateEmptyShadeView();
            inflateDismissView();
            mExpandedContents = mStackScroller;
    
            mBackdrop = (BackDropView) mStatusBarWindow.findViewById(R.id.backdrop);
            mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);
            mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);
    
            if (ENABLE_LOCKSCREEN_WALLPAPER) {
                mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
            }
    
            mKeyguardIndicationController =
                    SystemUIFactory.getInstance().createKeyguardIndicationController(mContext,
                    (ViewGroup) mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
                    mNotificationPanel.getLockIcon());
            mNotificationPanel.setKeyguardIndicationController(mKeyguardIndicationController);
    
    
            mAmbientIndicationContainer = mStatusBarWindow.findViewById(
                    R.id.ambient_indication_container);
    
            // set the initial view visibility
            setAreThereNotifications();
    
            // TODO: Find better place for this callback.
            mBatteryController.addCallback(new BatteryStateChangeCallback() {
                @Override
                public void onPowerSaveChanged(boolean isPowerSave) {
                    mHandler.post(mCheckBarModes);
                    if (mDozeServiceHost != null) {
                        mDozeServiceHost.firePowerSaveChanged(isPowerSave);
                    }
                }
    
                @Override
                public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
                    // noop
                }
            });
    
            mLightBarController = Dependency.get(LightBarController.class);
            if (mNavigationBar != null) {
                mNavigationBar.setLightBarController(mLightBarController);
            }
    
            ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
            ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
            View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
            mScrimController = SystemUIFactory.getInstance().createScrimController(mLightBarController,
                    scrimBehind, scrimInFront, headsUpScrim, mLockscreenWallpaper,
                    scrimsVisible -> {
                        if (mStatusBarWindowManager != null) {
                            mStatusBarWindowManager.setScrimsVisible(scrimsVisible);
                        }
                    });
            if (mScrimSrcModeEnabled) {
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        boolean asSrc = mBackdrop.getVisibility() != View.VISIBLE;
                        mScrimController.setDrawBehindAsSrc(asSrc);
                        mStackScroller.setDrawBackgroundAsSrc(asSrc);
                    }
                };
                mBackdrop.setOnVisibilityChangedRunnable(runnable);
                runnable.run();
            }
            mHeadsUpManager.addListener(mScrimController);
            mStackScroller.setScrimController(mScrimController);
            mDozeScrimController = new DozeScrimController(mScrimController, context);
    
            // Other icons
            mVolumeComponent = getComponent(VolumeComponent.class);
    
            mNotificationPanel.setUserSetupComplete(mUserSetup);
            if (UserManager.get(mContext).isUserSwitcherEnabled()) {
                createUserSwitcher();
            }
    
            // Set up the quick settings tile panel
            View container = mStatusBarWindow.findViewById(R.id.qs_frame);
            if (container != null) {
                FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
                ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
                        Dependency.get(ExtensionController.class).newExtension(QS.class)
                                .withPlugin(QS.class)
                                .withFeature(
                                        PackageManager.FEATURE_AUTOMOTIVE, () -> new CarQSFragment())
                                .withDefault(() -> new QSFragment())
                                .build());
                final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this,
                        mIconController);
                mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow,
                        mScrimController);
                fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
                    QS qs = (QS) f;
                    if (qs instanceof QSFragment) {
                        ((QSFragment) qs).setHost(qsh);
                        mQSPanel = ((QSFragment) qs).getQsPanel();
                        mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
                        mKeyguardStatusBar.setQSPanel(mQSPanel);
                    }
                });
            }
    
            mReportRejectedTouch = mStatusBarWindow.findViewById(R.id.report_rejected_touch);
            if (mReportRejectedTouch != null) {
                updateReportRejectedTouchVisibility();
                mReportRejectedTouch.setOnClickListener(v -> {
                    Uri session = mFalsingManager.reportRejectedTouch();
                    if (session == null) { return; }
    
                    StringWriter message = new StringWriter();
                    message.write("Build info: ");
                    message.write(SystemProperties.get("ro.build.description"));
                    message.write("\nSerial number: ");
                    message.write(SystemProperties.get("ro.serialno"));
                    message.write("\n");
    
                    PrintWriter falsingPw = new PrintWriter(message);
                    FalsingLog.dump(falsingPw);
                    falsingPw.flush();
    
                    startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND)
                                    .setType("*/*")
                                    .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report")
                                    .putExtra(Intent.EXTRA_STREAM, session)
                                    .putExtra(Intent.EXTRA_TEXT, message.toString()),
                            "Share rejected touch report")
                                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
                            true /* onlyProvisioned */, true /* dismissShade */);
                });
            }
    
            PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
            if (!pm.isScreenOn()) {
                mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
            }
            mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
                    "GestureWakeLock");
            mVibrator = mContext.getSystemService(Vibrator.class);
            int[] pattern = mContext.getResources().getIntArray(
                    R.array.config_cameraLaunchGestureVibePattern);
            mCameraLaunchGestureVibePattern = new long[pattern.length];
            for (int i = 0; i < pattern.length; i++) {
                mCameraLaunchGestureVibePattern[i] = pattern[i];
            }
    
            // receive broadcasts
            IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
            filter.addAction(Intent.ACTION_SCREEN_OFF);
            filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG);
            context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
    
            IntentFilter demoFilter = new IntentFilter();
            if (DEBUG_MEDIA_FAKE_ARTWORK) {
                demoFilter.addAction(ACTION_FAKE_ARTWORK);
            }
            demoFilter.addAction(ACTION_DEMO);
            context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
                    android.Manifest.permission.DUMP, null);
    
            // listen for USER_SETUP_COMPLETE setting (per-user)
            mDeviceProvisionedController.addCallback(mUserSetupObserver);
            mUserSetupObserver.onUserSetupChanged();
    
            // disable profiling bars, since they overlap and clutter the output on app windows
            ThreadedRenderer.overrideProperty("disableProfileBars", "true");
    
            // Private API call to make the shadows look better for Recents
            ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
        }
    

    makeStatusBarView()
    6.1: 找到 mNotificationPanel
    6.2: 找到 NotificationStackScrollLayout
    6.3: 找到KeyguardStatusBarView
    6.4: 创建NotificationIconAreaController
    6.5: 找到KeyguardIndicationController
    6.6: createNavigationBar();
    ....

    Notification

    1. NotificationManager -> notify -> notifyAsUser() -> enqueueNotificationWithTag(说明调用者: INotificationManager)

    aidl默认调用NotificationManagerService

    1. NotificationManagerService -> enqueueNotificationWithTag() -> enqueueNotificationInternal()

    post(new EnqueueNotificationRunnable(userid, r)); 将Notification发送到EnqueueNotificationRunnable 处理

    1. EnqueueNotificationRunnable -> run() -> PostNotificationRunnable-> run

    调用 NotificationManagerService.NotificationManager 的 notifyRemovedLocked

    1. NotificationManagerService.NotificationManager -> notifyPosted() -> listener.onNotificationPosted(sbnHolder, rankingUpdate);

    2. PopupDataProvider -> onNotificationPosted -> updateLauncherIconBadges -> updateNotificationHeader -> updateNotificationHeader -> mNotificationItemView.updateHeader(badgeInfo.getNotificationCount(), palette);

    3. NotificationItemView -> updateHeader

    NavigationBar

    1. StatusBar -> start() -> createAndWindows() ->addStatusBarWindow() -> makeStatusBarView() -> createNavigationBar()
    protected void createNavigationBar() {
           mNavigationBarView = NavigationBarFragment.create(mContext, (tag, fragment) -> {
               mNavigationBar = (NavigationBarFragment) fragment;
               if (mLightBarController != null) {
                   mNavigationBar.setLightBarController(mLightBarController);
               }
               mNavigationBar.setCurrentSysuiVisibility(mSystemUiVisibility);
           });
       }
    
    

    KeyGuard

    1. StatusBar -> start() -> startKeyguard() -> keyguardViewMediator.registerStatusBar
    2. KeyguradViewMediator -> registerStatusBar
    3. StatusBarKeyguardViewManager ->registerStatusBar -> SystemUIFactory.getInstance().createKeyguardBouncer
    4. SystemUIFactory -> createKeyguardBouncer

    // mContainer (viewGroup) 其实是 StatusBarWindowView的对象

    1. KeyguardBouncer -> inflateView -> mContainer.addView(mRoot, mContainer.getChildCount())
     KeyguardBouncer 部分核心源码:
    public KeyguardBouncer(Context context, ViewMediatorCallback callback,
                LockPatternUtils lockPatternUtils, ViewGroup container,
                DismissCallbackRegistry dismissCallbackRegistry) {
            mContext = context;
            mCallback = callback;
            mLockPatternUtils = lockPatternUtils;
            mContainer = container;
            KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
            mFalsingManager = FalsingManager.getInstance(mContext);
            mDismissCallbackRegistry = dismissCallbackRegistry;
            mHandler = new Handler();
        }
    
        public void show(boolean resetSecuritySelection) {
            final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
            if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
                // In split system user mode, we never unlock system user.
                return;
            }
            mFalsingManager.onBouncerShown();
            ensureView();
            if (resetSecuritySelection) {
                // showPrimarySecurityScreen() updates the current security method. This is needed in
                // case we are already showing and the current security method changed.
                mKeyguardView.showPrimarySecurityScreen();
            }
            if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
                return;
            }
    
            final int activeUserId = ActivityManager.getCurrentUser();
            final boolean isSystemUser =
                    UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
            final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;
    
            // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is
            // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
            if (allowDismissKeyguard && mKeyguardView.dismiss(activeUserId)) {
                return;
            }
    
            // This condition may indicate an error on Android, so log it.
            if (!allowDismissKeyguard) {
                Slog.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId);
            }
    
            mShowingSoon = true;
    
            // Split up the work over multiple frames.
            DejankUtils.postAfterTraversal(mShowRunnable);
        }
    protected void inflateView() {
            removeView();
            mHandler.removeCallbacks(mRemoveViewRunnable);
            mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
            mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
            mKeyguardView.setLockPatternUtils(mLockPatternUtils);
            mKeyguardView.setViewMediatorCallback(mCallback);
            mContainer.addView(mRoot, mContainer.getChildCount());
            mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
                    com.android.systemui.R.dimen.status_bar_height);
            mRoot.setVisibility(View.INVISIBLE);
    
            final WindowInsets rootInsets = mRoot.getRootWindowInsets();
            if (rootInsets != null) {
                mRoot.dispatchApplyWindowInsets(rootInsets);
            }
        }
    

    相关文章

      网友评论

          本文标题:StatusBar总结

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