blob: 458672a41b77e1dbb7cfbee21ea5eaa23f8b7163 [file] [log] [blame]
Jason Monk744b6362015-11-03 18:24:29 -05001/**
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;
Jason Monk6bea9502016-02-25 13:07:41 -050021import android.content.ActivityNotFoundException;
Jason Monke79790b2015-12-02 15:39:19 -050022import android.content.BroadcastReceiver;
Jason Monkfcad09a2016-06-07 14:01:32 -040023import android.content.ComponentName;
Jason Monke79790b2015-12-02 15:39:19 -050024import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
Jason Monkfcad09a2016-06-07 14:01:32 -040027import android.content.pm.PackageManager;
Jason Monkf18a55d2015-11-12 10:52:21 -050028import android.content.res.TypedArray;
Jason Monke79790b2015-12-02 15:39:19 -050029import android.os.AsyncTask;
Jason Monk744b6362015-11-03 18:24:29 -050030import android.os.Bundle;
jackqdyuleidfc6ce52016-08-24 09:48:54 -070031import android.os.UserHandle;
32import android.os.UserManager;
Jason Monkcafda1f2016-02-05 10:16:22 -050033import android.provider.Settings;
Jason Monk744b6362015-11-03 18:24:29 -050034import android.support.v4.widget.DrawerLayout;
Jason Monkfcad09a2016-06-07 14:01:32 -040035import android.util.ArraySet;
Jason Monke79790b2015-12-02 15:39:19 -050036import android.util.Log;
Jason Monk744b6362015-11-03 18:24:29 -050037import android.util.Pair;
38import android.view.Gravity;
39import android.view.LayoutInflater;
40import android.view.MenuItem;
41import android.view.View;
42import android.view.ViewGroup;
43import android.view.Window;
Jason Monkcafda1f2016-02-05 10:16:22 -050044import android.view.WindowManager.LayoutParams;
Jason Monk744b6362015-11-03 18:24:29 -050045import android.widget.AdapterView;
Fan Zhang7163d772016-03-29 10:30:13 -070046import android.widget.FrameLayout;
Jason Monk744b6362015-11-03 18:24:29 -050047import android.widget.ListView;
48import android.widget.Toolbar;
Fan Zhang7163d772016-03-29 10:30:13 -070049
Jason Monk744b6362015-11-03 18:24:29 -050050import com.android.settingslib.R;
Jason Monkec02e472016-03-28 10:44:43 -040051import com.android.settingslib.applications.InterestingConfigChanges;
Jason Monk744b6362015-11-03 18:24:29 -050052
Jason Monke79790b2015-12-02 15:39:19 -050053import java.util.ArrayList;
Jason Monk744b6362015-11-03 18:24:29 -050054import java.util.HashMap;
55import java.util.List;
56
57public class SettingsDrawerActivity extends Activity {
58
Jason Monke79790b2015-12-02 15:39:19 -050059 protected static final boolean DEBUG_TIMING = false;
60 private static final String TAG = "SettingsDrawerActivity";
61
Clara Bayarri962694d2016-04-29 16:56:02 +010062 public static final String EXTRA_SHOW_MENU = "show_drawer_menu";
Jason Monk946483a2016-01-22 15:19:44 -050063
Jason Monke79790b2015-12-02 15:39:19 -050064 private static List<DashboardCategory> sDashboardCategories;
Jason Monkf509d7e2016-01-07 16:22:53 -050065 private static HashMap<Pair<String, String>, Tile> sTileCache;
Jason Monkfcad09a2016-06-07 14:01:32 -040066 // Serves as a temporary list of tiles to ignore until we heard back from the PM that they
67 // are disabled.
68 private static ArraySet<ComponentName> sTileBlacklist = new ArraySet<>();
Jason Monkec02e472016-03-28 10:44:43 -040069 private static InterestingConfigChanges sConfigTracker;
Jason Monke79790b2015-12-02 15:39:19 -050070
71 private final PackageReceiver mPackageReceiver = new PackageReceiver();
72 private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
73
Jason Monk744b6362015-11-03 18:24:29 -050074 private SettingsDrawerAdapter mDrawerAdapter;
Fan Zhang7163d772016-03-29 10:30:13 -070075 private FrameLayout mContentHeaderContainer;
Jason Monk744b6362015-11-03 18:24:29 -050076 private DrawerLayout mDrawerLayout;
Jason Monk946483a2016-01-22 15:19:44 -050077 private boolean mShowingMenu;
jackqdyuleidfc6ce52016-08-24 09:48:54 -070078 private UserManager mUserManager;
Jason Monk744b6362015-11-03 18:24:29 -050079
80 @Override
81 protected void onCreate(@Nullable Bundle savedInstanceState) {
82 super.onCreate(savedInstanceState);
83
Jason Monke79790b2015-12-02 15:39:19 -050084 long startTime = System.currentTimeMillis();
85
Udam Saini48987f62016-03-03 13:20:18 -080086 TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
87 if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
88 getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
89 getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
90 requestWindowFeature(Window.FEATURE_NO_TITLE);
91 }
Jason Monk744b6362015-11-03 18:24:29 -050092 super.setContentView(R.layout.settings_with_drawer);
Fan Zhang7163d772016-03-29 10:30:13 -070093 mContentHeaderContainer = (FrameLayout) findViewById(R.id.content_header_container);
Jason Monk744b6362015-11-03 18:24:29 -050094 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
Jason Monk51a94232015-11-04 14:57:15 -050095 if (mDrawerLayout == null) {
96 return;
97 }
Jason Monk744b6362015-11-03 18:24:29 -050098 Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
Jason Monkf18a55d2015-11-12 10:52:21 -050099 if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
100 toolbar.setVisibility(View.GONE);
101 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
102 mDrawerLayout = null;
103 return;
104 }
Jason Monk2a5d79a2015-12-03 10:51:58 -0500105 getDashboardCategories();
Jason Monk744b6362015-11-03 18:24:29 -0500106 setActionBar(toolbar);
107 mDrawerAdapter = new SettingsDrawerAdapter(this);
108 ListView listView = (ListView) findViewById(R.id.left_drawer);
109 listView.setAdapter(mDrawerAdapter);
110 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
111 public void onItemClick(android.widget.AdapterView<?> parent, View view, int position,
112 long id) {
113 onTileClicked(mDrawerAdapter.getTile(position));
114 };
115 });
jackqdyuleidfc6ce52016-08-24 09:48:54 -0700116
117 mUserManager = UserManager.get(this);
Jason Monke79790b2015-12-02 15:39:19 -0500118 if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
119 + " ms");
Jason Monk744b6362015-11-03 18:24:29 -0500120 }
121
122 @Override
123 public boolean onOptionsItemSelected(MenuItem item) {
Jason Monk946483a2016-01-22 15:19:44 -0500124 if (mShowingMenu && mDrawerLayout != null && item.getItemId() == android.R.id.home
Jason Monk51a94232015-11-04 14:57:15 -0500125 && mDrawerAdapter.getCount() != 0) {
Jason Monk744b6362015-11-03 18:24:29 -0500126 openDrawer();
127 return true;
128 }
129 return super.onOptionsItemSelected(item);
130 }
131
132 @Override
133 protected void onResume() {
134 super.onResume();
135
Jason Monk2a5d79a2015-12-03 10:51:58 -0500136 if (mDrawerLayout != null) {
137 final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
138 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
139 filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
140 filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
141 filter.addDataScheme("package");
142 registerReceiver(mPackageReceiver, filter);
Jason Monke79790b2015-12-02 15:39:19 -0500143
Jason Monk2a5d79a2015-12-03 10:51:58 -0500144 new CategoriesUpdater().execute();
145 }
Jason Monk946483a2016-01-22 15:19:44 -0500146 if (getIntent() != null && getIntent().getBooleanExtra(EXTRA_SHOW_MENU, false)) {
147 showMenuIcon();
148 }
Jason Monke79790b2015-12-02 15:39:19 -0500149 }
150
151 @Override
152 protected void onPause() {
Jason Monk2a5d79a2015-12-03 10:51:58 -0500153 if (mDrawerLayout != null) {
154 unregisterReceiver(mPackageReceiver);
155 }
Jason Monke79790b2015-12-02 15:39:19 -0500156
157 super.onPause();
158 }
159
160 public void addCategoryListener(CategoryListener listener) {
161 mCategoryListeners.add(listener);
162 }
163
164 public void remCategoryListener(CategoryListener listener) {
165 mCategoryListeners.remove(listener);
Jason Monk744b6362015-11-03 18:24:29 -0500166 }
167
Anna Galusza1774a272016-02-01 15:44:00 -0800168 public void setIsDrawerPresent(boolean isPresent) {
Anna Galuszafb695c62016-02-02 10:06:05 -0800169 if (isPresent) {
Anna Galusza1774a272016-02-01 15:44:00 -0800170 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
171 updateDrawer();
172 } else {
Udam Saini68dab672016-03-29 10:49:18 -0700173 if (mDrawerLayout != null) {
174 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
175 mDrawerLayout = null;
176 }
Anna Galusza1774a272016-02-01 15:44:00 -0800177 }
178 }
179
Jason Monk744b6362015-11-03 18:24:29 -0500180 public void openDrawer() {
Jason Monk51a94232015-11-04 14:57:15 -0500181 if (mDrawerLayout != null) {
182 mDrawerLayout.openDrawer(Gravity.START);
183 }
Jason Monk744b6362015-11-03 18:24:29 -0500184 }
185
186 public void closeDrawer() {
Jason Monk51a94232015-11-04 14:57:15 -0500187 if (mDrawerLayout != null) {
188 mDrawerLayout.closeDrawers();
189 }
Jason Monk744b6362015-11-03 18:24:29 -0500190 }
191
Fan Zhang7163d772016-03-29 10:30:13 -0700192 public void setContentHeaderView(View headerView) {
193 mContentHeaderContainer.removeAllViews();
194 if (headerView != null) {
195 mContentHeaderContainer.addView(headerView);
196 }
197 }
198
Jason Monk744b6362015-11-03 18:24:29 -0500199 @Override
200 public void setContentView(@LayoutRes int layoutResID) {
Jason Monk4ea66572016-03-30 11:05:51 -0400201 final ViewGroup parent = (ViewGroup) findViewById(R.id.content_frame);
202 if (parent != null) {
203 parent.removeAllViews();
204 }
205 LayoutInflater.from(this).inflate(layoutResID, parent);
Jason Monk744b6362015-11-03 18:24:29 -0500206 }
207
208 @Override
209 public void setContentView(View view) {
210 ((ViewGroup) findViewById(R.id.content_frame)).addView(view);
211 }
212
213 @Override
214 public void setContentView(View view, ViewGroup.LayoutParams params) {
215 ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
216 }
217
218 public void updateDrawer() {
Jason Monk51a94232015-11-04 14:57:15 -0500219 if (mDrawerLayout == null) {
220 return;
221 }
Jason Monk744b6362015-11-03 18:24:29 -0500222 // TODO: Do this in the background with some loading.
223 mDrawerAdapter.updateCategories();
Jason Monk51a94232015-11-04 14:57:15 -0500224 if (mDrawerAdapter.getCount() != 0) {
225 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
Jason Monk51a94232015-11-04 14:57:15 -0500226 } else {
227 mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
228 }
Jason Monk744b6362015-11-03 18:24:29 -0500229 }
230
Jason Monk946483a2016-01-22 15:19:44 -0500231 public void showMenuIcon() {
232 mShowingMenu = true;
233 getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
Fan Zhangc10db982016-08-11 13:52:04 -0700234 getActionBar().setHomeActionContentDescription(R.string.content_description_menu_button);
Jason Monk946483a2016-01-22 15:19:44 -0500235 getActionBar().setDisplayHomeAsUpEnabled(true);
236 }
237
Jason Monke79790b2015-12-02 15:39:19 -0500238 public List<DashboardCategory> getDashboardCategories() {
Jason Monk2a5d79a2015-12-03 10:51:58 -0500239 if (sDashboardCategories == null) {
240 sTileCache = new HashMap<>();
Jason Monkec02e472016-03-28 10:44:43 -0400241 sConfigTracker = new InterestingConfigChanges();
Jason Monkb0ae8f82016-04-12 10:30:43 -0400242 // Apply initial current config.
243 sConfigTracker.applyNewConfig(getResources());
Jason Monk2a5d79a2015-12-03 10:51:58 -0500244 sDashboardCategories = TileUtils.getCategories(this, sTileCache);
245 }
Jason Monke79790b2015-12-02 15:39:19 -0500246 return sDashboardCategories;
247 }
248
249 protected void onCategoriesChanged() {
250 updateDrawer();
251 final int N = mCategoryListeners.size();
252 for (int i = 0; i < N; i++) {
253 mCategoryListeners.get(i).onCategoriesChanged();
Jason Monk744b6362015-11-03 18:24:29 -0500254 }
Jason Monk744b6362015-11-03 18:24:29 -0500255 }
256
Jason Monkf509d7e2016-01-07 16:22:53 -0500257 public boolean openTile(Tile tile) {
Jason Monk744b6362015-11-03 18:24:29 -0500258 closeDrawer();
Jason Monk3175a6e2015-11-30 15:05:35 -0500259 if (tile == null) {
Jason Monkcafda1f2016-02-05 10:16:22 -0500260 startActivity(new Intent(Settings.ACTION_SETTINGS).addFlags(
261 Intent.FLAG_ACTIVITY_CLEAR_TASK));
262 return true;
Jason Monk3175a6e2015-11-30 15:05:35 -0500263 }
Jason Monk6bea9502016-02-25 13:07:41 -0500264 try {
jackqdyuleidfc6ce52016-08-24 09:48:54 -0700265 updateUserHandlesIfNeeded(tile);
Jason Monk6bea9502016-02-25 13:07:41 -0500266 int numUserHandles = tile.userHandle.size();
267 if (numUserHandles > 1) {
268 ProfileSelectDialog.show(getFragmentManager(), tile);
269 return false;
270 } else if (numUserHandles == 1) {
271 // Show menu on top level items.
272 tile.intent.putExtra(EXTRA_SHOW_MENU, true);
273 tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
274 startActivityAsUser(tile.intent, tile.userHandle.get(0));
275 } else {
276 // Show menu on top level items.
277 tile.intent.putExtra(EXTRA_SHOW_MENU, true);
278 tile.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
279 startActivity(tile.intent);
280 }
281 } catch (ActivityNotFoundException e) {
282 Log.w(TAG, "Couldn't find tile " + tile.intent, e);
Jason Monk0d72d202015-11-04 13:16:00 -0500283 }
284 return true;
Jason Monk744b6362015-11-03 18:24:29 -0500285 }
286
jackqdyuleidfc6ce52016-08-24 09:48:54 -0700287 private void updateUserHandlesIfNeeded(Tile tile) {
288 List<UserHandle> userHandles = tile.userHandle;
289
290 for (int i = userHandles.size()-1; i >= 0; i--) {
291 if (mUserManager.getUserInfo(userHandles.get(i).getIdentifier()) == null) {
292 if (DEBUG_TIMING) {
293 Log.d(TAG, "Delete the user: " + userHandles.get(i).getIdentifier());
294 }
295 userHandles.remove(i);
296 }
297 }
298 }
299
Jason Monkf509d7e2016-01-07 16:22:53 -0500300 protected void onTileClicked(Tile tile) {
Jason Monk0d72d202015-11-04 13:16:00 -0500301 if (openTile(tile)) {
302 finish();
303 }
304 }
305
Hyunyoung Songbe6c4482016-05-04 10:23:06 -0700306 public HashMap<Pair<String, String>, Tile> getTileCache() {
307 if (sTileCache == null) {
308 getDashboardCategories();
309 }
310 return sTileCache;
311 }
312
Jason Monk0d72d202015-11-04 13:16:00 -0500313 public void onProfileTileOpen() {
Jason Monk744b6362015-11-03 18:24:29 -0500314 finish();
315 }
Jason Monke79790b2015-12-02 15:39:19 -0500316
Jason Monkfcad09a2016-06-07 14:01:32 -0400317 public void setTileEnabled(ComponentName component, boolean enabled) {
318 PackageManager pm = getPackageManager();
319 int state = pm.getComponentEnabledSetting(component);
320 boolean isEnabled = state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
321 if (isEnabled != enabled || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
322 if (enabled) {
323 sTileBlacklist.remove(component);
324 } else {
325 sTileBlacklist.add(component);
326 }
327 pm.setComponentEnabledSetting(component, enabled
328 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
329 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
330 PackageManager.DONT_KILL_APP);
331 new CategoriesUpdater().execute();
332 }
333 }
334
Jason Monke79790b2015-12-02 15:39:19 -0500335 public interface CategoryListener {
336 void onCategoriesChanged();
337 }
338
339 private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> {
340 @Override
341 protected List<DashboardCategory> doInBackground(Void... params) {
Jason Monkec02e472016-03-28 10:44:43 -0400342 if (sConfigTracker.applyNewConfig(getResources())) {
343 sTileCache.clear();
344 }
Jason Monke79790b2015-12-02 15:39:19 -0500345 return TileUtils.getCategories(SettingsDrawerActivity.this, sTileCache);
346 }
347
348 @Override
Richard Ho8c4e4b02016-06-13 16:54:04 -0700349 protected void onPreExecute() {
350 if (sConfigTracker == null || sTileCache == null) {
351 getDashboardCategories();
352 }
353 }
354
355 @Override
Jason Monke79790b2015-12-02 15:39:19 -0500356 protected void onPostExecute(List<DashboardCategory> dashboardCategories) {
Jason Monkfcad09a2016-06-07 14:01:32 -0400357 for (int i = 0; i < dashboardCategories.size(); i++) {
358 DashboardCategory category = dashboardCategories.get(i);
359 for (int j = 0; j < category.tiles.size(); j++) {
360 Tile tile = category.tiles.get(j);
361 if (sTileBlacklist.contains(tile.intent.getComponent())) {
362 category.tiles.remove(j--);
363 }
364 }
365 }
Jason Monke79790b2015-12-02 15:39:19 -0500366 sDashboardCategories = dashboardCategories;
367 onCategoriesChanged();
368 }
369 }
370
371 private class PackageReceiver extends BroadcastReceiver {
372 @Override
373 public void onReceive(Context context, Intent intent) {
374 new CategoriesUpdater().execute();
375 }
376 }
Jason Monk744b6362015-11-03 18:24:29 -0500377}