Analysis of the problem that the Touch Event caused by Android5.0L exiting the horizontal and vertical screen switching of the APP is invalid (frozen screen) (the Key Event is still valid)
I. symptom
1. For apps that require forced horizontal screen access for multiple times, such as Real FootBall2015, when exiting the app, there is a probability that the app will exit choppy, and then the TP cannot be entered.
2. When a problem occurs, the Power key responds.
3. This problem also occurs on Driver only.
Platform: MSM8916
Android: 5.0.2L
BuildType: user
System software version: vA6P + L5P0
System RAM: 1 GB
Reference machine behavior:
1. ALTO4.5TMO did not reproduce this problem in the same simple test. After analyzing the code, it is found that 4.4.4KK and 5.0.2L have different mechanisms. The following describes the specific comparative analysis process.
2. Nexus4 and Nexus5 did not reproduce this problem in the same simple test. Because there is no source code, the Debug and log printing are not allowed. In the future, we will try to obtain the source code of nexus to understand its modification solution.
Ii. Solutions
Through preliminary analysis, in-depth analysis, and comparative analysis (the specific analysis process, key code, and log will be attached below) we have clearly understood the cause, process, and normal process of the problem, and many conditions have played a key role in this problem, which eventually leads to an endless loop of problems. If it is an emergency backup solution, we can determine the conditions in any key conditions to avoid such problems, but if it is a long-term final solution, we need to solve it from the source of the problem.
Clarify the root cause of the problem:
1. The animation execution depends on the VSYNC signal, but the arrival of the VSYNC signal is regular and cannot be forced to happen under 16.66ms.
2. win death and app death are irregular and may occur at any time point.
3. to exit the Window, you need to switch the landscape to the portrait screen, and you need to freeze the screen and input.
4. Restore the screen and restore the input. All windows must be Rotate ready.
5. When a problem occurs, the exit window must be processed before the screen and input are frozen, so that the finishExit can meet the Rotate ready condition.
Once the exit window is not frozen before the screen is frozen or input, the processing of the exit animation will become a fuse that triggers an endless loop of problems.
To address the root cause of the above problems, we provide the following solutions:
1. Cut off the fuse
If the frozen VSYNC is not synchronized with the animation due to a large mechanism, the exit animation of the exit window is frozen, therefore, you do not need to execute the exit animation. You need to clear the animation to be executed and ensure that the finishExit operation is normal to meet the Rotate ready condition, let the system's normal mechanism for recovery. The AOSP code has taken into account the arrival of VSYNC but there is also a window animation, but it does not take into account the exit animation situation, therefore, with no major impact, we have added a new exit animation condition judgment in the original AOSP mechanism to solve the problem.
2. native code and comments
The above Code clearly shows that if the screen has frozen okToDisplay, it will be false, so the code body in if will not be executed, so the animation status will not be updated, so the following will be returned directly. In addition, we can also see that there is another condition and its comments, clearly indicating that if the screen has been frozen but there is a window animation (not an exit animation), then we can clear the animation, make sure to execute the following cleanup code, but unfortunately this condition does not include the exit animation of the current problem, so the normal finishExit cleanup Code cannot be executed. Work in finishExit is also crucial, the Code is as follows:
Through the above code, we can see that finishExit mainly performs several key actions. First, finishExit all the subwindows in the current window, and then add the window to the list of surface to be destroyed, at the same time, set mDeferRemoval to false, which is very important and directly affects whether the mDeferRemoval of the apptoken we analyzed can be deleted normally. At the same time, add the window to the list to be deleted, this is the list to be deleted.
3. Final modified code scheme
We need to modify a line of code to solve this problem perfectly in the original mechanism process. The specific code is as follows:
If the screen and input have been frozen, but the exit animation of the window is not yet executed, set the normal execution animation status to true to ensure that the finishExit is executed properly and the normal process is finally resumed, solve the problem.
Iii. Preliminary Analysis
Take a typical log generated when an Idol347 problem occurs as an example. When a problem occurs, the log contains a large amount of information as follows:
By checking the code, we can see that the above log is written in the dispatchOnceInnerLocked of InputDispatcher. The details are as follows:
Through the above code, we can find that this log is printed only when the mDispatchFrozen condition is true.
When is the mDispatchFrozen condition set to true?Find the answer in the Code:
Through the above code, we can find that the mDispatchFrozen is set in the setInputDispatchMode function. Next, we will continue to see where to call the setInputDispatchMode. By checking the code, we can find that it was all the way from WindowManagerService, JNI is passed in the process, as follows:
In what scenarios will WindowManagerService freeze input? By viewing the code and adding logs, we can view the specific call stack information when a problem occurs:
Through the specific call stack, we can find that the ActivityManagerService will resume the next app when processing the app death notification. During the resume process, it will call the WindowManagerService method to check whether screen conversion is required, if you want to convert the screen, call startFreezingDisplayLocked to freeze the display. The input will be frozen during the display Freezing Process:
Now that you know the scenario of freezing input, there is another more important question. In what scenarios will WindowManagerService restore normal input? If there is a freeze, it will be restored. continue to view the code and call stack information:
From the call stack information, we can find that during the process of processing the app died notification and resume the next app, we will call the unfreeze display and the unfreeze display process will unfreeze the input, however, we can see from the log that when a problem occurs, the unfreeze display function returns the result because the mWindowsFreezingScreen condition is true Before restoring the input. Therefore, the input does not return to normal. After preliminary analysis, the first problem has been found: If mWindowsFreezingScreen is set to true, the input cannot be restored and restored. But why is the mWindowsFreezingScreen condition true? Is it only this place that will be restored? We will continue to analyze these two questions.
Iv. In-depth analysis of problems
After a preliminary analysis, we found the first problem and two problems. Next, we will analyze the problem in depth to find the root cause of the problem.
1. Why is the mWindowsFreezingScreen condition true?
2. Where can I restore normal input?
By checking the code, we can find that mWindowsFreezingScreen has two places set to true and one place set to false:
Through the above code, we can know that if you want to screen the updateRotationUncheckedLocked, mWindowsFreezingScreen will be set to true once, and if the screen has been frozen when you call makeWindowFreezingScreenIfNeededLocked each time, mWindowsFreezingScreen will also be set to true. However, if you set mWindowsFreezingScreen to false, the input is restored when you set it to false. This indirectly answers our second question. In addition to the first place in the preliminary analysis to unfreeze the input, there is also a place to unfreeze the input, that is, restore mlayoutandplacesurfaceslockedinner:
This function is a very important function of WindowManagerService. Based on the name, we can know the first and second functions of this function. It mainly manages various statuses such as layout, calculation, window removal, and animation scheduling, it is a function with a very high call frequency. Any changes to the window status will be executed here. If mWindowsFreezingScreen is set to false, a condition must be met, that is, mInnerFields. mOrientationChangeComplete must be true. We will continue to trace mInnerFields. when mOrientationChangeComplete is set to true, it is found that there is only one place mInnerFields. mOrientationChangeComplete is set to true. The Code is as follows:
After analysis, we can see that it has a relationship with Animation and continue to trace the call relationship. We found that copyAnimToLayoutParamsLocked was called in the animateLocked of WindowAnimator, the animateLocked is called by the Choreographer FrameDisplayEventReceiver after the VSYNC signal is sent. The call stack is as follows:
Before copyAnimToLayoutParamsLocked is called, animateLocked first calls updateWindowsLocked to update the animation of all applications, including exiting and deleted applications, and then calls WindowStateAnimator's prepareSurfaceLocked to calculate the corresponding state, the Code is as follows:
When updateWindowsLocked is executed, the stepAnimationLocked of WindowStateAnimator is called. This function plays a critical role in this issue. The following describes the function.
ActivityManagerService does not synchronize the processing Window died and animation with WindowManagerService when processing app died, therefore, the exit animation of Window died may not be able to wait until the next VSYNC (16.666ms once) to execute an animation operation, the screen and input will be frozen by ActivityManagerService when resume's next app needs to be switched to the screen. When the next VSYNC comes, it will execute the exit animation of window died and it will find that the screen has been frozen, as a result, the window of finishExit cannot be returned directly, which becomes the most critical point of this problem.
The key processing code of Window died is as follows:
PerformLayoutAndPlaceSurfacesLocked will eventually be called to performLayoutAndPlaceSurfacesLockedInner, and then the window size calculation and related status updates will be executed. The key operation that affects this issue is to call updateResizingWindows:
Because of window dead, the window and visible content and size have changed. Therefore, makeWindowFreezingScreenIfNeededLocked will be called. This function will determine whether the screen has been frozen. If it has been frozen, mInnerFields will be called. mOrientationChangeComplete is always set to false, although WindowAnimator will call copyAnimToLayoutParamsLocked to replace mInnerFields. mOrientationChangeComplete is set to true. However, after copyAnimToLayoutParamsLocked is executed, requestTraversalLocked needs to be called to execute receivmlayoutandplacesurfaceslocked. Therefore, it is set to false again by the handler, in fact, the Window content and major changes will be updated during the execution of javasmlayoutandplacesurfaceslocked. Normally, the conditions for executing makeWindowFreezingScreenIfNeededLocked will not always be met. The specific code is as follows:
However, the current situation is special, because the Window has ended, so mClient is called. resized will cause RemoteException, so that the status in the code above cannot be set to false. As a result, the conditions for calling makeWindowFreezingScreenIfNeededLocked are always met, and WindowManagerService cannot unfreeze the screen or restore the input, here, an endless loop of unfrozen and normal input will be formed together with the stepAnimationLocked processing of WindowStateAnimator.
Where is the endless loop?
1. Window exits and calls the removeWindowLocked of WindowManagerService.
2. removeWindowLocked will execute the exit animation, call receivmlayoutandplacesurfaceslocked for a calculation and State Processing, schedule the animation, and put it in the processing list of the next vsync, because the animation has not been processed, mInnerFields. mOrientationChangeComplete is not true, so mWindowsFreezingScreen is not set to false, and the screen and input are not restored and restored.
3. After the ActivityManagerService receives the notification from the app died, the next app is resume. The next app is different from the current ending orientation, triggering the freezing of the screen and input.
4. When VSYNC arrives, the animation-related operations will be executed. Because the screen has been frozen, the exit Window will not be able to execute the animation operation and directly return the result. As a result, finishExit will not be executed, the final Window will not be deleted normally. Run copyAnimToLayoutParamsLocked to set mInnerFields. mOrientationChangeComplete to true, and then call requestTraversalLocked to send the message to the message queue for the next execution.
5. Execute performLayoutAndPlaceSurfacesLocked and call updateResizingWindows. Because the exited Window is not finishExit and the Window size and content status are updated by executing reportResized, mClient is called because the Window has exited. remoteException occurs when resized executes IPC (cross-process call). As a result, the key status value is not reset. Therefore, during the execution of updateResizingWindows, makeWindowFreezingScreenIfNeededLocked is called because the Window status has always met the conditions, because the window has been frozen, the mInnerFields. mOrientationChangeComplete is always set to false, so mWindowsFreezingScreen is not set to false, and stopFreezingDisplayLocked is called to unfreeze the screen and restore the input. ScheduleAnimationLocked is called to schedule the next animation to the VSYNC list.
6. When the next VSYNC arrives, repeat steps 4 and 5 to form an endless loop where the screen cannot be restored or the input is restored.
V. Mechanism differences between KK4.4.4 and L5.0.2
1. L5.0.2 new condition mDeferRemoval
After receiving the dead notification of the app, ActivityManagerService calls the removeAppToken of WindowManagerService. The specific code and call relationship are as follows:
In the removeAppToken process, KK4.4.4 has some differences with L5.0.2. L5.0.2 adds a new condition mDeferRemoval. to process this condition L5.0.2, some code is added to complete this mechanism feature together, the key code is as follows:
The key code for kkk4.4.4 is as follows:
The mDeferRemoval condition affects the deletion of apptoken and the deletion of the Window associated with apptoken in the mDeferRemoval apptokens. It is also strongly related to the animation being executed or exiting, through the above analysis and code, we know that there is an endless loop in WindowManagerService when a problem occurs. Therefore, when checkForDeferredActions is called during the execution of javasmlayoutandplacesurfaceslocked, stack. the isAnimating () condition will always be met, because there is an exit window that has not been finishExit, so the deletion of the mExitingAppTokens will not be performed, so the apptoken will always exist, the Window associated with this apptoken also exists.
KK4.4.4 does not have the mDeferRemoval condition. Therefore, the apptoken will be deleted during the procedure of migrating mlayoutandplacesurfaceslocked.
In addition, when kkk4.4.4 freezes the screen and then VSYNC executes the animation, the Window is not stored in the WindowList by finishExit, but KK4.4.4 does not have the mDeferRemoval mechanism, therefore, when rebuildAppWindowListLocked is enabled, finishExit will fail, but its apptoken has been deleted from the window deleted by task and exitingAppTokens, MTK also adds a patch to completely remove the Window to prevent Window leakage. The specific code is as follows:
Therefore, when you exit the forced landscape screen window and enter launcher, finishExit cannot be performed normally, if you do not enter other apps, you can use adb shell dumpsys | grep "game" to see that this window is still in progress. However, when you enter other app windows, handleAppTransitionReadyLocked will be called, then call rebuildAppWindowListLocked to delete it. You cannot see the finishExit window after executing the above command because of the mechanism and code analyzed above.
2. L5.0.2 use NavigationBar with virtual buttons
Because L5.0.2 uses a NavigationBar with a virtual key, when the window that exits the forced landscape screen app returns to Launcher, the layout conditions for using the solid button on the KK4.4.4 mobile phone in config change are different. L5.0.2 during layout, the rotate will cause config change from full screen display to exit to launcher, so a layout is executed and the NavigationBar area needs to be updated, therefore, when computeFrameLw is executed, mContentFrame changes, causing mContentInsets changes. the setInsetsChanged () condition is met. Since the Window size and content status are updated during the execution of reportResized, mClient is called because the Window has exited. remoteException occurs when resized executes IPC (cross-process call). As a result, the key state value is not set to be cleared, so the same is true here. The layout conditions will always be met, the specific key code in performLayoutLockedInner is as follows:
Win. mLayoutSeq: This condition affects the persistence of the window freezing status and the placement of the mInnerFields. mOrientationChangeComplete status. The key code is as follows:
The layout parameter log after the execution window rotate is as follows:
In the Red Circle parameter, cf is the size of the contentframe rectangle, which is calculated with the frame to obtain a ci, because the screen is changed from full screen to launcher, therefore, the NavigationBar is computed and refreshed, so the ci is different from the previous w. setInsetsChanged (); true, w. mContentInsetsChanged is true.
Because the NavigationBar is not used in KK4.4.4, the above conditions are not met. In this experiment, I open the NavigationBar of kkk4.4.4. In the same case, the above conditions are met, but KK4.4.4 will not be frozen, because the KK4.4.4 mentioned in my reference has MTK patch, a condition is added: mDisplayFrozenTimeout. After WINDOW_FREEZE_TIMEOUT, mDisplayFrozenTimeout will be set to true, therefore, the code that keeps the screen frozen in the makeWindowFreezingScreenIfNeededLocked function will not be displayed, as shown below:
In addition, there is another modification in KK4.4.4 that can be referenced by me, which will directly affect this problem. In WindowAnimator, a code is added to determine that the screen conversion animation ends and the input is restored. The details are as follows:
The above differences make the kkk4.4.4 of the mtk I will not encounter the problem that the frozen screen cannot be entered.
Vi. Follow-up actions and other related questions
1. Try to get the Nexus source code to understand its solution
2. The temporary scheme of force unfreezing and restoring input during Window Freezing timeout, as well as the problems it may cause:
The first problem is: Why does the Window Freezing timeout occur every time the application that forces the landscape screen to be applied to the portrait screen?
Analysis: Because the window being exited is not finishExit, it will always exist and affect mInnerFields. the mOrientationChangeComplete condition is always false. Therefore, the restored code and the app transition code will not be executed normally, leading to force unfreezing and restoring the input after timeout. The key code is as follows:
The second problem is: Why does the screen rotation wait for Window Freezing timeout in the same application?
The same principle applies to the first problem. Because there is a window that is not finishExit, stopFreezingDisplayLocked will not be executed in a timely manner, while stopFreezingDisplayLocked will perform the ScreenRotationAnimation dismiss operation, dismiss will give the ScreenRotationAnimation to start and then execute the ScreenRotationAnimation. The key code is as follows:
Analyzed by vincent. song from SWD2 Framework team.
Vincent.song@tcl.com
201504231130