use of com.android.tools.idea.rendering.multi.CompatibilityRenderTarget in project android by JetBrains.
the class StudioEmbeddedRenderTarget method getCompatibilityTarget.
/**
* Returns a CompatibilityRenderTarget that will use StudioEmbeddedRenderTarget to do the rendering
* @throws IOException if the local layoutlib distribution is not found
*/
public static CompatibilityRenderTarget getCompatibilityTarget(@NotNull IAndroidTarget target) throws IOException {
if (ourDisableEmbeddedTargetForTesting) {
return new CompatibilityRenderTarget(target, target.getVersion().getApiLevel(), target);
}
int api = target.getVersion().getApiLevel();
if (target instanceof CompatibilityRenderTarget) {
CompatibilityRenderTarget compatRenderTarget = (CompatibilityRenderTarget) target;
target = compatRenderTarget.getRealTarget();
}
return new CompatibilityRenderTarget(getInstance(), api, target);
}
use of com.android.tools.idea.rendering.multi.CompatibilityRenderTarget in project android by JetBrains.
the class TargetMenuAction method addCompatibilityTargets.
private void addCompatibilityTargets(@NotNull DefaultActionGroup group) {
Configuration configuration = myRenderContext.getConfiguration();
assert configuration != null;
IAndroidTarget currentTarget = configuration.getTarget();
IAndroidTarget highestTarget = configuration.getConfigurationManager().getHighestApiTarget();
assert highestTarget != null;
int highestApiLevel = highestTarget.getVersion().getFeatureLevel();
int minApi = Math.max(getMinSdkVersion(), SHOW_FROM_API_LEVEL);
for (int apiLevel = highestApiLevel; apiLevel >= minApi; apiLevel--) {
IAndroidTarget target = new CompatibilityRenderTarget(highestTarget, apiLevel, null);
boolean isSelected = target.getVersion().equals(currentTarget.getVersion());
group.add(new SetTargetAction(myRenderContext, target.getVersionName(), target, isSelected));
}
}
use of com.android.tools.idea.rendering.multi.CompatibilityRenderTarget in project android by JetBrains.
the class VariantItemListener method itemStateChanged.
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() != ItemEvent.SELECTED) {
return;
}
VariantsComboItem item = (VariantsComboItem) e.getItem();
Configuration oldConfiguration = myContext.getConfiguration();
ConfigurationManager manager = oldConfiguration.getConfigurationManager();
Configuration newConfiguration = Configuration.create(manager, null, null, item.getRestrictedConfiguration());
// Target and locale are global so we need to set them in the configuration manager when updated
VersionQualifier newVersionQualifier = item.getRestrictedConfiguration().getVersionQualifier();
if (newVersionQualifier != null) {
IAndroidTarget realTarget = manager.getHighestApiTarget() != null ? manager.getHighestApiTarget() : manager.getTarget();
assert realTarget != null;
manager.setTarget(new CompatibilityRenderTarget(realTarget, newVersionQualifier.getVersion(), null));
} else {
manager.setTarget(null);
}
LocaleQualifier newLocaleQualifier = item.getRestrictedConfiguration().getLocaleQualifier();
manager.setLocale(newLocaleQualifier != null ? Locale.create(newLocaleQualifier) : Locale.ANY);
oldConfiguration.setDevice(null, false);
Configuration.copyCompatible(newConfiguration, oldConfiguration);
oldConfiguration.updated(ConfigurationListener.MASK_FOLDERCONFIG);
}
use of com.android.tools.idea.rendering.multi.CompatibilityRenderTarget in project android by JetBrains.
the class RenderService method warnIfObsoleteLayoutLib.
private static void warnIfObsoleteLayoutLib(@NotNull final Module module, @NotNull RenderLogger logger, @Nullable final EditorDesignSurface surface, @NotNull IAndroidTarget target) {
if (!ourWarnAboutObsoleteLayoutLibVersions) {
return;
}
if (!LayoutLibraryLoader.USE_SDK_LAYOUTLIB) {
// We are using the version shipped with studio, it can never be obsolete. StudioEmbeddedRenderTarget does not implement getVersion.
ourWarnAboutObsoleteLayoutLibVersions = false;
return;
}
if (target instanceof CompatibilityRenderTarget) {
target = ((CompatibilityRenderTarget) target).getRenderTarget();
}
final AndroidVersion version = target.getVersion();
final int revision;
// are minimum revisions; if a later version is available, it will be installed.
switch(version.getFeatureLevel()) {
case 23:
revision = 2;
break;
case 22:
revision = 2;
break;
case 21:
revision = 2;
break;
case 20:
revision = 2;
break;
case 19:
revision = 4;
break;
case 18:
revision = 3;
break;
case 17:
revision = 3;
break;
case 16:
revision = 5;
break;
case 15:
revision = 5;
break;
case 14:
revision = 4;
break;
case 13:
revision = 1;
break;
case 12:
revision = 3;
break;
case 11:
revision = 2;
break;
case 10:
revision = 2;
break;
case 8:
revision = 3;
break;
default:
revision = -1;
break;
}
if (revision >= 0 && target.getRevision() < revision) {
RenderProblem.Html problem = RenderProblem.create(WARNING);
problem.tag("obsoleteLayoutlib");
HtmlBuilder builder = problem.getHtmlBuilder();
builder.add("Using an obsolete version of the " + target.getVersionName() + " layout library which contains many known bugs: ");
builder.addLink("Install Update", logger.getLinkManager().createRunnableLink(() -> {
// Don't warn again
//noinspection AssignmentToStaticFieldFromInstanceMethod
ourWarnAboutObsoleteLayoutLibVersions = false;
List<String> requested = Lists.newArrayList();
// The revision to install. Note that this will install a higher version than this if available;
// e.g. even if we ask for version 4, if revision 7 is available it will be installed, not revision 4.
requested.add(DetailsTypes.getPlatformPath(version));
ModelWizardDialog dialog = SdkQuickfixUtils.createDialogForPaths(module.getProject(), requested);
if (dialog != null && dialog.showAndGet()) {
if (surface != null) {
// Force the target to be recomputed; this will pick up the new revision object from the local sdk.
Configuration configuration = surface.getConfiguration();
if (configuration != null) {
configuration.getConfigurationManager().setTarget(null);
}
surface.requestRender();
// However, due to issue https://code.google.com/p/android/issues/detail?id=76096 it may not yet
// take effect.
Messages.showInfoMessage(module.getProject(), "Note: Due to a bug you may need to restart the IDE for the new layout library to fully take effect", "Restart Recommended");
}
}
}));
builder.addLink(", ", "Ignore For Now", null, logger.getLinkManager().createRunnableLink(() -> {
//noinspection AssignmentToStaticFieldFromInstanceMethod
ourWarnAboutObsoleteLayoutLibVersions = false;
if (surface != null) {
surface.requestRender();
}
}));
logger.addMessage(problem);
}
}
use of com.android.tools.idea.rendering.multi.CompatibilityRenderTarget in project android by JetBrains.
the class RenderTask method createRenderSession.
/**
* Renders the model and returns the result as a {@link com.android.ide.common.rendering.api.RenderSession}.
*
* @param factory Factory for images which would be used to render layouts to.
* @return the {@link RenderResult resulting from rendering the current model
*/
@Nullable
private RenderResult createRenderSession(@NotNull IImageFactory factory) {
if (myPsiFile == null) {
throw new IllegalStateException("createRenderSession shouldn't be called on RenderTask without PsiFile");
}
ResourceResolver resolver = ResourceResolver.copy(getResourceResolver());
if (resolver == null) {
// Abort the rendering if the resources are not found.
return null;
}
ILayoutPullParser modelParser = LayoutPullParserFactory.create(this);
if (modelParser == null) {
return null;
}
if (modelParser instanceof LayoutPsiPullParser) {
// For regular layouts, if we use appcompat, we have to emulat the app:srcCompat attribute behaviour
AndroidModuleModel androidModel = AndroidModuleModel.get(myRenderService.getFacet());
boolean useSrcCompat = androidModel != null && GradleUtil.dependsOn(androidModel, APPCOMPAT_LIB_ARTIFACT);
((LayoutPsiPullParser) modelParser).setUseSrcCompat(useSrcCompat);
}
myLayoutlibCallback.reset();
ILayoutPullParser includingParser = getIncludingLayoutParser(resolver, modelParser);
if (includingParser != null) {
modelParser = includingParser;
}
IAndroidTarget target = myConfiguration.getTarget();
int simulatedPlatform = target instanceof CompatibilityRenderTarget ? target.getVersion().getApiLevel() : 0;
Module module = myRenderService.getModule();
HardwareConfig hardwareConfig = myHardwareConfigHelper.getConfig();
final SessionParams params = new SessionParams(modelParser, myRenderingMode, module, /* projectKey */
hardwareConfig, resolver, myLayoutlibCallback, myMinSdkVersion.getApiLevel(), myTargetSdkVersion.getApiLevel(), myLogger, simulatedPlatform);
params.setAssetRepository(myAssetRepository);
params.setFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG, AndroidPsiUtils.getRootTagName(myPsiFile));
params.setFlag(RenderParamsFlags.FLAG_KEY_RECYCLER_VIEW_SUPPORT, true);
params.setFlag(RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING, true);
params.setFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE, true);
// Request margin and baseline information.
// TODO: Be smarter about setting this; start without it, and on the first request
// for an extended view info, re-render in the same session, and then set a flag
// which will cause this to create extended view info each time from then on in the
// same session
params.setExtendedViewInfoMode(true);
MergedManifest manifestInfo = MergedManifest.get(module);
LayoutDirectionQualifier qualifier = myConfiguration.getFullConfig().getLayoutDirectionQualifier();
if (qualifier != null && qualifier.getValue() == LayoutDirection.RTL && !getLayoutLib().isRtl(myLocale.toLocaleId())) {
// We don't have a flag to force RTL regardless of locale, so just pick a RTL locale (note that
// this is decoupled from resource lookup)
params.setLocale("ur");
} else {
params.setLocale(myLocale.toLocaleId());
}
try {
params.setRtlSupport(manifestInfo.isRtlSupported());
} catch (Exception e) {
// ignore.
}
// Don't show navigation buttons on older platforms
Device device = myConfiguration.getDevice();
if (!myShowDecorations || HardwareConfigHelper.isWear(device)) {
params.setForceNoDecor();
} else {
try {
params.setAppLabel(manifestInfo.getApplicationLabel());
params.setAppIcon(manifestInfo.getApplicationIcon());
String activity = myConfiguration.getActivity();
if (activity != null) {
params.setActivityName(activity);
ActivityAttributes attributes = manifestInfo.getActivityAttributes(activity);
if (attributes != null) {
if (attributes.getLabel() != null) {
params.setAppLabel(attributes.getLabel());
}
if (attributes.getIcon() != null) {
params.setAppIcon(attributes.getIcon());
}
}
}
} catch (Exception e) {
// ignore.
}
}
if (myOverrideBgColor != null) {
params.setOverrideBgColor(myOverrideBgColor.intValue());
} else if (requiresTransparency()) {
params.setOverrideBgColor(0);
}
params.setImageFactory(factory);
if (myTimeout > 0) {
params.setTimeout(myTimeout);
}
try {
myLayoutlibCallback.setLogger(myLogger);
myLayoutlibCallback.setResourceResolver(resolver);
RenderResult result = ApplicationManager.getApplication().runReadAction(new Computable<RenderResult>() {
@NotNull
@Override
public RenderResult compute() {
Module module = myRenderService.getModule();
RenderSecurityManager securityManager = isSecurityManagerEnabled ? RenderSecurityManagerFactory.create(module, getPlatform()) : null;
if (securityManager != null) {
securityManager.setActive(true, myCredential);
}
try {
int retries = 0;
RenderSession session = null;
while (retries < 10) {
if (session != null) {
session.dispose();
}
session = myLayoutLib.createSession(params);
Result result = session.getResult();
if (result.getStatus() != Result.Status.ERROR_TIMEOUT) {
// Sometimes happens at startup; treat it as a timeout; typically a retry fixes it
if (!result.isSuccess() && "The main Looper has already been prepared.".equals(result.getErrorMessage())) {
retries++;
continue;
}
break;
}
retries++;
}
if (session.getResult().isSuccess()) {
// Advance the frame time to display the material progress bars
// TODO: Expose this through the RenderTask API to allow callers to customize this value
long now = System.nanoTime();
session.setSystemBootTimeNanos(now);
session.setSystemTimeNanos(now);
session.setElapsedFrameTimeNanos(TimeUnit.MILLISECONDS.toNanos(500));
}
RenderResult result = RenderResult.create(RenderTask.this, session, myPsiFile, myLogger, myImagePool.copyOf(session.getImage()));
myRenderSession = session;
return result;
} finally {
if (securityManager != null) {
securityManager.dispose(myCredential);
}
}
}
});
addDiagnostics(result.getRenderResult());
return result;
} catch (RuntimeException t) {
// Exceptions from the bridge
myLogger.error(null, t.getLocalizedMessage(), t, null);
throw t;
}
}
Aggregations