Home | History | Annotate | Download | only in drawer
      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
     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
    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
    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
    147     protected void onPause() {
    148         if (mDrawerLayout != null) {
    149             unregisterReceiver(mPackageReceiver);
    150         }
    151 
    152         super.onPause();
    153     }
    154 
    155     public void addCategoryListener(CategoryListener listener) {
    156         mCategoryListeners.add(listener);
    157     }
    158 
    159     public void remCategoryListener(CategoryListener listener) {
    160         mCategoryListeners.remove(listener);
    161     }
    162 
    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 
    175     public void openDrawer() {
    176         if (mDrawerLayout != null) {
    177             mDrawerLayout.openDrawer(Gravity.START);
    178         }
    179     }
    180 
    181     public void closeDrawer() {
    182         if (mDrawerLayout != null) {
    183             mDrawerLayout.closeDrawers();
    184         }
    185     }
    186 
    187     public void setContentHeaderView(View headerView) {
    188         mContentHeaderContainer.removeAllViews();
    189         if (headerView != null) {
    190             mContentHeaderContainer.addView(headerView);
    191         }
    192     }
    193 
    194     @Override
    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
    204     public void setContentView(View view) {
    205         ((ViewGroup) findViewById(R.id.content_frame)).addView(view);
    206     }
    207 
    208     @Override
    209     public void setContentView(View view, ViewGroup.LayoutParams params) {
    210         ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
    211     }
    212 
    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 
    226     public void showMenuIcon() {
    227         mShowingMenu = true;
    228         getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
    229         getActionBar().setDisplayHomeAsUpEnabled(true);
    230     }
    231 
    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 
    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 
    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 
    280     protected void onTileClicked(Tile tile) {
    281         if (openTile(tile)) {
    282             finish();
    283         }
    284     }
    285 
    286     public HashMap<Pair<String, String>, Tile> getTileCache() {
    287         if (sTileCache == null) {
    288             getDashboardCategories();
    289         }
    290         return sTileCache;
    291     }
    292 
    293     public void onProfileTileOpen() {
    294         finish();
    295     }
    296 
    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 {
    316         void onCategoriesChanged();
    317     }
    318 
    319     private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> {
    320         @Override
    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
    329         protected void onPreExecute() {
    330             if (sConfigTracker == null || sTileCache == null) {
    331                 getDashboardCategories();
    332             }
    333         }
    334 
    335         @Override
    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
    353         public void onReceive(Context context, Intent intent) {
    354             new CategoriesUpdater().execute();
    355         }
    356     }
    357 }
    358