文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android 13 NavigationBar

2023-10-01 11:28

关注

Android 13 NavigationBar流程

一、概述

Android SystemUI之NavigationBar

packages/apps/Settings/src/com/android/settings/gestures/SystemNavigationGestureSettings.javaframeworks/base/core/java/android/content/om/OverlayManager.javaframeworks/base/services/core/java/com/android/server/om/OverlayManagerService.javaframeworks/base/services/core/java/com/android/server/am/ActivityManagerService.javaframeworks/base/services/core/java/com/android/server/am/ProcessList.javaframeworks/base/core/java/android/app/ActivityThread.javaframeworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.javaframeworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.javaframeworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.javaframeworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.javaframeworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.javaframeworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.javaframeworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.javapackages/apps/Launcher3/src/com/android/launcher3/util/DisplayController.javapackages/apps/Launcher3/quickstep/src/com/android/quickstep/TouchInteractionService.java#SystemNavigationGestureSettings.java|-setCurrentSystemNavigationMode(IOverlayManager overlayManager, String key)  |_overlayManager.setEnabledExclusiveInCategory(overlayPackage, USER_CURRENT)  #OverlayManager.java  |-setEnabledExclusiveInCategory(@NonNull final String packageName, @NonNull UserHandle user)    |_mService.setEnabledExclusiveInCategory(packageName, user.getIdentifier())    #OverlayManagerService.java    |-setEnabledExclusiveInCategory(@Nullable String packageName,final int userIdArg)      |_mImpl.setEnabledExclusive(overlay,  true , realUserId).ifPresent(OverlayManagerService.this::updateTargetPackagesLocked);        |_updateTargetPackagesLocked(@Nullable Set updatedTargets)          |_updateActivityManager(affectedPackages, userId);          |  |_am.scheduleApplicationInfoChanged(targetPackageNames, userId);          |  #ActivityManagerService.java          |  |-scheduleApplicationInfoChanged(List packageNames, int userId)           |    |_updateApplicationInfoLOSP(@NonNull List packagesToUpdate,boolean updateFrameworkRes, int userId)          |      |_mProcessList.updateApplicationInfoLOSP(packagesToUpdate, userId, updateFrameworkRes);          |      |  #ProcessList.java          |      |  |-updateApplicationInfoLOSP(List packagesToUpdate, int userId,boolean updateFrameworkRes)          |      |    |_app.getThread().scheduleApplicationInfoChanged(ai);          |      |    |   #ActivityThread.java          |      |    |   |-scheduleApplicationInfoChanged(ApplicationInfo ai)          |      |    |     |_sendMessage(H.APPLICATION_INFO_CHANGED, ai);          |      |    |       |_handleApplicationInfoChanged(@NonNull final ApplicationInfo ai)           |      |    |_mService.mActivityTaskManager.updateAssetConfiguration(targetProcesses, updateFrameworkRes);          |      |      #ActivityTaskManagerService.java          |      |      |-updateAssetConfiguration(List processes,boolean updateFrameworkRes)          |      |        |_updateConfiguration(newConfig);          |      |        |  |_updateConfigurationLocked(Configuration values, ActivityRecord starting,boolean initLocale, boolean persistent, int userId, boolean deferResume,ActivityTaskManagerService.UpdateConfigurationResult result)          |      |        |    |_updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,boolean persistent, int userId, boolean deferResume)          |      |        |_wpc.updateAssetConfiguration(assetSeq);          |      |_executor.execute(display::onOverlayChanged);          |      |_executor.execute(mWindowManager::onOverlayChanged);          |_broadcastActionOverlayChanged(targets, userId);            |_ ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, null,null, null, android.app.AppOpsManager.OP_NONE, null, false, false, userId);//ACTION_OVERLAY_CHANGED            #NavigationModeController.java            |  |-onReceive(Context context, Intent intent)            |    |_updateCurrentInteractionMode(true );            |      |_mListeners.get(i).onNavigationModeChanged(mode);            |      #NavigationBar.java            |      |-onNavigationModeChanged(int mode)             |      |  |_updateScreenPinningGestures();            |      |  |_ setNavBarMode(mode);            |      |  |_mView.setShouldShowSwipeUpUi(mOverviewProxyService.shouldShowSwipeUpUI());            |      #NavigationBarController..java            |      |-onNavigationModeChanged(int mode)             |      |  |_navBar.getView().updateStates();            |      |    #NavigationBarView.java            |      |    |-updateStates()            |      |      |_mNavigationInflaterView.onLikelyDefaultLayoutChange();            |      |      #NavigationBarInflaterView.java            |      |      |-onLikelyDefaultLayoutChange()            |      |        |_getDefaultLayout()            |      #EdgeBackGestureHandler.java            |      |-onNavigationModeChanged(int mode)             |        |_updateIsEnabled();            |          |_ mInputMonitor = InputManager.getInstance().monitorGestureInput("edge-swipe", mDisplayId);            |          |_mInputEventReceiver = new InputChannelCompat.InputEventReceiver(mInputMonitor.getInputChannel(), Looper.getMainLooper(),Choreographer.getInstance(), this::onInputEvent);            #DisplayController.java            |-onIntent(Intent intent)            |  |_handleInfoChange(display);            |    |_MAIN_EXECUTOR.execute(() -> notifyChange(displayInfoContext, flags));            #TouchInteractionService.java            |-initInputMonitor("onNavigationModeChanged()");              |_mInputMonitorCompat = new InputMonitorCompat("swipe-up", mDeviceState.getDisplayId());              |_mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),mMainChoreographer, this::onInputEvent);
1、Settings切换Navigation Mode
1.1 #setCurrentSystemNavigationMode

<-SystemNavigationGestureSettings.java>

static void setCurrentSystemNavigationMode(IOverlayManager overlayManager, String key) {        String overlayPackage = NAV_BAR_MODE_GESTURAL_OVERLAY;        switch (key) {            case KEY_SYSTEM_NAV_GESTURAL:                overlayPackage = NAV_BAR_MODE_GESTURAL_OVERLAY;                break;            case KEY_SYSTEM_NAV_2BUTTONS:                overlayPackage = NAV_BAR_MODE_2BUTTON_OVERLAY;                break;            case KEY_SYSTEM_NAV_3BUTTONS:                overlayPackage = NAV_BAR_MODE_3BUTTON_OVERLAY;                break;        }        try {            overlayManager.setEnabledExclusiveInCategory(overlayPackage, USER_CURRENT);        } catch (RemoteException e) {            throw e.rethrowFromSystemServer();        }}
2、framework-overlay
2.1 #setEnabledExclusiveInCategory

<-OverlayManager.java>

product/overlay/NavigationBarModeGestural/NavigationBarModeGesturalOverlay.apk*/product/overlay/NavigationBarMode3Button/NavigationBarMode3ButtonOverlay.apk*/public void setEnabledExclusiveInCategory(@NonNull final String packageName,            @NonNull UserHandle user) throws SecurityException, IllegalStateException {        try {            if (!mService.setEnabledExclusiveInCategory(packageName, user.getIdentifier())) {                throw new IllegalStateException("setEnabledExclusiveInCategory failed");            }        } catch (SecurityException e) {            rethrowSecurityException(e);        } catch (RemoteException e) {            throw e.rethrowFromSystemServer();        }}

<-OverlayManagerService.java>

@Overridepublic boolean setEnabledExclusiveInCategory(@Nullable String packageName,                final int userIdArg) {            if (packageName == null) {                return false;            }            try {                traceBegin(TRACE_TAG_RRO, "OMS#setEnabledExclusiveInCategory " + packageName);                final OverlayIdentifier overlay = new OverlayIdentifier(packageName);                final int realUserId = handleIncomingUser(userIdArg,                        "setEnabledExclusiveInCategory");                enforceActor(overlay, "setEnabledExclusiveInCategory", realUserId);                final long ident = Binder.clearCallingIdentity();                try {                    synchronized (mLock) {                        try {mImpl.setEnabledExclusive(overlay,        true , realUserId)    .ifPresent(OverlayManagerService.this::updateTargetPackagesLocked);return true;                        } catch (OperationFailedException e) {return false;                        }                    }                } finally {                    Binder.restoreCallingIdentity(ident);                }            } finally {                traceEnd(TRACE_TAG_RRO);            }}private void updateTargetPackagesLocked(@Nullable Set updatedTargets) {        if (CollectionUtils.isEmpty(updatedTargets)) {            return;        }        persistSettingsLocked();        final SparseArray> userTargets = groupTargetsByUserId(updatedTargets);        for (int i = 0, n = userTargets.size(); i < n; i++) {            final ArraySet targets = userTargets.valueAt(i);            final int userId = userTargets.keyAt(i);            final List affectedPackages = updatePackageManagerLocked(targets, userId);            if (affectedPackages.isEmpty()) {                // The package manager paths are already up-to-date.                continue;            }            FgThread.getHandler().post(() -> {                // Send configuration changed events for all target packages that have been affected                // by overlay state changes.                updateActivityManager(affectedPackages, userId);//更新所有应用的资源配置                // Do not send broadcasts for all affected targets. Overlays targeting the framework                // or shared libraries may cause too many broadcasts to be sent at once.                broadcastActionOverlayChanged(targets, userId);            });        }}private void updateActivityManager(@NonNull List targetPackageNames, final int userId) {        final IActivityManager am = ActivityManager.getService();        try {            am.scheduleApplicationInfoChanged(targetPackageNames, userId);        } catch (RemoteException e) {            Slog.e(TAG, "updateActivityManager remote exception", e);        }}private static void broadcastActionOverlayChanged(@NonNull final Set targetPackages,            final int userId) {        CollectionUtils.forEach(targetPackages, target -> {            final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,                    Uri.fromParts("package", target, null));            intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);            try {                ActivityManager.getService().broadcastIntent(null, intent, null, null, 0, null,                        null, null, android.app.AppOpsManager.OP_NONE, null, false, false, userId);            } catch (RemoteException e) {                Slog.e(TAG, "broadcastActionOverlayChanged remote exception", e);            }        });}

<-ActivityManagerService.java>

 @Override    public void scheduleApplicationInfoChanged(List packageNames, int userId) {        enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,                "scheduleApplicationInfoChanged()");        final long origId = Binder.clearCallingIdentity();        try {            final boolean updateFrameworkRes = packageNames.contains("android");            synchronized (mProcLock) {                updateApplicationInfoLOSP(packageNames, updateFrameworkRes, userId);            }            AppWidgetManagerInternal widgets = LocalServices.getService(                    AppWidgetManagerInternal.class);            if (widgets != null) {                widgets.applyResourceOverlaysToWidgets(new HashSet<>(packageNames), userId,                        updateFrameworkRes);            }        } finally {            Binder.restoreCallingIdentity(origId);        }}@GuardedBy(anyOf = {"this", "mProcLock"})private void updateApplicationInfoLOSP(@NonNull List packagesToUpdate,            boolean updateFrameworkRes, int userId) {        if (updateFrameworkRes) {            ParsingPackageUtils.readConfigUseRoundIcon(null);        }        mProcessList.updateApplicationInfoLOSP(packagesToUpdate, userId, updateFrameworkRes);        if (updateFrameworkRes) {            // Update system server components that need to know about changed overlays. Because the            // overlay is applied in ActivityThread, we need to serialize through its thread too.            final Executor executor = ActivityThread.currentActivityThread().getExecutor();            final DisplayManagerInternal display =                    LocalServices.getService(DisplayManagerInternal.class);            if (display != null) {                executor.execute(display::onOverlayChanged);            }            if (mWindowManager != null) {                executor.execute(mWindowManager::onOverlayChanged);            }        }}

<-ProcessList.java>

@GuardedBy(anyOf = {"mService", "mProcLock"})void updateApplicationInfoLOSP(List packagesToUpdate, int userId,            boolean updateFrameworkRes) {        final ArrayList targetProcesses = new ArrayList<>();        for (int i = mLruProcesses.size() - 1; i >= 0; i--) {            final ProcessRecord app = mLruProcesses.get(i);            if (app.getThread() == null) {                continue;            }            if (userId != UserHandle.USER_ALL && app.userId != userId) {                continue;            }            app.getPkgList().forEachPackage(packageName -> {                if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {                    try {                        final ApplicationInfo ai = AppGlobals.getPackageManager()    .getApplicationInfo(packageName, STOCK_PM_FLAGS, app.userId);                        if (ai != null) {if (ai.packageName.equals(app.info.packageName)) {    app.info = ai;    PlatformCompatCache.getInstance()            .onApplicationInfoChanged(ai);}app.getThread().scheduleApplicationInfoChanged(ai);targetProcesses.add(app.getWindowProcessController());                        }                    } catch (RemoteException e) {                        Slog.w(TAG, String.format("Failed to update %s ApplicationInfo for %s",        packageName, app));                    }                }            });        }        mService.mActivityTaskManager.updateAssetConfiguration(targetProcesses, updateFrameworkRes);}

<-ActivityThread.java>

public void scheduleApplicationInfoChanged(ApplicationInfo ai) {            mResourcesManager.appendPendingAppInfoUpdate(new String[]{ai.sourceDir}, ai);            mH.removeMessages(H.APPLICATION_INFO_CHANGED, ai);            sendMessage(H.APPLICATION_INFO_CHANGED, ai);}public void handleMessage(Message msg) {            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));            switch (msg.what) {            ...            case APPLICATION_INFO_CHANGED:                    handleApplicationInfoChanged((ApplicationInfo) msg.obj);                    break;            ...            }            Object obj = msg.obj;            if (obj instanceof SomeArgs) {                ((SomeArgs) obj).recycle();            }            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));        }}@VisibleForTesting(visibility = PACKAGE)public void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {        // Updates triggered by package installation go through a package update        // receiver. Here we try to capture ApplicationInfo changes that are        // caused by other sources, such as overlays. That means we want to be as conservative        // about code changes as possible. Take the diff of the old ApplicationInfo and the new        // to see if anything needs to change.        LoadedApk apk;        LoadedApk resApk;        // Update all affected loaded packages with new package information        synchronized (mResourcesManager) {            WeakReference ref = mPackages.get(ai.packageName);            apk = ref != null ? ref.get() : null;            ref = mResourcePackages.get(ai.packageName);            resApk = ref != null ? ref.get() : null;        }        if (apk != null) {            final ArrayList oldPaths = new ArrayList<>();            LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths);            apk.updateApplicationInfo(ai, oldPaths);        }        if (resApk != null) {            final ArrayList oldPaths = new ArrayList<>();            LoadedApk.makePaths(this, resApk.getApplicationInfo(), oldPaths);            resApk.updateApplicationInfo(ai, oldPaths);        }        synchronized (mResourcesManager) {            // Update all affected Resources objects to use new ResourcesImpl            mResourcesManager.applyAllPendingAppInfoUpdates();        }}

<-ActivityTaskManagerService.java>

public void updateAssetConfiguration(List processes,            boolean updateFrameworkRes) {        synchronized (mGlobalLock) {            final int assetSeq = increaseAssetConfigurationSeq();            if (updateFrameworkRes) {                Configuration newConfig = new Configuration();                newConfig.assetsSeq = assetSeq;                updateConfiguration(newConfig);            }            // Always update the override of every process so the asset sequence of the process is            // always greater than or equal to the global configuration.            for (int i = processes.size() - 1; i >= 0; i--) {                final WindowProcessController wpc = processes.get(i);                wpc.updateAssetConfiguration(assetSeq);            }        }}@Overridepublic boolean updateConfiguration(Configuration values) {        mAmInternal.enforceCallingPermission(CHANGE_CONFIGURATION, "updateConfiguration()");        synchronized (mGlobalLock) {            if (mWindowManager == null) {                Slog.w(TAG, "Skip updateConfiguration because mWindowManager isn't set");                return false;            }            if (values == null) {                // sentinel: fetch the current configuration from the window manager                values = mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY);            }            mH.sendMessage(PooledLambda.obtainMessage(                    ActivityManagerInternal::updateOomLevelsForDisplay, mAmInternal,                    DEFAULT_DISPLAY));            final long origId = Binder.clearCallingIdentity();            try {                if (values != null) {                    Settings.System.clearConfiguration(values);                }                updateConfigurationLocked(values, null, false, false ,                        UserHandle.USER_NULL, false ,                        mTmpUpdateConfigurationResult);                return mTmpUpdateConfigurationResult.changes != 0;            } finally {                Binder.restoreCallingIdentity(origId);            }        }}boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,            boolean initLocale, boolean persistent, int userId, boolean deferResume,            ActivityTaskManagerService.UpdateConfigurationResult result) {        int changes = 0;        boolean kept = true;        deferWindowLayout();        try {            if (values != null) {                changes = updateGlobalConfigurationLocked(values, initLocale, persistent, userId,                        deferResume);            }            kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);        } finally {            continueWindowLayout();        }        if (result != null) {            result.changes = changes;            result.activityRelaunched = !kept;        }        return kept;}int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,            boolean persistent, int userId, boolean deferResume) {        final DisplayContent defaultDisplay =                mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY);        mTempConfig.setTo(getGlobalConfiguration());        final int changes = mTempConfig.updateFrom(values);        if (changes == 0) {            // Since calling to Activity.setRequestedOrientation leads to freezing the window with            // setting WindowManagerService.mWaitingForConfig to true, it is important that we call            // performDisplayOverrideConfigUpdate in order to send the new display configuration            // (even if there are no actual changes) to unfreeze the window.            defaultDisplay.performDisplayOverrideConfigUpdate(values, deferResume);            return 0;        }        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.i(TAG_CONFIGURATION,                "Updating global configuration to: " + values);        writeConfigurationChanged(changes);        FrameworkStatsLog.write(FrameworkStatsLog.RESOURCE_CONFIGURATION_CHANGED,                values.colorMode,                values.densityDpi,                values.fontScale,                values.hardKeyboardHidden,                values.keyboard,                values.keyboardHidden,                values.mcc,                values.mnc,                values.navigation,                values.navigationHidden,                values.orientation,                values.screenHeightDp,                values.screenLayout,                values.screenWidthDp,                values.smallestScreenWidthDp,                values.touchscreen,                values.uiMode);        if (!initLocale && !values.getLocales().isEmpty() && values.userSetLocale) {            final LocaleList locales = values.getLocales();            int bestLocaleIndex = 0;            if (locales.size() > 1) {                if (mSupportedSystemLocales == null) {                    mSupportedSystemLocales = Resources.getSystem().getAssets().getLocales();                }                bestLocaleIndex = Math.max(0, locales.getFirstMatchIndex(mSupportedSystemLocales));            }            SystemProperties.set("persist.sys.locale",                    locales.get(bestLocaleIndex).toLanguageTag());            LocaleList.setDefault(locales, bestLocaleIndex);            final Message m = PooledLambda.obtainMessage(                    ActivityTaskManagerService::sendLocaleToMountDaemonMsg, this,                    locales.get(bestLocaleIndex));            mH.sendMessage(m);        }        mTempConfig.seq = increaseConfigurationSeqLocked();        // Update stored global config and notify everyone about the change.        mRootWindowContainer.onConfigurationChanged(mTempConfig);        Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig);        // TODO(multi-display): Update UsageEvents#Event to include displayId.        mUsageStatsInternal.reportConfigurationChange(mTempConfig, mAmInternal.getCurrentUserId());        // TODO: If our config changes, should we auto dismiss any currently showing dialogs?        updateShouldShowDialogsLocked(mTempConfig);        AttributeCache ac = AttributeCache.instance();        if (ac != null) {            ac.updateConfiguration(mTempConfig);        }        // Make sure all resources in our process are updated right now, so that anyone who is going        // to retrieve resource values after we return will be sure to get the new ones. This is        // especially important during boot, where the first config change needs to guarantee all        // resources have that config before following boot code is executed.        mSystemThread.applyConfigurationToResources(mTempConfig);        // We need another copy of global config because we're scheduling some calls instead of        // running them in place. We need to be sure that object we send will be handled unchanged.        final Configuration configCopy = new Configuration(mTempConfig);        if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {            final Message msg = PooledLambda.obtainMessage(                    ActivityTaskManagerService::sendPutConfigurationForUserMsg,                    this, userId, configCopy);            mH.sendMessage(msg);        }        SparseArray pidMap = mProcessMap.getPidMap();        for (int i = pidMap.size() - 1; i >= 0; i--) {            final int pid = pidMap.keyAt(i);            final WindowProcessController app = pidMap.get(pid);            if (DEBUG_CONFIGURATION) {                Slog.v(TAG_CONFIGURATION, "Update process config of "                        + app.mName + " to new config " + configCopy);            }            app.onConfigurationChanged(configCopy);        }        final Message msg = PooledLambda.obtainMessage(                ActivityManagerInternal::broadcastGlobalConfigurationChanged,                mAmInternal, changes, initLocale);        mH.sendMessage(msg);        // Override configuration of the default display duplicates global config, so we need to        // update it also. This will also notify WindowManager about changes.        defaultDisplay.performDisplayOverrideConfigUpdate(mRootWindowContainer.getConfiguration(),                deferResume);        return changes;}
3、SystemUI流程
3.1 #updateCurrentInteractionMode

<-NavigationModeController.java>

private BroadcastReceiver mReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            if (DEBUG) {                Log.d(TAG, "ACTION_OVERLAY_CHANGED");            }            updateCurrentInteractionMode(true );        }};public void updateCurrentInteractionMode(boolean notify) {        mCurrentUserContext = getCurrentUserContext();        int mode = getCurrentInteractionMode(mCurrentUserContext);        mUiBgExecutor.execute(() ->            Settings.Secure.putString(mCurrentUserContext.getContentResolver(),                    Secure.NAVIGATION_MODE, String.valueOf(mode)));        if (DEBUG) {            Log.d(TAG, "updateCurrentInteractionMode: mode=" + mode);            dumpAssetPaths(mCurrentUserContext);        }        if (notify) {            for (int i = 0; i < mListeners.size(); i++) {                mListeners.get(i).onNavigationModeChanged(mode);//通过onNavigationModeChanged接口回调更新systemUI配置更改            }        }}
3.2 #onNavigationModeChanged

<-NavigationBar.java>

private final ModeChangedListener mModeChangedListener = new ModeChangedListener() {        @Override        public void onNavigationModeChanged(int mode) {            mNavBarMode = mode;            if (!QuickStepContract.isGesturalMode(mode)) {                // Reset the override alpha                if (getBarTransitions() != null) {                    getBarTransitions().setBackgroundOverrideAlpha(1f);                }            }            updateScreenPinningGestures();            if (!canShowSecondaryHandle()) {                resetSecondaryHandle();            }            setNavBarMode(mode);            mView.setShouldShowSwipeUpUi(mOverviewProxyService.shouldShowSwipeUpUI());        }};private void updateScreenPinningGestures() {        // Change the cancel pin gesture to home and back if recents button is invisible        boolean pinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();        ButtonDispatcher backButton = mView.getBackButton();        ButtonDispatcher recentsButton = mView.getRecentsButton();        if (pinningActive) {            boolean recentsVisible = mView.isRecentsButtonVisible();            backButton.setOnLongClickListener(recentsVisible                    ? this::onLongPressBackRecents                    : this::onLongPressBackHome);            recentsButton.setOnLongClickListener(this::onLongPressBackRecents);        } else {            backButton.setOnLongClickListener(null);            recentsButton.setOnLongClickListener(null);        }        // Note, this needs to be set after even if we're setting the listener to null        backButton.setLongClickable(pinningActive);        recentsButton.setLongClickable(pinningActive);}

<-NavigationBarController…java>

public void onNavigationModeChanged(int mode) {        if (mNavMode == mode) {            return;        }        final int oldMode = mNavMode;        mNavMode = mode;        updateAccessibilityButtonModeIfNeeded();        mHandler.post(() -> {            // create/destroy nav bar based on nav mode only in unfolded state            if (oldMode != mNavMode) {                updateNavbarForTaskbar();            }            for (int i = 0; i < mNavigationBars.size(); i++) {                NavigationBar navBar = mNavigationBars.valueAt(i);                if (navBar == null) {                    continue;                }                navBar.getView().updateStates();            }        });}

<-NavigationBarView.java>

public void updateStates() {        if (mNavigationInflaterView != null) {            // Reinflate the navbar if needed, no-op unless the swipe up state changes            mNavigationInflaterView.onLikelyDefaultLayoutChange();        }        updateSlippery();        reloadNavIcons();        updateNavButtonIcons();        mBgExecutor.execute(() -> setNavBarVirtualKeyHapticFeedbackEnabled(!mShowSwipeUpUi));        getHomeButton().setAccessibilityDelegate(                mShowSwipeUpUi ? mQuickStepAccessibilityDelegate : null); }

<-NavigationBarInflaterView.java>

@Overridepublic void onNavigationModeChanged(int mode) {        mNavBarMode = mode;}public void onLikelyDefaultLayoutChange() {        // Reevaluate new layout        final String newValue = getDefaultLayout();        if (!Objects.equals(mCurrentLayout, newValue)) {            clearViews();            inflateLayout(newValue);        }}protected String getDefaultLayout() {       final int defaultResource = QuickStepContract.isGesturalMode(mNavBarMode)                ? R.string.config_navBarLayoutHandle                : mOverviewProxyService.shouldShowSwipeUpUI()                        ? R.string.config_navBarLayoutQuickstep                        : R.string.config_navBarLayout;        return getContext().getString(defaultResource);}

<-EdgeBackGestureHandler.java>

public void onNavigationModeChanged(int mode) {        mIsGesturalModeEnabled = QuickStepContract.isGesturalMode(mode);        updateIsEnabled();        updateCurrentUserResources();}private void updateIsEnabled() {        boolean isEnabled = mIsAttached && mIsGesturalModeEnabled;        if (isEnabled == mIsEnabled) {            return;        }        mIsEnabled = isEnabled;        disposeInputChannel();        if (mEdgeBackPlugin != null) {            mEdgeBackPlugin.onDestroy();            mEdgeBackPlugin = null;        }        if (!mIsEnabled) {            mGestureNavigationSettingsObserver.unregister();            if (DEBUG_MISSING_GESTURE) {                Log.d(DEBUG_MISSING_GESTURE_TAG, "Unregister display listener");            }            mPluginManager.removePluginListener(this);            TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);            DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);            mPipOptional.ifPresent(pip -> pip.setOnIsInPipStateChangedListener(null));            try {                mWindowManagerService.unregisterSystemGestureExclusionListener(                        mGestureExclusionListener, mDisplayId);            } catch (RemoteException | IllegalArgumentException e) {                Log.e(TAG, "Failed to unregister window manager callbacks", e);            }        } else {            mGestureNavigationSettingsObserver.register();            updateDisplaySize();            if (DEBUG_MISSING_GESTURE) {                Log.d(DEBUG_MISSING_GESTURE_TAG, "Register display listener");            }            TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);            DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,                    mMainExecutor::execute, mOnPropertiesChangedListener);            mPipOptional.ifPresent(                    pip -> pip.setOnIsInPipStateChangedListener(mOnIsInPipStateChangedListener));            try {                mWindowManagerService.registerSystemGestureExclusionListener(                        mGestureExclusionListener, mDisplayId);            } catch (RemoteException | IllegalArgumentException e) {                Log.e(TAG, "Failed to register window manager callbacks", e);            }            // Register input event receiver            mInputMonitor = InputManager.getInstance().monitorGestureInput(                    "edge-swipe", mDisplayId);            mInputEventReceiver = new InputChannelCompat.InputEventReceiver(                    mInputMonitor.getInputChannel(), Looper.getMainLooper(),                    Choreographer.getInstance(), this::onInputEvent);            // Add a nav bar panel window            mIsNewBackAffordanceEnabled = mFeatureFlags.isEnabled(Flags.NEW_BACK_AFFORDANCE);            resetEdgeBackPlugin();            mPluginManager.addPluginListener(                    this, NavigationEdgeBackPlugin.class,  false);        }        // Update the ML model resources.        updateMLModelState();}
4、Launcher3流程
4.1 #onIntent

<-DisplayController.java>

private void onIntent(Intent intent) {        if (mDestroyed) {            return;        }        boolean reconfigure = false;        if (ACTION_OVERLAY_CHANGED.equals(intent.getAction())) {            reconfigure = true;        } else if (ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) {            Configuration config = mContext.getResources().getConfiguration();            reconfigure = mInfo.fontScale != config.fontScale                    || mInfo.densityDpi != config.densityDpi;        }        if (reconfigure) {            Log.d(TAG, "Configuration changed, notifying listeners");            Display display = mDM.getDisplay(DEFAULT_DISPLAY);            if (display != null) {                handleInfoChange(display);            }        }}@AnyThread    private void handleInfoChange(Display display) {        WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(mContext);        Info oldInfo = mInfo;        Context displayInfoContext = getDisplayInfoContext(display);        Info newInfo = new Info(displayInfoContext, wmProxy, oldInfo.mPerDisplayBounds);        Log.d(TAG,"handleInfoChange newInfo.navigationMode ="+newInfo.navigationMode+"; oldInfo.navigationMode ="+oldInfo.navigationMode);        if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale                || newInfo.navigationMode != oldInfo.navigationMode) {            // Cache may not be valid anymore, recreate without cache            newInfo = new Info(displayInfoContext, wmProxy,                    wmProxy.estimateInternalDisplayBounds(displayInfoContext));        }        int change = 0;        if (!newInfo.normalizedDisplayInfo.equals(oldInfo.normalizedDisplayInfo)) {            change |= CHANGE_ACTIVE_SCREEN;        }        if (newInfo.rotation != oldInfo.rotation) {            change |= CHANGE_ROTATION;        }        if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale) {            change |= CHANGE_DENSITY;        }        if (newInfo.navigationMode != oldInfo.navigationMode) {            change |= CHANGE_NAVIGATION_MODE;        }        if (!newInfo.supportedBounds.equals(oldInfo.supportedBounds)                || !newInfo.mPerDisplayBounds.equals(oldInfo.mPerDisplayBounds)) {            change |= CHANGE_SUPPORTED_BOUNDS;            }        if (DEBUG) {            Log.d(TAG, "handleInfoChange - change: 0b" + Integer.toBinaryString(change));        }        if (change != 0) {            mInfo = newInfo;            final int flags = change;            MAIN_EXECUTOR.execute(() -> notifyChange(displayInfoContext, flags));        }}
4.2 #onNavigationModeChanged

<-TouchInteractionService.java>

private void onNavigationModeChanged() {        initInputMonitor("onNavigationModeChanged()");        resetHomeBounceSeenOnQuickstepEnabledFirstTime();}private void initInputMonitor(String reason) {        disposeEventHandlers("Initializing input monitor due to: " + reason);        if (mDeviceState.isButtonNavMode()) {            return;        }        mInputMonitorCompat = new InputMonitorCompat("swipe-up", mDeviceState.getDisplayId());        mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),                    mMainChoreographer, this::onInputEvent);        mRotationTouchHelper.updateGestureTouchRegions();}

来源地址:https://blog.csdn.net/TSK_Amine/article/details/129300940

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯