background
The company does system applications, so it needs to provide an interface to disable the status bar drop – down. This feature itself has already been implemented. But the solution, which worked fine on Android 9 and 10, suffered from a failure to disable dropdowns on Android 11.
Solution on Android 9 and 10 (basically the same)
Defines a field to control the pull – off. Pay attention to. Start with persist. Sys instead of sys.*. The sys.* parameter value is saved in memory and will be invalid on restart. This definition persist. Sys. Statusbar. Prohibit. frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
public class DragDownHelper implements Gefingerpoken{...// In the first line of onInterceptTouchEvent, judge
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (isStatusBarDragDownProhibited()) {
return false; }... }public boolean onTouchEvent(MotionEvent event) {
if(! mDraggingDown) {return false;
}
/ / code 1
if (isStatusBarDragDownProhibited()) {
return false; }}private boolean isStatusBarDragDownProhibited(a) {
return SystemProperties.getBoolean("persist.sys.statusbar.prohibit".false); }}Copy the code
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
public class StatusBar.{...public boolean interceptTouchEvent(MotionEvent event) {
if (DEBUG_GESTURES) {
if(event.getActionMasked() ! = MotionEvent.ACTION_MOVE) { EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH, event.getActionMasked(), (int) event.getX(), (int) event.getY(), mDisabled1, mDisabled2); }}if (SPEW) {
Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1="
+ mDisabled1 + " mDisabled2=" + mDisabled2);
} else if (CHATTY) {
if(event.getAction() ! = MotionEvent.ACTION_MOVE) { Log.d(TAG, String.format("panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x", MotionEvent.actionToString(event.getAction()), event.getRawX(), event.getRawY(), mDisabled1, mDisabled2)); }}if (DEBUG_GESTURES) {
mGestureRec.add(event);
}
// Code 2 intercepts the event
if (isStatusBarDragDownProhibited()) {
return true;
}
if (mStatusBarWindowState == WINDOW_STATE_SHOWING) {
final boolean upOrCancel =
event.getAction() == MotionEvent.ACTION_UP ||
event.getAction() == MotionEvent.ACTION_CANCEL;
if(upOrCancel && ! mExpandedVisible) { setInteracting(StatusBarManager.WINDOW_STATUS_BAR,false);
} else {
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); }}return false;
}
private boolean isStatusBarDragDownProhibited(a) {
return SystemProperties.getBoolean("persist.sys.statusbar.prohibit".false); }}Copy the code
Changes to Android 11
In Android 11, there is a bug that causes the status bar to drop down if you swipe in the middle of the screen. Why does this problem arise?
Falling in the middle of the screen, the event will go to OverviewProxyService. OnStatusBarMotionEvent method. This approach, however, differs between Android 10 and 11.
The code in Android 10 is as follows
class OverviewProxyService {
@Override
public void onStatusBarMotionEvent(MotionEvent event) {
if(! verifyCaller("onStatusBarMotionEvent")) {
return;
}
long token = Binder.clearCallingIdentity();
try {
// TODO move this logic to message queue
mHandler.post(()->{
StatusBar bar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
if(bar ! =null) {
/ / code 1
bar.dispatchNotificationsPanelTouchEvent(event);
int action = event.getActionMasked();
if (action == ACTION_DOWN) {
mStatusBarGestureDownEvent = MotionEvent.obtain(event);
}
if (action == ACTION_UP || action == ACTION_CANCEL) {
mStatusBarGestureDownEvent.recycle();
mStatusBarGestureDownEvent = null; } event.recycle(); }}); }finally{ Binder.restoreCallingIdentity(token); }}}Copy the code
As shown above in the android 10. Call the bar dispatchNotificationsPanelTouchEvent (event); . This method is the final call to NotificationsPanelView onTouchEvent method, in this method, have banned the drop-down intercept processing.
Here’s the code for Android 11
class OverviewProxyService{
@Override
public void onStatusBarMotionEvent(MotionEvent event) {
if(! verifyCaller("onStatusBarMotionEvent")) {
return;
}
long token = Binder.clearCallingIdentity();
try {
// TODO move this logic to message queue
mStatusBarOptionalLazy.ifPresent(statusBarLazy -> {
mHandler.post(()-> {
StatusBar statusBar = statusBarLazy.get();
int action = event.getActionMasked();
if (action == ACTION_DOWN) {
mInputFocusTransferStarted = true;
mInputFocusTransferStartY = event.getY();
mInputFocusTransferStartMillis = event.getEventTime();
/ / code 1
statusBar.onInputFocusTransfer(
mInputFocusTransferStarted, false /* cancel */.0 /* velocity */);
}
if (action == ACTION_UP || action == ACTION_CANCEL) {
mInputFocusTransferStarted = false;
statusBar.onInputFocusTransfer(mInputFocusTransferStarted,
action == ACTION_CANCEL,
(event.getY() - mInputFocusTransferStartY)/ (event.getEventTime() - mInputFocusTransferStartMillis));
}
event.recycle();
});
});
} finally{ Binder.restoreCallingIdentity(token); }}}Copy the code
11 of the android calls the statusBar. OnInputFocusTransfer method, Through the following process StatusBar. OnInputFocusTransfer – > NotificationPanelViewController# stopWaitingForOpenPanelGesture – > NotificationPanelViewController# fling – > PanelViewController# fling – > NotificationPanelViewController# flingToHeight without it OnTouch method, so it is not intercepted.
Android 11 disables the status bar dropdown
Modify the panelsEnabled method on CommoneQueue
public boolean panelsEnabled(a) {
final int disabled1 = getDisabled1(DEFAULT_DISPLAY);
final int disabled2 = getDisabled2(DEFAULT_DISPLAY);
return (disabled1 & StatusBarManager.DISABLE_EXPAND) == 0
&& (disabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0&&! ONLY_CORE_APPS && ! isStatusBarDragDownProhibited(); }private boolean isStatusBarDragDownProhibited(a){
return SystemProperties.getBoolean("sys.statusbar.dragdown.prohibit".false);
}
Copy the code
In the onInputFocusTransfer method, the drop – down operation is intercepted.
class SatusBar{
public void onInputFocusTransfer(boolean start, boolean cancel, float velocity) {
if(! mCommandQueue.panelsEnabled()) {return;
}
if (start) {
mNotificationPanelViewController.startWaitingForOpenPanelGesture();
} else{ mNotificationPanelViewController.stopWaitingForOpenPanelGesture(cancel, velocity); }}}Copy the code