1 /* 2 * Copyright (C) 2019 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.setupdesign.util; 18 19 import android.app.Activity; 20 import android.content.Context; 21 import android.content.res.TypedArray; 22 import android.os.Build; 23 import android.view.Gravity; 24 import android.view.View; 25 import com.google.android.setupcompat.PartnerCustomizationLayout; 26 import com.google.android.setupcompat.internal.TemplateLayout; 27 import com.google.android.setupcompat.partnerconfig.PartnerConfig; 28 import com.google.android.setupcompat.partnerconfig.PartnerConfigHelper; 29 import com.google.android.setupcompat.util.WizardManagerHelper; 30 import com.google.android.setupdesign.GlifLayout; 31 import com.google.android.setupdesign.R; 32 import java.util.Locale; 33 34 /** The helper reads styles from the partner configurations. */ 35 public final class PartnerStyleHelper { 36 37 private static final String TAG = "PartnerStyleHelper"; 38 /** 39 * Returns the partner configuration of layout gravity, usually apply to widgets in header area. 40 */ getLayoutGravity(Context context)41 public static int getLayoutGravity(Context context) { 42 String gravity = 43 PartnerConfigHelper.get(context).getString(context, PartnerConfig.CONFIG_LAYOUT_GRAVITY); 44 if (gravity == null) { 45 return 0; 46 } 47 switch (gravity.toLowerCase(Locale.ROOT)) { 48 case "center": 49 return Gravity.CENTER; 50 case "start": 51 return Gravity.START; 52 default: 53 return 0; 54 } 55 } 56 57 /** Returns the given layout if apply partner heavy theme. */ isPartnerHeavyThemeLayout(TemplateLayout layout)58 public static boolean isPartnerHeavyThemeLayout(TemplateLayout layout) { 59 if (!(layout instanceof GlifLayout)) { 60 return false; 61 } 62 return ((GlifLayout) layout).shouldApplyPartnerHeavyThemeResource(); 63 } 64 65 /** Returns the given layout if apply partner light theme. */ isPartnerLightThemeLayout(TemplateLayout layout)66 public static boolean isPartnerLightThemeLayout(TemplateLayout layout) { 67 if (!(layout instanceof PartnerCustomizationLayout)) { 68 return false; 69 } 70 return ((PartnerCustomizationLayout) layout).shouldApplyPartnerResource(); 71 } 72 73 /** 74 * Returns if the current layout/activity of the given {@code view} applies partner customized 75 * configurations or not. 76 * 77 * @param view A PartnerCustomizationLayout view, would be used to get the activity and context. 78 */ shouldApplyPartnerResource(View view)79 public static boolean shouldApplyPartnerResource(View view) { 80 if (view == null) { 81 return false; 82 } 83 if (view instanceof PartnerCustomizationLayout) { 84 return isPartnerLightThemeLayout((PartnerCustomizationLayout) view); 85 } 86 return shouldApplyPartnerResource(view.getContext()); 87 } 88 shouldApplyPartnerResource(Context context)89 private static boolean shouldApplyPartnerResource(Context context) { 90 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { 91 return false; 92 } 93 94 if (!PartnerConfigHelper.get(context).isAvailable()) { 95 return false; 96 } 97 98 Activity activity = null; 99 try { 100 activity = PartnerCustomizationLayout.lookupActivityFromContext(context); 101 if (activity != null) { 102 TemplateLayout layout = findLayoutFromActivity(activity); 103 if (layout instanceof PartnerCustomizationLayout) { 104 return ((PartnerCustomizationLayout) layout).shouldApplyPartnerResource(); 105 } 106 } 107 } catch (IllegalArgumentException | ClassCastException ex) { 108 // fall through 109 } 110 111 // try best to get partner resource settings from attrs 112 boolean isSetupFlow = false; 113 if (activity != null) { 114 isSetupFlow = WizardManagerHelper.isAnySetupWizard(activity.getIntent()); 115 } 116 TypedArray a = context.obtainStyledAttributes(new int[] {R.attr.sucUsePartnerResource}); 117 boolean usePartnerResource = a.getBoolean(0, true); 118 a.recycle(); 119 120 return isSetupFlow || usePartnerResource; 121 } 122 123 /** 124 * Returns if the current layout/activity applies heavy partner customized configurations or not. 125 * 126 * @param view A view would be used to get the activity and context. 127 */ shouldApplyPartnerHeavyThemeResource(View view)128 public static boolean shouldApplyPartnerHeavyThemeResource(View view) { 129 if (view == null) { 130 return false; 131 } 132 if (view instanceof GlifLayout) { 133 return isPartnerHeavyThemeLayout((GlifLayout) view); 134 } 135 return shouldApplyPartnerHeavyThemeResource(view.getContext()); 136 } 137 shouldApplyPartnerHeavyThemeResource(Context context)138 static boolean shouldApplyPartnerHeavyThemeResource(Context context) { 139 try { 140 Activity activity = PartnerCustomizationLayout.lookupActivityFromContext(context); 141 TemplateLayout layout = findLayoutFromActivity(activity); 142 if (layout instanceof GlifLayout) { 143 return ((GlifLayout) layout).shouldApplyPartnerHeavyThemeResource(); 144 } 145 } catch (IllegalArgumentException | ClassCastException ex) { 146 // fall through 147 } 148 149 // try best to get partner resource settings from attr 150 TypedArray a = context.obtainStyledAttributes(new int[] {R.attr.sudUsePartnerHeavyTheme}); 151 boolean usePartnerHeavyTheme = a.getBoolean(0, false); 152 a.recycle(); 153 usePartnerHeavyTheme = 154 usePartnerHeavyTheme || PartnerConfigHelper.shouldApplyExtendedPartnerConfig(context); 155 156 return shouldApplyPartnerResource(context) && usePartnerHeavyTheme; 157 } 158 159 /** 160 * Returns if the current layout/activity applies dynamic color configurations or not. 161 * 162 * @param view A GlifLayout view would be used to get the activity and context. 163 */ useDynamicColor(View view)164 public static boolean useDynamicColor(View view) { 165 if (view == null) { 166 return false; 167 } 168 return getDynamicColorAttributeFromTheme(view.getContext()); 169 } 170 getDynamicColorAttributeFromTheme(Context context)171 static boolean getDynamicColorAttributeFromTheme(Context context) { 172 try { 173 Activity activity = PartnerCustomizationLayout.lookupActivityFromContext(context); 174 TemplateLayout layout = findLayoutFromActivity(activity); 175 if (layout instanceof GlifLayout) { 176 return ((GlifLayout) layout).shouldApplyDynamicColor(); 177 } 178 } catch (IllegalArgumentException | ClassCastException ex) { 179 // fall through 180 } 181 182 // try best to get dynamic color settings from attr 183 TypedArray a = context.obtainStyledAttributes(new int[] {R.attr.sucFullDynamicColor}); 184 boolean useDynamicColorTheme = 185 a.hasValue( 186 com.google 187 .android 188 .setupcompat 189 .R 190 .styleable 191 .SucPartnerCustomizationLayout_sucFullDynamicColor); 192 a.recycle(); 193 194 return useDynamicColorTheme; 195 } 196 findLayoutFromActivity(Activity activity)197 private static TemplateLayout findLayoutFromActivity(Activity activity) { 198 if (activity == null) { 199 return null; 200 } 201 // This only worked after activity setContentView, otherwise it will return null 202 View rootView = activity.findViewById(R.id.suc_layout_status); 203 return rootView != null ? (TemplateLayout) rootView.getParent() : null; 204 } 205 PartnerStyleHelper()206 private PartnerStyleHelper() {} 207 } 208