1744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk/**
2744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * Copyright (C) 2015 The Android Open Source Project
3744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk *
4744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
5744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * you may not use this file except in compliance with the License.
6744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * You may obtain a copy of the License at
7744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk *
8744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
9744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk *
10744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * Unless required by applicable law or agreed to in writing, software
11744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
12744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * See the License for the specific language governing permissions and
14744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * limitations under the License.
15744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk */
16744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkpackage com.android.settingslib.drawer;
17744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
18744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.annotation.LayoutRes;
19744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.annotation.Nullable;
20744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.app.Activity;
216bea950bfae14380959203b447bd870569061e4aJason Monkimport android.content.ActivityNotFoundException;
22e79790b26803ee338b2fdc3404344094d7f94476Jason Monkimport android.content.BroadcastReceiver;
23fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monkimport android.content.ComponentName;
24e79790b26803ee338b2fdc3404344094d7f94476Jason Monkimport android.content.Context;
25e79790b26803ee338b2fdc3404344094d7f94476Jason Monkimport android.content.Intent;
26e79790b26803ee338b2fdc3404344094d7f94476Jason Monkimport android.content.IntentFilter;
27fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monkimport android.content.pm.PackageManager;
28f18a55da5a757199090a96439e9d12ca6b5f7f80Jason Monkimport android.content.res.TypedArray;
29e79790b26803ee338b2fdc3404344094d7f94476Jason Monkimport android.os.AsyncTask;
30744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.os.Bundle;
31dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyuleiimport android.os.UserHandle;
32dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyuleiimport android.os.UserManager;
33cafda1f90ebf79ec3a56d43d8d3c0d63c9d84cb2Jason Monkimport android.provider.Settings;
34744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.support.v4.widget.DrawerLayout;
35f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhangimport android.text.TextUtils;
36fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monkimport android.util.ArraySet;
37e79790b26803ee338b2fdc3404344094d7f94476Jason Monkimport android.util.Log;
38744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.util.Pair;
39744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.view.Gravity;
40744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.view.LayoutInflater;
41744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.view.MenuItem;
42744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.view.View;
43744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.view.ViewGroup;
44744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.view.Window;
45cafda1f90ebf79ec3a56d43d8d3c0d63c9d84cb2Jason Monkimport android.view.WindowManager.LayoutParams;
46744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.widget.AdapterView;
477163d771088906d1beb8a9503175b4cc708ace4cFan Zhangimport android.widget.FrameLayout;
48744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.widget.ListView;
49744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.widget.Toolbar;
507163d771088906d1beb8a9503175b4cc708ace4cFan Zhang
51744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport com.android.settingslib.R;
52ec02e471a628f8b893a629d0d6116712290f828eJason Monkimport com.android.settingslib.applications.InterestingConfigChanges;
53744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
54e79790b26803ee338b2fdc3404344094d7f94476Jason Monkimport java.util.ArrayList;
55744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport java.util.HashMap;
56744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport java.util.List;
57744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
58744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkpublic class SettingsDrawerActivity extends Activity {
59744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
60e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    protected static final boolean DEBUG_TIMING = false;
61e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    private static final String TAG = "SettingsDrawerActivity";
62f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
63e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
64962694db3834b20a10e7d7756470b389f418c8d8Clara Bayarri    public static final String EXTRA_SHOW_MENU = "show_drawer_menu";
65946483a69e55b661c42e1976f4c70dabff9df89aJason Monk
66e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    private static List<DashboardCategory> sDashboardCategories;
67f509d7e65a062957be86619b3cb894e99268c4aeJason Monk    private static HashMap<Pair<String, String>, Tile> sTileCache;
68fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk    // Serves as a temporary list of tiles to ignore until we heard back from the PM that they
69fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk    // are disabled.
70fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk    private static ArraySet<ComponentName> sTileBlacklist = new ArraySet<>();
71ec02e471a628f8b893a629d0d6116712290f828eJason Monk    private static InterestingConfigChanges sConfigTracker;
72e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
73e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    private final PackageReceiver mPackageReceiver = new PackageReceiver();
74e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
75e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
76744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    private SettingsDrawerAdapter mDrawerAdapter;
777163d771088906d1beb8a9503175b4cc708ace4cFan Zhang    private FrameLayout mContentHeaderContainer;
78744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    private DrawerLayout mDrawerLayout;
79946483a69e55b661c42e1976f4c70dabff9df89aJason Monk    private boolean mShowingMenu;
80dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei    private UserManager mUserManager;
81744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
82744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    @Override
83744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    protected void onCreate(@Nullable Bundle savedInstanceState) {
84744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        super.onCreate(savedInstanceState);
85744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
86e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        long startTime = System.currentTimeMillis();
87e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
8848987f65df7825b18bb16d2135d267d090c8a6fbUdam Saini        TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
8948987f65df7825b18bb16d2135d267d090c8a6fbUdam Saini        if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
9048987f65df7825b18bb16d2135d267d090c8a6fbUdam Saini            getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
9148987f65df7825b18bb16d2135d267d090c8a6fbUdam Saini            getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
9248987f65df7825b18bb16d2135d267d090c8a6fbUdam Saini            requestWindowFeature(Window.FEATURE_NO_TITLE);
9348987f65df7825b18bb16d2135d267d090c8a6fbUdam Saini        }
94744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        super.setContentView(R.layout.settings_with_drawer);
957163d771088906d1beb8a9503175b4cc708ace4cFan Zhang        mContentHeaderContainer = (FrameLayout) findViewById(R.id.content_header_container);
96744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
9751a942380ba15f83393922203e7e9aebe64e8debJason Monk        if (mDrawerLayout == null) {
9851a942380ba15f83393922203e7e9aebe64e8debJason Monk            return;
9951a942380ba15f83393922203e7e9aebe64e8debJason Monk        }
100744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
101f18a55da5a757199090a96439e9d12ca6b5f7f80Jason Monk        if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
102f18a55da5a757199090a96439e9d12ca6b5f7f80Jason Monk            toolbar.setVisibility(View.GONE);
103f18a55da5a757199090a96439e9d12ca6b5f7f80Jason Monk            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
104f18a55da5a757199090a96439e9d12ca6b5f7f80Jason Monk            mDrawerLayout = null;
105f18a55da5a757199090a96439e9d12ca6b5f7f80Jason Monk            return;
106f18a55da5a757199090a96439e9d12ca6b5f7f80Jason Monk        }
1072a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk        getDashboardCategories();
108744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        setActionBar(toolbar);
109744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        mDrawerAdapter = new SettingsDrawerAdapter(this);
110744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        ListView listView = (ListView) findViewById(R.id.left_drawer);
111744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        listView.setAdapter(mDrawerAdapter);
112744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
113744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk            public void onItemClick(android.widget.AdapterView<?> parent, View view, int position,
114744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk                    long id) {
115744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk                onTileClicked(mDrawerAdapter.getTile(position));
116f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang            }
117744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        });
118dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei
119dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei        mUserManager = UserManager.get(this);
120e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
121e79790b26803ee338b2fdc3404344094d7f94476Jason Monk                + " ms");
122744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
123744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
124744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    @Override
125744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    public boolean onOptionsItemSelected(MenuItem item) {
126946483a69e55b661c42e1976f4c70dabff9df89aJason Monk        if (mShowingMenu && mDrawerLayout != null && item.getItemId() == android.R.id.home
12751a942380ba15f83393922203e7e9aebe64e8debJason Monk                && mDrawerAdapter.getCount() != 0) {
128744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk            openDrawer();
129744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk            return true;
130744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        }
131744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        return super.onOptionsItemSelected(item);
132744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
133744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
134744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    @Override
135744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    protected void onResume() {
136744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        super.onResume();
137744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
1382a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk        if (mDrawerLayout != null) {
1392a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk            final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
1402a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
1412a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk            filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
1422a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk            filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
1432a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk            filter.addDataScheme("package");
1442a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk            registerReceiver(mPackageReceiver, filter);
1452a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk
1462a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk            new CategoriesUpdater().execute();
1472a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk        }
148f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        final Intent intent = getIntent();
149f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        if (intent != null) {
150f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang            if (intent.hasExtra(EXTRA_SHOW_MENU)) {
151f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                if (intent.getBooleanExtra(EXTRA_SHOW_MENU, false)) {
152f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                    // Intent explicitly set to show menu.
153f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                    showMenuIcon();
154f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                }
155f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang            } else if (isTopLevelTile(intent)) {
156f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                showMenuIcon();
157f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang            }
158946483a69e55b661c42e1976f4c70dabff9df89aJason Monk        }
159e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    }
160e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
161e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    @Override
162e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    protected void onPause() {
1632a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk        if (mDrawerLayout != null) {
1642a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk            unregisterReceiver(mPackageReceiver);
1652a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk        }
166e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
167e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        super.onPause();
168e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    }
169e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
170f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang    private boolean isTopLevelTile(Intent intent) {
171f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        final ComponentName componentName = intent.getComponent();
172f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        if (componentName == null) {
173f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang            return false;
174f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        }
175f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        // Look for a tile that has the same component as incoming intent
176f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        final List<DashboardCategory> categories = getDashboardCategories();
177f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        for (DashboardCategory category : categories) {
178f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang            for (Tile tile : category.tiles) {
179f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                if (TextUtils.equals(tile.intent.getComponent().getClassName(),
180f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                        componentName.getClassName())) {
181f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                    if (DEBUG) {
182f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                        Log.d(TAG, "intent is for top level tile: " + tile.title);
183f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                    }
184f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                    return true;
185f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                }
186f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang            }
187f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        }
188f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        if (DEBUG) {
189f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang            Log.d(TAG, "Intent is not for top level settings " + intent);
190f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        }
191f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        return false;
192f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang    }
193f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang
194e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    public void addCategoryListener(CategoryListener listener) {
195e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        mCategoryListeners.add(listener);
196e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    }
197e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
198e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    public void remCategoryListener(CategoryListener listener) {
199e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        mCategoryListeners.remove(listener);
200744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
201744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
2021774a27b8405146153aba9a6f1c6427a072d458cAnna Galusza    public void setIsDrawerPresent(boolean isPresent) {
203fb695c633cb57de8746e624fc62127a0a7fa6ec7Anna Galusza        if (isPresent) {
2041774a27b8405146153aba9a6f1c6427a072d458cAnna Galusza            mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
2051774a27b8405146153aba9a6f1c6427a072d458cAnna Galusza            updateDrawer();
2061774a27b8405146153aba9a6f1c6427a072d458cAnna Galusza        } else {
20768dab67de2d9d254f5e71b6b8912f3c940eda1fdUdam Saini            if (mDrawerLayout != null) {
20868dab67de2d9d254f5e71b6b8912f3c940eda1fdUdam Saini                mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
20968dab67de2d9d254f5e71b6b8912f3c940eda1fdUdam Saini                mDrawerLayout = null;
21068dab67de2d9d254f5e71b6b8912f3c940eda1fdUdam Saini            }
2111774a27b8405146153aba9a6f1c6427a072d458cAnna Galusza        }
2121774a27b8405146153aba9a6f1c6427a072d458cAnna Galusza    }
2131774a27b8405146153aba9a6f1c6427a072d458cAnna Galusza
214744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    public void openDrawer() {
21551a942380ba15f83393922203e7e9aebe64e8debJason Monk        if (mDrawerLayout != null) {
21651a942380ba15f83393922203e7e9aebe64e8debJason Monk            mDrawerLayout.openDrawer(Gravity.START);
21751a942380ba15f83393922203e7e9aebe64e8debJason Monk        }
218744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
219744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
220744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    public void closeDrawer() {
22151a942380ba15f83393922203e7e9aebe64e8debJason Monk        if (mDrawerLayout != null) {
22251a942380ba15f83393922203e7e9aebe64e8debJason Monk            mDrawerLayout.closeDrawers();
22351a942380ba15f83393922203e7e9aebe64e8debJason Monk        }
224744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
225744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
2267163d771088906d1beb8a9503175b4cc708ace4cFan Zhang    public void setContentHeaderView(View headerView) {
2277163d771088906d1beb8a9503175b4cc708ace4cFan Zhang        mContentHeaderContainer.removeAllViews();
2287163d771088906d1beb8a9503175b4cc708ace4cFan Zhang        if (headerView != null) {
2297163d771088906d1beb8a9503175b4cc708ace4cFan Zhang            mContentHeaderContainer.addView(headerView);
2307163d771088906d1beb8a9503175b4cc708ace4cFan Zhang        }
2317163d771088906d1beb8a9503175b4cc708ace4cFan Zhang    }
2327163d771088906d1beb8a9503175b4cc708ace4cFan Zhang
233744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    @Override
234744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    public void setContentView(@LayoutRes int layoutResID) {
2354ea6657d587f0e06a335b9faf355e222d7cbd385Jason Monk        final ViewGroup parent = (ViewGroup) findViewById(R.id.content_frame);
2364ea6657d587f0e06a335b9faf355e222d7cbd385Jason Monk        if (parent != null) {
2374ea6657d587f0e06a335b9faf355e222d7cbd385Jason Monk            parent.removeAllViews();
2384ea6657d587f0e06a335b9faf355e222d7cbd385Jason Monk        }
2394ea6657d587f0e06a335b9faf355e222d7cbd385Jason Monk        LayoutInflater.from(this).inflate(layoutResID, parent);
240744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
241744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
242744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    @Override
243744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    public void setContentView(View view) {
244744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        ((ViewGroup) findViewById(R.id.content_frame)).addView(view);
245744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
246744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
247744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    @Override
248744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    public void setContentView(View view, ViewGroup.LayoutParams params) {
249744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
250744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
251744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
252744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    public void updateDrawer() {
25351a942380ba15f83393922203e7e9aebe64e8debJason Monk        if (mDrawerLayout == null) {
25451a942380ba15f83393922203e7e9aebe64e8debJason Monk            return;
25551a942380ba15f83393922203e7e9aebe64e8debJason Monk        }
256744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        // TODO: Do this in the background with some loading.
257744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        mDrawerAdapter.updateCategories();
25851a942380ba15f83393922203e7e9aebe64e8debJason Monk        if (mDrawerAdapter.getCount() != 0) {
25951a942380ba15f83393922203e7e9aebe64e8debJason Monk            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
26051a942380ba15f83393922203e7e9aebe64e8debJason Monk        } else {
26151a942380ba15f83393922203e7e9aebe64e8debJason Monk            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
26251a942380ba15f83393922203e7e9aebe64e8debJason Monk        }
263744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
264744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
265946483a69e55b661c42e1976f4c70dabff9df89aJason Monk    public void showMenuIcon() {
266946483a69e55b661c42e1976f4c70dabff9df89aJason Monk        mShowingMenu = true;
267946483a69e55b661c42e1976f4c70dabff9df89aJason Monk        getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
268c10db985f399a3257a5dcfa80c3388e8b8ee3db4Fan Zhang        getActionBar().setHomeActionContentDescription(R.string.content_description_menu_button);
269946483a69e55b661c42e1976f4c70dabff9df89aJason Monk        getActionBar().setDisplayHomeAsUpEnabled(true);
270946483a69e55b661c42e1976f4c70dabff9df89aJason Monk    }
271946483a69e55b661c42e1976f4c70dabff9df89aJason Monk
272e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    public List<DashboardCategory> getDashboardCategories() {
2732a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk        if (sDashboardCategories == null) {
2742a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk            sTileCache = new HashMap<>();
275ec02e471a628f8b893a629d0d6116712290f828eJason Monk            sConfigTracker = new InterestingConfigChanges();
276b0ae8f820927fc6c039b4e4efd6d3f15c1a6a141Jason Monk            // Apply initial current config.
277b0ae8f820927fc6c039b4e4efd6d3f15c1a6a141Jason Monk            sConfigTracker.applyNewConfig(getResources());
2782a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk            sDashboardCategories = TileUtils.getCategories(this, sTileCache);
2792a5d79aa6fd882ef6f46439f5156c516f173f06aJason Monk        }
280e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        return sDashboardCategories;
281e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    }
282e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
283e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    protected void onCategoriesChanged() {
284e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        updateDrawer();
285e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        final int N = mCategoryListeners.size();
286e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        for (int i = 0; i < N; i++) {
287e79790b26803ee338b2fdc3404344094d7f94476Jason Monk            mCategoryListeners.get(i).onCategoriesChanged();
288744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        }
289744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
290744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
291f509d7e65a062957be86619b3cb894e99268c4aeJason Monk    public boolean openTile(Tile tile) {
292744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        closeDrawer();
2933175a6e395e870c9ab5f291ed7d5edb8f802e218Jason Monk        if (tile == null) {
294cafda1f90ebf79ec3a56d43d8d3c0d63c9d84cb2Jason Monk            startActivity(new Intent(Settings.ACTION_SETTINGS).addFlags(
295cafda1f90ebf79ec3a56d43d8d3c0d63c9d84cb2Jason Monk                    Intent.FLAG_ACTIVITY_CLEAR_TASK));
296cafda1f90ebf79ec3a56d43d8d3c0d63c9d84cb2Jason Monk            return true;
2973175a6e395e870c9ab5f291ed7d5edb8f802e218Jason Monk        }
2986bea950bfae14380959203b447bd870569061e4aJason Monk        try {
299dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei            updateUserHandlesIfNeeded(tile);
3006bea950bfae14380959203b447bd870569061e4aJason Monk            int numUserHandles = tile.userHandle.size();
3016bea950bfae14380959203b447bd870569061e4aJason Monk            if (numUserHandles > 1) {
3026bea950bfae14380959203b447bd870569061e4aJason Monk                ProfileSelectDialog.show(getFragmentManager(), tile);
3036bea950bfae14380959203b447bd870569061e4aJason Monk                return false;
3046bea950bfae14380959203b447bd870569061e4aJason Monk            } else if (numUserHandles == 1) {
3056bea950bfae14380959203b447bd870569061e4aJason Monk                // Show menu on top level items.
3066bea950bfae14380959203b447bd870569061e4aJason Monk                tile.intent.putExtra(EXTRA_SHOW_MENU, true);
3076bea950bfae14380959203b447bd870569061e4aJason Monk                tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
3086bea950bfae14380959203b447bd870569061e4aJason Monk                startActivityAsUser(tile.intent, tile.userHandle.get(0));
3096bea950bfae14380959203b447bd870569061e4aJason Monk            } else {
3106bea950bfae14380959203b447bd870569061e4aJason Monk                // Show menu on top level items.
3116bea950bfae14380959203b447bd870569061e4aJason Monk                tile.intent.putExtra(EXTRA_SHOW_MENU, true);
3126bea950bfae14380959203b447bd870569061e4aJason Monk                tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
3136bea950bfae14380959203b447bd870569061e4aJason Monk                startActivity(tile.intent);
3146bea950bfae14380959203b447bd870569061e4aJason Monk            }
3156bea950bfae14380959203b447bd870569061e4aJason Monk        } catch (ActivityNotFoundException e) {
3166bea950bfae14380959203b447bd870569061e4aJason Monk            Log.w(TAG, "Couldn't find tile " + tile.intent, e);
3170d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk        }
3180d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk        return true;
319744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
320744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk
321dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei    private void updateUserHandlesIfNeeded(Tile tile) {
322dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei        List<UserHandle> userHandles = tile.userHandle;
323dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei
324f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang        for (int i = userHandles.size() - 1; i >= 0; i--) {
325dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei            if (mUserManager.getUserInfo(userHandles.get(i).getIdentifier()) == null) {
326f311b74b8fd1e391f62bac39842328dc8e6a6014Fan Zhang                if (DEBUG) {
327dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei                    Log.d(TAG, "Delete the user: " + userHandles.get(i).getIdentifier());
328dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei                }
329dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei                userHandles.remove(i);
330dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei            }
331dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei        }
332dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei    }
333dfc6ce5d9523eaeb6a409814a8666bf7a6153164jackqdyulei
334f509d7e65a062957be86619b3cb894e99268c4aeJason Monk    protected void onTileClicked(Tile tile) {
3350d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk        if (openTile(tile)) {
3360d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk            finish();
3370d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk        }
3380d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk    }
3390d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk
340be6c44823bc29a275539b5fd3876994e73a78f94Hyunyoung Song    public HashMap<Pair<String, String>, Tile> getTileCache() {
341be6c44823bc29a275539b5fd3876994e73a78f94Hyunyoung Song        if (sTileCache == null) {
342be6c44823bc29a275539b5fd3876994e73a78f94Hyunyoung Song            getDashboardCategories();
343be6c44823bc29a275539b5fd3876994e73a78f94Hyunyoung Song        }
344be6c44823bc29a275539b5fd3876994e73a78f94Hyunyoung Song        return sTileCache;
345be6c44823bc29a275539b5fd3876994e73a78f94Hyunyoung Song    }
346be6c44823bc29a275539b5fd3876994e73a78f94Hyunyoung Song
3470d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk    public void onProfileTileOpen() {
348744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk        finish();
349744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk    }
350e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
351fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk    public void setTileEnabled(ComponentName component, boolean enabled) {
352fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk        PackageManager pm = getPackageManager();
353fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk        int state = pm.getComponentEnabledSetting(component);
354fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk        boolean isEnabled = state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
355fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk        if (isEnabled != enabled || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
356fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk            if (enabled) {
357fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                sTileBlacklist.remove(component);
358fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk            } else {
359fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                sTileBlacklist.add(component);
360fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk            }
361fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk            pm.setComponentEnabledSetting(component, enabled
362fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                    ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
363fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                    : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
364fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                    PackageManager.DONT_KILL_APP);
365fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk            new CategoriesUpdater().execute();
366fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk        }
367fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk    }
368fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk
369e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    public interface CategoryListener {
370e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        void onCategoriesChanged();
371e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    }
372e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
373e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> {
374e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        @Override
375e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        protected List<DashboardCategory> doInBackground(Void... params) {
376ec02e471a628f8b893a629d0d6116712290f828eJason Monk            if (sConfigTracker.applyNewConfig(getResources())) {
377ec02e471a628f8b893a629d0d6116712290f828eJason Monk                sTileCache.clear();
378ec02e471a628f8b893a629d0d6116712290f828eJason Monk            }
379e79790b26803ee338b2fdc3404344094d7f94476Jason Monk            return TileUtils.getCategories(SettingsDrawerActivity.this, sTileCache);
380e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        }
381e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
382e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        @Override
3838c4e4b0865dada1f89c72b8abd44229df44a3250Richard Ho        protected void onPreExecute() {
3848c4e4b0865dada1f89c72b8abd44229df44a3250Richard Ho            if (sConfigTracker == null || sTileCache == null) {
3858c4e4b0865dada1f89c72b8abd44229df44a3250Richard Ho                getDashboardCategories();
3868c4e4b0865dada1f89c72b8abd44229df44a3250Richard Ho            }
3878c4e4b0865dada1f89c72b8abd44229df44a3250Richard Ho        }
3888c4e4b0865dada1f89c72b8abd44229df44a3250Richard Ho
3898c4e4b0865dada1f89c72b8abd44229df44a3250Richard Ho        @Override
390e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        protected void onPostExecute(List<DashboardCategory> dashboardCategories) {
391fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk            for (int i = 0; i < dashboardCategories.size(); i++) {
392fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                DashboardCategory category = dashboardCategories.get(i);
393fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                for (int j = 0; j < category.tiles.size(); j++) {
394fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                    Tile tile = category.tiles.get(j);
395fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                    if (sTileBlacklist.contains(tile.intent.getComponent())) {
396fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                        category.tiles.remove(j--);
397fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                    }
398fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk                }
399fcad09a777353d24fe38ba054c0e1007d3eeb2f4Jason Monk            }
400e79790b26803ee338b2fdc3404344094d7f94476Jason Monk            sDashboardCategories = dashboardCategories;
401e79790b26803ee338b2fdc3404344094d7f94476Jason Monk            onCategoriesChanged();
402e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        }
403e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    }
404e79790b26803ee338b2fdc3404344094d7f94476Jason Monk
405e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    private class PackageReceiver extends BroadcastReceiver {
406e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        @Override
407e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        public void onReceive(Context context, Intent intent) {
408e79790b26803ee338b2fdc3404344094d7f94476Jason Monk            new CategoriesUpdater().execute();
409e79790b26803ee338b2fdc3404344094d7f94476Jason Monk        }
410e79790b26803ee338b2fdc3404344094d7f94476Jason Monk    }
411744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk}
412