1 /*
2  * Copyright 2014, 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 
17 package com.android.managedprovisioning.common;
18 
19 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
20 
21 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.VIEW_UNKNOWN;
22 import static com.android.managedprovisioning.provisioning.Constants.LOCK_TO_PORTRAIT_MODE;
23 
24 import android.app.Activity;
25 import android.app.DialogFragment;
26 import android.app.Fragment;
27 import android.app.FragmentManager;
28 import android.app.FragmentTransaction;
29 import android.content.pm.ActivityInfo;
30 import android.content.res.Configuration;
31 import android.os.Bundle;
32 
33 import androidx.annotation.NonNull;
34 import androidx.annotation.VisibleForTesting;
35 import androidx.appcompat.app.AppCompatActivity;
36 import androidx.appcompat.app.AppCompatDelegate;
37 
38 import com.android.managedprovisioning.ManagedProvisioningBaseApplication;
39 import com.android.managedprovisioning.ManagedProvisioningScreens;
40 import com.android.managedprovisioning.R;
41 import com.android.managedprovisioning.analytics.MetricsWriterFactory;
42 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker;
43 import com.android.managedprovisioning.analytics.TimeLogger;
44 import com.android.managedprovisioning.common.ThemeHelper.DefaultNightModeChecker;
45 import com.android.managedprovisioning.common.ThemeHelper.DefaultSetupWizardBridge;
46 import com.android.managedprovisioning.preprovisioning.EncryptionController;
47 
48 /**
49  * Base class for setting up the layout.
50  */
51 public abstract class SetupLayoutActivity extends AppCompatActivity {
52     protected final Utils mUtils;
53     protected final SettingsFacade mSettingsFacade;
54     private final ThemeHelper mThemeHelper;
55     private final TransitionHelper mTransitionHelper;
56     private TimeLogger mTimeLogger;
57 
SetupLayoutActivity()58     public SetupLayoutActivity() {
59         this(new Utils(), new SettingsFacade(),
60                 new ThemeHelper(new DefaultNightModeChecker(), new DefaultSetupWizardBridge()));
61     }
62 
63     @VisibleForTesting
SetupLayoutActivity( Utils utils, SettingsFacade settingsFacade, ThemeHelper themeHelper)64     protected SetupLayoutActivity(
65             Utils utils, SettingsFacade settingsFacade, ThemeHelper themeHelper) {
66         mUtils = utils;
67         mSettingsFacade = settingsFacade;
68         mThemeHelper = themeHelper;
69         // TODO(b/183036855): Add dependency injection in ManagedProvisioning
70         mTransitionHelper = new TransitionHelper();
71     }
72 
73     @Override
onCreate(Bundle savedInstanceState)74     protected void onCreate(Bundle savedInstanceState) {
75         if (!isWaitingScreen()) {
76             mTransitionHelper.applyContentScreenTransitions(this);
77         }
78         updateDefaultNightMode();
79         setTheme(mThemeHelper.inferThemeResId(this, getIntent()));
80         if (shouldSetupDynamicColors()) {
81             mThemeHelper.setupDynamicColors(this);
82         }
83         super.onCreate(savedInstanceState);
84 
85         getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
86 
87         mTimeLogger = new TimeLogger(this, getMetricsCategory());
88         mTimeLogger.start();
89 
90         // lock orientation to portrait on phones if necessary
91         if (LOCK_TO_PORTRAIT_MODE && getResources().getBoolean(R.bool.lock_to_portrait)) {
92             setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
93         }
94         logMetrics();
95     }
96 
shouldSetupDynamicColors()97     protected boolean shouldSetupDynamicColors() {
98         return true;
99     }
100 
101     @Override
onConfigurationChanged(@onNull Configuration newConfig)102     public void onConfigurationChanged(@NonNull Configuration newConfig) {
103         super.onConfigurationChanged(newConfig);
104         updateDefaultNightMode();
105     }
106 
updateDefaultNightMode()107     private void updateDefaultNightMode() {
108         int nightMode = mThemeHelper.getDefaultNightMode(this, getIntent());
109         AppCompatDelegate delegate = AppCompatDelegate.create(this, /* callback= */ null);
110         delegate.setLocalNightMode(nightMode);
111     }
112 
113     @Override
onResume()114     protected void onResume() {
115         super.onResume();
116         if (isWaitingScreen()) {
117             mTransitionHelper.applyWaitingScreenTransitions(this);
118         }
119     }
120 
logMetrics()121     private void logMetrics() {
122         // TODO(b/183036855): Add dependency injection in ManagedProvisioning
123         ProvisioningAnalyticsTracker analyticsTracker = new ProvisioningAnalyticsTracker(
124                 MetricsWriterFactory.getMetricsWriter(this, new SettingsFacade()),
125                 new ManagedProvisioningSharedPreferences(this));
126         final int orientation = getResources().getConfiguration().orientation;
127         analyticsTracker.logIsLandscape(
128                 orientation == Configuration.ORIENTATION_LANDSCAPE,
129                 getLocalClassName());
130     }
131 
132     @Override
onDestroy()133     public void onDestroy() {
134         mTimeLogger.stop();
135         super.onDestroy();
136     }
137 
getMetricsCategory()138     protected int getMetricsCategory() {
139         return VIEW_UNKNOWN;
140     }
141 
getUtils()142     protected Utils getUtils() {
143         return mUtils;
144     }
145 
getThemeHelper()146     protected ThemeHelper getThemeHelper() {
147         return mThemeHelper;
148     }
149 
getTransitionHelper()150     protected TransitionHelper getTransitionHelper() {
151         return mTransitionHelper;
152     }
153 
getBaseApplication()154     private ManagedProvisioningBaseApplication getBaseApplication() {
155         return ((ManagedProvisioningBaseApplication) getApplication());
156     }
157 
getActivityForScreen(ManagedProvisioningScreens screen)158     protected Class<? extends Activity> getActivityForScreen(ManagedProvisioningScreens screen) {
159         return getBaseApplication().getActivityClassForScreen(screen);
160     }
161 
getEncryptionController()162     protected EncryptionController getEncryptionController() {
163         return getBaseApplication().getEncryptionController();
164     }
165 
166     /**
167      * Whether the current screen is a waiting screen.
168      *
169      * <p>A waiting screen is a screen that shows a spinner and not content.
170      */
isWaitingScreen()171     protected boolean isWaitingScreen() {
172         return false;
173     }
174 
175     /**
176      * Constructs and shows a {@link DialogFragment} unless it is already displayed.
177      * @param dialogBuilder Lightweight builder, that it is inexpensive to discard it if dialog
178      * already shown.
179      * @param tag The tag for this dialog, as per {@link FragmentTransaction#add(Fragment, String)}.
180      */
showDialog(DialogBuilder dialogBuilder, String tag)181     protected void showDialog(DialogBuilder dialogBuilder, String tag) {
182         FragmentManager fragmentManager = getFragmentManager();
183         if (!isDialogAdded(tag)) {
184             dialogBuilder.build().show(fragmentManager, tag);
185         }
186     }
187 
188     /**
189      * Checks whether the {@link DialogFragment} associated with the given tag is currently showing.
190      * @param tag The tag for this dialog.
191      */
isDialogAdded(String tag)192     protected boolean isDialogAdded(String tag) {
193         Fragment fragment = getFragmentManager().findFragmentByTag(tag);
194         return (fragment != null) && (fragment.isAdded());
195     }
196 }