11c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan/* 21c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * Copyright (C) 2015 The Android Open Source Project 31c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * 41c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * Licensed under the Apache License, Version 2.0 (the "License"); 51c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * you may not use this file except in compliance with the License. 61c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * You may obtain a copy of the License at 71c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * 81c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * http://www.apache.org/licenses/LICENSE-2.0 91c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * 101c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * Unless required by applicable law or agreed to in writing, software 111c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * distributed under the License is distributed on an "AS IS" BASIS, 121c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * See the License for the specific language governing permissions and 141c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * limitations under the License. 151c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan */ 161c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanpackage com.android.systemui.statusbar.car; 171c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 181c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport android.content.Context; 191c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport android.content.Intent; 201c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport android.content.pm.PackageManager; 211c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport android.content.pm.ResolveInfo; 221c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport android.content.res.Resources; 231c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport android.content.res.TypedArray; 241c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport android.graphics.drawable.Drawable; 251c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport android.support.v4.util.SimpleArrayMap; 269f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyerimport android.util.SparseBooleanArray; 271c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport android.view.View; 281c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport android.widget.LinearLayout; 29c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson 301c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport com.android.systemui.R; 311c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport com.android.systemui.statusbar.phone.ActivityStarter; 321c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 331c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport java.net.URISyntaxException; 341c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport java.util.ArrayList; 3504a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsevimport java.util.Arrays; 361c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanimport java.util.List; 371c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 381c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan/** 391c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * A controller to populate data for CarNavigationBarView and handle user interactions. 401c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * <p/> 411c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * Each button inside the navigation bar is defined by data in arrays_car.xml. OEMs can customize 421c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * the navigation buttons by updating arrays_car.xml appropriately in an overlay. 431c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan */ 441c6d0589f1c6429ca84402227cd5954479cf66edVictor Chanclass CarNavigationBarController { 45c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan private static final String EXTRA_FACET_CATEGORIES = "categories"; 46c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan private static final String EXTRA_FACET_PACKAGES = "packages"; 47c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan private static final String EXTRA_FACET_ID = "filter_id"; 48c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan private static final String EXTRA_FACET_LAUNCH_PICKER = "launch_picker"; 491c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 501c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // Each facet of the navigation bar maps to a set of package names or categories defined in 511c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // arrays_car.xml. Package names for a given facet are delimited by ";" 521c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private static final String FACET_FILTER_DEMILITER = ";"; 531c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 541c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private Context mContext; 551c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private CarNavigationBarView mNavBar; 561c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private ActivityStarter mActivityStarter; 571c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 581c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // Set of categories each facet will filter on. 591c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private List<String[]> mFacetCategories = new ArrayList<String[]>(); 601c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // Set of package names each facet will filter on. 611c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private List<String[]> mFacetPackages = new ArrayList<String[]>(); 621c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 631c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private SimpleArrayMap<String, Integer> mFacetCategoryMap 641c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan = new SimpleArrayMap<String, Integer>(); 651c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private SimpleArrayMap<String, Integer> mFacetPackageMap 661c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan = new SimpleArrayMap<String, Integer>(); 671c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 6804a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsev private List<Intent> mIntents; 6904a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsev private List<Intent> mLongPressIntents; 701c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 711c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private List<CarNavigationButton> mNavButtons = new ArrayList<CarNavigationButton>(); 721c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 731c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private int mCurrentFacetIndex; 749f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer private SparseBooleanArray mFacetHasMultipleAppsCache = new SparseBooleanArray(); 751c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 761c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan public CarNavigationBarController(Context context, 771c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan CarNavigationBarView navBar, 781c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan ActivityStarter activityStarter) { 791c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mContext = context; 801c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mNavBar = navBar; 811c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mActivityStarter = activityStarter; 821c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan bind(); 831c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 841c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 851c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan public void taskChanged(String packageName) { 861c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // If the package name belongs to a filter, then highlight appropriate button in 871c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // the navigation bar. 881c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (mFacetPackageMap.containsKey(packageName)) { 891c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan setCurrentFacet(mFacetPackageMap.get(packageName)); 901c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 911c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 921c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // Check if the package matches any of the categories for the facets 931c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan String category = getPackageCategory(packageName); 941c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (category != null) { 951c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan setCurrentFacet(mFacetCategoryMap.get(category)); 961c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 971c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 981c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 999f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer public void onPackageChange(String packageName) { 1009f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer if (mFacetPackageMap.containsKey(packageName)) { 1019f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer int index = mFacetPackageMap.get(packageName); 1029f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer mFacetHasMultipleAppsCache.put(index, facetHasMultiplePackages(index)); 1039f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer // No need to check categories because we've already refreshed the cache. 1049f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer return; 1059f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer } 1069f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer 1079f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer String category = getPackageCategory(packageName); 1089f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer if (mFacetCategoryMap.containsKey(category)) { 1099a8386a8036c160b54544c01d2f1d24093edda5fRakesh Iyer int index = mFacetCategoryMap.get(category); 1109f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer mFacetHasMultipleAppsCache.put(index, facetHasMultiplePackages(index)); 1119f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer } 1129f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer } 1139f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer 1141c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private void bind() { 1151c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // Read up arrays_car.xml and populate the navigation bar here. 1161c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan Resources r = mContext.getResources(); 1171c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan TypedArray icons = r.obtainTypedArray(R.array.car_facet_icons); 1181c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan TypedArray intents = r.obtainTypedArray(R.array.car_facet_intent_uris); 1191c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan TypedArray longpressIntents = 1201c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan r.obtainTypedArray(R.array.car_facet_longpress_intent_uris); 1211c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan TypedArray facetPackageNames = r.obtainTypedArray(R.array.car_facet_package_filters); 1221c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 1231c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan TypedArray facetCategories = r.obtainTypedArray(R.array.car_facet_category_filters); 1241c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 1251c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (icons.length() != intents.length() 1261c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan || icons.length() != longpressIntents.length() 1271c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan || icons.length() != facetPackageNames.length() 1281c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan || icons.length() != facetCategories.length()) { 1291c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan throw new RuntimeException("car_facet array lengths do not match"); 1301c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1311c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 13204a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsev mIntents = createEmptyIntentList(icons.length()); 13304a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsev mLongPressIntents = createEmptyIntentList(icons.length()); 13404a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsev 1351c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan for (int i = 0; i < icons.length(); i++) { 1361c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan Drawable icon = icons.getDrawable(i); 1371c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan try { 13804a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsev mIntents.set(i, 1391c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan Intent.parseUri(intents.getString(i), Intent.URI_INTENT_SCHEME)); 1401c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 1411c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan String longpressUri = longpressIntents.getString(i); 1421c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan boolean hasLongpress = !longpressUri.isEmpty(); 1431c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (hasLongpress) { 14404a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsev mLongPressIntents.set(i, 1451c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan Intent.parseUri(longpressUri, Intent.URI_INTENT_SCHEME)); 1461c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1471c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 1481c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan CarNavigationButton button = createNavButton(icon, i, hasLongpress); 1491c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mNavButtons.add(button); 150c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan mNavBar.addButton(button, 151c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan createNavButton(icon, i, hasLongpress) /* lightsOutButton */); 1521c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 1531c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan initFacetFilterMaps(i, 1541c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan facetPackageNames.getString(i).split(FACET_FILTER_DEMILITER), 1551c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan facetCategories.getString(i).split(FACET_FILTER_DEMILITER)); 1569f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer mFacetHasMultipleAppsCache.put(i, facetHasMultiplePackages(i)); 1571c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } catch (URISyntaxException e) { 1581c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan throw new RuntimeException("Malformed intent uri", e); 1591c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1601c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1611c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1621c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 163c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan private void initFacetFilterMaps(int id, String[] packageNames, String[] categories) { 1641c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mFacetCategories.add(categories); 1651c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan for (int i = 0; i < categories.length; i++) { 1661c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mFacetCategoryMap.put(categories[i], id); 1671c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1681c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 1691c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mFacetPackages.add(packageNames); 1701c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan for (int i = 0; i < packageNames.length; i++) { 1711c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mFacetPackageMap.put(packageNames[i], id); 1721c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1731c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1741c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 1751c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private String getPackageCategory(String packageName) { 1761c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan PackageManager pm = mContext.getPackageManager(); 1771c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan int size = mFacetCategories.size(); 1781c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // For each facet, check if the given package name matches one of its categories 1791c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan for (int i = 0; i < size; i++) { 1801c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan String[] categories = mFacetCategories.get(i); 1811c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan for (int j = 0; j < categories.length; j++) { 1821c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan String category = categories[j]; 1831c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan Intent intent = new Intent(); 1841c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan intent.setPackage(packageName); 1851c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan intent.setAction(Intent.ACTION_MAIN); 1861c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan intent.addCategory(category); 1871c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan List<ResolveInfo> list = pm.queryIntentActivities(intent, 0); 1881c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (list.size() > 0) { 1891c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // Cache this package name into facetPackageMap, so we won't have to query 1901c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // all categories next time this package name shows up. 1911c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mFacetPackageMap.put(packageName, mFacetCategoryMap.get(category)); 1921c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan return category; 1931c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1941c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1951c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1961c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan return null; 1971c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 1981c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 1991c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan /** 2001c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * Helper method to check if a given facet has multiple packages associated with it. 2011c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan * This can be resource defined package names or package names filtered by facet category. 2021c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan */ 2031c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private boolean facetHasMultiplePackages(int index) { 2041c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan PackageManager pm = mContext.getPackageManager(); 2051c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 2061c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // Check if the packages defined for the filter actually exists on the device 2071c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan String[] packages = mFacetPackages.get(index); 2081c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (packages.length > 1) { 2091c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan int count = 0; 2101c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan for (int i = 0; i < packages.length; i++) { 2111c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan count += pm.getLaunchIntentForPackage(packages[i]) != null ? 1 : 0; 2121c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (count > 1) { 2131c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan return true; 2141c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2151c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2161c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2171c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 2181c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // If there weren't multiple packages defined for the facet, check the categories 2191c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan // and see if they resolve to multiple package names 2201c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan String categories[] = mFacetCategories.get(index); 2211c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 2221c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan int count = 0; 2231c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan for (int i = 0; i < categories.length; i++) { 2241c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan String category = categories[i]; 2251c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan Intent intent = new Intent(); 2261c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan intent.setAction(Intent.ACTION_MAIN); 2271c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan intent.addCategory(category); 2281c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan count += pm.queryIntentActivities(intent, 0).size(); 2291c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (count > 1) { 2301c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan return true; 2311c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2321c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2331c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan return false; 2341c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2351c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 2361c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private void setCurrentFacet(int index) { 2371c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (index == mCurrentFacetIndex) { 2381c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan return; 2391c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2401c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 2411c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (mNavButtons.get(mCurrentFacetIndex) != null) { 2421c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mNavButtons.get(mCurrentFacetIndex) 2431c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan .setSelected(false /* selected */, false /* showMoreIcon */); 2441c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2451c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 2461c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (mNavButtons.get(index) != null) { 2471c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mNavButtons.get(index).setSelected(true /* selected */, 2489f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer mFacetHasMultipleAppsCache.get(index) /* showMoreIcon */); 2491c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2501c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan mCurrentFacetIndex = index; 2511c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2521c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 2531c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private CarNavigationButton createNavButton(Drawable icon, final int id, 2541c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan boolean longClickEnabled) { 2551c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan CarNavigationButton button = (CarNavigationButton) View.inflate(mContext, 2561c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan R.layout.car_navigation_button, null); 2571c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan button.setResources(icon); 2581c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan LinearLayout.LayoutParams lp = 2591c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1); 2601c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan button.setLayoutParams(lp); 2611c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 2621c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan button.setOnClickListener(new View.OnClickListener() { 2631c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan @Override 2641c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan public void onClick(View v) { 2651c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan onFacetClicked(id); 2661c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2671c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan }); 2681c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 2691c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (longClickEnabled) { 2701c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan button.setLongClickable(true); 2711c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan button.setOnLongClickListener(new View.OnLongClickListener() { 2721c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan @Override 2731c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan public boolean onLongClick(View v) { 2741c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan onFacetLongClicked(id); 2751c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan return true; 2761c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2771c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan }); 2781c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } else { 2791c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan button.setLongClickable(false); 2801c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 281c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan 2821c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan return button; 2831c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2841c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 2851c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private void startActivity(Intent intent) { 2861c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan if (mActivityStarter != null && intent != null) { 2879f831f64dc10751b260e336372f6b16277b0bd47Rakesh Iyer mActivityStarter.startActivity(intent, false); 2881c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2891c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 2901c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 2911c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private void onFacetClicked(int index) { 292c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan Intent intent = mIntents.get(index); 293c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan String packageName = intent.getPackage(); 294c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan 295c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan if (packageName == null) { 296c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan return; 297c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan } 298c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan 299c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories.get(index)); 300c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages.get(index)); 301c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan // The facet is identified by the index in which it was added to the nav bar. 302c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan // This value can be used to determine which facet was selected 303c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan intent.putExtra(EXTRA_FACET_ID, Integer.toString(index)); 304c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan 305c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan // If the current facet is clicked, we want to launch the picker by default 306c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan // rather than the "preferred/last run" app. 307c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, index == mCurrentFacetIndex); 308c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan 309c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan setCurrentFacet(index); 310c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan startActivity(intent); 3111c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 3121c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan 3131c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan private void onFacetLongClicked(int index) { 314c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8Victor Chan setCurrentFacet(index); 3151c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan startActivity(mLongPressIntents.get(index)); 3161c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan } 31704a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsev 31804a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsev private List<Intent> createEmptyIntentList(int size) { 31904a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsev return Arrays.asList(new Intent[size]); 32004a22a26d61866add8a85ca50a623a5d8e4d4bb6Pavel Maltsev } 3211c6d0589f1c6429ca84402227cd5954479cf66edVictor Chan} 322