1 /** 2 * Copyright (C) 2018 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.settings.core; 17 18 import android.annotation.LayoutRes; 19 import android.app.ActivityManager; 20 import android.content.ComponentName; 21 import android.content.Intent; 22 import android.content.pm.PackageManager; 23 import android.content.res.TypedArray; 24 import android.os.Bundle; 25 import android.text.TextUtils; 26 import android.util.Log; 27 import android.view.LayoutInflater; 28 import android.view.View; 29 import android.view.ViewGroup; 30 import android.view.Window; 31 import android.widget.Toolbar; 32 33 import androidx.annotation.NonNull; 34 import androidx.annotation.Nullable; 35 import androidx.coordinatorlayout.widget.CoordinatorLayout; 36 import androidx.fragment.app.FragmentActivity; 37 38 import com.android.settings.R; 39 import com.android.settings.SetupWizardUtils; 40 import com.android.settings.SubSettings; 41 import com.android.settings.core.CategoryMixin.CategoryHandler; 42 import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin; 43 import com.android.settingslib.transition.SettingsTransitionHelper.TransitionType; 44 45 import com.google.android.material.appbar.AppBarLayout; 46 import com.google.android.material.appbar.CollapsingToolbarLayout; 47 import com.google.android.material.resources.TextAppearanceConfig; 48 import com.google.android.setupcompat.util.WizardManagerHelper; 49 import com.google.android.setupdesign.util.ThemeHelper; 50 51 /** Base activity for Settings pages */ 52 public class SettingsBaseActivity extends FragmentActivity implements CategoryHandler { 53 54 /** 55 * What type of page transition should be apply. 56 */ 57 public static final String EXTRA_PAGE_TRANSITION_TYPE = "page_transition_type"; 58 59 protected static final boolean DEBUG_TIMING = false; 60 private static final String TAG = "SettingsBaseActivity"; 61 private static final int DEFAULT_REQUEST = -1; 62 private static final float TOOLBAR_LINE_SPACING_MULTIPLIER = 1.1f; 63 64 protected CategoryMixin mCategoryMixin; 65 protected CollapsingToolbarLayout mCollapsingToolbarLayout; 66 protected AppBarLayout mAppBarLayout; 67 private Toolbar mToolbar; 68 69 @Override getCategoryMixin()70 public CategoryMixin getCategoryMixin() { 71 return mCategoryMixin; 72 } 73 74 @Override onCreate(@ullable Bundle savedInstanceState)75 protected void onCreate(@Nullable Bundle savedInstanceState) { 76 super.onCreate(savedInstanceState); 77 if (isFinishing()) { 78 return; 79 } 80 if (isLockTaskModePinned() && !isSettingsRunOnTop()) { 81 Log.w(TAG, "Devices lock task mode pinned."); 82 finish(); 83 } 84 final long startTime = System.currentTimeMillis(); 85 getLifecycle().addObserver(new HideNonSystemOverlayMixin(this)); 86 TextAppearanceConfig.setShouldLoadFontSynchronously(true); 87 88 mCategoryMixin = new CategoryMixin(this); 89 getLifecycle().addObserver(mCategoryMixin); 90 91 final TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme); 92 if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) { 93 requestWindowFeature(Window.FEATURE_NO_TITLE); 94 } 95 // Apply SetupWizard light theme during setup flow. This is for SubSettings pages. 96 final boolean isAnySetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent()); 97 if (isAnySetupWizard && this instanceof SubSettings) { 98 if (ThemeHelper.trySetDynamicColor(this)) { 99 final int appliedTheme = ThemeHelper.isSetupWizardDayNightEnabled(this) 100 ? R.style.SudDynamicColorThemeSettings_SetupWizard_DayNight 101 : R.style.SudDynamicColorThemeSettings_SetupWizard; 102 setTheme(appliedTheme); 103 } else { 104 setTheme(SetupWizardUtils.getTheme(this, getIntent())); 105 } 106 } 107 108 if (isToolbarEnabled() && !isAnySetupWizard) { 109 super.setContentView(R.layout.collapsing_toolbar_base_layout); 110 mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar); 111 mAppBarLayout = findViewById(R.id.app_bar); 112 if (mCollapsingToolbarLayout != null) { 113 mCollapsingToolbarLayout.setLineSpacingMultiplier(TOOLBAR_LINE_SPACING_MULTIPLIER); 114 } 115 disableCollapsingToolbarLayoutScrollingBehavior(); 116 } else { 117 super.setContentView(R.layout.settings_base_layout); 118 } 119 120 // This is to hide the toolbar from those pages which don't need a toolbar originally. 121 final Toolbar toolbar = findViewById(R.id.action_bar); 122 if (!isToolbarEnabled() || isAnySetupWizard) { 123 toolbar.setVisibility(View.GONE); 124 return; 125 } 126 setActionBar(toolbar); 127 128 if (DEBUG_TIMING) { 129 Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime) + " ms"); 130 } 131 } 132 133 @Override setActionBar(@ndroidx.annotation.Nullable Toolbar toolbar)134 public void setActionBar(@androidx.annotation.Nullable Toolbar toolbar) { 135 super.setActionBar(toolbar); 136 137 mToolbar = toolbar; 138 } 139 140 @Override onNavigateUp()141 public boolean onNavigateUp() { 142 if (!super.onNavigateUp()) { 143 finishAfterTransition(); 144 } 145 return true; 146 } 147 148 @Override startActivityForResult(Intent intent, int requestCode, @androidx.annotation.Nullable Bundle options)149 public void startActivityForResult(Intent intent, int requestCode, 150 @androidx.annotation.Nullable Bundle options) { 151 final int transitionType = getTransitionType(intent); 152 super.startActivityForResult(intent, requestCode, options); 153 if (transitionType == TransitionType.TRANSITION_SLIDE) { 154 overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out); 155 } else if (transitionType == TransitionType.TRANSITION_FADE) { 156 overridePendingTransition(android.R.anim.fade_in, R.anim.sud_stay); 157 } 158 } 159 160 @Override onPause()161 protected void onPause() { 162 // For accessibility activities launched from setup wizard. 163 if (getTransitionType(getIntent()) == TransitionType.TRANSITION_FADE) { 164 overridePendingTransition(R.anim.sud_stay, android.R.anim.fade_out); 165 } 166 super.onPause(); 167 } 168 169 @Override setContentView(@ayoutRes int layoutResID)170 public void setContentView(@LayoutRes int layoutResID) { 171 final ViewGroup parent = findViewById(R.id.content_frame); 172 if (parent != null) { 173 parent.removeAllViews(); 174 } 175 LayoutInflater.from(this).inflate(layoutResID, parent); 176 } 177 178 @Override setContentView(View view)179 public void setContentView(View view) { 180 ((ViewGroup) findViewById(R.id.content_frame)).addView(view); 181 } 182 183 @Override setContentView(View view, ViewGroup.LayoutParams params)184 public void setContentView(View view, ViewGroup.LayoutParams params) { 185 ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params); 186 } 187 188 @Override setTitle(CharSequence title)189 public void setTitle(CharSequence title) { 190 super.setTitle(title); 191 if (mCollapsingToolbarLayout != null) { 192 mCollapsingToolbarLayout.setTitle(title); 193 } 194 } 195 196 @Override setTitle(int titleId)197 public void setTitle(int titleId) { 198 super.setTitle(getText(titleId)); 199 if (mCollapsingToolbarLayout != null) { 200 mCollapsingToolbarLayout.setTitle(getText(titleId)); 201 } 202 } 203 204 /** 205 * SubSetting page should show a toolbar by default. If the page wouldn't show a toolbar, 206 * override this method and return false value. 207 * 208 * @return ture by default 209 */ isToolbarEnabled()210 protected boolean isToolbarEnabled() { 211 return true; 212 } 213 isLockTaskModePinned()214 private boolean isLockTaskModePinned() { 215 final ActivityManager activityManager = 216 getApplicationContext().getSystemService(ActivityManager.class); 217 return activityManager.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_PINNED; 218 } 219 isSettingsRunOnTop()220 private boolean isSettingsRunOnTop() { 221 final ActivityManager activityManager = 222 getApplicationContext().getSystemService(ActivityManager.class); 223 final String taskPkgName = activityManager.getRunningTasks(1 /* maxNum */) 224 .get(0 /* index */).baseActivity.getPackageName(); 225 return TextUtils.equals(getPackageName(), taskPkgName); 226 } 227 228 /** 229 * @return whether or not the enabled state actually changed. 230 */ setTileEnabled(ComponentName component, boolean enabled)231 public boolean setTileEnabled(ComponentName component, boolean enabled) { 232 final PackageManager pm = getPackageManager(); 233 int state = pm.getComponentEnabledSetting(component); 234 boolean isEnabled = state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 235 if (isEnabled != enabled || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { 236 if (enabled) { 237 mCategoryMixin.removeFromDenylist(component); 238 } else { 239 mCategoryMixin.addToDenylist(component); 240 } 241 pm.setComponentEnabledSetting(component, enabled 242 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 243 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 244 PackageManager.DONT_KILL_APP); 245 return true; 246 } 247 return false; 248 } 249 disableCollapsingToolbarLayoutScrollingBehavior()250 private void disableCollapsingToolbarLayoutScrollingBehavior() { 251 if (mAppBarLayout == null) { 252 return; 253 } 254 final CoordinatorLayout.LayoutParams params = 255 (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams(); 256 final AppBarLayout.Behavior behavior = new AppBarLayout.Behavior(); 257 behavior.setDragCallback( 258 new AppBarLayout.Behavior.DragCallback() { 259 @Override 260 public boolean canDrag(@NonNull AppBarLayout appBarLayout) { 261 return false; 262 } 263 }); 264 params.setBehavior(behavior); 265 } 266 getTransitionType(Intent intent)267 private int getTransitionType(Intent intent) { 268 return intent.getIntExtra(EXTRA_PAGE_TRANSITION_TYPE, TransitionType.TRANSITION_NONE); 269 } 270 } 271