diff options
7 files changed, 501 insertions, 101 deletions
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 000000000000..9d292cc0259a --- /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 000000000000..87c8f04a19bf --- /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 230479d2c9db..8c760fc45e72 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 000000000000..3e2c4c62ef74 --- /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 e2d64b049ca0..efc3646c5015 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 @@ class CarNavigationBarView extends NavigationBarView { @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); - } - } - } - - 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; + mNavButtons = (LinearLayout) findViewById(R.id.nav_buttons); + mLightsOutButtons = (LinearLayout) findViewById(R.id.lights_out); } - 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 000000000000..36b3a8ae816e --- /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 31631f8efa66..f6f1f94017aa 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 @@ public class CarStatusBar extends PhoneStatusBar { 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 @@ public class CarStatusBar extends PhoneStatusBar { // 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"); + } + } + } } |