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.ActionBar; 21 import android.app.Activity; 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.util.ArraySet; 32 import android.util.Log; 33 import android.view.LayoutInflater; 34 import android.view.View; 35 import android.view.ViewGroup; 36 import android.view.Window; 37 import android.view.WindowManager.LayoutParams; 38 import android.widget.FrameLayout; 39 import android.widget.Toolbar; 40 41 import com.android.settingslib.R; 42 43 import java.util.ArrayList; 44 import java.util.List; 45 46 public class SettingsDrawerActivity extends Activity { 47 48 protected static final boolean DEBUG_TIMING = false; 49 private static final String TAG = "SettingsDrawerActivity"; 50 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 51 52 public static final String EXTRA_SHOW_MENU = "show_drawer_menu"; 53 54 // Serves as a temporary list of tiles to ignore until we heard back from the PM that they 55 // are disabled. 56 private static ArraySet<ComponentName> sTileBlacklist = new ArraySet<>(); 57 58 private final PackageReceiver mPackageReceiver = new PackageReceiver(); 59 private final List<CategoryListener> mCategoryListeners = new ArrayList<>(); 60 61 private FrameLayout mContentHeaderContainer; 62 63 @Override 64 protected void onCreate(@Nullable Bundle savedInstanceState) { 65 super.onCreate(savedInstanceState); 66 67 long startTime = System.currentTimeMillis(); 68 69 TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme); 70 if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) { 71 getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 72 requestWindowFeature(Window.FEATURE_NO_TITLE); 73 } 74 super.setContentView(R.layout.settings_with_drawer); 75 mContentHeaderContainer = (FrameLayout) findViewById(R.id.content_header_container); 76 77 Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar); 78 if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) { 79 toolbar.setVisibility(View.GONE); 80 return; 81 } 82 setActionBar(toolbar); 83 84 if (DEBUG_TIMING) { 85 Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime) 86 + " ms"); 87 } 88 } 89 90 @Override 91 public boolean onNavigateUp() { 92 finish(); 93 return true; 94 } 95 96 @Override 97 protected void onResume() { 98 super.onResume(); 99 final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); 100 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 101 filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 102 filter.addAction(Intent.ACTION_PACKAGE_REPLACED); 103 filter.addDataScheme("package"); 104 registerReceiver(mPackageReceiver, filter); 105 106 new CategoriesUpdateTask().execute(); 107 final Intent intent = getIntent(); 108 if (intent != null && intent.getBooleanExtra(EXTRA_SHOW_MENU, false)) { 109 // Intent explicitly set to show menu. 110 showMenuIcon(); 111 } 112 } 113 114 @Override 115 protected void onPause() { 116 unregisterReceiver(mPackageReceiver); 117 super.onPause(); 118 } 119 120 public void addCategoryListener(CategoryListener listener) { 121 mCategoryListeners.add(listener); 122 } 123 124 public void remCategoryListener(CategoryListener listener) { 125 mCategoryListeners.remove(listener); 126 } 127 128 public void setContentHeaderView(View headerView) { 129 mContentHeaderContainer.removeAllViews(); 130 if (headerView != null) { 131 mContentHeaderContainer.addView(headerView); 132 } 133 } 134 135 @Override 136 public void setContentView(@LayoutRes int layoutResID) { 137 final ViewGroup parent = findViewById(R.id.content_frame); 138 if (parent != null) { 139 parent.removeAllViews(); 140 } 141 LayoutInflater.from(this).inflate(layoutResID, parent); 142 } 143 144 @Override 145 public void setContentView(View view) { 146 ((ViewGroup) findViewById(R.id.content_frame)).addView(view); 147 } 148 149 @Override 150 public void setContentView(View view, ViewGroup.LayoutParams params) { 151 ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params); 152 } 153 154 private void showMenuIcon() { 155 final ActionBar actionBar = getActionBar(); 156 if (actionBar != null) { 157 actionBar.setDisplayHomeAsUpEnabled(true); 158 } 159 } 160 161 private void onCategoriesChanged() { 162 final int N = mCategoryListeners.size(); 163 for (int i = 0; i < N; i++) { 164 mCategoryListeners.get(i).onCategoriesChanged(); 165 } 166 } 167 168 public void onProfileTileOpen() { 169 finish(); 170 } 171 172 /** 173 * @return whether or not the enabled state actually changed. 174 */ 175 public boolean setTileEnabled(ComponentName component, boolean enabled) { 176 PackageManager pm = getPackageManager(); 177 int state = pm.getComponentEnabledSetting(component); 178 boolean isEnabled = state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 179 if (isEnabled != enabled || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { 180 if (enabled) { 181 sTileBlacklist.remove(component); 182 } else { 183 sTileBlacklist.add(component); 184 } 185 pm.setComponentEnabledSetting(component, enabled 186 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 187 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 188 PackageManager.DONT_KILL_APP); 189 return true; 190 } 191 return false; 192 } 193 194 /** 195 * Updates dashboard categories. Only necessary to call this after setTileEnabled 196 */ 197 public void updateCategories() { 198 new CategoriesUpdateTask().execute(); 199 } 200 201 public String getSettingPkg() { 202 return TileUtils.SETTING_PKG; 203 } 204 205 public interface CategoryListener { 206 void onCategoriesChanged(); 207 } 208 209 private class CategoriesUpdateTask extends AsyncTask<Void, Void, Void> { 210 211 private final CategoryManager mCategoryManager; 212 213 public CategoriesUpdateTask() { 214 mCategoryManager = CategoryManager.get(SettingsDrawerActivity.this); 215 } 216 217 @Override 218 protected Void doInBackground(Void... params) { 219 mCategoryManager.reloadAllCategories(SettingsDrawerActivity.this, getSettingPkg()); 220 return null; 221 } 222 223 @Override 224 protected void onPostExecute(Void result) { 225 mCategoryManager.updateCategoryFromBlacklist(sTileBlacklist); 226 onCategoriesChanged(); 227 } 228 } 229 230 private class PackageReceiver extends BroadcastReceiver { 231 @Override 232 public void onReceive(Context context, Intent intent) { 233 new CategoriesUpdateTask().execute(); 234 } 235 } 236 } 237