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