Highlight car nav facet when recent task changes.

CarStatusBar will now register a ITaskStackListener
to handle changes in task stack and highlight the
appropriate facet for the current task. Currently using resource
defined package names and category to the filter for a given
facet. OEMs are expected to use categories definied in Intent.java

Also refactored business logic from CarNavigationBarView
into CarNavigationBar controller.

Change-Id: I203917ea43f2f488a1167f27dab84f1c451b3e93
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 31631f8..f6f1f94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -16,30 +16,52 @@
 
 package com.android.systemui.statusbar.car;
 
+import android.app.ActivityManager;
+import android.app.ITaskStackListener;
 import android.content.Context;
 import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.Looper;
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
 
 import com.android.systemui.R;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 
 /**
  * A status bar (and navigation bar) tailored for the automotive use case.
  */
 public class CarStatusBar extends PhoneStatusBar {
+    private SystemServicesProxy mSystemServicesProxy;
+    private TaskStackListenerImpl mTaskStackListener;
+    private Handler mHandler;
+
+    private CarNavigationBarView mCarNavigationBar;
+    private CarNavigationBarController mController;
+
+    @Override
+    public void start() {
+        super.start();
+        mHandler = new Handler();
+        mTaskStackListener = new TaskStackListenerImpl(mHandler);
+        mSystemServicesProxy = new SystemServicesProxy(mContext);
+        mSystemServicesProxy.registerTaskStackListener(mTaskStackListener);
+    }
+
     @Override
     protected void addNavigationBar() {
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
-                    WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
-                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
-                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
-                    | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+                WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                 PixelFormat.TRANSLUCENT);
         lp.setTitle("CarNavigationBar");
         lp.windowAnimations = 0;
@@ -51,11 +73,11 @@
         if (mNavigationBarView != null) {
             return;
         }
-
-        CarNavigationBarView carNavBar =
+        mCarNavigationBar =
                 (CarNavigationBarView) View.inflate(context, R.layout.car_navigation_bar, null);
-        carNavBar.setActivityStarter(this);
-        mNavigationBarView = carNavBar;
+        mController = new CarNavigationBarController(context, mCarNavigationBar,
+                this /* ActivityStarter*/);
+        mNavigationBarView = mCarNavigationBar;
     }
 
     @Override
@@ -63,4 +85,40 @@
         // The navigation bar for a vehicle will not need to be repositioned, as it is always
         // set at the bottom.
     }
+
+    /**
+     * An implementation of ITaskStackListener, that listens for changes in the system task
+     * stack and notifies the navigation bar.
+     */
+    private class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable {
+        private Handler mHandler;
+
+        public TaskStackListenerImpl(Handler handler) {
+            this.mHandler = handler;
+        }
+
+        @Override
+        public void onActivityPinned() {
+        }
+
+        @Override
+        public void onTaskStackChanged() {
+            mHandler.removeCallbacks(this);
+            mHandler.post(this);
+        }
+
+        @Override
+        public void run() {
+            ensureMainThread();
+            SystemServicesProxy ssp = Recents.getSystemServices();
+            ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getTopMostTask();
+            mController.taskChanged(runningTaskInfo.baseActivity.getPackageName());
+        }
+
+        private void ensureMainThread() {
+            if (!Looper.getMainLooper().isCurrentThread()) {
+                throw new RuntimeException("Must be called on the UI thread");
+            }
+        }
+    }
 }