1 /*
2  * Copyright (C) 2022 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.layoutlib.bridge.intensive.util;
18 
19 import com.android.SdkConstants;
20 import com.android.ide.common.rendering.api.AssetRepository;
21 import com.android.ide.common.rendering.api.IImageFactory;
22 import com.android.ide.common.rendering.api.ILayoutLog;
23 import com.android.ide.common.rendering.api.LayoutlibCallback;
24 import com.android.ide.common.rendering.api.ResourceNamespace;
25 import com.android.ide.common.rendering.api.ResourceReference;
26 import com.android.ide.common.rendering.api.SessionParams;
27 import com.android.ide.common.rendering.api.SessionParams.RenderingMode;
28 import com.android.ide.common.resources.ResourceResolver;
29 import com.android.ide.common.resources.configuration.FolderConfiguration;
30 import com.android.ide.common.resources.deprecated.ResourceRepository;
31 import com.android.layoutlib.bridge.android.RenderParamsFlags;
32 import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
33 import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser;
34 import com.android.resources.ResourceType;
35 
36 import android.annotation.NonNull;
37 
38 import java.util.HashMap;
39 import java.util.Map;
40 
41 import com.google.common.collect.ImmutableMap;
42 
43 /**
44  * Builder to help setting up {@link SessionParams} objects.
45  */
46 public class SessionParamsBuilder {
47 
48     private LayoutPullParser mLayoutParser;
49     private RenderingMode mRenderingMode = RenderingMode.NORMAL;
50     private Object mProjectKey = null;
51     private ConfigGenerator mConfigGenerator = ConfigGenerator.NEXUS_5;
52     private ResourceRepository mFrameworkResources;
53     private ResourceRepository mProjectResources;
54     private String mThemeName;
55     private boolean isProjectTheme;
56     private LayoutlibCallback mLayoutlibCallback;
57     private int mTargetSdk;
58     private int mMinSdk = 0;
59     private ILayoutLog mLayoutLog;
60     private Map<SessionParams.Key, Object> mFlags = new HashMap<>();
61     private AssetRepository mAssetRepository = null;
62     private boolean mDecor = true;
63     private IImageFactory mImageFactory = null;
64     private boolean enableLayoutValidator = false;
65     private boolean enableLayoutValidatorImageCheck = false;
66     private boolean transparentBackground = false;
67 
68     @NonNull
setParser(@onNull LayoutPullParser layoutParser)69     public SessionParamsBuilder setParser(@NonNull LayoutPullParser layoutParser) {
70         mLayoutParser = layoutParser;
71 
72         return this;
73     }
74 
75     @NonNull
setRenderingMode(@onNull RenderingMode renderingMode)76     public SessionParamsBuilder setRenderingMode(@NonNull RenderingMode renderingMode) {
77         mRenderingMode = renderingMode;
78         return this;
79     }
80 
81     @NonNull
setConfigGenerator(@onNull ConfigGenerator configGenerator)82     public SessionParamsBuilder setConfigGenerator(@NonNull ConfigGenerator configGenerator) {
83         mConfigGenerator = configGenerator;
84         return this;
85     }
86 
87     @NonNull
setProjectResources(@onNull ResourceRepository resources)88     public SessionParamsBuilder setProjectResources(@NonNull ResourceRepository resources) {
89         mProjectResources = resources;
90         return this;
91     }
92 
93     @NonNull
setFrameworkResources(@onNull ResourceRepository resources)94     public SessionParamsBuilder setFrameworkResources(@NonNull ResourceRepository resources) {
95         mFrameworkResources = resources;
96         return this;
97     }
98 
99     @NonNull
setTheme(@onNull String themeName, boolean isProjectTheme)100     public SessionParamsBuilder setTheme(@NonNull String themeName, boolean isProjectTheme) {
101         mThemeName = themeName;
102         this.isProjectTheme = isProjectTheme;
103         return this;
104     }
105 
106     @NonNull
setTheme(@onNull String themeName)107     public SessionParamsBuilder setTheme(@NonNull String themeName) {
108         boolean isProjectTheme;
109         if (themeName.startsWith(SdkConstants.PREFIX_ANDROID)) {
110             themeName = themeName.substring(SdkConstants.PREFIX_ANDROID.length());
111             isProjectTheme = false;
112         } else {
113             isProjectTheme = true;
114         }
115         return setTheme(themeName, isProjectTheme);
116     }
117 
118     @NonNull
setCallback(@onNull LayoutlibCallback callback)119     public SessionParamsBuilder setCallback(@NonNull LayoutlibCallback callback) {
120         mLayoutlibCallback = callback;
121         return this;
122     }
123 
124     @NonNull
setTargetSdk(int targetSdk)125     public SessionParamsBuilder setTargetSdk(int targetSdk) {
126         mTargetSdk = targetSdk;
127         return this;
128     }
129 
130     @SuppressWarnings("unused")
131     @NonNull
setMinSdk(int minSdk)132     public SessionParamsBuilder setMinSdk(int minSdk) {
133         mMinSdk = minSdk;
134         return this;
135     }
136 
137     @NonNull
setLayoutLog(@onNull ILayoutLog layoutLog)138     public SessionParamsBuilder setLayoutLog(@NonNull ILayoutLog layoutLog) {
139         mLayoutLog = layoutLog;
140         return this;
141     }
142 
143     @NonNull
setFlag(@onNull SessionParams.Key flag, Object value)144     public SessionParamsBuilder setFlag(@NonNull SessionParams.Key flag, Object value) {
145         mFlags.put(flag, value);
146         return this;
147     }
148 
149     @NonNull
setAssetRepository(@onNull AssetRepository repository)150     public SessionParamsBuilder setAssetRepository(@NonNull AssetRepository repository) {
151         mAssetRepository = repository;
152         return this;
153     }
154 
155     @NonNull
disableDecoration()156     public SessionParamsBuilder disableDecoration() {
157         mDecor = false;
158         return this;
159     }
160 
161     @NonNull
setImageFactory(@onNull IImageFactory imageFactory)162     public SessionParamsBuilder setImageFactory(@NonNull IImageFactory imageFactory) {
163         mImageFactory = imageFactory;
164         return this;
165     }
166 
167     @NonNull
enableLayoutValidation()168     public SessionParamsBuilder enableLayoutValidation() {
169         this.enableLayoutValidator = true;
170         return this;
171     }
172 
173     @NonNull
enableLayoutValidationImageCheck()174     public SessionParamsBuilder enableLayoutValidationImageCheck() {
175         this.enableLayoutValidatorImageCheck = true;
176         return this;
177     }
178 
179     @NonNull
setTransparentBackground()180     public SessionParamsBuilder setTransparentBackground() {
181         this.transparentBackground = true;
182         return this;
183     }
184 
185     @NonNull
build()186     public SessionParams build() {
187         assert mFrameworkResources != null;
188         assert mProjectResources != null;
189         assert mThemeName != null;
190         assert mLayoutLog != null;
191         assert mLayoutlibCallback != null;
192 
193         FolderConfiguration config = mConfigGenerator.getFolderConfig();
194         ResourceResolver resourceResolver = ResourceResolver.create(
195                 ImmutableMap.of(
196                         ResourceNamespace.ANDROID, mFrameworkResources.getConfiguredResources(config),
197                         ResourceNamespace.TODO(), mProjectResources.getConfiguredResources(config)),
198                 new ResourceReference(
199                         ResourceNamespace.fromBoolean(!isProjectTheme),
200                         ResourceType.STYLE,
201                         mThemeName));
202 
203         SessionParams params = new SessionParams(mLayoutParser, mRenderingMode, mProjectKey /* for
204         caching */, mConfigGenerator.getHardwareConfig(), resourceResolver, mLayoutlibCallback,
205                 mMinSdk, mTargetSdk, mLayoutLog);
206         params.setFlag(RenderParamsFlags.FLAG_ENABLE_LAYOUT_VALIDATOR, enableLayoutValidator);
207         params.setFlag(
208                 RenderParamsFlags.FLAG_ENABLE_LAYOUT_VALIDATOR_IMAGE_CHECK,
209                 enableLayoutValidatorImageCheck);
210         if (mImageFactory != null) {
211             params.setImageFactory(mImageFactory);
212         }
213 
214         mFlags.forEach(params::setFlag);
215         params.setAssetRepository(mAssetRepository);
216 
217         if (!mDecor) {
218             params.setForceNoDecor();
219         }
220 
221         if (transparentBackground) {
222             params.setTransparentBackground();
223         }
224 
225         return params;
226     }
227 }
228