• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.google.android.setupcompat.util;
18 
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.os.Build;
23 import android.os.Build.VERSION;
24 import android.os.Build.VERSION_CODES;
25 import android.provider.Settings;
26 import androidx.annotation.Nullable;
27 import androidx.annotation.VisibleForTesting;
28 import java.util.Arrays;
29 
30 /**
31  * Helper to interact with Wizard Manager in setup wizard, which should be used when a screen is
32  * shown inside the setup flow. This includes things like parsing extras passed by Wizard Manager,
33  * and invoking Wizard Manager to start the next action.
34  */
35 public class WizardManagerHelper {
36 
37   private static final String ACTION_NEXT = "com.android.wizard.NEXT";
38 
39   // EXTRA_SCRIPT_URI and EXTRA_ACTION_ID are used in setup wizard in versions before M and are
40   // kept for backwards compatibility.
41   @VisibleForTesting static final String EXTRA_SCRIPT_URI = "scriptUri";
42   @VisibleForTesting static final String EXTRA_ACTION_ID = "actionId";
43 
44   @VisibleForTesting static final String EXTRA_WIZARD_BUNDLE = "wizardBundle";
45   private static final String EXTRA_RESULT_CODE = "com.android.setupwizard.ResultCode";
46   @VisibleForTesting public static final String EXTRA_IS_FIRST_RUN = "firstRun";
47   @VisibleForTesting static final String EXTRA_IS_DEFERRED_SETUP = "deferredSetup";
48   @VisibleForTesting static final String EXTRA_IS_PRE_DEFERRED_SETUP = "preDeferredSetup";
49   @VisibleForTesting public static final String EXTRA_IS_SETUP_FLOW = "isSetupFlow";
50 
51   public static final String EXTRA_THEME = "theme";
52   public static final String EXTRA_USE_IMMERSIVE_MODE = "useImmersiveMode";
53 
54   public static final String SETTINGS_GLOBAL_DEVICE_PROVISIONED = "device_provisioned";
55   public static final String SETTINGS_SECURE_USER_SETUP_COMPLETE = "user_setup_complete";
56 
57   /**
58    * Gets an intent that will invoke the next step of setup wizard.
59    *
60    * @param originalIntent The original intent that was used to start the step, usually via {@link
61    *     Activity#getIntent()}.
62    * @param resultCode The result code of the step. See {@link ResultCodes}.
63    * @return A new intent that can be used with {@link Activity#startActivityForResult(Intent, int)}
64    *     to start the next step of the setup flow.
65    */
getNextIntent(Intent originalIntent, int resultCode)66   public static Intent getNextIntent(Intent originalIntent, int resultCode) {
67     return getNextIntent(originalIntent, resultCode, null);
68   }
69 
70   /**
71    * Gets an intent that will invoke the next step of setup wizard.
72    *
73    * @param originalIntent The original intent that was used to start the step, usually via {@link
74    *     Activity#getIntent()}.
75    * @param resultCode The result code of the step. See {@link ResultCodes}.
76    * @param data An intent containing extra result data.
77    * @return A new intent that can be used with {@link Activity#startActivityForResult(Intent, int)}
78    *     to start the next step of the setup flow.
79    */
getNextIntent(Intent originalIntent, int resultCode, Intent data)80   public static Intent getNextIntent(Intent originalIntent, int resultCode, Intent data) {
81     Intent intent = new Intent(ACTION_NEXT);
82     copyWizardManagerExtras(originalIntent, intent);
83     intent.putExtra(EXTRA_RESULT_CODE, resultCode);
84     if (data != null && data.getExtras() != null) {
85       intent.putExtras(data.getExtras());
86     }
87     intent.putExtra(EXTRA_THEME, originalIntent.getStringExtra(EXTRA_THEME));
88 
89     return intent;
90   }
91 
92   /**
93    * Copies the internal extras used by setup wizard from one intent to another. For low-level use
94    * only, such as when using {@link Intent#FLAG_ACTIVITY_FORWARD_RESULT} to relay to another
95    * intent.
96    *
97    * @param srcIntent Intent to get the wizard manager extras from.
98    * @param dstIntent Intent to copy the wizard manager extras to.
99    */
copyWizardManagerExtras(Intent srcIntent, Intent dstIntent)100   public static void copyWizardManagerExtras(Intent srcIntent, Intent dstIntent) {
101     dstIntent.putExtra(EXTRA_WIZARD_BUNDLE, srcIntent.getBundleExtra(EXTRA_WIZARD_BUNDLE));
102     for (String key :
103         Arrays.asList(
104             EXTRA_IS_FIRST_RUN,
105             EXTRA_IS_DEFERRED_SETUP,
106             EXTRA_IS_PRE_DEFERRED_SETUP,
107             EXTRA_IS_SETUP_FLOW)) {
108       dstIntent.putExtra(key, srcIntent.getBooleanExtra(key, false));
109     }
110 
111     for (String key : Arrays.asList(EXTRA_THEME, EXTRA_SCRIPT_URI, EXTRA_ACTION_ID)) {
112       dstIntent.putExtra(key, srcIntent.getStringExtra(key));
113     }
114   }
115 
116   /** @deprecated Use {@link isInitialSetupWizard} instead. */
117   @Deprecated
isSetupWizardIntent(Intent intent)118   public static boolean isSetupWizardIntent(Intent intent) {
119     return intent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false);
120   }
121 
122   /**
123    * Checks whether the current user has completed Setup Wizard. This is true if the current user
124    * has gone through Setup Wizard. The current user may or may not be the device owner and the
125    * device owner may have already completed setup wizard.
126    *
127    * @param context The context to retrieve the settings.
128    * @return true if the current user has completed Setup Wizard.
129    * @see #isDeviceProvisioned(Context)
130    */
isUserSetupComplete(Context context)131   public static boolean isUserSetupComplete(Context context) {
132     if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
133       return Settings.Secure.getInt(
134               context.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0)
135           == 1;
136     } else {
137       // For versions below JB MR1, there are no user profiles. Just return the global device
138       // provisioned state.
139       return Settings.Secure.getInt(
140               context.getContentResolver(), SETTINGS_GLOBAL_DEVICE_PROVISIONED, 0)
141           == 1;
142     }
143   }
144 
145   /**
146    * Checks whether the device is provisioned. This means that the device has gone through Setup
147    * Wizard at least once. Note that the user can still be in Setup Wizard even if this is true, for
148    * a secondary user profile triggered through Settings > Add account.
149    *
150    * @param context The context to retrieve the settings.
151    * @return true if the device is provisioned.
152    * @see #isUserSetupComplete(Context)
153    */
isDeviceProvisioned(Context context)154   public static boolean isDeviceProvisioned(Context context) {
155     if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
156       return Settings.Global.getInt(
157               context.getContentResolver(), SETTINGS_GLOBAL_DEVICE_PROVISIONED, 0)
158           == 1;
159     } else {
160       return Settings.Secure.getInt(
161               context.getContentResolver(), SETTINGS_GLOBAL_DEVICE_PROVISIONED, 0)
162           == 1;
163     }
164   }
165 
166   /**
167    * Checks whether an intent is running in the deferred setup wizard flow.
168    *
169    * @param originalIntent The original intent that was used to start the step, usually via {@link
170    *     Activity#getIntent()}.
171    * @return true if the intent passed in was running in deferred setup wizard.
172    */
isDeferredSetupWizard(Intent originalIntent)173   public static boolean isDeferredSetupWizard(Intent originalIntent) {
174     return originalIntent != null && originalIntent.getBooleanExtra(EXTRA_IS_DEFERRED_SETUP, false);
175   }
176 
177   /**
178    * Checks whether an intent is running in "pre-deferred" setup wizard flow.
179    *
180    * @param originalIntent The original intent that was used to start the step, usually via {@link
181    *     Activity#getIntent()}.
182    * @return true if the intent passed in was running in "pre-deferred" setup wizard.
183    */
isPreDeferredSetupWizard(Intent originalIntent)184   public static boolean isPreDeferredSetupWizard(Intent originalIntent) {
185     return originalIntent != null
186         && originalIntent.getBooleanExtra(EXTRA_IS_PRE_DEFERRED_SETUP, false);
187   }
188 
189   /**
190    * Checks whether an intent is is running in the initial setup wizard flow.
191    *
192    * @param intent The intent to be checked, usually from {@link Activity#getIntent()}.
193    * @return true if the intent passed in was intended to be used with setup wizard.
194    */
isInitialSetupWizard(Intent intent)195   public static boolean isInitialSetupWizard(Intent intent) {
196     return intent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false);
197   }
198 
199   /**
200    * Returns true if the intent passed in indicates that it is running in any setup wizard flow,
201    * including initial setup and deferred setup etc.
202    *
203    * @param originalIntent The original intent that was used to start the step, usually via {@link
204    *     Activity#getIntent()}.
205    */
isAnySetupWizard(@ullable Intent originalIntent)206   public static boolean isAnySetupWizard(@Nullable Intent originalIntent) {
207     if (originalIntent == null) {
208       return false;
209     }
210 
211     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
212       return originalIntent.getBooleanExtra(EXTRA_IS_SETUP_FLOW, false);
213     } else {
214       return isInitialSetupWizard(originalIntent)
215           || isPreDeferredSetupWizard(originalIntent)
216           || isDeferredSetupWizard(originalIntent);
217     }
218   }
219 }
220