Merge "Highlight car nav facet when recent task changes."
diff --git a/packages/SystemUI/res/drawable/car_ic_arrow.xml b/packages/SystemUI/res/drawable/car_ic_arrow.xml
new file mode 100644
index 0000000..9d292cc
--- /dev/null
+++ b/packages/SystemUI/res/drawable/car_ic_arrow.xml
@@ -0,0 +1,27 @@
+<!--
+ ~ Copyright (C) 2015 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
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48.0dp"
+ android:height="48.0dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M14.0,20.0l10.0,10.0 10.0,-10.0z"/>
+ <path
+ android:pathData="M0 0h48v48H0z"
+ android:fillColor="#00000000"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/car_navigation_button.xml b/packages/SystemUI/res/layout/car_navigation_button.xml
new file mode 100644
index 0000000..87c8f04
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_navigation_button.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2016, 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.
+*/
+-->
+
+<com.android.systemui.statusbar.car.CarNavigationButton
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center">
+ <com.android.keyguard.AlphaOptimizedImageButton
+ android:id="@+id/car_nav_button_icon"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_centerInParent="true"
+ android:animateLayoutChanges="true">
+ </com.android.keyguard.AlphaOptimizedImageButton>
+
+ <com.android.keyguard.AlphaOptimizedImageButton
+ android:id="@+id/car_nav_button_more_icon"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_toRightOf="@+id/car_nav_button_icon"
+ android:animateLayoutChanges="true">
+ </com.android.keyguard.AlphaOptimizedImageButton>
+</com.android.systemui.statusbar.car.CarNavigationButton>
diff --git a/packages/SystemUI/res/values/arrays_car.xml b/packages/SystemUI/res/values/arrays_car.xml
index 230479d..8c760fc 100644
--- a/packages/SystemUI/res/values/arrays_car.xml
+++ b/packages/SystemUI/res/values/arrays_car.xml
@@ -22,7 +22,9 @@
isn't a longpress action associated with a shortcut item, put in an empty item to make
sure everything lines up.
-->
- <array name="car_shortcut_icons" />
- <array name="car_shortcut_intent_uris" />
- <array name="car_shortcut_longpress_intent_uris" />
+ <array name="car_facet_icons" />
+ <array name="car_facet_intent_uris" />
+ <array name="car_facet_longpress_intent_uris" />
+ <array name="car_facet_package_filters"/>
+ <array name="car_facet_category_filters"/>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
new file mode 100644
index 0000000..3e2c4c6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2015 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.car;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.support.v4.util.SimpleArrayMap;
+import android.view.View;
+import android.widget.LinearLayout;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.ActivityStarter;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A controller to populate data for CarNavigationBarView and handle user interactions.
+ * <p/>
+ * Each button inside the navigation bar is defined by data in arrays_car.xml. OEMs can customize
+ * the navigation buttons by updating arrays_car.xml appropriately in an overlay.
+ */
+class CarNavigationBarController {
+
+ // Each facet of the navigation bar maps to a set of package names or categories defined in
+ // arrays_car.xml. Package names for a given facet are delimited by ";"
+ private static final String FACET_FILTER_DEMILITER = ";";
+
+ private Context mContext;
+ private CarNavigationBarView mNavBar;
+ private ActivityStarter mActivityStarter;
+
+ // Set of categories each facet will filter on.
+ private List<String[]> mFacetCategories = new ArrayList<String[]>();
+ // Set of package names each facet will filter on.
+ private List<String[]> mFacetPackages = new ArrayList<String[]>();
+
+ private SimpleArrayMap<String, Integer> mFacetCategoryMap
+ = new SimpleArrayMap<String, Integer>();
+ private SimpleArrayMap<String, Integer> mFacetPackageMap
+ = new SimpleArrayMap<String, Integer>();
+
+ private List<Intent> mIntents = new ArrayList<Intent>();
+ private List<Intent> mLongPressIntents = new ArrayList<Intent>();
+
+ private List<CarNavigationButton> mNavButtons = new ArrayList<CarNavigationButton>();
+
+ private int mCurrentFacetIndex;
+
+ public CarNavigationBarController(Context context,
+ CarNavigationBarView navBar,
+ ActivityStarter activityStarter) {
+ mContext = context;
+ mNavBar = navBar;
+ mActivityStarter = activityStarter;
+ bind();
+ }
+
+ public void taskChanged(String packageName) {
+ // If the package name belongs to a filter, then highlight appropriate button in
+ // the navigation bar.
+ if (mFacetPackageMap.containsKey(packageName)) {
+ setCurrentFacet(mFacetPackageMap.get(packageName));
+ }
+
+ // Check if the package matches any of the categories for the facets
+ String category = getPackageCategory(packageName);
+ if (category != null) {
+ setCurrentFacet(mFacetCategoryMap.get(category));
+ }
+ }
+
+ private void bind() {
+ // Read up arrays_car.xml and populate the navigation bar here.
+ Resources r = mContext.getResources();
+ TypedArray icons = r.obtainTypedArray(R.array.car_facet_icons);
+ TypedArray intents = r.obtainTypedArray(R.array.car_facet_intent_uris);
+ TypedArray longpressIntents =
+ r.obtainTypedArray(R.array.car_facet_longpress_intent_uris);
+ TypedArray facetPackageNames = r.obtainTypedArray(R.array.car_facet_package_filters);
+
+ TypedArray facetCategories = r.obtainTypedArray(R.array.car_facet_category_filters);
+
+ if (icons.length() != intents.length()
+ || icons.length() != longpressIntents.length()
+ || icons.length() != facetPackageNames.length()
+ || icons.length() != facetCategories.length()) {
+ throw new RuntimeException("car_facet array lengths do not match");
+ }
+
+ for (int i = 0; i < icons.length(); i++) {
+ Drawable icon = icons.getDrawable(i);
+ try {
+ mIntents.add(i,
+ Intent.parseUri(intents.getString(i), Intent.URI_INTENT_SCHEME));
+
+ String longpressUri = longpressIntents.getString(i);
+ boolean hasLongpress = !longpressUri.isEmpty();
+ if (hasLongpress) {
+ mLongPressIntents.add(i,
+ Intent.parseUri(longpressUri, Intent.URI_INTENT_SCHEME));
+ }
+
+ CarNavigationButton button = createNavButton(icon, i, hasLongpress);
+ mNavButtons.add(button);
+ mNavBar.addButton(button, createNavButton(icon, i, hasLongpress));
+
+ initFacetFilterMaps(i,
+ facetPackageNames.getString(i).split(FACET_FILTER_DEMILITER),
+ facetCategories.getString(i).split(FACET_FILTER_DEMILITER));
+ } catch (URISyntaxException e) {
+ throw new RuntimeException("Malformed intent uri", e);
+ }
+ }
+ }
+
+ private void initFacetFilterMaps(int id, String[] packageNames, String[] categories){
+ mFacetCategories.add(categories);
+ for (int i = 0; i < categories.length; i++) {
+ mFacetCategoryMap.put(categories[i], id);
+ }
+
+ mFacetPackages.add(packageNames);
+ for (int i = 0; i < packageNames.length; i++) {
+ mFacetPackageMap.put(packageNames[i], id);
+ }
+ }
+
+ private String getPackageCategory(String packageName) {
+ PackageManager pm = mContext.getPackageManager();
+ int size = mFacetCategories.size();
+ // For each facet, check if the given package name matches one of its categories
+ for (int i = 0; i < size; i++) {
+ String[] categories = mFacetCategories.get(i);
+ for (int j = 0; j < categories.length; j++) {
+ String category = categories[j];
+ Intent intent = new Intent();
+ intent.setPackage(packageName);
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.addCategory(category);
+ List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
+ if (list.size() > 0) {
+ // Cache this package name into facetPackageMap, so we won't have to query
+ // all categories next time this package name shows up.
+ mFacetPackageMap.put(packageName, mFacetCategoryMap.get(category));
+ return category;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Helper method to check if a given facet has multiple packages associated with it.
+ * This can be resource defined package names or package names filtered by facet category.
+ */
+ private boolean facetHasMultiplePackages(int index) {
+ PackageManager pm = mContext.getPackageManager();
+
+ // Check if the packages defined for the filter actually exists on the device
+ String[] packages = mFacetPackages.get(index);
+ if (packages.length > 1) {
+ int count = 0;
+ for (int i = 0; i < packages.length; i++) {
+ count += pm.getLaunchIntentForPackage(packages[i]) != null ? 1 : 0;
+ if (count > 1) {
+ return true;
+ }
+ }
+ }
+
+ // If there weren't multiple packages defined for the facet, check the categories
+ // and see if they resolve to multiple package names
+ String categories[] = mFacetCategories.get(index);
+
+ int count = 0;
+ for (int i = 0; i < categories.length; i++) {
+ String category = categories[i];
+ Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.addCategory(category);
+ count += pm.queryIntentActivities(intent, 0).size();
+ if (count > 1) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void setCurrentFacet(int index) {
+ if (index == mCurrentFacetIndex) {
+ return;
+ }
+
+ if (mNavButtons.get(mCurrentFacetIndex) != null) {
+ mNavButtons.get(mCurrentFacetIndex)
+ .setSelected(false /* selected */, false /* showMoreIcon */);
+ }
+
+ if (mNavButtons.get(index) != null) {
+ mNavButtons.get(index).setSelected(true /* selected */,
+ facetHasMultiplePackages(index) /* showMoreIcon */);
+ }
+ mCurrentFacetIndex = index;
+ }
+
+ private CarNavigationButton createNavButton(Drawable icon, final int id,
+ boolean longClickEnabled) {
+ CarNavigationButton button = (CarNavigationButton) View.inflate(mContext,
+ R.layout.car_navigation_button, null);
+ button.setResources(icon);
+ LinearLayout.LayoutParams lp =
+ new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
+ button.setLayoutParams(lp);
+
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setCurrentFacet(id);
+ onFacetClicked(id);
+ }
+ });
+
+ if (longClickEnabled) {
+ button.setLongClickable(true);
+ button.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ onFacetLongClicked(id);
+ setCurrentFacet(id);
+ return true;
+ }
+ });
+ } else {
+ button.setLongClickable(false);
+ }
+ return button;
+ }
+
+ private void startActivity(Intent intent) {
+ if (mActivityStarter != null && intent != null) {
+ mActivityStarter.startActivity(intent, true);
+ }
+ }
+
+ private void onFacetClicked(int index) {
+ // TODO: determine what data to pass to the trampoline, so it can start
+ // the default app or the lens picker.
+ startActivity(mIntents.get(index));
+ }
+
+ private void onFacetLongClicked(int index) {
+ // TODO: determine what data to pass to the trampoline, so it can start
+ // the default app or the lens picker.
+ startActivity(mLongPressIntents.get(index));
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index e2d64b04..efc3646 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -17,36 +17,29 @@
package com.android.systemui.statusbar.car;
import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.R.color;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.ActivityStarter;
import com.android.systemui.statusbar.phone.NavigationBarView;
-import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
-import com.android.systemui.statusbar.policy.KeyButtonView;
-import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
/**
* A custom navigation bar for the automotive use case.
* <p>
- * The navigation bar in the automotive use case is more like a list of shortcuts, which we
- * expect to be customizable by the car OEMs. This implementation populates the nav_buttons layout
- * from resources rather than the layout file so customization would then mean updating
- * arrays_car.xml appropriately in an overlay.
+ * The navigation bar in the automotive use case is more like a list of shortcuts, rendered
+ * in a linear layout.
*/
class CarNavigationBarView extends NavigationBarView {
- private ActivityStarter mActivityStarter;
+ private LinearLayout mNavButtons;
+ private LinearLayout mLightsOutButtons;
public CarNavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -54,83 +47,13 @@
@Override
public void onFinishInflate() {
- // Read up arrays_car.xml and populate the navigation bar here.
- Context context = getContext();
- Resources r = getContext().getResources();
- TypedArray icons = r.obtainTypedArray(R.array.car_shortcut_icons);
- TypedArray intents = r.obtainTypedArray(R.array.car_shortcut_intent_uris);
- TypedArray longpressIntents =
- r.obtainTypedArray(R.array.car_shortcut_longpress_intent_uris);
-
- if (icons.length() != intents.length()) {
- throw new RuntimeException("car_shortcut_icons and car_shortcut_intents do not match");
- }
-
- LinearLayout navButtons = (LinearLayout) findViewById(R.id.nav_buttons);
- LinearLayout lightsOut = (LinearLayout) findViewById(R.id.lights_out);
-
- for (int i = 0; i < icons.length(); i++) {
- Drawable icon = icons.getDrawable(i);
-
- try {
- Intent intent = Intent.parseUri(intents.getString(i), Intent.URI_INTENT_SCHEME);
- Intent longpress = null;
- String longpressUri = longpressIntents.getString(i);
- if (!longpressUri.isEmpty()) {
- longpress = Intent.parseUri(longpressUri, Intent.URI_INTENT_SCHEME);
- }
-
- // nav_buttons and lights_out should match exactly.
- navButtons.addView(makeButton(context, icon, intent, longpress));
- lightsOut.addView(makeButton(context, icon, intent, longpress));
- } catch (URISyntaxException e) {
- throw new RuntimeException("Malformed intent uri", e);
- }
- }
+ mNavButtons = (LinearLayout) findViewById(R.id.nav_buttons);
+ mLightsOutButtons = (LinearLayout) findViewById(R.id.lights_out);
}
- private ImageButton makeButton(Context context, Drawable icon,
- final Intent intent, final Intent longpress) {
- ImageButton button = new ImageButton(context);
-
- button.setImageDrawable(icon);
- button.setScaleType(ScaleType.CENTER);
- button.setBackgroundColor(color.transparent);
- LinearLayout.LayoutParams lp =
- new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1);
- button.setLayoutParams(lp);
-
- button.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mActivityStarter != null) {
- mActivityStarter.startActivity(intent, true);
- }
- }
- });
-
- // Long click handlers are optional.
- if (longpress != null) {
- button.setLongClickable(true);
- button.setOnLongClickListener(new OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- if (mActivityStarter != null) {
- mActivityStarter.startActivity(longpress, true);
- return true;
- }
- return false;
- }
- });
- } else {
- button.setLongClickable(false);
- }
-
- return button;
- }
-
- public void setActivityStarter(ActivityStarter activityStarter) {
- mActivityStarter = activityStarter;
+ public void addButton(CarNavigationButton button, CarNavigationButton lightsOutButton){
+ mNavButtons.addView(button);
+ mLightsOutButtons.addView(lightsOutButton);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
new file mode 100644
index 0000000..36b3a8a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 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.car;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import com.android.keyguard.AlphaOptimizedImageButton;
+import com.android.systemui.R;
+
+/**
+ * A wrapper view for a car navigation facet, which includes a button icon and a drop down icon.
+ */
+public class CarNavigationButton extends RelativeLayout {
+ private static final float SELECTED_ALPHA = 1;
+ private static final float UNSELECTED_ALPHA = 0.7f;
+
+ private AlphaOptimizedImageButton mIcon;
+ private AlphaOptimizedImageButton mMoreIcon;
+
+ public CarNavigationButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public void onFinishInflate() {
+ super.onFinishInflate();
+ mIcon = (AlphaOptimizedImageButton) findViewById(R.id.car_nav_button_icon);
+ mIcon.setClickable(false);
+ mIcon.setScaleType(ImageView.ScaleType.CENTER);
+ mIcon.setBackgroundColor(android.R.color.transparent);
+ mIcon.setAlpha(UNSELECTED_ALPHA);
+
+ mMoreIcon = (AlphaOptimizedImageButton) findViewById(R.id.car_nav_button_more_icon);
+ mMoreIcon.setClickable(false);
+ mMoreIcon.setScaleType(ImageView.ScaleType.CENTER);
+ mMoreIcon.setBackgroundColor(android.R.color.transparent);
+ mMoreIcon.setVisibility(INVISIBLE);
+ mMoreIcon.setImageDrawable(getContext().getDrawable(R.drawable.car_ic_arrow));
+ mMoreIcon.setAlpha(UNSELECTED_ALPHA);
+ }
+
+ public void setResources(Drawable icon) {
+ mIcon.setImageDrawable(icon);
+ }
+
+ public void setSelected(boolean selected, boolean showMoreIcon) {
+ if (selected) {
+ mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : INVISIBLE);
+ mMoreIcon.setAlpha(SELECTED_ALPHA);
+ mIcon.setAlpha(SELECTED_ALPHA);
+ } else {
+ mMoreIcon.setVisibility(INVISIBLE);
+ mIcon.setAlpha(UNSELECTED_ALPHA);
+ }
+ }
+}
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");
+ }
+ }
+ }
}