CarNavigationBarController.java revision c0ca9e5a3fa09ac8f6adc861d508b58c7fffd0f8
12b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian/*
22b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * Copyright (C) 2015 The Android Open Source Project
32b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian *
42b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * Licensed under the Apache License, Version 2.0 (the "License");
52b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * you may not use this file except in compliance with the License.
62b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * You may obtain a copy of the License at
72b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian *
82b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian *      http://www.apache.org/licenses/LICENSE-2.0
92b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian *
102b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * Unless required by applicable law or agreed to in writing, software
112b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * distributed under the License is distributed on an "AS IS" BASIS,
122b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * See the License for the specific language governing permissions and
142b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * limitations under the License.
152b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian */
162b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianpackage com.android.systemui.statusbar.car;
172b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
182b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport android.content.Context;
192b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport android.content.Intent;
202b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport android.content.pm.PackageManager;
212b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport android.content.pm.ResolveInfo;
222b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport android.content.res.Resources;
232b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport android.content.res.TypedArray;
242b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport android.graphics.drawable.Drawable;
252b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport android.support.v4.util.SimpleArrayMap;
262b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport android.view.View;
272b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport android.widget.LinearLayout;
282b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport com.android.systemui.R;
292b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport com.android.systemui.statusbar.phone.ActivityStarter;
302b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
312b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport java.net.URISyntaxException;
322b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport java.util.ArrayList;
332b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianimport java.util.List;
342b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
352b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian/**
362b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * A controller to populate data for CarNavigationBarView and handle user interactions.
372b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * <p/>
382b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * Each button inside the navigation bar is defined by data in arrays_car.xml. OEMs can customize
392b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian * the navigation buttons by updating arrays_car.xml appropriately in an overlay.
402b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian */
412b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qianclass CarNavigationBarController {
422b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private static final String EXTRA_FACET_CATEGORIES = "categories";
432b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private static final String EXTRA_FACET_PACKAGES = "packages";
442b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private static final String EXTRA_FACET_ID = "filter_id";
452b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private static final String EXTRA_FACET_LAUNCH_PICKER = "launch_picker";
462b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
472b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    // Each facet of the navigation bar maps to a set of package names or categories defined in
482b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    // arrays_car.xml. Package names for a given facet are delimited by ";"
492b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private static final String FACET_FILTER_DEMILITER = ";";
502b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
512b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private Context mContext;
522b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private CarNavigationBarView mNavBar;
532b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private ActivityStarter mActivityStarter;
542b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
552b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    // Set of categories each facet will filter on.
562b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private List<String[]> mFacetCategories = new ArrayList<String[]>();
572b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    // Set of package names each facet will filter on.
582b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private List<String[]> mFacetPackages = new ArrayList<String[]>();
592b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
602b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private SimpleArrayMap<String, Integer> mFacetCategoryMap
612b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            = new SimpleArrayMap<String, Integer>();
622b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private SimpleArrayMap<String, Integer> mFacetPackageMap
635b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian            = new SimpleArrayMap<String, Integer>();
645b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian
655b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian    private List<Intent> mIntents = new ArrayList<Intent>();
665b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian    private List<Intent> mLongPressIntents = new ArrayList<Intent>();
675b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian
685b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian    private List<CarNavigationButton> mNavButtons = new ArrayList<CarNavigationButton>();
695b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian
70d93aa418071ba2bbf72de4003719d68650426c58Zhengyin Qian    private int mCurrentFacetIndex;
71d93aa418071ba2bbf72de4003719d68650426c58Zhengyin Qian    private String mCurrentPackageName;
725b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian
732b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    public CarNavigationBarController(Context context,
742b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                                      CarNavigationBarView navBar,
752b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                                      ActivityStarter activityStarter) {
762b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        mContext = context;
772b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        mNavBar = navBar;
782b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        mActivityStarter = activityStarter;
796d25c0bd81eee66810339d5db3d1ecd48691d229Zhengyin Qian        bind();
806d25c0bd81eee66810339d5db3d1ecd48691d229Zhengyin Qian    }
816d25c0bd81eee66810339d5db3d1ecd48691d229Zhengyin Qian
826d25c0bd81eee66810339d5db3d1ecd48691d229Zhengyin Qian    public void taskChanged(String packageName) {
836d25c0bd81eee66810339d5db3d1ecd48691d229Zhengyin Qian        mCurrentPackageName = packageName;
842b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // If the package name belongs to a filter, then highlight appropriate button in
852b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // the navigation bar.
862b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        if (mFacetPackageMap.containsKey(packageName)) {
87b403779c945a262dce678308f993f8d6ccd27ddaZhengyin Qian            setCurrentFacet(mFacetPackageMap.get(packageName));
882b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
892b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
902b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // Check if the package matches any of the categories for the facets
912b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        String category = getPackageCategory(packageName);
925b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian        if (category != null) {
935b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian            setCurrentFacet(mFacetCategoryMap.get(category));
942b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
952b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    }
962b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
972b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private void bind() {
982b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // Read up arrays_car.xml and populate the navigation bar here.
992b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        Resources r = mContext.getResources();
1002b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        TypedArray icons = r.obtainTypedArray(R.array.car_facet_icons);
1012b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        TypedArray intents = r.obtainTypedArray(R.array.car_facet_intent_uris);
1022b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        TypedArray longpressIntents =
1032b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                r.obtainTypedArray(R.array.car_facet_longpress_intent_uris);
1042b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        TypedArray facetPackageNames = r.obtainTypedArray(R.array.car_facet_package_filters);
1052b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
1062b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        TypedArray facetCategories = r.obtainTypedArray(R.array.car_facet_category_filters);
1072b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
1082b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        if (icons.length() != intents.length()
1092b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                || icons.length() != longpressIntents.length()
1102b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                || icons.length() != facetPackageNames.length()
1112b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                || icons.length() != facetCategories.length()) {
1122b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            throw new RuntimeException("car_facet array lengths do not match");
1132b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
1142b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
1152b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        for (int i = 0; i < icons.length(); i++) {
1162b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            Drawable icon = icons.getDrawable(i);
1172b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            try {
1182b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                mIntents.add(i,
1192b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                        Intent.parseUri(intents.getString(i), Intent.URI_INTENT_SCHEME));
1202b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
1212b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                String longpressUri = longpressIntents.getString(i);
1222b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                boolean hasLongpress = !longpressUri.isEmpty();
1232b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                if (hasLongpress) {
1242b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                    mLongPressIntents.add(i,
1252b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                            Intent.parseUri(longpressUri, Intent.URI_INTENT_SCHEME));
1262b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                }
1272b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
1282b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                CarNavigationButton button = createNavButton(icon, i, hasLongpress);
1292b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                mNavButtons.add(button);
1302b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                mNavBar.addButton(button,
1312b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                        createNavButton(icon, i, hasLongpress) /* lightsOutButton */);
1322b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
1332b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                initFacetFilterMaps(i,
1342b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                        facetPackageNames.getString(i).split(FACET_FILTER_DEMILITER),
1352b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                        facetCategories.getString(i).split(FACET_FILTER_DEMILITER));
1362b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            } catch (URISyntaxException e) {
1372b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                throw new RuntimeException("Malformed intent uri", e);
1382b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            }
1392b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
1402b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    }
1415b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian
1422b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private void initFacetFilterMaps(int id, String[] packageNames, String[] categories) {
1432b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        mFacetCategories.add(categories);
1442b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        for (int i = 0; i < categories.length; i++) {
1452b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            mFacetCategoryMap.put(categories[i], id);
1462b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
1472b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
1482b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        mFacetPackages.add(packageNames);
1492b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        for (int i = 0; i < packageNames.length; i++) {
1502b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            mFacetPackageMap.put(packageNames[i], id);
1512b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
1522b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    }
1532b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
1542b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private String getPackageCategory(String packageName) {
1552b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        PackageManager pm = mContext.getPackageManager();
1562b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        int size = mFacetCategories.size();
1572b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // For each facet, check if the given package name matches one of its categories
1582b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        for (int i = 0; i < size; i++) {
1596d25c0bd81eee66810339d5db3d1ecd48691d229Zhengyin Qian            String[] categories = mFacetCategories.get(i);
1602b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            for (int j = 0; j < categories.length; j++) {
1612b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                String category = categories[j];
1622b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                Intent intent = new Intent();
1632b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                intent.setPackage(packageName);
1642b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                intent.setAction(Intent.ACTION_MAIN);
1656d25c0bd81eee66810339d5db3d1ecd48691d229Zhengyin Qian                intent.addCategory(category);
1662b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
1672b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                if (list.size() > 0) {
1682b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                    // Cache this package name into facetPackageMap, so we won't have to query
1692b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                    // all categories next time this package name shows up.
1706d25c0bd81eee66810339d5db3d1ecd48691d229Zhengyin Qian                    mFacetPackageMap.put(packageName, mFacetCategoryMap.get(category));
1712b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                    return category;
1722b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                }
1732b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            }
1742b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
1752b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        return null;
1765b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian    }
1772b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
1785b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian    /**
1792b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian     * Helper method to check if a given facet has multiple packages associated with it.
1802b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian     * This can be resource defined package names or package names filtered by facet category.
1812b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian     */
1822b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private boolean facetHasMultiplePackages(int index) {
1832b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        PackageManager pm = mContext.getPackageManager();
1842b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
1852b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // Check if the packages defined for the filter actually exists on the device
1862b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        String[] packages = mFacetPackages.get(index);
1872b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        if (packages.length > 1) {
1882b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            int count = 0;
1892b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            for (int i = 0; i < packages.length; i++) {
1902b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                count += pm.getLaunchIntentForPackage(packages[i]) != null ? 1 : 0;
1912b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                if (count > 1) {
1922b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                    return true;
1932b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                }
1942b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            }
1952b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
1962b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
1972b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // If there weren't multiple packages defined for the facet, check the categories
1982b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // and see if they resolve to multiple package names
1992b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        String categories[] = mFacetCategories.get(index);
2002b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2012b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        int count = 0;
2025b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian        for (int i = 0; i < categories.length; i++) {
2035b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian            String category = categories[i];
2042b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            Intent intent = new Intent();
2055b42895d33d72e74e3e3446e1d43fc541fbf404fZhengyin Qian            intent.setAction(Intent.ACTION_MAIN);
2062b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            intent.addCategory(category);
2072b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            count += pm.queryIntentActivities(intent, 0).size();
2082b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            if (count > 1) {
2092b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                return true;
2102b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            }
2112b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
2122b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        return false;
2132b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    }
2142b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2152b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private void setCurrentFacet(int index) {
2162b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        if (index == mCurrentFacetIndex) {
2172b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            return;
2182b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
2192b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2202b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        if (mNavButtons.get(mCurrentFacetIndex) != null) {
2212b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            mNavButtons.get(mCurrentFacetIndex)
2222b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                    .setSelected(false /* selected */, false /* showMoreIcon */);
2232b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
2242b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2252b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        if (mNavButtons.get(index) != null) {
2262b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            mNavButtons.get(index).setSelected(true /* selected */,
2272b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                    facetHasMultiplePackages(index)  /* showMoreIcon */);
2282b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
2292b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        mCurrentFacetIndex = index;
2302b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    }
2312b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2322b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private CarNavigationButton createNavButton(Drawable icon, final int id,
2332b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                                                boolean longClickEnabled) {
2342b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        CarNavigationButton button = (CarNavigationButton) View.inflate(mContext,
2352b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                R.layout.car_navigation_button, null);
2362b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        button.setResources(icon);
2372b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        LinearLayout.LayoutParams lp =
2382b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
2392b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        button.setLayoutParams(lp);
2402b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2412b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        button.setOnClickListener(new View.OnClickListener() {
2422b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            @Override
2432b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            public void onClick(View v) {
2442b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                onFacetClicked(id);
2452b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            }
2462b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        });
2472b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2482b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        if (longClickEnabled) {
2492b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            button.setLongClickable(true);
2502b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            button.setOnLongClickListener(new View.OnLongClickListener() {
251b403779c945a262dce678308f993f8d6ccd27ddaZhengyin Qian                @Override
2522b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                public boolean onLongClick(View v) {
2532b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                    onFacetLongClicked(id);
2542b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                    return true;
2552b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian                }
2562b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            });
257d93aa418071ba2bbf72de4003719d68650426c58Zhengyin Qian        } else {
258d93aa418071ba2bbf72de4003719d68650426c58Zhengyin Qian            button.setLongClickable(false);
2592b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
2602b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
261b403779c945a262dce678308f993f8d6ccd27ddaZhengyin Qian        return button;
262b403779c945a262dce678308f993f8d6ccd27ddaZhengyin Qian    }
263b403779c945a262dce678308f993f8d6ccd27ddaZhengyin Qian
2642b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private void startActivity(Intent intent) {
265d93aa418071ba2bbf72de4003719d68650426c58Zhengyin Qian        if (mActivityStarter != null && intent != null) {
266d93aa418071ba2bbf72de4003719d68650426c58Zhengyin Qian            mActivityStarter.startActivity(intent, true);
2672b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
2682b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    }
2692b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2702b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private void onFacetClicked(int index) {
2712b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        Intent intent = mIntents.get(index);
2722b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        String packageName = intent.getPackage();
2732b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2742b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        if (packageName == null) {
2752b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            return;
2762b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
2772b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2782b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // Don't launch the lens picker if it's already running and the
2792b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // user clicks the same facet
2802b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        if (packageName.equals(mCurrentPackageName) && index == mCurrentFacetIndex) {
2812b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian            return;
2822b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        }
2832b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2842b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories.get(index));
2852b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages.get(index));
2862b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // The facet is identified by the index in which it was added to the nav bar.
2872b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // This value can be used to determine which facet was selected
2882b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        intent.putExtra(EXTRA_FACET_ID, Integer.toString(index));
2892b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2902b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // If the current facet is clicked, we want to launch the picker by default
2912b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        // rather than the "preferred/last run" app.
2922b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, index == mCurrentFacetIndex);
2932b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2942b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        setCurrentFacet(index);
2952b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        startActivity(intent);
2962b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    }
2972b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian
2982b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    private void onFacetLongClicked(int index) {
2992b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        setCurrentFacet(index);
3002b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian        startActivity(mLongPressIntents.get(index));
3012b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian    }
3022b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian}
3032b28ca2dcb5c6c6a510577f3ebd9c754d29638bfZhengyin Qian