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