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