1 /* 2 * Copyright (C) 2021 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.provisioning; 18 19 import static com.google.android.setupdesign.util.ThemeHelper.shouldApplyExtendedPartnerConfig; 20 21 import android.app.Activity; 22 import android.view.View; 23 import android.view.ViewGroup; 24 import android.widget.LinearLayout; 25 import android.widget.Space; 26 import android.widget.TextView; 27 28 import androidx.annotation.StringRes; 29 30 import com.android.managedprovisioning.R; 31 import com.android.managedprovisioning.common.InitializeLayoutConsumerHandler; 32 import com.android.managedprovisioning.common.StylerHelper; 33 import com.android.managedprovisioning.common.Utils; 34 import com.android.managedprovisioning.model.CustomizationParams; 35 import com.android.managedprovisioning.model.ProvisioningParams; 36 import com.android.managedprovisioning.provisioning.ProvisioningActivity.ProvisioningMode; 37 import com.android.managedprovisioning.provisioning.ProvisioningModeWrapperProvider.ProvisioningModeWrapper; 38 import com.android.managedprovisioning.provisioning.TransitionAnimationHelper.AnimationComponents; 39 import com.android.managedprovisioning.provisioning.TransitionAnimationHelper.TransitionAnimationCallback; 40 import com.android.managedprovisioning.provisioning.TransitionAnimationHelper.TransitionAnimationStateManager; 41 42 import com.airbnb.lottie.LottieAnimationView; 43 import com.google.android.setupdesign.GlifLayout; 44 import com.google.android.setupdesign.util.ContentStyler; 45 import com.google.android.setupdesign.util.DescriptionStyler; 46 import com.google.auto.value.AutoValue; 47 48 import java.util.function.Supplier; 49 50 @AutoValue 51 abstract class ProvisioningActivityBridgeImpl implements ProvisioningActivityBridge { 52 53 private TransitionAnimationHelper mTransitionAnimationHelper; 54 private ViewGroup mButtonFooterContainer; 55 getUtils()56 abstract Utils getUtils(); getParams()57 abstract ProvisioningParams getParams(); getProvisioningMode()58 abstract @ProvisioningMode int getProvisioningMode(); getProvisioningManager()59 abstract ProvisioningManager getProvisioningManager(); getTransitionAnimationCallback()60 abstract TransitionAnimationCallback getTransitionAnimationCallback(); getInitializeLayoutParamsConsumer()61 abstract InitializeLayoutConsumerHandler getInitializeLayoutParamsConsumer(); getShouldSkipEducationScreens()62 abstract boolean getShouldSkipEducationScreens(); getProgressLabelResId()63 abstract @StringRes int getProgressLabelResId(); getBridgeCallbacks()64 abstract ProvisioningActivityBridgeCallbacks getBridgeCallbacks(); getStateManager()65 abstract TransitionAnimationStateManager getStateManager(); 66 67 @Override initiateUi(Activity activity)68 public void initiateUi(Activity activity) { 69 boolean isPoProvisioning = getUtils().isProfileOwnerAction(getParams().provisioningAction); 70 int titleResId = 71 isPoProvisioning ? R.string.setup_profile_progress : R.string.setup_device_progress; 72 int layoutResId = getShouldSkipEducationScreens() 73 ? R.layout.empty_loading_layout 74 : R.layout.provisioning_progress; 75 76 CustomizationParams customizationParams = 77 CustomizationParams.createInstance(getParams(), activity, getUtils()); 78 getInitializeLayoutParamsConsumer().initializeLayoutParams( 79 layoutResId, /* headerResId */ null, customizationParams); 80 activity.setTitle(titleResId); 81 82 GlifLayout layout = activity.findViewById(R.id.setup_wizard_layout); 83 setupEducationViews( 84 layout, activity, getShouldSkipEducationScreens(), getProgressLabelResId()); 85 if (getUtils().isFinancedDeviceAction(getParams().provisioningAction)) { 86 // make the icon invisible 87 layout.findViewById(R.id.sud_layout_icon).setVisibility(View.INVISIBLE); 88 } 89 90 Utils.addNextButton(layout, v -> getBridgeCallbacks().onNextButtonClicked()); 91 //TODO(b/181323689): Add tests to ProvisioningActivityTest that the button is not 92 // shown for non-DO provisioning flows. 93 if (getUtils().isDeviceOwnerAction(getParams().provisioningAction)) { 94 Utils.addAbortAndResetButton(layout, v -> getBridgeCallbacks().onAbortButtonClicked()); 95 } 96 ViewGroup root = activity.findViewById(R.id.sud_layout_template_content); 97 mButtonFooterContainer = getButtonFooterContainer(root); 98 99 getUtils().onViewMeasured( 100 mButtonFooterContainer, 101 view -> onContainerMeasured( 102 view, 103 activity, 104 getBridgeCallbacks()::isProvisioningFinalized)); 105 } 106 onContainerMeasured( View view, Activity activity, Supplier<Boolean> checkIsProvisioningFinalised)107 private void onContainerMeasured( 108 View view, 109 Activity activity, 110 Supplier<Boolean> checkIsProvisioningFinalised) { 111 if (checkIsProvisioningFinalised.get()) { 112 view.setVisibility(View.VISIBLE); 113 return; 114 } 115 getProvisioningProgressLabelContainer(activity).setLayoutParams( 116 new LinearLayout.LayoutParams( 117 ViewGroup.LayoutParams.MATCH_PARENT, 118 view.getHeight())); 119 view.setVisibility(View.GONE); 120 } 121 122 @Override onStart(Activity activity)123 public void onStart(Activity activity) { 124 if (!getShouldSkipEducationScreens()) { 125 startTransitionAnimation(activity, getTransitionAnimationCallback()); 126 } 127 } 128 129 @Override onStop()130 public void onStop() { 131 if (!getShouldSkipEducationScreens()) { 132 endTransitionAnimation(); 133 } 134 } 135 136 @Override onProvisioningFinalized(Activity activity)137 public void onProvisioningFinalized(Activity activity) { 138 if (!getShouldSkipEducationScreens()) { 139 getProvisioningProgressLabelContainer(activity).setVisibility(View.GONE); 140 mButtonFooterContainer.setVisibility(View.VISIBLE); 141 } 142 143 if (getShouldSkipEducationScreens()) { 144 getBridgeCallbacks().onNextButtonClicked(); 145 } 146 } 147 148 @Override shouldShowButtonsWhenPreProvisioningCompletes()149 public boolean shouldShowButtonsWhenPreProvisioningCompletes() { 150 return mTransitionAnimationHelper.areAllTransitionsShown(); 151 } 152 startTransitionAnimation( Activity activity, TransitionAnimationCallback callback)153 private void startTransitionAnimation( 154 Activity activity, 155 TransitionAnimationCallback callback) { 156 final GlifLayout layout = activity.findViewById(R.id.setup_wizard_layout); 157 setupTransitionAnimationHelper(layout, callback); 158 mTransitionAnimationHelper.start(); 159 } 160 endTransitionAnimation()161 private void endTransitionAnimation() { 162 mTransitionAnimationHelper.stop(); 163 mTransitionAnimationHelper = null; 164 } 165 setupTransitionAnimationHelper( GlifLayout layout, TransitionAnimationCallback callback)166 private void setupTransitionAnimationHelper( 167 GlifLayout layout, 168 TransitionAnimationCallback callback) { 169 TextView header = layout.findViewById(R.id.suc_layout_title); 170 TextView description = layout.findViewById(R.id.sud_layout_subtitle); 171 ViewGroup item1 = layout.findViewById(R.id.item1); 172 ViewGroup item2 = layout.findViewById(R.id.item2); 173 LottieAnimationView drawable = layout.findViewById(R.id.animation); 174 ViewGroup drawableContainer = layout.findViewById(R.id.animation_container); 175 Space space1 = layout.findViewById(R.id.space1); 176 Space space2 = layout.findViewById(R.id.space2); 177 AnimationComponents animationComponents = 178 new AnimationComponents( 179 header, description, item1, item2, drawable, drawableContainer, 180 space1, space2); 181 182 ProvisioningModeWrapperProvider provider = new ProvisioningModeWrapperProvider(getParams()); 183 ProvisioningModeWrapper provisioningModeWrapper = provider 184 .getProvisioningModeWrapper(getProvisioningMode()); 185 mTransitionAnimationHelper = new TransitionAnimationHelper( 186 animationComponents, 187 callback, 188 getStateManager(), 189 new StylerHelper(), 190 provisioningModeWrapper); 191 } 192 setupEducationViews( GlifLayout layout, Activity activity, boolean shouldSkipEducationScreens, @StringRes int progressLabelResId)193 private void setupEducationViews( 194 GlifLayout layout, 195 Activity activity, 196 boolean shouldSkipEducationScreens, 197 @StringRes int progressLabelResId) { 198 addProvisioningProgressLabel(activity); 199 if (shouldSkipEducationScreens) { 200 TextView header = layout.findViewById(R.id.suc_layout_title); 201 header.setText(progressLabelResId); 202 getProvisioningProgressLabelContainer(activity).setVisibility(View.GONE); 203 } else { 204 setupProgressLabel(progressLabelResId, activity); 205 } 206 } 207 addProvisioningProgressLabel(Activity activity)208 private void addProvisioningProgressLabel(Activity activity) { 209 ViewGroup parent = activity.findViewById(R.id.sud_layout_template_content); 210 activity.getLayoutInflater().inflate(R.layout.label_provisioning_progress, parent, true); 211 } 212 getProvisioningProgressLabelContainer(Activity activity)213 private ViewGroup getProvisioningProgressLabelContainer(Activity activity) { 214 ViewGroup parent = activity.findViewById(R.id.sud_layout_template_content); 215 return parent.findViewById(R.id.provisioning_progress_container); 216 } 217 218 /** 219 * Returns the relevant progress label and takes care of visibilities to show the correct one. 220 */ setupProgressLabel(@tringRes int progressLabelResId, Activity activity)221 private void setupProgressLabel(@StringRes int progressLabelResId, Activity activity) { 222 TextView progressLabel = getRelevantProgressLabel(activity); 223 DescriptionStyler.applyPartnerCustomizationHeavyStyle(progressLabel); 224 progressLabel.setTextColor( 225 shouldApplyExtendedPartnerConfig(activity) 226 ? getUtils().getTextSecondaryColor(activity) 227 : getUtils().getAccentColor(activity)); 228 progressLabel.setText(progressLabelResId); 229 int sidePadding = (int) ContentStyler.getPartnerContentMarginStart(activity); 230 progressLabel.setPadding(sidePadding, /* top= */ 0, sidePadding, /* bottom= */ 0); 231 getProvisioningProgressLabelContainer(activity).setVisibility(View.VISIBLE); 232 } 233 getRelevantProgressLabel(Activity activity)234 private TextView getRelevantProgressLabel(Activity activity) { 235 ViewGroup parent = (ViewGroup) activity.findViewById(R.id.suc_layout_footer).getParent(); 236 TextView provisioningProgressLabel = parent.findViewById(R.id.provisioning_progress); 237 if (provisioningProgressLabel != null) { 238 return provisioningProgressLabel; 239 } 240 TextView leftProgress = parent.findViewById(R.id.provisioning_progress_left); 241 TextView rightProgress = parent.findViewById(R.id.provisioning_progress_right); 242 if (activity.getResources().getBoolean(R.bool.show_progress_label_on_left_side)) { 243 leftProgress.setVisibility(View.VISIBLE); 244 rightProgress.setVisibility(View.INVISIBLE); 245 return leftProgress; 246 } 247 leftProgress.setVisibility(View.INVISIBLE); 248 rightProgress.setVisibility(View.VISIBLE); 249 return rightProgress; 250 } 251 getButtonFooterContainer(ViewGroup root)252 private ViewGroup getButtonFooterContainer(ViewGroup root) { 253 return (ViewGroup) root.getChildAt(root.getChildCount() - 2); 254 } 255 builder()256 static Builder builder() { 257 return new AutoValue_ProvisioningActivityBridgeImpl.Builder(); 258 } 259 260 @AutoValue.Builder 261 abstract static class Builder { setUtils(Utils utils)262 abstract Builder setUtils(Utils utils); setParams(ProvisioningParams params)263 abstract Builder setParams(ProvisioningParams params); setProvisioningMode(@rovisioningMode int provisioningMode)264 abstract Builder setProvisioningMode(@ProvisioningMode int provisioningMode); setProvisioningManager(ProvisioningManager provisioningManager)265 abstract Builder setProvisioningManager(ProvisioningManager provisioningManager); setTransitionAnimationCallback(TransitionAnimationCallback callback)266 abstract Builder setTransitionAnimationCallback(TransitionAnimationCallback callback); setInitializeLayoutParamsConsumer( InitializeLayoutConsumerHandler initializeLayoutParamsConsumer)267 abstract Builder setInitializeLayoutParamsConsumer( 268 InitializeLayoutConsumerHandler initializeLayoutParamsConsumer); setShouldSkipEducationScreens(boolean shouldSkipEducationScreens)269 abstract Builder setShouldSkipEducationScreens(boolean shouldSkipEducationScreens); setProgressLabelResId(@tringRes int progressLabelResId)270 abstract Builder setProgressLabelResId(@StringRes int progressLabelResId); setBridgeCallbacks( ProvisioningActivityBridgeCallbacks callbacks)271 abstract Builder setBridgeCallbacks( 272 ProvisioningActivityBridgeCallbacks callbacks); setStateManager(TransitionAnimationStateManager stateManager)273 abstract Builder setStateManager(TransitionAnimationStateManager stateManager); build()274 abstract ProvisioningActivityBridgeImpl build(); 275 } 276 } 277