Layout state should be one of 100 but it is 10

RecyclerView滑动异常排查
本文介绍了一个关于RecyclerView中集成ListView时遇到的滑动异常问题。问题发生在后台数据更新后,表现为RecyclerView无法滑动且界面卡死。通过调试发现是由于ListView在设置文本时出现问题所导致。

使用场景是这样的:

在RecyclerView中有一个不可滑动的ListView用来展示数据,有一个控件控制ListView的显示和隐藏,刚开始好好的,后来调试的时候后台改了点数据就出现RecyclerView不能滑动,并且在后台打印错误。因为只有数据改变了,所以问题处在数据身上。

最后出现问题的原因是ListView中设置文本的时候出现了问题,导致出现问题,界面卡死。

做个记录。

请问如下代码有“状态值(如-1,0,1,2,3)是在读取和解析XML配置后,根据配置中的属性(如enabled和defaultDisplay)计算得出的”吗? /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.display; import static android.view.Display.DEFAULT_DISPLAY; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.hardware.devicestate.DeviceStateManager; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.SystemClock; import android.os.SystemProperties; import android.text.TextUtils; import android.util.ArrayMap; import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.view.Display; import android.view.DisplayAddress; import android.view.DisplayInfo; import android.view.DisplayAddress; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.foldables.FoldGracePeriodProvider; import com.android.server.LocalServices; import com.android.server.display.feature.DisplayManagerFlags; import com.android.server.display.layout.DisplayIdProducer; import com.android.server.display.layout.Layout; import com.android.server.display.mode.SyntheticModeManager; import com.android.server.display.utils.DebugUtils; import com.android.server.policy.WindowManagerPolicy; import com.android.server.utils.FoldSettingProvider; import java.io.PrintWriter; import java.util.Arrays; import java.util.function.Consumer; /** * Responsible for creating {@link LogicalDisplay}s and associating them to the * {@link DisplayDevice} objects supplied through {@link DisplayAdapter.Listener}. * * Additionally this class will keep track of which {@link DisplayGroup} each * {@link LogicalDisplay} belongs to. * * For devices with a single internal display, the mapping is done once and left * alone. For devices with multiple built-in displays, such as foldable devices, * {@link LogicalDisplay}s can be remapped to different {@link DisplayDevice}s. */ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { private static final String TAG = "LogicalDisplayMapper"; // To enable these logs, run: // 'adb shell setprop persist.log.tag.LogicalDisplayMapper DEBUG && adb reboot' private static final boolean DEBUG = DebugUtils.isDebuggable(TAG); public static final int LOGICAL_DISPLAY_EVENT_ADDED = 1; public static final int LOGICAL_DISPLAY_EVENT_CHANGED = 2; public static final int LOGICAL_DISPLAY_EVENT_REMOVED = 3; public static final int LOGICAL_DISPLAY_EVENT_SWAPPED = 4; public static final int LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED = 5; public static final int LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION = 6; public static final int LOGICAL_DISPLAY_EVENT_HDR_SDR_RATIO_CHANGED = 7; public static final int LOGICAL_DISPLAY_EVENT_CONNECTED = 8; public static final int LOGICAL_DISPLAY_EVENT_DISCONNECTED = 9; public static final int DISPLAY_GROUP_EVENT_ADDED = 1; public static final int DISPLAY_GROUP_EVENT_CHANGED = 2; public static final int DISPLAY_GROUP_EVENT_REMOVED = 3; private static final int TIMEOUT_STATE_TRANSITION_MILLIS = 500; private static final int MSG_TRANSITION_TO_PENDING_DEVICE_STATE = 1; private static final int UPDATE_STATE_NEW = 0; private static final int UPDATE_STATE_TRANSITION = 1; private static final int UPDATE_STATE_UPDATED = 2; private static int sNextNonDefaultDisplayId = DEFAULT_DISPLAY + 1; /** * Temporary display info, used for comparing display configurations. */ private final DisplayInfo mTempDisplayInfo = new DisplayInfo(); private final DisplayInfo mTempNonOverrideDisplayInfo = new DisplayInfo(); /** * True if the display mapper service should pretend there is only one display * and only tell applications about the existence of the default logical display. * The display manager can still mirror content to secondary displays but applications * cannot present unique content on those displays. * Used for demonstration purposes only. */ private final boolean mSingleDisplayDemoMode; /** * True if the device can have more than one internal display on at a time. */ private final boolean mSupportsConcurrentInternalDisplays; /** * Wake the device when transitioning into these device state. */ private final SparseBooleanArray mDeviceStatesOnWhichToWakeUp; /** * Sleep the device when transitioning into these device state. */ private final SparseBooleanArray mDeviceStatesOnWhichToSelectiveSleep; /** * Map of all logical displays indexed by logical display id. * Any modification to mLogicalDisplays must invalidate the DisplayManagerGlobal cache. * TODO: multi-display - Move the aforementioned comment? */ private final SparseArray<LogicalDisplay> mLogicalDisplays = new SparseArray<LogicalDisplay>(); private int mNextBuiltInDisplayId = 4096; // Cache whether or not the display was enabled on the last update. private final SparseBooleanArray mDisplaysEnabledCache = new SparseBooleanArray(); /** Map of all display groups indexed by display group id. */ private final SparseArray<DisplayGroup> mDisplayGroups = new SparseArray<>(); /** * Map of display groups which are linked to virtual devices (all displays in the group are * linked to that device). Keyed by virtual device unique id. */ private final SparseIntArray mDeviceDisplayGroupIds = new SparseIntArray(); /** * Map of display group ids indexed by display group name. */ private final ArrayMap<String, Integer> mDisplayGroupIdsByName = new ArrayMap<>(); private final DisplayDeviceRepository mDisplayDeviceRepo; private final DeviceStateToLayoutMap mDeviceStateToLayoutMap; private final Listener mListener; private final DisplayManagerService.SyncRoot mSyncRoot; private final LogicalDisplayMapperHandler mHandler; private final FoldSettingProvider mFoldSettingProvider; private final FoldGracePeriodProvider mFoldGracePeriodProvider; private final PowerManager mPowerManager; /** * Has an entry for every logical display that the rest of the system has been notified about. * Any entry in here requires us to send a {@link LOGICAL_DISPLAY_EVENT_REMOVED} event when it * is deleted or {@link LOGICAL_DISPLAY_EVENT_CHANGED} when it is changed. The values are any * of the {@code UPDATE_STATE_*} constant types. */ private final SparseIntArray mUpdatedLogicalDisplays = new SparseIntArray(); /** * Keeps track of all the display groups that we already told other people about. IOW, if a * display group is in this array, then we *must* send change and remove notifications for it * because other components know about them. Also, what this array stores is a change counter * for each group, so we know if the group itself has changes since we last sent out a * notification. See {@link DisplayGroup#getChangeCountLocked}. */ private final SparseIntArray mUpdatedDisplayGroups = new SparseIntArray(); /** * Array used in {@link #updateLogicalDisplaysLocked} to track events that need to be sent out. */ private final SparseIntArray mLogicalDisplaysToUpdate = new SparseIntArray(); /** * Array used in {@link #updateLogicalDisplaysLocked} to track events that need to be sent out. */ private final SparseIntArray mDisplayGroupsToUpdate = new SparseIntArray(); /** * ArrayMap of display device unique ID to virtual device ID. Used in {@link * #updateLogicalDisplaysLocked} to establish which Virtual Devices own which Virtual Displays. */ private final ArrayMap<String, Integer> mVirtualDeviceDisplayMapping = new ArrayMap<>(); private WindowManagerPolicy mWindowManagerPolicy; private int mNextNonDefaultGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; private final DisplayIdProducer mIdProducer = (isDefault) -> isDefault ? DEFAULT_DISPLAY : sNextNonDefaultDisplayId++; private Layout mCurrentLayout = null; private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; private int mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; private int mDeviceStateToBeAppliedAfterBoot = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; private boolean mBootCompleted = false; private boolean mInteractive; private final DisplayManagerFlags mFlags; private final SyntheticModeManager mSyntheticModeManager; LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider, FoldGracePeriodProvider foldGracePeriodProvider, @NonNull DisplayDeviceRepository repo, @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot, @NonNull Handler handler, DisplayManagerFlags flags) { this(context, foldSettingProvider, foldGracePeriodProvider, repo, listener, syncRoot, handler, new DeviceStateToLayoutMap((isDefault) -> isDefault ? DEFAULT_DISPLAY : sNextNonDefaultDisplayId++, flags), flags, new SyntheticModeManager(flags)); } LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider, FoldGracePeriodProvider foldGracePeriodProvider, @NonNull DisplayDeviceRepository repo, @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot, @NonNull Handler handler, @NonNull DeviceStateToLayoutMap deviceStateToLayoutMap, DisplayManagerFlags flags, SyntheticModeManager syntheticModeManager) { mSyncRoot = syncRoot; mPowerManager = context.getSystemService(PowerManager.class); mInteractive = mPowerManager.isInteractive(); mHandler = new LogicalDisplayMapperHandler(handler.getLooper()); mDisplayDeviceRepo = repo; mListener = listener; mFoldSettingProvider = foldSettingProvider; mFoldGracePeriodProvider = foldGracePeriodProvider; mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false); mSupportsConcurrentInternalDisplays = context.getResources().getBoolean( com.android.internal.R.bool.config_supportsConcurrentInternalDisplays); mDeviceStatesOnWhichToWakeUp = toSparseBooleanArray(context.getResources().getIntArray( com.android.internal.R.array.config_deviceStatesOnWhichToWakeUp)); mDeviceStatesOnWhichToSelectiveSleep = toSparseBooleanArray( context.getResources().getIntArray( com.android.internal.R.array.config_deviceStatesOnWhichToSleep)); mDisplayDeviceRepo.addListener(this); mDeviceStateToLayoutMap = deviceStateToLayoutMap; mFlags = flags; mSyntheticModeManager = syntheticModeManager; } @Override public void onDisplayDeviceEventLocked(DisplayDevice device, int event) { switch (event) { case DisplayDeviceRepository.DISPLAY_DEVICE_EVENT_ADDED: if (DEBUG) { Slog.d(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked()); } handleDisplayDeviceAddedLocked(device); break; case DisplayDeviceRepository.DISPLAY_DEVICE_EVENT_REMOVED: if (DEBUG) { Slog.d(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked()); } handleDisplayDeviceRemovedLocked(device); updateLogicalDisplaysLocked(); break; } } @Override public void onDisplayDeviceChangedLocked(DisplayDevice device, int diff) { if (DEBUG) { Slog.d(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked()); } finishStateTransitionLocked(false /*force*/); updateLogicalDisplaysLocked(diff); } @Override public void onTraversalRequested() { mListener.onTraversalRequested(); } public void onWindowManagerReady() { mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class); } public LogicalDisplay getDisplayLocked(int displayId) { return getDisplayLocked(displayId, /* includeDisabled= */ true); } public LogicalDisplay getDisplayLocked(int displayId, boolean includeDisabled) { LogicalDisplay display = mLogicalDisplays.get(displayId); if (display == null || display.isEnabledLocked() || includeDisabled) { return display; } return null; } public LogicalDisplay getDisplayLocked(DisplayDevice device) { return getDisplayLocked(device, /* includeDisabled= */ true); } public LogicalDisplay getDisplayLocked(DisplayDevice device, boolean includeDisabled) { if (device == null) { return null; } final int count = mLogicalDisplays.size(); for (int i = 0; i < count; i++) { final LogicalDisplay display = mLogicalDisplays.valueAt(i); if (display.getPrimaryDisplayDeviceLocked() == device) { if (display.isEnabledLocked() || includeDisabled) { return display; } return null; } } return null; } public int[] getDisplayIdsLocked(int callingUid, boolean includeDisabled) { final int count = mLogicalDisplays.size(); int[] displayIds = new int[count]; int n = 0; for (int i = 0; i < count; i++) { LogicalDisplay display = mLogicalDisplays.valueAt(i); if (display.isEnabledLocked() || includeDisabled) { DisplayInfo info = display.getDisplayInfoLocked(); if (info.hasAccess(callingUid)) { displayIds[n++] = mLogicalDisplays.keyAt(i); } } } if (n != count) { displayIds = Arrays.copyOfRange(displayIds, 0, n); } return displayIds; } public void forEachLocked(Consumer<LogicalDisplay> consumer) { forEachLocked(consumer, /* includeDisabled= */ true); } public void forEachLocked(Consumer<LogicalDisplay> consumer, boolean includeDisabled) { final int count = mLogicalDisplays.size(); for (int i = 0; i < count; i++) { LogicalDisplay display = mLogicalDisplays.valueAt(i); if (display.isEnabledLocked() || includeDisabled) { consumer.accept(display); } } } @VisibleForTesting public int getDisplayGroupIdFromDisplayIdLocked(int displayId) { final LogicalDisplay display = getDisplayLocked(displayId); if (display == null) { return Display.INVALID_DISPLAY_GROUP; } final int size = mDisplayGroups.size(); for (int i = 0; i < size; i++) { final DisplayGroup displayGroup = mDisplayGroups.valueAt(i); if (displayGroup.containsLocked(display)) { return mDisplayGroups.keyAt(i); } } return Display.INVALID_DISPLAY_GROUP; } public DisplayGroup getDisplayGroupLocked(int groupId) { return mDisplayGroups.get(groupId); } /** * Returns the {@link DisplayInfo} for this device state, indicated by the given display id. The * DisplayInfo represents the attributes of the indicated display in the layout associated with * this state. This is used to get display information for various displays in various states; * e.g. to help apps preload resources for the possible display states. * * @param deviceState the state to query possible layouts for * @param displayId the display id to retrieve * @return {@code null} if no corresponding {@link DisplayInfo} could be found, or the * {@link DisplayInfo} with a matching display id. */ @Nullable public DisplayInfo getDisplayInfoForStateLocked(int deviceState, int displayId) { // Retrieve the layout for this particular state. final Layout layout = mDeviceStateToLayoutMap.get(deviceState); if (layout == null) { // TODO(b/352019542): remove the log once b/345960547 is fixed. Slog.d(TAG, "Cannot get layout for given state:" + deviceState); return null; } // Retrieve the details of the given display within this layout. Layout.Display display = layout.getById(displayId); if (display == null) { // TODO(b/352019542): remove the log once b/345960547 is fixed. Slog.d(TAG, "Cannot get display for given layout:" + layout); return null; } // Retrieve the display info for the display that matches the display id. final DisplayDevice device = mDisplayDeviceRepo.getByAddressLocked(display.getAddress()); if (device == null) { Slog.w(TAG, "The display device (" + display.getAddress() + "), is not available" + " for the display state " + mDeviceState); return null; } LogicalDisplay logicalDisplay = getDisplayLocked(device, /* includeDisabled= */ true); if (logicalDisplay == null) { Slog.w(TAG, "The logical display associated with address (" + display.getAddress() + "), is not available for the display state " + mDeviceState); return null; } DisplayInfo displayInfo = new DisplayInfo(logicalDisplay.getDisplayInfoLocked()); displayInfo.displayId = displayId; return displayInfo; } public void dumpLocked(PrintWriter pw) { pw.println("LogicalDisplayMapper:"); IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); ipw.increaseIndent(); ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); ipw.println("mCurrentLayout=" + mCurrentLayout); ipw.println("mDeviceStatesOnWhichToWakeUp=" + mDeviceStatesOnWhichToWakeUp); ipw.println("mDeviceStatesOnWhichSelectiveSleep=" + mDeviceStatesOnWhichToSelectiveSleep); ipw.println("mInteractive=" + mInteractive); ipw.println("mBootCompleted=" + mBootCompleted); ipw.println(); ipw.println("mDeviceState=" + mDeviceState); ipw.println("mPendingDeviceState=" + mPendingDeviceState); ipw.println("mDeviceStateToBeAppliedAfterBoot=" + mDeviceStateToBeAppliedAfterBoot); final int logicalDisplayCount = mLogicalDisplays.size(); ipw.println(); ipw.println("Logical Displays: size=" + logicalDisplayCount); for (int i = 0; i < logicalDisplayCount; i++) { int displayId = mLogicalDisplays.keyAt(i); LogicalDisplay display = mLogicalDisplays.valueAt(i); ipw.println("Display " + displayId + ":"); ipw.increaseIndent(); display.dumpLocked(ipw); ipw.decreaseIndent(); ipw.println(); } mDeviceStateToLayoutMap.dumpLocked(ipw); } /** * Creates an association between a displayDevice and a virtual device. Any displays associated * with this virtual device will be grouped together in a single {@link DisplayGroup} unless * created with {@link Display.FLAG_OWN_DISPLAY_GROUP}. * * @param displayDevice the displayDevice to be linked * @param virtualDeviceUniqueId the unique ID of the virtual device. */ void associateDisplayDeviceWithVirtualDevice( DisplayDevice displayDevice, int virtualDeviceUniqueId) { mVirtualDeviceDisplayMapping.put(displayDevice.getUniqueId(), virtualDeviceUniqueId); } void setDeviceStateLocked(int state) { if (!mBootCompleted) { // The boot animation might still be in progress, we do not want to switch states now // as the boot animation would end up with an incorrect size. if (DEBUG) { Slog.d(TAG, "Postponing transition to state: " + mPendingDeviceState + " until boot is completed"); } mDeviceStateToBeAppliedAfterBoot = state; return; } Slog.i(TAG, "Requesting Transition to state: " + state + ", from state=" + mDeviceState + ", interactive=" + mInteractive + ", mBootCompleted=" + mBootCompleted); // As part of a state transition, we may need to turn off some displays temporarily so that // the transition is smooth. Plus, on some devices, only one internal displays can be // on at a time. We use LogicalDisplay.setIsInTransition to mark a display that needs to be // temporarily turned off. resetLayoutLocked(mDeviceState, state, /* transitionValue= */ true); mPendingDeviceState = state; mDeviceStateToBeAppliedAfterBoot = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; final boolean wakeDevice = shouldDeviceBeWoken(mPendingDeviceState, mDeviceState, mInteractive, mBootCompleted); final boolean sleepDevice = shouldDeviceBePutToSleep(mPendingDeviceState, mDeviceState, mInteractive, mBootCompleted); // If all displays are off already, we can just transition here, unless we are trying to // wake or sleep the device as part of this transition. In that case defer the final // transition until later once the device is awake/asleep. if (areAllTransitioningDisplaysOffLocked() && !wakeDevice && !sleepDevice) { transitionToPendingStateLocked(); return; } if (DEBUG) { Slog.d(TAG, "Postponing transition to state: " + mPendingDeviceState); } // Send the transitioning phase updates to DisplayManager so that the displays can // start turning OFF in preparation for the new layout. updateLogicalDisplaysLocked(); if (wakeDevice || sleepDevice) { if (wakeDevice) { // We already told the displays to turn off, now we need to wake the device as // we transition to this new state. We do it here so that the waking happens // between the transition from one layout to another. mHandler.post(() -> { mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_UNFOLD_DEVICE, "server.display:unfold"); }); } else if (sleepDevice) { // Send the device to sleep when required. int goToSleepFlag = mFoldSettingProvider.shouldSleepOnFold() ? 0 : PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP; mHandler.post(() -> { mPowerManager.goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD, goToSleepFlag); }); } } mHandler.sendEmptyMessageDelayed(MSG_TRANSITION_TO_PENDING_DEVICE_STATE, TIMEOUT_STATE_TRANSITION_MILLIS); } void onBootCompleted() { synchronized (mSyncRoot) { mBootCompleted = true; if (mDeviceStateToBeAppliedAfterBoot != DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER) { setDeviceStateLocked(mDeviceStateToBeAppliedAfterBoot); } } } void onEarlyInteractivityChange(boolean interactive) { synchronized (mSyncRoot) { if (mInteractive != interactive) { mInteractive = interactive; finishStateTransitionLocked(false /*force*/); } } } /** * Returns if the device should be woken up or not. Called to check if the device state we are * moving to is one that should awake the device, as well as if we are moving from a device * state that shouldn't have been already woken from. * * @param pendingState device state we are moving to * @param currentState device state we are currently in * @param isInteractive if the device is in an interactive state * @param isBootCompleted is the device fully booted * * @see #shouldDeviceBePutToSleep * @see #setDeviceStateLocked */ @VisibleForTesting boolean shouldDeviceBeWoken(int pendingState, int currentState, boolean isInteractive, boolean isBootCompleted) { return mDeviceStatesOnWhichToWakeUp.get(pendingState) && !mDeviceStatesOnWhichToWakeUp.get(currentState) && !isInteractive && isBootCompleted; } /** * Returns if the device should be put to sleep or not. * * Includes a check to verify that the device state that we are moving to, {@code pendingState}, * is the same as the physical state of the device, {@code baseState}. Also if the * 'Stay Awake On Fold' is not enabled. Different values for these parameters indicate a device * state override is active, and we shouldn't put the device to sleep to provide a better user * experience. * * @param pendingState device state we are moving to * @param currentState device state we are currently in * @param isInteractive if the device is in an interactive state * @param isBootCompleted is the device fully booted * * @see #shouldDeviceBeWoken * @see #setDeviceStateLocked */ @VisibleForTesting boolean shouldDeviceBePutToSleep(int pendingState, int currentState, boolean isInteractive, boolean isBootCompleted) { return currentState != DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER && mDeviceStatesOnWhichToSelectiveSleep.get(pendingState) && !mDeviceStatesOnWhichToSelectiveSleep.get(currentState) && isInteractive && isBootCompleted && !mFoldSettingProvider.shouldStayAwakeOnFold(); } private boolean areAllTransitioningDisplaysOffLocked() { final int count = mLogicalDisplays.size(); for (int i = 0; i < count; i++) { final LogicalDisplay display = mLogicalDisplays.valueAt(i); if (!display.isInTransitionLocked()) { continue; } final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); if (device != null) { final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); if (info.state != Display.STATE_OFF) { return false; } } } return true; } private void transitionToPendingStateLocked() { resetLayoutLocked(mDeviceState, mPendingDeviceState, /* transitionValue= */ false); mDeviceState = mPendingDeviceState; mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; applyLayoutLocked(); updateLogicalDisplaysLocked(); } private void finishStateTransitionLocked(boolean force) { if (mPendingDeviceState == DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER) { return; } final boolean waitingToWakeDevice = mDeviceStatesOnWhichToWakeUp.get(mPendingDeviceState) && !mDeviceStatesOnWhichToWakeUp.get(mDeviceState) && !mInteractive && mBootCompleted; // The device should only wait for sleep if #shouldStayAwakeOnFold method returns false. // If not, device should be marked ready for transition immediately. final boolean waitingToSleepDevice = mDeviceStatesOnWhichToSelectiveSleep.get( mPendingDeviceState) && !mDeviceStatesOnWhichToSelectiveSleep.get(mDeviceState) && mInteractive && mBootCompleted && !shouldStayAwakeOnFold(); final boolean displaysOff = areAllTransitioningDisplaysOffLocked(); final boolean isReadyToTransition = displaysOff && !waitingToWakeDevice && !waitingToSleepDevice; if (isReadyToTransition || force) { transitionToPendingStateLocked(); mHandler.removeMessages(MSG_TRANSITION_TO_PENDING_DEVICE_STATE); } else if (DEBUG) { Slog.d(TAG, "Not yet ready to transition to state=" + mPendingDeviceState + " with displays-off=" + displaysOff + ", force=" + force + ", mInteractive=" + mInteractive + ", isReady=" + isReadyToTransition); } } private void handleDisplayDeviceAddedLocked(DisplayDevice device) { DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked(); // The default Display needs to have additional initialization. // This initializes a default dynamic display layout for the default // device, which is used as a fallback in case no static layout definitions // exist or cannot be loaded. if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY) != 0) { initializeDefaultDisplayDeviceLocked(device); } // Create a logical display for the new display device LogicalDisplay display = createNewLogicalDisplayLocked( device, mIdProducer.getId(/* isDefault= */ false)); applyLayoutLocked(); updateLogicalDisplaysLocked(); } private void handleDisplayDeviceRemovedLocked(DisplayDevice device) { final Layout layout = mDeviceStateToLayoutMap.get(DeviceStateToLayoutMap.STATE_DEFAULT); Layout.Display layoutDisplay = layout.getById(DEFAULT_DISPLAY); if (layoutDisplay == null) { return; } DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked(); // Remove any virtual device mapping which exists for the display. mVirtualDeviceDisplayMapping.remove(device.getUniqueId()); if (layoutDisplay.getAddress().equals(deviceInfo.address)) { layout.removeDisplayLocked(DEFAULT_DISPLAY); // Need to find another local display and make it default for (int i = 0; i < mLogicalDisplays.size(); i++) { LogicalDisplay nextDisplay = mLogicalDisplays.valueAt(i); DisplayDevice nextDevice = nextDisplay.getPrimaryDisplayDeviceLocked(); if (nextDevice == null) { continue; } DisplayDeviceInfo nextDeviceInfo = nextDevice.getDisplayDeviceInfoLocked(); if ((nextDeviceInfo.flags & DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY) != 0 && !nextDeviceInfo.address.equals(deviceInfo.address)) { layout.createDefaultDisplayLocked(nextDeviceInfo.address, mIdProducer); applyLayoutLocked(); return; } } } } @VisibleForTesting void updateLogicalDisplays() { synchronized (mSyncRoot) { updateLogicalDisplaysLocked(); } } void updateLogicalDisplaysLocked() { updateLogicalDisplaysLocked(DisplayDeviceInfo.DIFF_EVERYTHING); } private void updateLogicalDisplaysLocked(int diff) { updateLogicalDisplaysLocked(diff, /* isSecondLoop= */ false); } /** * Updates the rest of the display system once all the changes are applied for display * devices and logical displays. The includes releasing invalid/empty LogicalDisplays, * creating/adjusting/removing DisplayGroups, and notifying the rest of the system of the * relevant changes. * * @param diff The DisplayDeviceInfo.DIFF_* of what actually changed to enable finer-grained * display update listeners * @param isSecondLoop If true, this is the second time this is called for the same change. */ private void updateLogicalDisplaysLocked(int diff, boolean isSecondLoop) { boolean reloop = false; // Go through all the displays and figure out if they need to be updated. // Loops in reverse so that displays can be removed during the loop without affecting the // rest of the loop. for (int i = mLogicalDisplays.size() - 1; i >= 0; i--) { final int displayId = mLogicalDisplays.keyAt(i); LogicalDisplay display = mLogicalDisplays.valueAt(i); assignDisplayGroupLocked(display); boolean wasDirty = display.isDirtyLocked(); mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); display.getNonOverrideDisplayInfoLocked(mTempNonOverrideDisplayInfo); display.updateLocked(mDisplayDeviceRepo, mSyntheticModeManager); final DisplayInfo newDisplayInfo = display.getDisplayInfoLocked(); final int updateState = mUpdatedLogicalDisplays.get(displayId, UPDATE_STATE_NEW); final boolean wasPreviouslyUpdated = updateState != UPDATE_STATE_NEW; final boolean wasPreviouslyEnabled = mDisplaysEnabledCache.get(displayId); final boolean isCurrentlyEnabled = display.isEnabledLocked(); // The display is no longer valid and needs to be removed. if (!display.isValidLocked()) { // Remove from group final DisplayGroup displayGroup = getDisplayGroupLocked( getDisplayGroupIdFromDisplayIdLocked(displayId)); if (displayGroup != null) { displayGroup.removeDisplayLocked(display); } if (wasPreviouslyUpdated) { // The display isn't actually removed from our internal data structures until // after the notification is sent; see {@link #sendUpdatesForDisplaysLocked}. if (mFlags.isConnectedDisplayManagementEnabled()) { if (mDisplaysEnabledCache.get(displayId)) { // We still need to send LOGICAL_DISPLAY_EVENT_DISCONNECTED reloop = true; mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_REMOVED); } else { mUpdatedLogicalDisplays.delete(displayId); mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_DISCONNECTED); } } else { mUpdatedLogicalDisplays.delete(displayId); mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_REMOVED); } } else { // This display never left this class, safe to remove without notification mLogicalDisplays.removeAt(i); } continue; // The display is new. } else if (!wasPreviouslyUpdated) { if (mFlags.isConnectedDisplayManagementEnabled()) { // We still need to send LOGICAL_DISPLAY_EVENT_ADDED reloop = true; mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CONNECTED); } else { mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_ADDED); } // Underlying displays device has changed to a different one. } else if (!TextUtils.equals(mTempDisplayInfo.uniqueId, newDisplayInfo.uniqueId)) { mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_SWAPPED); // Something about the display device has changed. } else if (mFlags.isConnectedDisplayManagementEnabled() && wasPreviouslyEnabled != isCurrentlyEnabled) { int event = isCurrentlyEnabled ? LOGICAL_DISPLAY_EVENT_ADDED : LOGICAL_DISPLAY_EVENT_REMOVED; mLogicalDisplaysToUpdate.put(displayId, event); } else if (wasDirty || !mTempDisplayInfo.equals(newDisplayInfo)) { // If only the hdr/sdr ratio changed, then send just the event for that case if ((diff == DisplayDeviceInfo.DIFF_HDR_SDR_RATIO)) { mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_HDR_SDR_RATIO_CHANGED); } else { mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED); } // The display is involved in a display layout transition } else if (updateState == UPDATE_STATE_TRANSITION) { mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION); // Display frame rate overrides changed. } else if (!display.getPendingFrameRateOverrideUids().isEmpty()) { mLogicalDisplaysToUpdate.put( displayId, LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED); // Non-override display values changed. } else { // While application shouldn't know nor care about the non-overridden info, we // still need to let WindowManager know so it can update its own internal state for // things like display cutouts. display.getNonOverrideDisplayInfoLocked(mTempDisplayInfo); if (!mTempNonOverrideDisplayInfo.equals(mTempDisplayInfo)) { mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED); } } mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_UPDATED); } // Go through the groups and do the same thing. We do this after displays since group // information can change in the previous loop. // Loops in reverse so that groups can be removed during the loop without affecting the // rest of the loop. for (int i = mDisplayGroups.size() - 1; i >= 0; i--) { final int groupId = mDisplayGroups.keyAt(i); final DisplayGroup group = mDisplayGroups.valueAt(i); final boolean wasPreviouslyUpdated = mUpdatedDisplayGroups.indexOfKey(groupId) > -1; final int changeCount = group.getChangeCountLocked(); if (group.isEmptyLocked()) { mUpdatedDisplayGroups.delete(groupId); if (wasPreviouslyUpdated) { mDisplayGroupsToUpdate.put(groupId, DISPLAY_GROUP_EVENT_REMOVED); } continue; } else if (!wasPreviouslyUpdated) { mDisplayGroupsToUpdate.put(groupId, DISPLAY_GROUP_EVENT_ADDED); } else if (mUpdatedDisplayGroups.get(groupId) != changeCount) { mDisplayGroupsToUpdate.put(groupId, DISPLAY_GROUP_EVENT_CHANGED); } mUpdatedDisplayGroups.put(groupId, changeCount); } // Send the display and display group updates in order by message type. This is important // to ensure that addition and removal notifications happen in the right order. sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION); sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_ADDED); sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_REMOVED); if (mFlags.isConnectedDisplayManagementEnabled()) { sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_DISCONNECTED); } sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_CHANGED); sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED); sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_SWAPPED); if (mFlags.isConnectedDisplayManagementEnabled()) { sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_CONNECTED); } sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_ADDED); sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_HDR_SDR_RATIO_CHANGED); sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_CHANGED); sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_REMOVED); mLogicalDisplaysToUpdate.clear(); mDisplayGroupsToUpdate.clear(); if (reloop) { if (isSecondLoop) { Slog.wtf(TAG, "Trying to loop a third time"); return; } updateLogicalDisplaysLocked(diff, /* isSecondLoop= */ true); } } /** * Send the specified message for all relevant displays in the specified display-to-message map. */ private void sendUpdatesForDisplaysLocked(int msg) { for (int i = mLogicalDisplaysToUpdate.size() - 1; i >= 0; --i) { final int currMsg = mLogicalDisplaysToUpdate.valueAt(i); if (currMsg != msg) { continue; } final int id = mLogicalDisplaysToUpdate.keyAt(i); final LogicalDisplay display = getDisplayLocked(id); if (DEBUG) { final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); final String uniqueId = device == null ? "null" : device.getUniqueId(); Slog.d(TAG, "Sending " + displayEventToString(msg) + " for display=" + id + " with device=" + uniqueId); } if (mFlags.isConnectedDisplayManagementEnabled()) { if (msg == LOGICAL_DISPLAY_EVENT_ADDED) { mDisplaysEnabledCache.put(id, true); } else if (msg == LOGICAL_DISPLAY_EVENT_REMOVED) { mDisplaysEnabledCache.delete(id); } } mListener.onLogicalDisplayEventLocked(display, msg); if (mFlags.isConnectedDisplayManagementEnabled()) { if (msg == LOGICAL_DISPLAY_EVENT_DISCONNECTED) { mLogicalDisplays.delete(id); } } else if (msg == LOGICAL_DISPLAY_EVENT_REMOVED) { // We wait until we sent the EVENT_REMOVED event before actually removing the // display. mLogicalDisplays.delete(id); } } } /** * Send the specified message for all relevant display groups in the specified message map. */ private void sendUpdatesForGroupsLocked(int msg) { for (int i = mDisplayGroupsToUpdate.size() - 1; i >= 0; --i) { final int currMsg = mDisplayGroupsToUpdate.valueAt(i); if (currMsg != msg) { continue; } final int id = mDisplayGroupsToUpdate.keyAt(i); mListener.onDisplayGroupEventLocked(id, msg); if (msg == DISPLAY_GROUP_EVENT_REMOVED) { // We wait until we sent the EVENT_REMOVED event before actually removing the // group. mDisplayGroups.delete(id); // Remove possible reference to the removed group. int deviceIndex = mDeviceDisplayGroupIds.indexOfValue(id); if (deviceIndex >= 0) { mDeviceDisplayGroupIds.removeAt(deviceIndex); } } } } /** This method should be called before LogicalDisplay.updateLocked, * DisplayInfo in LogicalDisplay (display.getDisplayInfoLocked()) is not updated yet, * and should not be used directly or indirectly in this method */ private void assignDisplayGroupLocked(LogicalDisplay display) { if (!display.isValidLocked()) { // null check for display.mPrimaryDisplayDevice return; } // updated primary device directly from LogicalDisplay (not from DisplayInfo) final DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked(); // final in LogicalDisplay final int displayId = display.getDisplayIdLocked(); final String primaryDisplayUniqueId = displayDevice.getUniqueId(); final Integer linkedDeviceUniqueId = mVirtualDeviceDisplayMapping.get(primaryDisplayUniqueId); // Get current display group data int groupId = getDisplayGroupIdFromDisplayIdLocked(displayId); Integer deviceDisplayGroupId = null; if (linkedDeviceUniqueId != null && mDeviceDisplayGroupIds.indexOfKey(linkedDeviceUniqueId) > 0) { deviceDisplayGroupId = mDeviceDisplayGroupIds.get(linkedDeviceUniqueId); } final DisplayGroup oldGroup = getDisplayGroupLocked(groupId); // groupName directly from LogicalDisplay (not from DisplayInfo) final String groupName = display.getDisplayGroupNameLocked(); // DisplayDeviceInfo is safe to use, it is updated earlier final DisplayDeviceInfo displayDeviceInfo = displayDevice.getDisplayDeviceInfoLocked(); // Get the new display group if a change is needed, if display group name is empty and // {@code DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP} is not set, the display is assigned // to the default display group. final boolean needsOwnDisplayGroup = (displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP) != 0 || !TextUtils.isEmpty(groupName); final boolean hasOwnDisplayGroup = groupId != Display.DEFAULT_DISPLAY_GROUP; final boolean needsDeviceDisplayGroup = !needsOwnDisplayGroup && linkedDeviceUniqueId != null; final boolean hasDeviceDisplayGroup = deviceDisplayGroupId != null && groupId == deviceDisplayGroupId; if (groupId == Display.INVALID_DISPLAY_GROUP || hasOwnDisplayGroup != needsOwnDisplayGroup || hasDeviceDisplayGroup != needsDeviceDisplayGroup) { groupId = assignDisplayGroupIdLocked(needsOwnDisplayGroup, display.getDisplayGroupNameLocked(), needsDeviceDisplayGroup, linkedDeviceUniqueId); } // Create a new group if needed DisplayGroup newGroup = getDisplayGroupLocked(groupId); if (newGroup == null) { newGroup = new DisplayGroup(groupId); mDisplayGroups.append(groupId, newGroup); } if (oldGroup != newGroup) { if (oldGroup != null) { oldGroup.removeDisplayLocked(display); } newGroup.addDisplayLocked(display); display.updateDisplayGroupIdLocked(groupId); Slog.i(TAG, "Setting new display group " + groupId + " for display " + displayId + ", from previous group: " + (oldGroup != null ? oldGroup.getGroupId() : "null")); } } /** * Goes through all the displays used in the layouts for the specified {@code fromState} and * {@code toState} and un/marks them for transition. When a new layout is requested, we * mark the displays that will change into a transitional phase so that they can all be turned * OFF. Once all are confirmed OFF, then this method gets called again to reset transition * marker. This helps to ensure that all display-OFF requests are made before * display-ON which in turn hides any resizing-jank windows might incur when switching displays. * * @param fromState The state we are switching from. * @param toState The state we are switching to. * @param transitionValue The value to mark the transition state: true == transitioning. */ private void resetLayoutLocked(int fromState, int toState, boolean transitionValue) { final Layout fromLayout = mDeviceStateToLayoutMap.get(fromState); final Layout toLayout = mDeviceStateToLayoutMap.get(toState); final int count = mLogicalDisplays.size(); for (int i = 0; i < count; i++) { final LogicalDisplay logicalDisplay = mLogicalDisplays.valueAt(i); final int displayId = logicalDisplay.getDisplayIdLocked(); final DisplayDevice device = logicalDisplay.getPrimaryDisplayDeviceLocked(); if (device == null) { // If there's no device, then the logical display is due to be removed. Ignore it. continue; } // Grab the display associations this display-device has in the old layout and the // new layout. final DisplayAddress address = device.getDisplayDeviceInfoLocked().address; // Virtual displays do not have addresses, so account for nulls. final Layout.Display fromDisplay = address != null ? fromLayout.getByAddress(address) : null; final Layout.Display toDisplay = address != null ? toLayout.getByAddress(address) : null; // If the display is in one of the layouts but not the other, then the content will // change, so in this case we also want to blank the displays to avoid jank. final boolean displayNotInBothLayouts = (fromDisplay == null) != (toDisplay == null); // If a layout doesn't mention a display-device at all, then the display-device defaults // to enabled. This is why we treat null as "enabled" in the code below. final boolean wasEnabled = fromDisplay == null || fromDisplay.isEnabled(); final boolean willBeEnabled = toDisplay == null || toDisplay.isEnabled(); final boolean deviceHasNewLogicalDisplayId = fromDisplay != null && toDisplay != null && fromDisplay.getLogicalDisplayId() != toDisplay.getLogicalDisplayId(); // We consider a display-device as changing/transition if // 1) It's already marked as transitioning // 2) It's going from enabled to disabled, or vice versa // 3) It's enabled, but it's mapped to a new logical display ID. To the user this // would look like apps moving from one screen to another since task-stacks stay // with the logical display [ID]. // 4) It's in one layout but not the other, so the content will change. final boolean isTransitioning = logicalDisplay.isInTransitionLocked() || (wasEnabled != willBeEnabled) || deviceHasNewLogicalDisplayId || displayNotInBothLayouts; if (isTransitioning) { if (transitionValue != logicalDisplay.isInTransitionLocked()) { Slog.i(TAG, "Set isInTransition on display " + displayId + ": " + transitionValue); } // This will either mark the display as "transitioning" if we are starting to change // the device state, or remove the transitioning marker if the state change is // ending. logicalDisplay.setIsInTransitionLocked(transitionValue); mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_TRANSITION); } } } /** * Apply (or reapply) the currently selected display layout. */ private void applyLayoutLocked() { final Layout oldLayout = mCurrentLayout; mCurrentLayout = mDeviceStateToLayoutMap.get(mDeviceState); Slog.i(TAG, "Applying layout: " + mCurrentLayout + ", Previous layout: " + oldLayout); // Go through each of the displays in the current layout set. final int size = mCurrentLayout.size(); for (int i = 0; i < size; i++) { final Layout.Display displayLayout = mCurrentLayout.getAt(i); // If the underlying display-device we want to use for this display // doesn't exist, then skip it. This can happen at startup as display-devices // trickle in one at a time. When the new display finally shows up, the layout is // recalculated so that the display is properly added to the current layout. final DisplayAddress address = displayLayout.getAddress(); final DisplayDevice device = mDisplayDeviceRepo.getByAddressLocked(address); if (device == null) { Slog.w(TAG, "applyLayoutLocked: The display device (" + address + "), is not " + "available for the display state " + mDeviceState); continue; } // Now that we have a display-device, we need a LogicalDisplay to map it to. Find the // right one, if it doesn't exist, create a new one. final int logicalDisplayId = displayLayout.getLogicalDisplayId(); LogicalDisplay newDisplay = getDisplayLocked(logicalDisplayId); boolean newDisplayCreated = false; if (newDisplay == null) { newDisplay = createNewLogicalDisplayLocked( null /*displayDevice*/, logicalDisplayId); newDisplayCreated = true; } // Now swap the underlying display devices between the old display and the new display final LogicalDisplay oldDisplay = getDisplayLocked(device); if (newDisplay != oldDisplay) { // Display is swapping, notify WindowManager, so it can prepare for // the display switch if (!newDisplayCreated && mWindowManagerPolicy != null) { mWindowManagerPolicy.onDisplaySwitchStart(newDisplay.getDisplayIdLocked()); } newDisplay.swapDisplaysLocked(oldDisplay); } DisplayDeviceConfig config = device.getDisplayDeviceConfig(); newDisplay.setDevicePositionLocked(displayLayout.getPosition()); newDisplay.setLeadDisplayLocked(displayLayout.getLeadDisplayId()); newDisplay.updateLayoutLimitedRefreshRateLocked( config.getRefreshRange(displayLayout.getRefreshRateZoneId()) ); newDisplay.updateThermalRefreshRateThrottling( config.getThermalRefreshRateThrottlingData( displayLayout.getRefreshRateThermalThrottlingMapId() ) ); setEnabledLocked(newDisplay, displayLayout.isEnabled()); newDisplay.setThermalBrightnessThrottlingDataIdLocked( displayLayout.getThermalBrightnessThrottlingMapId() == null ? DisplayDeviceConfig.DEFAULT_ID : displayLayout.getThermalBrightnessThrottlingMapId()); newDisplay.setPowerThrottlingDataIdLocked( displayLayout.getPowerThrottlingMapId() == null ? DisplayDeviceConfig.DEFAULT_ID : displayLayout.getPowerThrottlingMapId()); newDisplay.setDisplayGroupNameLocked(displayLayout.getDisplayGroupName()); } } /** * Creates a new logical display for the specified device and display Id and adds it to the list * of logical displays. * * @param device The device to associate with the LogicalDisplay. * @param displayId The display ID to give the new display. If invalid, a new ID is assigned. * @return The new logical display if created, null otherwise. */ private LogicalDisplay createNewLogicalDisplayLocked(DisplayDevice device, int displayId) { final int layerStack = assignLayerStackLocked(displayId); final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device, mFlags.isPixelAnisotropyCorrectionInLogicalDisplayEnabled(), mFlags.isAlwaysRotateDisplayDeviceEnabled()); display.updateLocked(mDisplayDeviceRepo, mSyntheticModeManager); final DisplayInfo info = display.getDisplayInfoLocked(); if (info.type == Display.TYPE_INTERNAL && mDeviceStateToLayoutMap.size() > 1) { // If this is an internal display and the device uses a display layout configuration, // the display should be disabled as later we will receive a device state update, which // will tell us which internal displays should be enabled and which should be disabled. display.setEnabledLocked(false); } mLogicalDisplays.put(displayId, display); return display; } void setEnabledLocked(LogicalDisplay display, boolean isEnabled) { final int displayId = display.getDisplayIdLocked(); final DisplayInfo info = display.getDisplayInfoLocked(); final boolean disallowSecondaryDisplay = mSingleDisplayDemoMode && (info.type != Display.TYPE_INTERNAL); if (isEnabled && disallowSecondaryDisplay) { Slog.i(TAG, "Not creating a logical display for a secondary display because single" + " display demo mode is enabled: " + display.getDisplayInfoLocked()); isEnabled = false; } if (display.isEnabledLocked() != isEnabled) { Slog.i(TAG, "SetEnabled on display " + displayId + ": " + isEnabled); display.setEnabledLocked(isEnabled); } } private int assignDisplayGroupIdLocked(boolean isOwnDisplayGroup, String displayGroupName, boolean isDeviceDisplayGroup, Integer linkedDeviceUniqueId) { if (isDeviceDisplayGroup && linkedDeviceUniqueId != null) { int deviceDisplayGroupId = mDeviceDisplayGroupIds.get(linkedDeviceUniqueId); // A value of 0 indicates that no device display group was found. if (deviceDisplayGroupId == 0) { deviceDisplayGroupId = mNextNonDefaultGroupId++; mDeviceDisplayGroupIds.put(linkedDeviceUniqueId, deviceDisplayGroupId); } return deviceDisplayGroupId; } if (!isOwnDisplayGroup) return Display.DEFAULT_DISPLAY_GROUP; Integer displayGroupId = mDisplayGroupIdsByName.get(displayGroupName); if (displayGroupId == null) { displayGroupId = Integer.valueOf(mNextNonDefaultGroupId++); mDisplayGroupIdsByName.put(displayGroupName, displayGroupId); } return displayGroupId; } private void initializeDefaultDisplayDeviceLocked(DisplayDevice device) { // We always want to make sure that our default layout creates a logical // display for the default display device that is found. // To that end, when we are notified of a new default display, we add it to // the default layout definition if it is not already there. final Layout layout = mDeviceStateToLayoutMap.get(DeviceStateToLayoutMap.STATE_DEFAULT); if (layout.getById(DEFAULT_DISPLAY) != null) { // The layout should only have one default display return; } final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); layout.createDefaultDisplayLocked(info.address, mIdProducer); } private int assignLayerStackLocked(int displayId) { // Currently layer stacks and display ids are the same. // This need not be the case. return displayId; } private SparseBooleanArray toSparseBooleanArray(int[] input) { final SparseBooleanArray retval = new SparseBooleanArray(2); for (int i = 0; input != null && i < input.length; i++) { retval.put(input[i], true); } return retval; } /** * Returns true if the device would definitely have outer display ON/Stay Awake on fold based on * the value of `Continue using app on fold` setting */ private boolean shouldStayAwakeOnFold() { return mFoldSettingProvider.shouldStayAwakeOnFold() || ( mFoldSettingProvider.shouldSelectiveStayAwakeOnFold() && mFoldGracePeriodProvider.isEnabled()); } private String displayEventToString(int msg) { switch(msg) { case LOGICAL_DISPLAY_EVENT_ADDED: return "added"; case LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION: return "transition"; case LOGICAL_DISPLAY_EVENT_CHANGED: return "changed"; case LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED: return "framerate_override"; case LOGICAL_DISPLAY_EVENT_SWAPPED: return "swapped"; case LOGICAL_DISPLAY_EVENT_REMOVED: return "removed"; case LOGICAL_DISPLAY_EVENT_HDR_SDR_RATIO_CHANGED: return "hdr_sdr_ratio_changed"; case LOGICAL_DISPLAY_EVENT_CONNECTED: return "connected"; case LOGICAL_DISPLAY_EVENT_DISCONNECTED: return "disconnected"; } return null; } void setDisplayEnabledLocked(@NonNull LogicalDisplay display, boolean enabled) { boolean isEnabled = display.isEnabledLocked(); if (isEnabled == enabled) { Slog.w(TAG, "Display is already " + (isEnabled ? "enabled" : "disabled") + ": " + display.getDisplayIdLocked()); return; } setEnabledLocked(display, enabled); updateLogicalDisplaysLocked(); } public interface Listener { void onLogicalDisplayEventLocked(LogicalDisplay display, int event); void onDisplayGroupEventLocked(int groupId, int event); void onTraversalRequested(); } private class LogicalDisplayMapperHandler extends Handler { LogicalDisplayMapperHandler(Looper looper) { super(looper, null, true /*async*/); } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_TRANSITION_TO_PENDING_DEVICE_STATE: synchronized (mSyncRoot) { finishStateTransitionLocked(true /*force*/); } break; } } } }
10-25
Currently You are now a website builder. These are the code in my cart.php & functions.php. Currently, i am very satisfied with my layout. However, I want to achieve cart like Shopee / Taobao / Lazada, that allow my customer to 1) Do selective checkout, where only selected items are sent to checkout page, and after order created, only these items will be removed from cart. On the other side, non-selected items are retained inside cart, until customer remove them manually through 清除購物車 / 移除選中商品 or customer check out them. Only remove when order is created. If customer go back from checkout page or payment page, or anything, as long as order is not created, dont remove them. Currently im using restore cart way to achieve this, but everything from cart is removed currently after order created. theres some mistake that stop me from achieving this. I turned on feature where customer can see how many items are inside cart through the cart icon at header. At the same time, i dont want my customer to notice that their cart is cleared and recovered before (the amount of items in cart icon will show 0 when havent recover and the number of items after recover). I dont want them to notice the change, therefore, we have to recover it fast until customer did not notice them. Please be considerate regarding customer that use PC because they might access my website through another tab, at there, they can see the amount of items in cart icon. Therefore, i want it to always show the correct amount, only remove when the order is created and maintain if the order is not created. I dont want them to notice how it works (recovering) 2) All these 全选 刪除選中的商品 清空購物車 输入优惠券代码 应用优惠券 已选商品: 0 件,共计: RM0.00 结算 works perfectly fine, please remain them. Maintaining all the layout and achieved functions. Please check which part stopped me from achieving the selective checkout (maintain non-selected items inside cart, only remove selected to checkout items when order created, and dont let customer nmotice the change in their cart. I want them to no matter access from where, either new tab, other device etc, they will see the correct items in their cart) For now, If i cancel the payment halfway, i am logged out when back from payment page, and when i check from other tab, non-selected items are removed from cart, only selected items are still inside cart. Also, when i login back after payment page, it redirects me to pay-only page. Please refer how taobao cart works, and review which part is stopping me from achieve taobao cart, give me the part of code to be changed and the new code to replaced with the current one, as i have no coding basic
08-31
(venv) D:\Audio2Face\Audio2Face-3D-SDK>trtexec --version &&&& RUNNING TensorRT.trtexec [TensorRT v101401] [b48] # trtexec --version [11/27/2025-14:33:27] [I] TF32 is enabled by default. Add --noTF32 flag to further improve accuracy with some performance cost. === Model Options === --onnx=<file> ONNX model === Build Options === --minShapes=spec Build with dynamic shapes using a profile with the min shapes provided --optShapes=spec Build with dynamic shapes using a profile with the opt shapes provided --maxShapes=spec Build with dynamic shapes using a profile with the max shapes provided --minShapesCalib=spec Calibrate with dynamic shapes using a profile with the min shapes provided --optShapesCalib=spec Calibrate with dynamic shapes using a profile with the opt shapes provided --maxShapesCalib=spec Calibrate with dynamic shapes using a profile with the max shapes provided Note: All three of min, opt and max shapes must be supplied. However, if only opt shapes is supplied then it will be expanded so that min shapes and max shapes are set to the same values as opt shapes. Input names can be wrapped with escaped single quotes (ex: 'Input:0'). Example input shapes spec: input0:1x3x256x256,input1:1x3x128x128 For scalars (0-D shapes), use input0:scalar or simply input0: with nothing after the colon. Each input shape is supplied as a key-value pair where key is the input name and value is the dimensions (including the batch dimension) to be used for that input. Each key-value pair has the key and value separated using a colon (:). Multiple input shapes can be provided via comma-separated key-value pairs, and each input name can contain at most one wildcard ('*') character. --inputIOFormats=spec Type and format of each of the input tensors (default = all inputs in fp32:chw) See --outputIOFormats help for the grammar of type and format list. Note: If this option is specified, please set comma-separated types and formats for all inputs following the same order as network inputs ID (even if only one input needs specifying IO format) or set the type and format once for broadcasting. --outputIOFormats=spec Type and format of each of the output tensors (default = all outputs in fp32:chw) Note: If this option is specified, please set comma-separated types and formats for all outputs following the same order as network outputs ID (even if only one output needs specifying IO format) or set the type and format once for broadcasting. IO Formats: spec ::= IOfmt[","spec] IOfmt ::= type:fmt type ::= "fp32"|"fp16"|"bf16"|"int32"|"int64"|"int8"|"uint8"|"bool" fmt ::= ("chw"|"chw2"|"hwc8"|"chw4"|"chw16"|"chw32"|"dhwc8"| "cdhw32"|"hwc"|"dla_linear"|"dla_hwc4"|"hwc16"|"dhwc")["+"fmt] --memPoolSize=poolspec Specify the size constraints of the designated memory pool(s) Supports the following base-2 suffixes: B (Bytes), G (Gibibytes), K (Kibibytes), M (Mebibytes). If none of suffixes is appended, the defualt unit is in MiB. Note: Also accepts decimal sizes, e.g. 0.25M. Will be rounded down to the nearest integer bytes. In particular, for dlaSRAM the bytes will be rounded down to the nearest power of 2. Pool constraint: poolspec ::= poolfmt[","poolspec] poolfmt ::= pool:size pool ::= "workspace"|"dlaSRAM"|"dlaLocalDRAM"|"dlaGlobalDRAM"|"tacticSharedMem" --profilingVerbosity=mode Specify profiling verbosity. mode ::= layer_names_only|detailed|none (default = layer_names_only). Please only assign once. --avgTiming=M Set the number of times averaged in each iteration for kernel selection (default = 8) --refit Mark the engine as refittable. This will allow the inspection of refittable layers and weights within the engine. --stripWeights Strip weights from plan. This flag works with either refit or refit with identical weights. Default to latter, but you can switch to the former by enabling both --stripWeights and --refit at the same time. --stripAllWeights Alias for combining the --refit and --stripWeights options. It marks all weights as refittable, disregarding any performance impact. Additionally, it strips all refittable weights after the engine is built. --weightless [Deprecated] this knob has been deprecated. Please use --stripWeights --versionCompatible, --vc Mark the engine as version compatible. This allows the engine to be used with newer versions of TensorRT on the same host OS, as well as TensorRT's dispatch and lean runtimes. --pluginInstanceNorm, --pi Set `kNATIVE_INSTANCENORM` to false in the ONNX parser. This will cause the ONNX parser to use a plugin InstanceNorm implementation over the native implementation when parsing. --uint8AsymmetricQuantizationDLA Set `kENABLE_UINT8_AND_ASYMMETRIC_QUANTIZATION_DLA` to true in the ONNX parser. This directs the onnx parser to allow UINT8 as a quantization data type and import zero point values directly without converting to float type or all-zero values. Should only be set with DLA software version >= 3.16. --useRuntime=runtime TensorRT runtime to execute engine. "lean" and "dispatch" require loading VC engine and do not support building an engine. runtime::= "full"|"lean"|"dispatch" --leanDLLPath=<file> External lean runtime DLL to use in version compatible mode. --excludeLeanRuntime When --versionCompatible is enabled, this flag indicates that the generated engine should not include an embedded lean runtime. If this is set, the user must explicitly specify a valid lean runtime to use when loading the engine. --monitorMemory Enable memory monitor report for debugging usage. (default = disabled) --sparsity=spec Control sparsity (default = disabled). Sparsity: spec ::= "disable", "enable", "force" Note: Description about each of these options is as below disable = do not enable sparse tactics in the builder (this is the default) enable = enable sparse tactics in the builder (but these tactics will only be considered if the weights have the right sparsity pattern) force = enable sparse tactics in the builder and force-overwrite the weights to have a sparsity pattern (even if you loaded a model yourself) [Deprecated] this knob has been deprecated. Please use <polygraphy surgeon prune> to rewrite the weights. --noTF32 Disable tf32 precision (default is to enable tf32, in addition to fp32) --fp16 Enable fp16 precision, in addition to fp32 (default = disabled) --bf16 Enable bf16 precision, in addition to fp32 (default = disabled) --int8 Enable int8 precision, in addition to fp32 (default = disabled) --fp8 Enable fp8 precision, in addition to fp32 (default = disabled) --int4 Enable int4 precision, in addition to fp32 (default = disabled) --best Enable all precisions to achieve the best performance (default = disabled) Note: --fp16, --bf16, --int8, --fp8, --int4, --best are deprecated and superseded by strong typing. The AutoCast tool (https://nvidia.github.io/TensorRT-Model-Optimizer/guides/8_autocast.html) can be used to convert the network to be strongly typed. --stronglyTyped Create a strongly typed network. (default = disabled) --directIO [Deprecated] Avoid reformatting at network boundaries. (default = disabled) --precisionConstraints=spec Control precision constraint setting. (default = none) Precision Constraints: spec ::= "none" | "obey" | "prefer" none = no constraints prefer = meet precision constraints set by --layerPrecisions/--layerOutputTypes if possible obey = meet precision constraints set by --layerPrecisions/--layerOutputTypes or fail otherwise --layerPrecisions=spec Control per-layer precision constraints. Effective only when precisionConstraints is set to "obey" or "prefer". (default = none) The specs are read left-to-right, and later ones override earlier ones. Each layer name can contain at most one wildcard ('*') character. Per-layer precision spec ::= layerPrecision[","spec] layerPrecision ::= layerName":"precision precision ::= "fp32"|"fp16"|"bf16"|"int32"|"int8" --layerOutputTypes=spec Control per-layer output type constraints. Effective only when precisionConstraints is set to "obey" or "prefer". (default = none The specs are read left-to-right, and later ones override earlier ones. Each layer name can contain at most one wildcard ('*') character. If a layer has more than one output, then multiple types separated by "+" can be provided for this layer. Per-layer output type spec ::= layerOutputTypes[","spec] layerOutputTypes ::= layerName":"type type ::= "fp32"|"fp16"|"bf16"|"int32"|"int8"["+"type] --layerDeviceTypes=spec Specify layer-specific device type. The specs are read left-to-right, and later ones override earlier ones. If a layer does not have a device type specified, the layer will opt for the default device type. Per-layer device type spec ::= layerDeviceTypePair[","spec] layerDeviceTypePair ::= layerName":"deviceType deviceType ::= "GPU"|"DLA" --decomposableAttentions=spec Specify decomposable attentions by comma-separated names. The specs are read left-to-right, and later ones override earlier ones. Each layer name can contain at most one wildcard ('*') character. --calib=<file> Read INT8 calibration cache file --safe Enable build safety certified engine, --stronglyTyped will be enabled by default with this option. If DLA is enabled, --buildDLAStandalone will be specified --dumpKernelText Dump the kernel text to a file, only available when --safe is enabled --buildDLAStandalone Enable build DLA standalone loadable which can be loaded by cuDLA, when this option is enabled, --allowGPUFallback is disallowed and --skipInference is enabled by default. Additionally, specifying --inputIOFormats and --outputIOFormats restricts I/O data type and memory layout (default = disabled) --allowGPUFallback When DLA is enabled, allow GPU fallback for unsupported layers (default = disabled) --consistency Perform consistency checking on safety certified engine --restricted Enable safety scope checking with kSAFETY_SCOPE build flag --saveEngine=<file> Save the serialized engine --loadEngine=<file> Load a serialized engine --asyncFileReader Load a serialized engine using async stream reader. Should be combined with --loadEngine. --getPlanVersionOnly Print TensorRT version when loaded plan was created. Works without deserialization of the plan. Use together with --loadEngine. Supported only for engines created with 8.6 and forward. --tacticSources=tactics Specify the tactics to be used by adding (+) or removing (-) tactics from the default tactic sources (default = all available tactics). Note: Currently only cuDNN, cuBLAS, cuBLAS-LT, and edge mask convolutions are listed as optional tactics. Tactic Sources: tactics ::= tactic[","tactics] tactic ::= (+|-)lib lib ::= "CUBLAS"|"CUBLAS_LT"|"CUDNN"|"EDGE_MASK_CONVOLUTIONS" |"JIT_CONVOLUTIONS" For example, to disable cudnn and enable cublas: --tacticSources=-CUDNN,+CUBLAS --noBuilderCache Disable timing cache in builder (default is to enable timing cache) --noCompilationCache Disable Compilation cache in builder, and the cache is part of timing cache (default is to enable compilation cache) --errorOnTimingCacheMiss Emit error when a tactic being timed is not present in the timing cache (default = false) --timingCacheFile=<file> Save/load the serialized global timing cache --preview=features Specify preview feature to be used by adding (+) or removing (-) preview features from the default Preview Features: features ::= feature[","features] feature ::= (+|-)flag flag ::= "aliasedPluginIO1003" |"runtimeActivationResize" |"profileSharing0806" --builderOptimizationLevel Set the builder optimization level. (default is 3) A Higher level allows TensorRT to spend more time searching for better optimization strategy. Valid values include integers from 0 to the maximum optimization level, which is currently 5. --maxTactics Set the maximum number of tactics to time when there is a choice of tactics. (default is -1) Larger number of tactics allow TensorRT to spend more building time on evaluating tactics. Default value -1 means TensorRT can decide the number of tactics based on its own heuristic. --hardwareCompatibilityLevel=mode Make the engine file compatible with other GPU architectures. (default = none) Hardware Compatibility Level: mode ::= "none" | "ampere+" | "sameComputeCapability" none = no compatibility ampere+ = compatible with Ampere and newer GPUs sameComputeCapability = compatible with GPUs that have the same Compute Capability version --runtimePlatform=platform Set the target platform for runtime execution. (default = SameAsBuild) When this option is enabled, --skipInference is enabled by default. RuntimePlatfrom: platform ::= "SameAsBuild" | "WindowsAMD64" SameAsBuild = no requirement for cross-platform compatibility. WindowsAMD64 = set the target platform for engine execution as Windows AMD64 system --tempdir=<dir> Overrides the default temporary directory TensorRT will use when creating temporary files. See IRuntime::setTemporaryDirectory API documentation for more information. --tempfileControls=controls Controls what TensorRT is allowed to use when creating temporary executable files. Should be a comma-separated list with entries in the format (in_memory|temporary):(allow|deny). in_memory: Controls whether TensorRT is allowed to create temporary in-memory executable files. temporary: Controls whether TensorRT is allowed to create temporary executable files in the filesystem (in the directory given by --tempdir). For example, to allow in-memory files and disallow temporary files: --tempfileControls=in_memory:allow,temporary:deny If a flag is unspecified, the default behavior is "allow". --maxAuxStreams=N Set maximum number of auxiliary streams per inference stream that TRT is allowed to use to run kernels in parallel if the network contains ops that can run in parallel, with the cost of more memory usage. Set this to 0 for optimal memory usage. (default = using heuristics) --profile Build with dynamic shapes using a profile with the min/max/opt shapes provided. Can be specified multiple times to create multiple profiles with contiguous index. (ex: --profile=0 --minShapes=<spec> --optShapes=<spec> --maxShapes=<spec> --profile=1 ...) --calibProfile Select the optimization profile to calibrate by index. (default = 0) --allowWeightStreaming Enable a weight streaming engine. Must be specified with --stronglyTyped. TensorRT will disable weight streaming at runtime unless --weightStreamingBudget is specified. --markDebug Specify list of names of tensors to be marked as debug tensors. Separate names with a comma --markUnfusedTensorsAsDebugTensors Mark unfused tensors as debug tensors --tilingOptimizationLevel Set the tiling optimization level. (default is 0) A Higher level allows TensorRT to spend more time searching for better optimization strategy. Valid values include integers from 0 to the maximum tiling optimization level(3). --l2LimitForTiling Set the L2 cache usage limit for tiling optimization(default is -1) --remoteAutoTuningConfig Set the remote auto tuning config. Must be specified with --safe. Format: protocol://username[:password]@hostname[:port]?param1=value1&param2=value2 Example: ssh://user:pass@192.0.2.100:22?remote_exec_path=/opt/tensorrt/bin&remote_lib_path=/opt/tensorrt/lib --refitFromOnnx Refit the loaded engine with the weights from the provided ONNX model. The model should be identical to the one used to generate the engine. === Inference Options === --shapes=spec Set input shapes for dynamic shapes inference inputs. Note: Input names can be wrapped with escaped single quotes (ex: 'Input:0'). Example input shapes spec: input0:1x3x256x256, input1:1x3x128x128 For scalars (0-D shapes), use input0:scalar or simply input0: with nothing after the colon. Each input shape is supplied as a key-value pair where key is the input name and value is the dimensions (including the batch dimension) to be used for that input. Each key-value pair has the key and value separated using a colon (:). Multiple input shapes can be provided via comma-separated key-value pairs, and each input name can contain at most one wildcard ('*') character. --loadInputs=spec Load input values from files (default = generate random inputs). Input names can be wrapped with single quotes (ex: 'Input:0') Input values spec ::= Ival[","spec] Ival ::= name":"file Consult the README for more information on generating files for custom inputs. --iterations=N Run at least N inference iterations (default = 10) --warmUp=N Run for N milliseconds to warmup before measuring performance (default = 200) --duration=N Run performance measurements for at least N seconds wallclock time (default = 3) If -1 is specified, inference will keep running unless stopped manually --sleepTime=N Delay inference start with a gap of N milliseconds between launch and compute (default = 0) --idleTime=N Sleep N milliseconds between two continuous iterations(default = 0) --infStreams=N Instantiate N execution contexts to run inference concurrently (default = 1) --exposeDMA Serialize DMA transfers to and from device (default = disabled). --noDataTransfers Disable DMA transfers to and from device (default = enabled). Note some device-to-host data transfers will remain if output dumping is enabled via the --dumpOutput or --exportOutput flags. --useManagedMemory Use managed memory instead of separate host and device allocations (default = disabled). --useSpinWait Actively synchronize on GPU events. This option may decrease synchronization time but increase CPU usage and power (default = disabled) --threads Enable multithreading to drive engines with independent threads or speed up refitting (default = disabled) --useCudaGraph Use CUDA graph to capture engine execution and then launch inference (default = disabled). This flag may be ignored if the graph capture fails. --timeDeserialize Time the amount of time it takes to deserialize the network and exit. --timeRefit Time the amount of time it takes to refit the engine before inference. --separateProfileRun Do not attach the profiler in the benchmark run; if profiling is enabled, a second profile run will be executed (default = disabled) --skipInference Exit after the engine has been built and skip inference perf measurement (default = disabled) --persistentCacheRatio Set the persistentCacheLimit in ratio, 0.5 represent half of max persistent L2 size (default = 0) --useProfile Set the optimization profile for the inference context (default = 0 ). --allocationStrategy=spec Specify how the internal device memory for inference is allocated. Strategy: spec ::= "static"|"profile"|"runtime" static = Allocate device memory based on max size across all profiles. profile = Allocate device memory based on max size of the current profile. runtime = Allocate device memory based on the actual input shapes. --saveDebugTensors Specify list of names of tensors to turn on the debug state and filename to save raw outputs to. These tensors must be specified as debug tensors during build time. Input values spec ::= Ival[","spec] Ival ::= name":"file --saveAllDebugTensors Save all debug tensors to files. Including debug tensors marked by --markDebug and --markUnfusedTensorsAsDebugTensors Multiple file formats can be saved simultaneously. Input values spec ::= format[","format] format ::= "summary"|"numpy"|"string"|"raw" --weightStreamingBudget Set the maximum amount of GPU memory TensorRT is allowed to use for weights. It can take on the following values: -2: (default) Disable weight streaming at runtime. -1: TensorRT will automatically decide the budget. 0-100%: Percentage of streamable weights that reside on the GPU. 0% saves the most memory but will have the worst performance. Requires the '%' character. >=0B: The exact amount of streamable weights that reside on the GPU. Supports the following base-2 suffixes: B (Bytes), G (Gibibytes), K (Kibibytes), M (Mebibytes). === Reporting Options === --verbose Use verbose logging (default = false) --avgRuns=N Report performance measurements averaged over N consecutive iterations (default = 10) --percentile=P1,P2,P3,... Report performance for the P1,P2,P3,... percentages (0<=P_i<=100, 0 representing max perf, and 100 representing min perf; (default = 90,95,99%) --dumpRefit Print the refittable layers and weights from a refittable engine --dumpOutput Print the output tensor(s) of the last inference iteration (default = disabled) --dumpRawBindingsToFile Print the input/output tensor(s) of the last inference iteration to file(default = disabled) --dumpProfile Print profile information per layer (default = disabled) --dumpLayerInfo Print layer information of the engine to console (default = disabled) --dumpOptimizationProfile Print the optimization profile(s) information (default = disabled) --exportTimes=<file> Write the timing results in a json file (default = disabled) --exportOutput=<file> Write the output tensors to a json file (default = disabled) --exportProfile=<file> Write the profile information per layer in a json file (default = disabled) --exportLayerInfo=<file> Write the layer information of the engine in a json file (default = disabled) === System Options === --device=N Select cuda device N (default = 0) --useDLACore=N Select DLA core N for layers that support DLA (default = none) --staticPlugins Plugin library (.so) to load statically (can be specified multiple times) --dynamicPlugins Plugin library (.so) to load dynamically and may be serialized with the engine if they are included in --setPluginsToSerialize (can be specified multiple times) --setPluginsToSerialize Plugin library (.so) to be serialized with the engine (can be specified multiple times) --ignoreParsedPluginLibs By default, when building a version-compatible engine, plugin libraries specified by the ONNX parser are implicitly serialized with the engine (unless --excludeLeanRuntime is specified) and loaded dynamically. Enable this flag to ignore these plugin libraries instead. --safetyPlugins Plugin library (.so) for TensorRT auto safety to manually load safety plugins specified by the command line arguments. Example: --safetyPlugins=/path/to/plugin_lib.so[pluginNamespace1::plugin1,pluginNamespace2::plugin2]. The option can be specified multiple times with different plugin libraries. === Help === --help, -h Print this message [11/27/2025-14:33:27] [E] Model missing or format not recognized &&&& FAILED TensorRT.trtexec [TensorRT v101401] [b48] # trtexec --version
最新发布
11-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值