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