Tapping outside the status bar panels closes them.

Bug: 2994011
Change-Id: I0c5a28de5269f4136e6b118d5f6ac4aa38cd6d07
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml
index ba7029d9..cf5b9c7 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml
@@ -16,7 +16,7 @@
 -->
 
 <!--    android:background="@drawable/status_bar_closed_default_background" -->
-<FrameLayout
+<com.android.systemui.statusbar.tablet.TabletStatusBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:background="@drawable/status_bar_background"
@@ -132,5 +132,5 @@
         android:visibility="invisible"
         android:clickable="true"
         />
-</FrameLayout>
+</com.android.systemui.statusbar.tablet.TabletStatusBarView>
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
index c4819a4..ea61ad0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -34,6 +34,7 @@
 import android.view.animation.AnimationUtils;
 import android.view.Gravity;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
@@ -55,8 +56,13 @@
 
 public class TabletStatusBarService extends StatusBarService {
     public static final boolean DEBUG = false;
-    public static final String TAG = "TabletStatusBar";
+    public static final String TAG = "TabletStatusBarService";
 
+    public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
+    public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
+    public static final int MSG_OPEN_SYSTEM_PANEL = 1010;
+    public static final int MSG_CLOSE_SYSTEM_PANEL = 1011;
+    
     private static final int MAX_IMAGE_LEVEL = 10000;
 
     int mIconSize;
@@ -66,8 +72,9 @@
     // tracking all current notifications
     private NotificationData mNotns = new NotificationData();
     
-    View mStatusBarView;
+    TabletStatusBarView mStatusBarView;
     NotificationIconArea mNotificationIconArea;
+    View mSystemInfo;
 
     View mNotificationPanel;
     SystemPanel mSystemPanel;
@@ -99,6 +106,10 @@
 
         mNotificationPanel = View.inflate(this, R.layout.sysbar_panel_notifications, null);
         mNotificationPanel.setVisibility(View.GONE);
+        mNotificationPanel.setOnTouchListener(
+                new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL));
+
+        mStatusBarView.setIgnoreChildren(0, mNotificationIconArea, mNotificationPanel);
 
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 400, // ViewGroup.LayoutParams.WRAP_CONTENT,
@@ -118,6 +129,9 @@
 
         mSystemPanel = (SystemPanel) View.inflate(this, R.layout.sysbar_panel_system, null);
         mSystemPanel.setVisibility(View.GONE);
+        mSystemPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_SYSTEM_PANEL));
+
+        mStatusBarView.setIgnoreChildren(1, mSystemInfo, mSystemPanel);
 
         lp = new WindowManager.LayoutParams(
                 800,
@@ -147,14 +161,17 @@
 
         mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
 
-        final View sb = View.inflate(this, R.layout.status_bar, null);
+        final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
+                this, R.layout.status_bar, null);
         mStatusBarView = sb;
 
+        sb.setHandler(mHandler);
+
         mBarContents = sb.findViewById(R.id.bar_contents);
         mCurtains = sb.findViewById(R.id.lights_out);
-        View systemInfo = sb.findViewById(R.id.systemInfo);
+        mSystemInfo = sb.findViewById(R.id.systemInfo);
 
-        systemInfo.setOnLongClickListener(new SetLightsOnListener(false));
+        mSystemInfo.setOnLongClickListener(new SetLightsOnListener(false));
 
         SetLightsOnListener on = new SetLightsOnListener(true);
         mCurtains.setOnClickListener(on);
@@ -193,10 +210,6 @@
     }
 
     private class H extends Handler {
-        public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
-        public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
-        public static final int MSG_OPEN_SYSTEM_PANEL = 1010;
-        public static final int MSG_CLOSE_SYSTEM_PANEL = 1011;
         public void handleMessage(Message m) {
             switch (m.what) {
                 case MSG_OPEN_NOTIFICATION_PANEL:
@@ -446,15 +459,15 @@
     }
 
     public void animateExpand() {
-        mHandler.removeMessages(H.MSG_OPEN_NOTIFICATION_PANEL);
-        mHandler.sendEmptyMessage(H.MSG_OPEN_NOTIFICATION_PANEL);
+        mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
+        mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
     }
 
     public void animateCollapse() {
-        mHandler.removeMessages(H.MSG_CLOSE_NOTIFICATION_PANEL);
-        mHandler.sendEmptyMessage(H.MSG_CLOSE_NOTIFICATION_PANEL);
-        mHandler.removeMessages(H.MSG_CLOSE_SYSTEM_PANEL);
-        mHandler.sendEmptyMessage(H.MSG_CLOSE_SYSTEM_PANEL);
+        mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PANEL);
+        mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
+        mHandler.removeMessages(MSG_CLOSE_SYSTEM_PANEL);
+        mHandler.sendEmptyMessage(MSG_CLOSE_SYSTEM_PANEL);
     }
 
     public void setLightsOn(boolean on) {
@@ -478,24 +491,18 @@
 
     public void notificationIconsClicked(View v) {
         if (DEBUG) Slog.d(TAG, "clicked notification icons");
-        mHandler.removeMessages(H.MSG_CLOSE_SYSTEM_PANEL);
-        mHandler.sendEmptyMessage(H.MSG_CLOSE_SYSTEM_PANEL);
-
         int msg = (mNotificationPanel.getVisibility() == View.GONE) 
-            ? H.MSG_OPEN_NOTIFICATION_PANEL
-            : H.MSG_CLOSE_NOTIFICATION_PANEL;
+            ? MSG_OPEN_NOTIFICATION_PANEL
+            : MSG_CLOSE_NOTIFICATION_PANEL;
         mHandler.removeMessages(msg);
         mHandler.sendEmptyMessage(msg);
     }
 
     public void systemInfoClicked(View v) {
         if (DEBUG) Slog.d(TAG, "clicked system info");
-        mHandler.removeMessages(H.MSG_CLOSE_NOTIFICATION_PANEL);
-        mHandler.sendEmptyMessage(H.MSG_CLOSE_NOTIFICATION_PANEL);
-
         int msg = (mSystemPanel.getVisibility() == View.GONE) 
-            ? H.MSG_OPEN_SYSTEM_PANEL
-            : H.MSG_CLOSE_SYSTEM_PANEL;
+            ? MSG_OPEN_SYSTEM_PANEL
+            : MSG_CLOSE_SYSTEM_PANEL;
         mHandler.removeMessages(msg);
         mHandler.sendEmptyMessage(msg);
     }
@@ -741,6 +748,23 @@
         }
 
     }
+
+    public class TouchOutsideListener implements View.OnTouchListener {
+        private int mMsg;
+
+        public TouchOutsideListener(int msg) {
+            mMsg = msg;
+        }
+
+        public boolean onTouch(View v, MotionEvent ev) {
+            if (ev.getAction() == MotionEvent.ACTION_OUTSIDE) {
+                mHandler.removeMessages(mMsg);
+                mHandler.sendEmptyMessage(mMsg);
+                return true;
+            }
+            return false;
+        }
+    }
 }
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
new file mode 100644
index 0000000..d836e4a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010 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.systemui.statusbar.tablet;
+
+import android.content.Context;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
+
+public class TabletStatusBarView extends FrameLayout {
+    private Handler mHandler;
+
+    private View[] mIgnoreChildren = new View[2];
+    private View[] mPanels = new View[2];
+    private int[] mPos = new int[2];
+
+    public TabletStatusBarView(Context context) {
+        super(context);
+    }
+
+    public TabletStatusBarView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            mHandler.removeMessages(TabletStatusBarService.MSG_CLOSE_NOTIFICATION_PANEL);
+            mHandler.sendEmptyMessage(TabletStatusBarService.MSG_CLOSE_NOTIFICATION_PANEL);
+            mHandler.removeMessages(TabletStatusBarService.MSG_CLOSE_SYSTEM_PANEL);
+            mHandler.sendEmptyMessage(TabletStatusBarService.MSG_CLOSE_SYSTEM_PANEL);
+
+            for (int i=0; i<mPanels.length; i++) {
+                if (mPanels[i].getVisibility() == View.VISIBLE) {
+                    if (eventInside(mIgnoreChildren[i], ev)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return super.onInterceptTouchEvent(ev);
+    }
+
+    private boolean eventInside(View v, MotionEvent ev) {
+        // assume that x and y are window coords because we are.
+        final int x = (int)ev.getX();
+        final int y = (int)ev.getY();
+
+        final int[] p = mPos;
+        v.getLocationInWindow(p);
+
+        final int l = p[0];
+        final int t = p[1];
+        final int r = p[0] + v.getWidth();
+        final int b = p[1] + v.getHeight();
+
+        return x >= l && x < r && y >= t && y < b;
+    }
+
+    public void setHandler(Handler h) {
+        mHandler = h;
+    }
+
+    public void setIgnoreChildren(int index, View ignore, View panel) {
+        mIgnoreChildren[index] = ignore;
+        mPanels[index] = panel;
+    }
+}