Move to Android N-MR1 SDK.
[android_tools.git] / sdk / sources / android-25 / com / android / settingslib / drawer / SettingsDrawerActivity.java
blobe6e0243c53e177ad47df4a90a7872faebe1cac0c
1 /**
2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.android.settingslib.drawer;
18 import android.annotation.LayoutRes;
19 import android.annotation.Nullable;
20 import android.app.Activity;
21 import android.content.ActivityNotFoundException;
22 import android.content.BroadcastReceiver;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.pm.PackageManager;
28 import android.content.res.TypedArray;
29 import android.os.AsyncTask;
30 import android.os.Bundle;
31 import android.os.UserHandle;
32 import android.os.UserManager;
33 import android.provider.Settings;
34 import android.support.v4.widget.DrawerLayout;
35 import android.text.TextUtils;
36 import android.util.ArraySet;
37 import android.util.Log;
38 import android.util.Pair;
39 import android.view.Gravity;
40 import android.view.LayoutInflater;
41 import android.view.MenuItem;
42 import android.view.View;
43 import android.view.ViewGroup;
44 import android.view.Window;
45 import android.view.WindowManager.LayoutParams;
46 import android.widget.AdapterView;
47 import android.widget.FrameLayout;
48 import android.widget.ListView;
49 import android.widget.Toolbar;
51 import com.android.settingslib.R;
52 import com.android.settingslib.applications.InterestingConfigChanges;
54 import java.util.ArrayList;
55 import java.util.HashMap;
56 import java.util.List;
58 public class SettingsDrawerActivity extends Activity {
60 protected static final boolean DEBUG_TIMING = false;
61 private static final String TAG = "SettingsDrawerActivity";
62 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
64 public static final String EXTRA_SHOW_MENU = "show_drawer_menu";
66 private static List<DashboardCategory> sDashboardCategories;
67 private static HashMap<Pair<String, String>, Tile> sTileCache;
68 // Serves as a temporary list of tiles to ignore until we heard back from the PM that they
69 // are disabled.
70 private static ArraySet<ComponentName> sTileBlacklist = new ArraySet<>();
71 private static InterestingConfigChanges sConfigTracker;
73 private final PackageReceiver mPackageReceiver = new PackageReceiver();
74 private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
76 private SettingsDrawerAdapter mDrawerAdapter;
77 private FrameLayout mContentHeaderContainer;
78 private DrawerLayout mDrawerLayout;
79 private boolean mShowingMenu;
80 private UserManager mUserManager;
82 @Override
83 protected void onCreate(@Nullable Bundle savedInstanceState) {
84 super.onCreate(savedInstanceState);
86 long startTime = System.currentTimeMillis();
88 TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
89 if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
90 getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
91 getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
92 requestWindowFeature(Window.FEATURE_NO_TITLE);
94 super.setContentView(R.layout.settings_with_drawer);
95 mContentHeaderContainer = (FrameLayout) findViewById(R.id.content_header_container);
96 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
97 if (mDrawerLayout == null) {
98 return;
100 Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
101 if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
102 toolbar.setVisibility(View.GONE);
103 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
104 mDrawerLayout = null;
105 return;
107 getDashboardCategories();
108 setActionBar(toolbar);
109 mDrawerAdapter = new SettingsDrawerAdapter(this);
110 ListView listView = (ListView) findViewById(R.id.left_drawer);
111 listView.setAdapter(mDrawerAdapter);
112 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
113 public void onItemClick(android.widget.AdapterView<?> parent, View view, int position,
114 long id) {
115 onTileClicked(mDrawerAdapter.getTile(position));
119 mUserManager = UserManager.get(this);
120 if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
121 + " ms");
124 @Override
125 public boolean onOptionsItemSelected(MenuItem item) {
126 if (mShowingMenu && mDrawerLayout != null && item.getItemId() == android.R.id.home
127 && mDrawerAdapter.getCount() != 0) {
128 openDrawer();
129 return true;
131 return super.onOptionsItemSelected(item);
134 @Override
135 protected void onResume() {
136 super.onResume();
138 if (mDrawerLayout != null) {
139 final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
140 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
141 filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
142 filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
143 filter.addDataScheme("package");
144 registerReceiver(mPackageReceiver, filter);
146 new CategoriesUpdater().execute();
148 final Intent intent = getIntent();
149 if (intent != null) {
150 if (intent.hasExtra(EXTRA_SHOW_MENU)) {
151 if (intent.getBooleanExtra(EXTRA_SHOW_MENU, false)) {
152 // Intent explicitly set to show menu.
153 showMenuIcon();
155 } else if (isTopLevelTile(intent)) {
156 showMenuIcon();
161 @Override
162 protected void onPause() {
163 if (mDrawerLayout != null) {
164 unregisterReceiver(mPackageReceiver);
167 super.onPause();
170 private boolean isTopLevelTile(Intent intent) {
171 final ComponentName componentName = intent.getComponent();
172 if (componentName == null) {
173 return false;
175 // Look for a tile that has the same component as incoming intent
176 final List<DashboardCategory> categories = getDashboardCategories();
177 for (DashboardCategory category : categories) {
178 for (Tile tile : category.tiles) {
179 if (TextUtils.equals(tile.intent.getComponent().getClassName(),
180 componentName.getClassName())) {
181 if (DEBUG) {
182 Log.d(TAG, "intent is for top level tile: " + tile.title);
184 return true;
188 if (DEBUG) {
189 Log.d(TAG, "Intent is not for top level settings " + intent);
191 return false;
194 public void addCategoryListener(CategoryListener listener) {
195 mCategoryListeners.add(listener);
198 public void remCategoryListener(CategoryListener listener) {
199 mCategoryListeners.remove(listener);
202 public void setIsDrawerPresent(boolean isPresent) {
203 if (isPresent) {
204 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
205 updateDrawer();
206 } else {
207 if (mDrawerLayout != null) {
208 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
209 mDrawerLayout = null;
214 public void openDrawer() {
215 if (mDrawerLayout != null) {
216 mDrawerLayout.openDrawer(Gravity.START);
220 public void closeDrawer() {
221 if (mDrawerLayout != null) {
222 mDrawerLayout.closeDrawers();
226 public void setContentHeaderView(View headerView) {
227 mContentHeaderContainer.removeAllViews();
228 if (headerView != null) {
229 mContentHeaderContainer.addView(headerView);
233 @Override
234 public void setContentView(@LayoutRes int layoutResID) {
235 final ViewGroup parent = (ViewGroup) findViewById(R.id.content_frame);
236 if (parent != null) {
237 parent.removeAllViews();
239 LayoutInflater.from(this).inflate(layoutResID, parent);
242 @Override
243 public void setContentView(View view) {
244 ((ViewGroup) findViewById(R.id.content_frame)).addView(view);
247 @Override
248 public void setContentView(View view, ViewGroup.LayoutParams params) {
249 ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
252 public void updateDrawer() {
253 if (mDrawerLayout == null) {
254 return;
256 // TODO: Do this in the background with some loading.
257 mDrawerAdapter.updateCategories();
258 if (mDrawerAdapter.getCount() != 0) {
259 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
260 } else {
261 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
265 public void showMenuIcon() {
266 mShowingMenu = true;
267 getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
268 getActionBar().setHomeActionContentDescription(R.string.content_description_menu_button);
269 getActionBar().setDisplayHomeAsUpEnabled(true);
272 public List<DashboardCategory> getDashboardCategories() {
273 if (sDashboardCategories == null) {
274 sTileCache = new HashMap<>();
275 sConfigTracker = new InterestingConfigChanges();
276 // Apply initial current config.
277 sConfigTracker.applyNewConfig(getResources());
278 sDashboardCategories = TileUtils.getCategories(this, sTileCache);
280 return sDashboardCategories;
283 protected void onCategoriesChanged() {
284 updateDrawer();
285 final int N = mCategoryListeners.size();
286 for (int i = 0; i < N; i++) {
287 mCategoryListeners.get(i).onCategoriesChanged();
291 public boolean openTile(Tile tile) {
292 closeDrawer();
293 if (tile == null) {
294 startActivity(new Intent(Settings.ACTION_SETTINGS).addFlags(
295 Intent.FLAG_ACTIVITY_CLEAR_TASK));
296 return true;
298 try {
299 updateUserHandlesIfNeeded(tile);
300 int numUserHandles = tile.userHandle.size();
301 if (numUserHandles > 1) {
302 ProfileSelectDialog.show(getFragmentManager(), tile);
303 return false;
304 } else if (numUserHandles == 1) {
305 // Show menu on top level items.
306 tile.intent.putExtra(EXTRA_SHOW_MENU, true);
307 tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
308 startActivityAsUser(tile.intent, tile.userHandle.get(0));
309 } else {
310 // Show menu on top level items.
311 tile.intent.putExtra(EXTRA_SHOW_MENU, true);
312 tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
313 startActivity(tile.intent);
315 } catch (ActivityNotFoundException e) {
316 Log.w(TAG, "Couldn't find tile " + tile.intent, e);
318 return true;
321 private void updateUserHandlesIfNeeded(Tile tile) {
322 List<UserHandle> userHandles = tile.userHandle;
324 for (int i = userHandles.size() - 1; i >= 0; i--) {
325 if (mUserManager.getUserInfo(userHandles.get(i).getIdentifier()) == null) {
326 if (DEBUG) {
327 Log.d(TAG, "Delete the user: " + userHandles.get(i).getIdentifier());
329 userHandles.remove(i);
334 protected void onTileClicked(Tile tile) {
335 if (openTile(tile)) {
336 finish();
340 public HashMap<Pair<String, String>, Tile> getTileCache() {
341 if (sTileCache == null) {
342 getDashboardCategories();
344 return sTileCache;
347 public void onProfileTileOpen() {
348 finish();
351 public void setTileEnabled(ComponentName component, boolean enabled) {
352 PackageManager pm = getPackageManager();
353 int state = pm.getComponentEnabledSetting(component);
354 boolean isEnabled = state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
355 if (isEnabled != enabled || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
356 if (enabled) {
357 sTileBlacklist.remove(component);
358 } else {
359 sTileBlacklist.add(component);
361 pm.setComponentEnabledSetting(component, enabled
362 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
363 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
364 PackageManager.DONT_KILL_APP);
365 new CategoriesUpdater().execute();
369 public interface CategoryListener {
370 void onCategoriesChanged();
373 private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> {
374 @Override
375 protected List<DashboardCategory> doInBackground(Void... params) {
376 if (sConfigTracker.applyNewConfig(getResources())) {
377 sTileCache.clear();
379 return TileUtils.getCategories(SettingsDrawerActivity.this, sTileCache);
382 @Override
383 protected void onPreExecute() {
384 if (sConfigTracker == null || sTileCache == null) {
385 getDashboardCategories();
389 @Override
390 protected void onPostExecute(List<DashboardCategory> dashboardCategories) {
391 for (int i = 0; i < dashboardCategories.size(); i++) {
392 DashboardCategory category = dashboardCategories.get(i);
393 for (int j = 0; j < category.tiles.size(); j++) {
394 Tile tile = category.tiles.get(j);
395 if (sTileBlacklist.contains(tile.intent.getComponent())) {
396 category.tiles.remove(j--);
400 sDashboardCategories = dashboardCategories;
401 onCategoriesChanged();
405 private class PackageReceiver extends BroadcastReceiver {
406 @Override
407 public void onReceive(Context context, Intent intent) {
408 new CategoriesUpdater().execute();