Recently, some commonly used buttons have been added to the status bar, including home, menu, and Back buttons,
Simulate messages when the physical button is pressed,
Refer to the following two articles to add custom buttons on the status bar,
1.
Add Shortcut Keys menu, home, and back in the statusbar of Android.
Http://blogold.chinaunix.net/u2/78893/showart_2349971.html
2.
Add Shortcut Keys menu, home, and back in the statusbar of Android, and analyze the causes of Button latency.
Http://hi.baidu.com/tigerpan/blog/item/63caae81b57580b16c811937.html
However, when you click a button on the status bar, deadlocks and false positives often occur. As mentioned in the second article,
Let's take a look at the execution process.
In the com. Android. server. windowmanagerservice. injectkeyevent (keyevent, Boolean) function, we can see that the dispatchkey (newevent, PID, UID) function is actually called. In this dispatchkey function:
You need to first find the current focus focusobj (focusobj: windowstate is the association between viewroot and windowmanagerservice in the maintenance window, and the communication between the two can be found in windowstate ); use focusobj to pass the keyevent to the current focus window. However, mkeywaiter is called before transmission. the waitfornexteventtarget () function waits for the current focus to process the last event (this includes keyevent, motionevent... ), how to determine whether to process the last event, use if (mfinished &&! Mdisplayfrozen) if (targetwin! = NULL) These two if statements are judged, and the most critical is the mfinished. Here we have to check viewroot. After the event is distributed in viewroot, swindowsession will be called. finishkey (mwindow); tells windowmanagerservice that mfinished = true is set in the dofinishedkeylocked () function. If mfinished is not true, wait (curtimeout) is used. This is the direct cause of pause.
Print the log to display our keyevent. action_down events cannot be mfinished all the time, so we need to track viewroot and find the simulated keyevent each time. the message of the action_down event cannot be processed at all, because the touchevent of statusbarview is not processed completely and is similar to the simulated keyevent. the action_down event is stuck in the next function of messagequeue, and viewroot itself is a handler. A large number of messages are passed by. The viewroot of statusbar must process both touch events and analog buttons, this kind of race deadlock occurs.
The keyevent for delayed sending simulation is my current solution. The sendKey function has been shown in the above example.
This is probably when you click the button (I personally understand). If you directly send the keyevent In The onclick event, The onclick message cannot be returned normally, as a result, the subsequent messages cannot be obtained and processed, which is the cause of a false pause. Therefore, refer to the above method to create a new thread, delayed sending of keyevent (I have not solved the problem by using the method of article 2 ).
Private void sendvkeydelay (INT key) {<br/> final int keycode = key; <br/> thread sendkeydelay = new thread () {<br/> Public void run () {<br/> try {<br/> thread. sleep (100); </P> <p> long now = systemclock. uptimemillis (); <br/> keyevent keydown = new keyevent (now, now, keyevent. action_down, <br/> keycode, 0); <br/> iwindowmanager WM = iwindowmanager. stub. asinterface (<br/> servicemanager. getservice ("window"); <br/> WM. injectkeyevent (keydown, false); </P> <p> keyevent keyup = new keyevent (now, now, keyevent. action_up, <br/> keycode, 0); <br/> WM. injectkeyevent (keyup, false); <br/>} catch (interruptedexception e) {<br/> E. printstacktrace (); <br/>} catch (RemoteException e) {<br/> E. printstacktrace (); <br/>}< br/>}; <br/> sendkeydelay. start (); <br/>}