| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Eclipse Public License, Version 1.0 (the "License"); you |
| * may not use this file except in compliance with the License. You may obtain a |
| * copy of the License at |
| * |
| * http://www.eclipse.org/org/documents/epl-v10.php |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| package com.android.ide.eclipse.tests.functests.layoutRendering; |
| |
| import com.android.SdkConstants; |
| import com.android.ide.common.rendering.LayoutLibrary; |
| import com.android.ide.common.rendering.api.ActionBarCallback; |
| import com.android.ide.common.rendering.api.AdapterBinding; |
| import com.android.ide.common.rendering.api.HardwareConfig; |
| import com.android.ide.common.rendering.api.ILayoutPullParser; |
| import com.android.ide.common.rendering.api.IProjectCallback; |
| import com.android.ide.common.rendering.api.RenderSession; |
| import com.android.ide.common.rendering.api.ResourceReference; |
| import com.android.ide.common.rendering.api.ResourceValue; |
| import com.android.ide.common.rendering.api.SessionParams; |
| import com.android.ide.common.rendering.api.SessionParams.RenderingMode; |
| import com.android.ide.common.resources.ResourceItem; |
| import com.android.ide.common.resources.ResourceRepository; |
| import com.android.ide.common.resources.ResourceResolver; |
| import com.android.ide.common.resources.configuration.DensityQualifier; |
| import com.android.ide.common.resources.configuration.FolderConfiguration; |
| import com.android.ide.common.resources.configuration.KeyboardStateQualifier; |
| import com.android.ide.common.resources.configuration.NavigationMethodQualifier; |
| import com.android.ide.common.resources.configuration.NavigationStateQualifier; |
| import com.android.ide.common.resources.configuration.ScreenDimensionQualifier; |
| import com.android.ide.common.resources.configuration.ScreenHeightQualifier; |
| import com.android.ide.common.resources.configuration.ScreenOrientationQualifier; |
| import com.android.ide.common.resources.configuration.ScreenRatioQualifier; |
| import com.android.ide.common.resources.configuration.ScreenSizeQualifier; |
| import com.android.ide.common.resources.configuration.ScreenWidthQualifier; |
| import com.android.ide.common.resources.configuration.SmallestScreenWidthQualifier; |
| import com.android.ide.common.resources.configuration.TextInputMethodQualifier; |
| import com.android.ide.common.resources.configuration.TouchScreenQualifier; |
| import com.android.ide.common.sdk.LoadStatus; |
| import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; |
| import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; |
| import com.android.ide.eclipse.tests.SdkLoadingTestCase; |
| import com.android.io.FolderWrapper; |
| import com.android.resources.Density; |
| import com.android.resources.Keyboard; |
| import com.android.resources.KeyboardState; |
| import com.android.resources.Navigation; |
| import com.android.resources.NavigationState; |
| import com.android.resources.ResourceType; |
| import com.android.resources.ScreenOrientation; |
| import com.android.resources.ScreenRatio; |
| import com.android.resources.ScreenSize; |
| import com.android.resources.TouchScreen; |
| import com.android.sdklib.IAndroidTarget; |
| import com.android.util.Pair; |
| |
| import org.kxml2.io.KXmlParser; |
| import org.xmlpull.v1.XmlPullParser; |
| import org.xmlpull.v1.XmlPullParserException; |
| |
| import java.io.File; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import javax.imageio.ImageIO; |
| |
| public class ApiDemosRenderingTest extends SdkLoadingTestCase { |
| |
| /** |
| * Custom parser that implements {@link ILayoutPullParser} (which itself extends |
| * {@link XmlPullParser}). |
| */ |
| private final static class TestParser extends KXmlParser implements ILayoutPullParser { |
| /** |
| * Since we're not going to go through the result of the rendering/layout, we can return |
| * null for the View Key. |
| */ |
| @Override |
| public Object getViewCookie() { |
| return null; |
| } |
| |
| @Override |
| public ILayoutPullParser getParser(String layoutName) { |
| return null; |
| } |
| } |
| |
| private final static class ProjectCallBack implements IProjectCallback { |
| // resource id counter. |
| // We start at 0x7f000000 to avoid colliding with the framework id |
| // since we have no access to the project R.java and we need to generate them automatically. |
| private int mIdCounter = 0x7f000000; |
| |
| // in some cases, the id that getResourceValue(String type, String name) returns |
| // will be sent back to get the type/name. This map stores the id/type/name we generate |
| // to be able to do the reverse resolution. |
| private Map<Integer, Pair<ResourceType, String>> mResourceMap = |
| new HashMap<Integer, Pair<ResourceType, String>>(); |
| |
| private boolean mCustomViewAttempt = false; |
| |
| @Override |
| public String getNamespace() { |
| // TODO: read from the ApiDemos manifest. |
| return "com.example.android.apis"; |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public Object loadView(String name, Class[] constructorSignature, Object[] constructorArgs) |
| throws ClassNotFoundException, Exception { |
| mCustomViewAttempt = true; |
| return null; |
| } |
| |
| @Override |
| public Integer getResourceId(ResourceType type, String name) { |
| Integer result = ++mIdCounter; |
| mResourceMap.put(result, Pair.of(type, name)); |
| return result; |
| } |
| |
| @Override |
| public Pair<ResourceType, String> resolveResourceId(int id) { |
| return mResourceMap.get(id); |
| } |
| |
| @Override |
| public String resolveResourceId(int[] id) { |
| return null; |
| } |
| |
| @Override |
| public ILayoutPullParser getParser(String layoutName) { |
| return null; |
| } |
| |
| @Override |
| public Object getAdapterItemValue(ResourceReference adapterView, Object adapterCookie, |
| ResourceReference itemRef, int fullPosition, int typePosition, |
| int fullChildPosition, int typeChildPosition, |
| ResourceReference viewRef, ViewAttribute viewAttribute, Object defaultValue) { |
| return null; |
| } |
| |
| @Override |
| public AdapterBinding getAdapterBinding(ResourceReference adapterView, |
| Object adapterCookie, Object viewObject) { |
| return null; |
| } |
| |
| @Override |
| public ILayoutPullParser getParser(ResourceValue layoutResource) { |
| return null; |
| } |
| |
| @Override |
| public ActionBarCallback getActionBarCallback() { |
| return new ActionBarCallback(); |
| } |
| } |
| |
| public void testApiDemos() throws IOException, XmlPullParserException { |
| findApiDemos(); |
| } |
| |
| private void findApiDemos() throws IOException, XmlPullParserException { |
| IAndroidTarget[] targets = getSdk().getTargets(); |
| |
| for (IAndroidTarget target : targets) { |
| String path = target.getPath(IAndroidTarget.SAMPLES); |
| File samples = new File(path); |
| if (samples.isDirectory()) { |
| File[] files = samples.listFiles(); |
| for (File file : files) { |
| if ("apidemos".equalsIgnoreCase(file.getName())) { |
| testSample(target, file); |
| return; |
| } |
| } |
| } |
| } |
| |
| fail("Failed to find ApiDemos!"); |
| } |
| |
| private void testSample(IAndroidTarget target, File sampleProject) throws IOException, XmlPullParserException { |
| AndroidTargetData data = getSdk().getTargetData(target); |
| if (data == null) { |
| fail("No AndroidData!"); |
| } |
| |
| LayoutLibrary layoutLib = data.getLayoutLibrary(); |
| if (layoutLib.getStatus() != LoadStatus.LOADED) { |
| fail("Fail to load the bridge: " + layoutLib.getLoadMessage()); |
| } |
| |
| FolderWrapper resFolder = new FolderWrapper(sampleProject, SdkConstants.FD_RES); |
| if (resFolder.exists() == false) { |
| fail("Sample project has no res folder!"); |
| } |
| |
| // look for the layout folder |
| File layoutFolder = new File(resFolder, SdkConstants.FD_RES_LAYOUT); |
| if (layoutFolder.isDirectory() == false) { |
| fail("Sample project has no layout folder!"); |
| } |
| |
| // first load the project's target framework resource |
| ResourceRepository framework = ResourceManager.getInstance().loadFrameworkResources(target); |
| |
| // now load the project resources |
| ResourceRepository project = new ResourceRepository(resFolder, false) { |
| @Override |
| protected ResourceItem createResourceItem(String name) { |
| return new ResourceItem(name); |
| } |
| |
| }; |
| |
| // Create a folder configuration that will be used for the rendering: |
| FolderConfiguration config = getConfiguration(); |
| |
| // get the configured resources |
| Map<ResourceType, Map<String, ResourceValue>> configuredFramework = |
| framework.getConfiguredResources(config); |
| Map<ResourceType, Map<String, ResourceValue>> configuredProject = |
| project.getConfiguredResources(config); |
| |
| boolean saveFiles = System.getenv("save_file") != null; |
| |
| // loop on the layouts and render them |
| File[] layouts = layoutFolder.listFiles(); |
| for (File layout : layouts) { |
| // create a parser for the layout file |
| TestParser parser = new TestParser(); |
| parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); |
| parser.setInput(new FileReader(layout)); |
| |
| System.out.println("Rendering " + layout.getName()); |
| |
| ProjectCallBack projectCallBack = new ProjectCallBack(); |
| |
| ResourceResolver resolver = ResourceResolver.create( |
| configuredProject, configuredFramework, |
| "Theme", false /*isProjectTheme*/); |
| |
| HardwareConfig hardwareConfig = new HardwareConfig( |
| 320, |
| 480, |
| Density.MEDIUM, |
| 160, //xdpi |
| 160, // ydpi |
| ScreenSize.NORMAL, |
| ScreenOrientation.PORTRAIT, |
| false /*software buttons */); |
| |
| RenderSession session = layoutLib.createSession(new SessionParams( |
| parser, |
| RenderingMode.NORMAL, |
| null /*projectKey*/, |
| hardwareConfig, |
| resolver, |
| projectCallBack, |
| 1, // minSdkVersion |
| 1, // targetSdkVersion |
| null //logger |
| )); |
| |
| if (session.getResult().isSuccess() == false) { |
| if (projectCallBack.mCustomViewAttempt == false) { |
| System.out.println("FAILED"); |
| fail(String.format("Rendering %1$s: %2$s", layout.getName(), |
| session.getResult().getErrorMessage())); |
| } else { |
| System.out.println("Ignore custom views for now"); |
| } |
| } else { |
| if (saveFiles) { |
| File tmp = File.createTempFile(layout.getName(), ".png"); |
| ImageIO.write(session.getImage(), "png", tmp); |
| } |
| System.out.println("Success!"); |
| } |
| } |
| } |
| |
| /** |
| * Returns a config. This must be a valid config like a device would return. This is to |
| * prevent issues where some resources don't exist in all cases and not in the default |
| * (for instance only available in hdpi and mdpi but not in default). |
| * @return |
| */ |
| private FolderConfiguration getConfiguration() { |
| FolderConfiguration config = new FolderConfiguration(); |
| |
| // this matches an ADP1. |
| config.addQualifier(new SmallestScreenWidthQualifier(320)); |
| config.addQualifier(new ScreenWidthQualifier(320)); |
| config.addQualifier(new ScreenHeightQualifier(480)); |
| config.addQualifier(new ScreenSizeQualifier(ScreenSize.NORMAL)); |
| config.addQualifier(new ScreenRatioQualifier(ScreenRatio.NOTLONG)); |
| config.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.PORTRAIT)); |
| config.addQualifier(new DensityQualifier(Density.MEDIUM)); |
| config.addQualifier(new TouchScreenQualifier(TouchScreen.FINGER)); |
| config.addQualifier(new KeyboardStateQualifier(KeyboardState.HIDDEN)); |
| config.addQualifier(new TextInputMethodQualifier(Keyboard.QWERTY)); |
| config.addQualifier(new NavigationStateQualifier(NavigationState.HIDDEN)); |
| config.addQualifier(new NavigationMethodQualifier(Navigation.TRACKBALL)); |
| config.addQualifier(new ScreenDimensionQualifier(480, 320)); |
| |
| config.updateScreenWidthAndHeight(); |
| |
| return config; |
| } |
| } |