blob: e3f608b73189d2c8eefb21b3525494149cb5145a [file] [log] [blame]
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +08001/*
2 * Copyright 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
17package com.google.android.setupcompat;
18
19import android.annotation.TargetApi;
20import android.app.Activity;
21import android.content.Context;
22import android.content.ContextWrapper;
23import android.content.res.TypedArray;
Setup Wizard Teamde9b52a2019-04-01 10:27:47 +080024import android.os.Build;
Setup Wizard Team1ed30732019-03-14 10:00:10 +080025import android.os.Build.VERSION;
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +080026import android.os.Build.VERSION_CODES;
Setup Wizard Team1d79d002018-12-13 14:30:13 +080027import android.os.PersistableBundle;
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +080028import android.util.AttributeSet;
Setup Wizard Teamd41e3be2019-01-17 16:07:58 +080029import android.util.Log;
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +080030import android.view.LayoutInflater;
31import android.view.View;
32import android.view.ViewGroup;
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +080033import android.view.WindowManager;
Setup Wizard Teamde9b52a2019-04-01 10:27:47 +080034import com.google.android.setupcompat.internal.LifecycleFragment;
Setup Wizard Teamd6fc4af2019-12-31 20:58:11 +080035import com.google.android.setupcompat.internal.PersistableBundles;
Maurice Lamc4529322019-02-14 22:04:56 +000036import com.google.android.setupcompat.internal.TemplateLayout;
Setup Wizard Team1d79d002018-12-13 14:30:13 +080037import com.google.android.setupcompat.logging.CustomEvent;
38import com.google.android.setupcompat.logging.MetricKey;
39import com.google.android.setupcompat.logging.SetupMetricsLogger;
Setup Wizard Team1ed30732019-03-14 10:00:10 +080040import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper;
Setup Wizard Teamd41e3be2019-01-17 16:07:58 +080041import com.google.android.setupcompat.template.FooterBarMixin;
42import com.google.android.setupcompat.template.FooterButton;
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +080043import com.google.android.setupcompat.template.StatusBarMixin;
44import com.google.android.setupcompat.template.SystemNavBarMixin;
45import com.google.android.setupcompat.util.WizardManagerHelper;
46
47/** A templatization layout with consistent style used in Setup Wizard or app itself. */
48public class PartnerCustomizationLayout extends TemplateLayout {
Setup Wizard Teamd41e3be2019-01-17 16:07:58 +080049 // Log tags can have at most 23 characters on N or before.
50 private static final String TAG = "PartnerCustomizedLayout";
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +080051
Setup Wizard Team67e7fef2019-03-23 08:06:48 +080052 /**
53 * Attribute indicating whether usage of partner theme resources is allowed. This corresponds to
54 * the {@code app:sucUsePartnerResource} XML attribute. Note that when running in setup wizard,
55 * this is always overridden to true.
56 */
Setup Wizard Teamde9b52a2019-04-01 10:27:47 +080057 private boolean usePartnerResourceAttr;
Setup Wizard Team1ed30732019-03-14 10:00:10 +080058
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +080059 private Activity activity;
60
61 public PartnerCustomizationLayout(Context context) {
62 this(context, 0, 0);
63 }
64
65 public PartnerCustomizationLayout(Context context, int template) {
66 this(context, template, 0);
67 }
68
69 public PartnerCustomizationLayout(Context context, int template, int containerId) {
70 super(context, template, containerId);
71 init(null, R.attr.sucLayoutTheme);
72 }
73
74 public PartnerCustomizationLayout(Context context, AttributeSet attrs) {
75 super(context, attrs);
76 init(attrs, R.attr.sucLayoutTheme);
77 }
78
79 @TargetApi(VERSION_CODES.HONEYCOMB)
80 public PartnerCustomizationLayout(Context context, AttributeSet attrs, int defStyleAttr) {
81 super(context, attrs, defStyleAttr);
82 init(attrs, defStyleAttr);
83 }
84
85 private void init(AttributeSet attrs, int defStyleAttr) {
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +080086
87 TypedArray a =
88 getContext()
89 .obtainStyledAttributes(
90 attrs, R.styleable.SucPartnerCustomizationLayout, defStyleAttr, 0);
91
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +080092 boolean layoutFullscreen =
93 a.getBoolean(R.styleable.SucPartnerCustomizationLayout_sucLayoutFullscreen, true);
Setup Wizard Teamff4fecb2018-12-19 11:31:37 +080094
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +080095 a.recycle();
96
Setup Wizard Team1ed30732019-03-14 10:00:10 +080097 if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP && layoutFullscreen) {
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +080098 setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
99 }
100
Setup Wizard Teamff4fecb2018-12-19 11:31:37 +0800101 registerMixin(
Setup Wizard Team67e7fef2019-03-23 08:06:48 +0800102 StatusBarMixin.class, new StatusBarMixin(this, activity.getWindow(), attrs, defStyleAttr));
103 registerMixin(SystemNavBarMixin.class, new SystemNavBarMixin(this, activity.getWindow()));
104 registerMixin(FooterBarMixin.class, new FooterBarMixin(this, attrs, defStyleAttr));
Setup Wizard Teamff4fecb2018-12-19 11:31:37 +0800105
Setup Wizard Team1ed30732019-03-14 10:00:10 +0800106 getMixin(SystemNavBarMixin.class).applyPartnerCustomizations(attrs, defStyleAttr);
107
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +0800108 // Override the FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, FLAG_TRANSLUCENT_STATUS,
109 // FLAG_TRANSLUCENT_NAVIGATION and SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN attributes of window forces
110 // showing status bar and navigation bar.
Setup Wizard Teamde9b52a2019-04-01 10:27:47 +0800111 if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
112 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
113 activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
114 activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
115 }
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +0800116 }
117
118 @Override
119 protected View onInflateTemplate(LayoutInflater inflater, int template) {
120 if (template == 0) {
121 template = R.layout.partner_customization_layout;
122 }
123 return inflateTemplate(inflater, 0, template);
124 }
125
Setup Wizard Teamde9b52a2019-04-01 10:27:47 +0800126 /**
127 * {@inheritDoc}
128 *
129 * <p>This method sets all these flags before onTemplateInflated since it will be too late and get
130 * incorrect flag value on PartnerCustomizationLayout if sets them after onTemplateInflated.
131 */
132 @Override
133 protected void onBeforeTemplateInflated(AttributeSet attrs, int defStyleAttr) {
134
Setup Wizard Teamde9b52a2019-04-01 10:27:47 +0800135 // Sets default value to true since this timing
136 // before PartnerCustomization members initialization
137 usePartnerResourceAttr = true;
138
139 activity = lookupActivityFromContext(getContext());
140
Setup Wizard Team75de5902020-09-22 20:34:53 +0800141 boolean isSetupFlow = WizardManagerHelper.isAnySetupWizard(activity.getIntent());
Setup Wizard Teamde9b52a2019-04-01 10:27:47 +0800142
143 TypedArray a =
144 getContext()
145 .obtainStyledAttributes(
146 attrs, R.styleable.SucPartnerCustomizationLayout, defStyleAttr, 0);
147
148 if (!a.hasValue(R.styleable.SucPartnerCustomizationLayout_sucUsePartnerResource)) {
Setup Wizard Team5b6b1b32019-04-02 13:42:22 +0800149 // TODO: Enable Log.WTF after other client already set sucUsePartnerResource.
Setup Wizard Teamde9b52a2019-04-01 10:27:47 +0800150 Log.e(TAG, "Attribute sucUsePartnerResource not found in " + activity.getComponentName());
151 }
152
153 usePartnerResourceAttr =
154 isSetupFlow
155 || a.getBoolean(R.styleable.SucPartnerCustomizationLayout_sucUsePartnerResource, true);
156
157 a.recycle();
158
159 if (Log.isLoggable(TAG, Log.DEBUG)) {
160 Log.d(
161 TAG,
162 "activity="
163 + activity.getClass().getSimpleName()
164 + " isSetupFlow="
165 + isSetupFlow
166 + " enablePartnerResourceLoading="
167 + enablePartnerResourceLoading()
168 + " usePartnerResourceAttr="
169 + usePartnerResourceAttr);
170 }
171 }
172
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +0800173 @Override
174 protected ViewGroup findContainer(int containerId) {
175 if (containerId == 0) {
176 containerId = R.id.suc_layout_content;
177 }
178 return super.findContainer(containerId);
179 }
180
181 @Override
182 protected void onAttachedToWindow() {
183 super.onAttachedToWindow();
Setup Wizard Team1d79d002018-12-13 14:30:13 +0800184 LifecycleFragment.attachNow(activity);
Setup Wizard Teamd41e3be2019-01-17 16:07:58 +0800185 getMixin(FooterBarMixin.class).onAttachedToWindow();
Setup Wizard Team1d79d002018-12-13 14:30:13 +0800186 }
187
188 @Override
189 protected void onDetachedFromWindow() {
190 super.onDetachedFromWindow();
Setup Wizard Teamde9b52a2019-04-01 10:27:47 +0800191 if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP
Setup Wizard Team3266cd82019-05-09 19:31:02 +0800192 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
Setup Wizard Teamde9b52a2019-04-01 10:27:47 +0800193 && WizardManagerHelper.isAnySetupWizard(activity.getIntent())) {
Setup Wizard Teamd41e3be2019-01-17 16:07:58 +0800194 FooterBarMixin footerBarMixin = getMixin(FooterBarMixin.class);
195 footerBarMixin.onDetachedFromWindow();
196 FooterButton primaryButton = footerBarMixin.getPrimaryButton();
197 FooterButton secondaryButton = footerBarMixin.getSecondaryButton();
198 PersistableBundle primaryButtonMetrics =
199 primaryButton != null
200 ? primaryButton.getMetrics("PrimaryFooterButton")
201 : PersistableBundle.EMPTY;
202 PersistableBundle secondaryButtonMetrics =
203 secondaryButton != null
204 ? secondaryButton.getMetrics("SecondaryFooterButton")
205 : PersistableBundle.EMPTY;
206
Setup Wizard Teamd6fc4af2019-12-31 20:58:11 +0800207 PersistableBundle persistableBundle =
208 PersistableBundles.mergeBundles(
Setup Wizard Teamd41e3be2019-01-17 16:07:58 +0800209 footerBarMixin.getLoggingMetrics(), primaryButtonMetrics, secondaryButtonMetrics);
210
Setup Wizard Team1d79d002018-12-13 14:30:13 +0800211 SetupMetricsLogger.logCustomEvent(
212 getContext(),
Setup Wizard Team24bb1e22019-11-08 15:22:51 +0800213 CustomEvent.create(MetricKey.get("SetupCompatMetrics", activity), persistableBundle));
Setup Wizard Team1d79d002018-12-13 14:30:13 +0800214 }
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +0800215 }
216
Setup Wizard Team642e0962020-12-30 19:23:06 +0800217 public static Activity lookupActivityFromContext(Context context) {
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +0800218 if (context instanceof Activity) {
219 return (Activity) context;
220 } else if (context instanceof ContextWrapper) {
221 return lookupActivityFromContext(((ContextWrapper) context).getBaseContext());
222 } else {
223 throw new IllegalArgumentException("Cannot find instance of Activity in parent tree");
224 }
225 }
226
227 /**
Setup Wizard Team67e7fef2019-03-23 08:06:48 +0800228 * Returns true if partner resource loading is enabled. If true, and other necessary conditions
229 * for loading theme attributes are met, this layout will use customized theme attributes from OEM
230 * overlays. This is intended to be used with flag-based development, to allow a flag to control
231 * the rollout of partner resource loading.
Setup Wizard Teamd41e3be2019-01-17 16:07:58 +0800232 */
Setup Wizard Team67e7fef2019-03-23 08:06:48 +0800233 protected boolean enablePartnerResourceLoading() {
Setup Wizard Teamd41e3be2019-01-17 16:07:58 +0800234 return true;
235 }
236
Setup Wizard Team1ed30732019-03-14 10:00:10 +0800237 /** Returns if the current layout/activity applies partner customized configurations or not. */
Setup Wizard Team67e7fef2019-03-23 08:06:48 +0800238 public boolean shouldApplyPartnerResource() {
239 if (!enablePartnerResourceLoading()) {
240 return false;
241 }
242 if (!usePartnerResourceAttr) {
243 return false;
244 }
Setup Wizard Team3266cd82019-05-09 19:31:02 +0800245 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
Setup Wizard Team67e7fef2019-03-23 08:06:48 +0800246 return false;
247 }
248 if (!PartnerConfigHelper.get(getContext()).isAvailable()) {
249 return false;
250 }
251 return true;
Setup Wizard Team1ed30732019-03-14 10:00:10 +0800252 }
Setup Wizard Team8ccc9e62018-11-28 13:33:48 +0800253}