[go: nahoru, domu]

1/**
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.settingslib.drawer;
17
18import android.annotation.LayoutRes;
19import android.annotation.Nullable;
20import android.app.Activity;
21import android.content.ActivityNotFoundException;
22import android.content.BroadcastReceiver;
23import android.content.ComponentName;
24import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
27import android.content.pm.PackageManager;
28import android.content.res.TypedArray;
29import android.os.AsyncTask;
30import android.os.Bundle;
31import android.provider.Settings;
32import android.support.v4.widget.DrawerLayout;
33import android.util.ArraySet;
34import android.util.Log;
35import android.util.Pair;
36import android.view.Gravity;
37import android.view.LayoutInflater;
38import android.view.MenuItem;
39import android.view.View;
40import android.view.ViewGroup;
41import android.view.Window;
42import android.view.WindowManager.LayoutParams;
43import android.widget.AdapterView;
44import android.widget.ListView;
45import android.widget.Toolbar;
46import com.android.settingslib.R;
47import com.android.settingslib.applications.InterestingConfigChanges;
48
49import java.util.ArrayList;
50import java.util.HashMap;
51import java.util.List;
52
53public class SettingsDrawerActivity extends Activity {
54
55    protected static final boolean DEBUG_TIMING = false;
56    private static final String TAG = "SettingsDrawerActivity";
57
58    public static final String EXTRA_SHOW_MENU = "show_drawer_menu";
59
60    private static List<DashboardCategory> sDashboardCategories;
61    private static HashMap<Pair<String, String>, Tile> sTileCache;
62    // Serves as a temporary list of tiles to ignore until we heard back from the PM that they
63    // are disabled.
64    private static ArraySet<ComponentName> sTileBlacklist = new ArraySet<>();
65    private static InterestingConfigChanges sConfigTracker;
66
67    private final PackageReceiver mPackageReceiver = new PackageReceiver();
68    private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
69
70    private SettingsDrawerAdapter mDrawerAdapter;
71    private DrawerLayout mDrawerLayout;
72    private boolean mShowingMenu;
73
74    @Override
75    protected void onCreate(@Nullable Bundle savedInstanceState) {
76        super.onCreate(savedInstanceState);
77
78        long startTime = System.currentTimeMillis();
79
80        TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
81        if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
82            getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
83            getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
84            requestWindowFeature(Window.FEATURE_NO_TITLE);
85        }
86        super.setContentView(R.layout.settings_with_drawer);
87        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
88        if (mDrawerLayout == null) {
89            return;
90        }
91        Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
92        if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
93            toolbar.setVisibility(View.GONE);
94            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
95            mDrawerLayout = null;
96            return;
97        }
98        getDashboardCategories();
99        setActionBar(toolbar);
100        mDrawerAdapter = new SettingsDrawerAdapter(this);
101        ListView listView = (ListView) findViewById(R.id.left_drawer);
102        listView.setAdapter(mDrawerAdapter);
103        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
104            public void onItemClick(android.widget.AdapterView<?> parent, View view, int position,
105                    long id) {
106                onTileClicked(mDrawerAdapter.getTile(position));
107            };
108        });
109        if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
110                + " ms");
111    }
112
113    @Override
114    public boolean onOptionsItemSelected(MenuItem item) {
115        if (mShowingMenu && mDrawerLayout != null && item.getItemId() == android.R.id.home
116                && mDrawerAdapter.getCount() != 0) {
117            openDrawer();
118            return true;
119        }
120        return super.onOptionsItemSelected(item);
121    }
122
123    @Override
124    protected void onResume() {
125        super.onResume();
126
127        if (mDrawerLayout != null) {
128            final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
129            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
130            filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
131            filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
132            filter.addDataScheme("package");
133            registerReceiver(mPackageReceiver, filter);
134
135            new CategoriesUpdater().execute();
136        }
137        if (getIntent() != null && getIntent().getBooleanExtra(EXTRA_SHOW_MENU, false)) {
138            showMenuIcon();
139        }
140    }
141
142    @Override
143    protected void onPause() {
144        if (mDrawerLayout != null) {
145            unregisterReceiver(mPackageReceiver);
146        }
147
148        super.onPause();
149    }
150
151    public void addCategoryListener(CategoryListener listener) {
152        mCategoryListeners.add(listener);
153    }
154
155    public void remCategoryListener(CategoryListener listener) {
156        mCategoryListeners.remove(listener);
157    }
158
159    public void setIsDrawerPresent(boolean isPresent) {
160        if (isPresent) {
161            mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
162            updateDrawer();
163        } else {
164            if (mDrawerLayout != null) {
165                mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
166                mDrawerLayout = null;
167            }
168        }
169    }
170
171    public void openDrawer() {
172        if (mDrawerLayout != null) {
173            mDrawerLayout.openDrawer(Gravity.START);
174        }
175    }
176
177    public void closeDrawer() {
178        if (mDrawerLayout != null) {
179            mDrawerLayout.closeDrawers();
180        }
181    }
182
183    @Override
184    public void setContentView(@LayoutRes int layoutResID) {
185        final ViewGroup parent = (ViewGroup) findViewById(R.id.content_frame);
186        if (parent != null) {
187            parent.removeAllViews();
188        }
189        LayoutInflater.from(this).inflate(layoutResID, parent);
190    }
191
192    @Override
193    public void setContentView(View view) {
194        ((ViewGroup) findViewById(R.id.content_frame)).addView(view);
195    }
196
197    @Override
198    public void setContentView(View view, ViewGroup.LayoutParams params) {
199        ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
200    }
201
202    public void updateDrawer() {
203        if (mDrawerLayout == null) {
204            return;
205        }
206        // TODO: Do this in the background with some loading.
207        mDrawerAdapter.updateCategories();
208        if (mDrawerAdapter.getCount() != 0) {
209            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
210        } else {
211            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
212        }
213    }
214
215    public void showMenuIcon() {
216        mShowingMenu = true;
217        getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
218        getActionBar().setDisplayHomeAsUpEnabled(true);
219    }
220
221    public List<DashboardCategory> getDashboardCategories() {
222        if (sDashboardCategories == null) {
223            sTileCache = new HashMap<>();
224            sConfigTracker = new InterestingConfigChanges();
225            // Apply initial current config.
226            sConfigTracker.applyNewConfig(getResources());
227            sDashboardCategories = TileUtils.getCategories(this, sTileCache);
228        }
229        return sDashboardCategories;
230    }
231
232    protected void onCategoriesChanged() {
233        updateDrawer();
234        final int N = mCategoryListeners.size();
235        for (int i = 0; i < N; i++) {
236            mCategoryListeners.get(i).onCategoriesChanged();
237        }
238    }
239
240    public boolean openTile(Tile tile) {
241        closeDrawer();
242        if (tile == null) {
243            startActivity(new Intent(Settings.ACTION_SETTINGS).addFlags(
244                    Intent.FLAG_ACTIVITY_CLEAR_TASK));
245            return true;
246        }
247        try {
248            int numUserHandles = tile.userHandle.size();
249            if (numUserHandles > 1) {
250                ProfileSelectDialog.show(getFragmentManager(), tile);
251                return false;
252            } else if (numUserHandles == 1) {
253                // Show menu on top level items.
254                tile.intent.putExtra(EXTRA_SHOW_MENU, true);
255                tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
256                startActivityAsUser(tile.intent, tile.userHandle.get(0));
257            } else {
258                // Show menu on top level items.
259                tile.intent.putExtra(EXTRA_SHOW_MENU, true);
260                tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
261                startActivity(tile.intent);
262            }
263        } catch (ActivityNotFoundException e) {
264            Log.w(TAG, "Couldn't find tile " + tile.intent, e);
265        }
266        return true;
267    }
268
269    protected void onTileClicked(Tile tile) {
270        if (openTile(tile)) {
271            finish();
272        }
273    }
274
275    public void onProfileTileOpen() {
276        finish();
277    }
278
279    public void setTileEnabled(ComponentName component, boolean enabled) {
280        PackageManager pm = getPackageManager();
281        int state = pm.getComponentEnabledSetting(component);
282        boolean isEnabled = state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
283        if (isEnabled != enabled || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
284            if (enabled) {
285                sTileBlacklist.remove(component);
286            } else {
287                sTileBlacklist.add(component);
288            }
289            pm.setComponentEnabledSetting(component, enabled
290                    ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
291                    : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
292                    PackageManager.DONT_KILL_APP);
293            new CategoriesUpdater().execute();
294        }
295    }
296
297    public interface CategoryListener {
298        void onCategoriesChanged();
299    }
300
301    private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> {
302        @Override
303        protected List<DashboardCategory> doInBackground(Void... params) {
304            if (sConfigTracker.applyNewConfig(getResources())) {
305                sTileCache.clear();
306            }
307            return TileUtils.getCategories(SettingsDrawerActivity.this, sTileCache);
308        }
309
310        @Override
311        protected void onPreExecute() {
312            if (sConfigTracker == null || sTileCache == null) {
313                getDashboardCategories();
314            }
315        }
316
317        @Override
318        protected void onPostExecute(List<DashboardCategory> dashboardCategories) {
319            for (int i = 0; i < dashboardCategories.size(); i++) {
320                DashboardCategory category = dashboardCategories.get(i);
321                for (int j = 0; j < category.tiles.size(); j++) {
322                    Tile tile = category.tiles.get(j);
323                    if (sTileBlacklist.contains(tile.intent.getComponent())) {
324                        category.tiles.remove(j--);
325                    }
326                }
327            }
328            sDashboardCategories = dashboardCategories;
329            onCategoriesChanged();
330        }
331    }
332
333    private class PackageReceiver extends BroadcastReceiver {
334        @Override
335        public void onReceive(Context context, Intent intent) {
336            new CategoriesUpdater().execute();
337        }
338    }
339}
340