Loading packages/SystemUI/res/drawable/car_ic_arrow.xml 0 → 100644 +27 −0 Original line number Diff line number Diff line <!-- ~ 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> packages/SystemUI/res/layout/car_navigation_button.xml 0 → 100644 +42 −0 Original line number Diff line number Diff line <?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> packages/SystemUI/res/values/arrays_car.xml +5 −3 Original line number Diff line number Diff line Loading @@ -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> packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java 0 → 100644 +275 −0 Original line number Diff line number Diff line /* * 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)); } } packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java +11 −88 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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 Loading Loading
packages/SystemUI/res/drawable/car_ic_arrow.xml 0 → 100644 +27 −0 Original line number Diff line number Diff line <!-- ~ 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>
packages/SystemUI/res/layout/car_navigation_button.xml 0 → 100644 +42 −0 Original line number Diff line number Diff line <?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>
packages/SystemUI/res/values/arrays_car.xml +5 −3 Original line number Diff line number Diff line Loading @@ -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>
packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java 0 → 100644 +275 −0 Original line number Diff line number Diff line /* * 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)); } }
packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java +11 −88 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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 Loading