summaryrefslogtreecommitdiffstats
path: root/tools/layoutlib/bridge/src/android
diff options
context:
space:
mode:
Diffstat (limited to 'tools/layoutlib/bridge/src/android')
-rw-r--r--tools/layoutlib/bridge/src/android/animation/AnimationThread.java171
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java53
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/BridgeResources.java122
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java9
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java30
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java7
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java24
-rw-r--r--tools/layoutlib/bridge/src/android/os/Looper_Accessor.java24
-rw-r--r--tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java24
-rw-r--r--tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java128
-rw-r--r--tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java40
-rw-r--r--tools/layoutlib/bridge/src/android/view/BridgeInflater.java272
-rw-r--r--tools/layoutlib/bridge/src/android/view/Display_Delegate.java18
-rw-r--r--tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java1
-rw-r--r--tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java26
-rw-r--r--tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java24
16 files changed, 899 insertions, 74 deletions
diff --git a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java b/tools/layoutlib/bridge/src/android/animation/AnimationThread.java
new file mode 100644
index 0000000..2b5e4fa
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/animation/AnimationThread.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 android.animation;
+
+import com.android.ide.common.rendering.api.IAnimationListener;
+import com.android.ide.common.rendering.api.RenderSession;
+import com.android.ide.common.rendering.api.Result;
+import com.android.ide.common.rendering.api.Result.Status;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.RenderSessionImpl;
+
+import android.animation.ValueAnimator;
+import android.os.Handler;
+import android.os.Handler_Delegate;
+import android.os.Message;
+import android.os.Handler_Delegate.IHandlerCallback;
+
+import java.util.PriorityQueue;
+import java.util.Queue;
+
+/**
+ * Abstract animation thread.
+ * <p/>
+ * This does not actually start an animation, instead it fakes a looper that will play whatever
+ * animation is sending messages to its own {@link Handler}.
+ * <p/>
+ * Classes should implement {@link #preAnimation()} and {@link #postAnimation()}.
+ * <p/>
+ * If {@link #preAnimation()} does not start an animation somehow then the thread doesn't do
+ * anything.
+ *
+ */
+public abstract class AnimationThread extends Thread {
+
+ private static class MessageBundle implements Comparable<MessageBundle> {
+ final Handler mTarget;
+ final Message mMessage;
+ final long mUptimeMillis;
+
+ MessageBundle(Handler target, Message message, long uptimeMillis) {
+ mTarget = target;
+ mMessage = message;
+ mUptimeMillis = uptimeMillis;
+ }
+
+ public int compareTo(MessageBundle bundle) {
+ if (mUptimeMillis < bundle.mUptimeMillis) {
+ return -1;
+ }
+ return 1;
+ }
+ }
+
+ private final RenderSessionImpl mSession;
+
+ private Queue<MessageBundle> mQueue = new PriorityQueue<MessageBundle>();
+ private final IAnimationListener mListener;
+
+ public AnimationThread(RenderSessionImpl scene, String threadName,
+ IAnimationListener listener) {
+ super(threadName);
+ mSession = scene;
+ mListener = listener;
+ }
+
+ public abstract Result preAnimation();
+ public abstract void postAnimation();
+
+ @Override
+ public void run() {
+ Bridge.prepareThread();
+ try {
+ Handler_Delegate.setCallback(new IHandlerCallback() {
+ public void sendMessageAtTime(Handler handler, Message msg, long uptimeMillis) {
+ if (msg.what == ValueAnimator.ANIMATION_START ||
+ msg.what == ValueAnimator.ANIMATION_FRAME) {
+ mQueue.add(new MessageBundle(handler, msg, uptimeMillis));
+ } else {
+ // just ignore.
+ }
+ }
+ });
+
+ // call out to the pre-animation work, which should start an animation or more.
+ Result result = preAnimation();
+ if (result.isSuccess() == false) {
+ mListener.done(result);
+ }
+
+ // loop the animation
+ RenderSession session = mSession.getSession();
+ do {
+ // check early.
+ if (mListener.isCanceled()) {
+ break;
+ }
+
+ // get the next message.
+ MessageBundle bundle = mQueue.poll();
+ if (bundle == null) {
+ break;
+ }
+
+ // sleep enough for this bundle to be on time
+ long currentTime = System.currentTimeMillis();
+ if (currentTime < bundle.mUptimeMillis) {
+ try {
+ sleep(bundle.mUptimeMillis - currentTime);
+ } catch (InterruptedException e) {
+ // FIXME log/do something/sleep again?
+ e.printStackTrace();
+ }
+ }
+
+ // check after sleeping.
+ if (mListener.isCanceled()) {
+ break;
+ }
+
+ // ready to do the work, acquire the scene.
+ result = mSession.acquire(250);
+ if (result.isSuccess() == false) {
+ mListener.done(result);
+ return;
+ }
+
+ // process the bundle. If the animation is not finished, this will enqueue
+ // the next message, so mQueue will have another one.
+ try {
+ // check after acquiring in case it took a while.
+ if (mListener.isCanceled()) {
+ break;
+ }
+
+ bundle.mTarget.handleMessage(bundle.mMessage);
+ if (mSession.render(false /*freshRender*/).isSuccess()) {
+ mListener.onNewFrame(session);
+ }
+ } finally {
+ mSession.release();
+ }
+ } while (mListener.isCanceled() == false && mQueue.size() > 0);
+
+ mListener.done(Status.SUCCESS.createResult());
+
+ } catch (Throwable throwable) {
+ // can't use Bridge.getLog() as the exception might be thrown outside
+ // of an acquire/release block.
+ mListener.done(Status.ERROR_UNKNOWN.createResult("Error playing animation", throwable));
+
+ } finally {
+ postAnimation();
+ Handler_Delegate.setCallback(null);
+ Bridge.cleanupThread();
+ }
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java b/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java
new file mode 100644
index 0000000..a953918
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 android.content.res;
+
+import com.android.layoutlib.bridge.Bridge;
+
+import android.content.res.AssetManager;
+
+public class BridgeAssetManager extends AssetManager {
+
+ /**
+ * This initializes the static field {@link AssetManager#mSystem} which is used
+ * by methods who get a global asset manager using {@link AssetManager#getSystem()}.
+ * <p/>
+ * They will end up using our bridge asset manager.
+ * <p/>
+ * {@link Bridge} calls this method after setting up a new bridge.
+ */
+ public static AssetManager initSystem() {
+ if (!(AssetManager.sSystem instanceof BridgeAssetManager)) {
+ // Note that AssetManager() creates a system AssetManager and we override it
+ // with our BridgeAssetManager.
+ AssetManager.sSystem = new BridgeAssetManager();
+ AssetManager.sSystem.makeStringBlocks(false);
+ }
+ return AssetManager.sSystem;
+ }
+
+ /**
+ * Clears the static {@link AssetManager#sSystem} to make sure we don't leave objects
+ * around that would prevent us from unloading the library.
+ */
+ public static void clearSystem() {
+ AssetManager.sSystem = null;
+ }
+
+ private BridgeAssetManager() {
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
index 0928ec5..7b672da 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
@@ -214,7 +214,15 @@ public final class BridgeResources extends Resources {
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
- return value.getSecond().getValue();
+ ResourceValue resValue = value.getSecond();
+
+ assert resValue != null;
+ if (resValue != null) {
+ String v = resValue.getValue();
+ if (v != null) {
+ return v;
+ }
+ }
}
// id was not found or not resolved. Throw a NotFoundException.
@@ -318,20 +326,24 @@ public final class BridgeResources extends Resources {
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
- String v = value.getSecond().getValue();
-
- if (v != null) {
- if (v.equals(BridgeConstants.MATCH_PARENT) ||
- v.equals(BridgeConstants.FILL_PARENT)) {
- return LayoutParams.MATCH_PARENT;
- } else if (v.equals(BridgeConstants.WRAP_CONTENT)) {
- return LayoutParams.WRAP_CONTENT;
- }
+ ResourceValue resValue = value.getSecond();
+
+ assert resValue != null;
+ if (resValue != null) {
+ String v = resValue.getValue();
+ if (v != null) {
+ if (v.equals(BridgeConstants.MATCH_PARENT) ||
+ v.equals(BridgeConstants.FILL_PARENT)) {
+ return LayoutParams.MATCH_PARENT;
+ } else if (v.equals(BridgeConstants.WRAP_CONTENT)) {
+ return LayoutParams.WRAP_CONTENT;
+ }
- if (ResourceHelper.parseFloatAttribute(
- value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
- mTmpValue.type == TypedValue.TYPE_DIMENSION) {
- return mTmpValue.getDimension(getDisplayMetrics());
+ if (ResourceHelper.parseFloatAttribute(
+ value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
+ mTmpValue.type == TypedValue.TYPE_DIMENSION) {
+ return mTmpValue.getDimension(getDisplayMetrics());
+ }
}
}
}
@@ -348,14 +360,18 @@ public final class BridgeResources extends Resources {
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
- String v = value.getSecond().getValue();
-
- if (v != null) {
- if (ResourceHelper.parseFloatAttribute(
- value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
- mTmpValue.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelOffset(mTmpValue.data,
- getDisplayMetrics());
+ ResourceValue resValue = value.getSecond();
+
+ assert resValue != null;
+ if (resValue != null) {
+ String v = resValue.getValue();
+ if (v != null) {
+ if (ResourceHelper.parseFloatAttribute(
+ value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
+ mTmpValue.type == TypedValue.TYPE_DIMENSION) {
+ return TypedValue.complexToDimensionPixelOffset(mTmpValue.data,
+ getDisplayMetrics());
+ }
}
}
}
@@ -372,14 +388,18 @@ public final class BridgeResources extends Resources {
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
- String v = value.getSecond().getValue();
-
- if (v != null) {
- if (ResourceHelper.parseFloatAttribute(
- value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
- mTmpValue.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelSize(mTmpValue.data,
- getDisplayMetrics());
+ ResourceValue resValue = value.getSecond();
+
+ assert resValue != null;
+ if (resValue != null) {
+ String v = resValue.getValue();
+ if (v != null) {
+ if (ResourceHelper.parseFloatAttribute(
+ value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
+ mTmpValue.type == TypedValue.TYPE_DIMENSION) {
+ return TypedValue.complexToDimensionPixelSize(mTmpValue.data,
+ getDisplayMetrics());
+ }
}
}
}
@@ -395,17 +415,24 @@ public final class BridgeResources extends Resources {
public int getInteger(int id) throws NotFoundException {
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
- if (value != null && value.getSecond().getValue() != null) {
- String v = value.getSecond().getValue();
- int radix = 10;
- if (v.startsWith("0x")) {
- v = v.substring(2);
- radix = 16;
- }
- try {
- return Integer.parseInt(v, radix);
- } catch (NumberFormatException e) {
- // return exception below
+ if (value != null) {
+ ResourceValue resValue = value.getSecond();
+
+ assert resValue != null;
+ if (resValue != null) {
+ String v = resValue.getValue();
+ if (v != null) {
+ int radix = 10;
+ if (v.startsWith("0x")) {
+ v = v.substring(2);
+ radix = 16;
+ }
+ try {
+ return Integer.parseInt(v, radix);
+ } catch (NumberFormatException e) {
+ // return exception below
+ }
+ }
}
}
@@ -420,9 +447,16 @@ public final class BridgeResources extends Resources {
public boolean getBoolean(int id) throws NotFoundException {
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
- if (value != null && value.getSecond().getValue() != null) {
- String v = value.getSecond().getValue();
- return Boolean.parseBoolean(v);
+ if (value != null) {
+ ResourceValue resValue = value.getSecond();
+
+ assert resValue != null;
+ if (resValue != null) {
+ String v = resValue.getValue();
+ if (v != null) {
+ return Boolean.parseBoolean(v);
+ }
+ }
}
// id was not found or not resolved. Throw a NotFoundException.
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 9deed32..8fdac02 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -33,9 +33,6 @@ import com.android.resources.ResourceType;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.util.TypedValue;
@@ -897,12 +894,6 @@ public final class BridgeTypedArray extends TypedArray {
}
@Override
- public boolean getValueAt(int index, TypedValue outValue) {
- // pass
- return false;
- }
-
- @Override
public String toString() {
return Arrays.toString(mResourceData);
}
diff --git a/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java
new file mode 100644
index 0000000..0a7899a
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 android.content.res;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.util.TypedValue;
+
+public class TypedArray_Delegate {
+
+ @LayoutlibDelegate
+ public static boolean getValueAt(TypedArray theTypedArray, int index, TypedValue outValue) {
+ // pass
+ return false;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 66e59d8..eadec02 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -22,7 +22,6 @@ import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.resources.Density;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.os.Parcel;
@@ -149,7 +148,7 @@ public final class Bitmap_Delegate {
}
public static int getBufferedImageType(int nativeBitmapConfig) {
- switch (Config.sConfigs[nativeBitmapConfig]) {
+ switch (Config.nativeToConfig(nativeBitmapConfig)) {
case ALPHA_8:
return BufferedImage.TYPE_INT_ARGB;
case RGB_565:
@@ -210,7 +209,7 @@ public final class Bitmap_Delegate {
}
// create a delegate with the content of the stream.
- Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.sConfigs[nativeConfig]);
+ Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
return createBitmap(delegate, mutable, Bitmap.getDefaultDensity());
}
@@ -238,7 +237,7 @@ public final class Bitmap_Delegate {
image.setRGB(0, 0, width, height, argb, 0, width);
// create a delegate with the content of the stream.
- Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.sConfigs[nativeConfig]);
+ Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
return createBitmap(delegate, isMutable, Bitmap.getDefaultDensity());
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java
new file mode 100644
index 0000000..2745770
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 android.graphics;
+
+public class Typeface_Accessor {
+
+ public static void resetDefaults() {
+ Typeface.sDefaults = null;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java b/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java
new file mode 100644
index 0000000..ad95fcc
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 android.os;
+
+public class Looper_Accessor {
+
+ public static void cleanupThread() {
+ // clean up the looper
+ Looper.sThreadLocal.remove();
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
index 63711a7..bd332a6 100644
--- a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
@@ -68,4 +68,28 @@ public class SystemClock_Delegate {
/*package*/ static long currentThreadTimeMillis() {
return System.currentTimeMillis();
}
+
+ /**
+ * Returns microseconds running in the current thread.
+ *
+ * @return elapsed microseconds in the thread
+ *
+ * @hide
+ */
+ @LayoutlibDelegate
+ /*package*/ static long currentThreadTimeMicro() {
+ return System.currentTimeMillis() * 1000;
+ }
+
+ /**
+ * Returns current wall time in microseconds.
+ *
+ * @return elapsed microseconds in wall time
+ *
+ * @hide
+ */
+ @LayoutlibDelegate
+ /*package*/ static long currentTimeMicro() {
+ return elapsedRealtime() * 1000;
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java
new file mode 100644
index 0000000..0a3cdc6
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 android.util;
+
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.resources.ResourceType;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import android.util.AttributeSet;
+import android.util.XmlPullAttributes;
+
+/**
+ * A correct implementation of the {@link AttributeSet} interface on top of a XmlPullParser
+ */
+public class BridgeXmlPullAttributes extends XmlPullAttributes {
+
+ private final BridgeContext mContext;
+ private final boolean mPlatformFile;
+
+ public BridgeXmlPullAttributes(XmlPullParser parser, BridgeContext context,
+ boolean platformFile) {
+ super(parser);
+ mContext = context;
+ mPlatformFile = platformFile;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.util.XmlPullAttributes#getAttributeNameResource(int)
+ *
+ * This methods must return com.android.internal.R.attr.<name> matching
+ * the name of the attribute.
+ * It returns 0 if it doesn't find anything.
+ */
+ @Override
+ public int getAttributeNameResource(int index) {
+ // get the attribute name.
+ String name = getAttributeName(index);
+
+ // get the attribute namespace
+ String ns = mParser.getAttributeNamespace(index);
+
+ if (BridgeConstants.NS_RESOURCES.equals(ns)) {
+ Integer v = Bridge.getResourceId(ResourceType.ATTR, name);
+ if (v != null) {
+ return v.intValue();
+ }
+
+ return 0;
+ }
+
+ // this is not an attribute in the android namespace, we query the customviewloader, if
+ // the namespaces match.
+ if (mContext.getProjectCallback().getNamespace().equals(ns)) {
+ Integer v = mContext.getProjectCallback().getResourceId(ResourceType.ATTR, name);
+ if (v != null) {
+ return v.intValue();
+ }
+ }
+
+ return 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.util.XmlPullAttributes#getAttributeResourceValue(int, int)
+ */
+ @Override
+ public int getAttributeResourceValue(int index, int defaultValue) {
+ String value = getAttributeValue(index);
+
+ return resolveResourceValue(value, defaultValue);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.util.XmlPullAttributes#getAttributeResourceValue(java.lang.String, java.lang.String, int)
+ */
+ @Override
+ public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
+ String value = getAttributeValue(namespace, attribute);
+
+ return resolveResourceValue(value, defaultValue);
+ }
+
+ private int resolveResourceValue(String value, int defaultValue) {
+ // now look for this particular value
+ RenderResources resources = mContext.getRenderResources();
+ ResourceValue resource = resources.resolveResValue(
+ resources.findResValue(value, mPlatformFile));
+
+ if (resource != null) {
+ Integer id = null;
+ if (mPlatformFile || resource.isFramework()) {
+ id = Bridge.getResourceId(resource.getResourceType(), resource.getName());
+ } else {
+ id = mContext.getProjectCallback().getResourceId(
+ resource.getResourceType(), resource.getName());
+ }
+
+ if (id != null) {
+ return id;
+ }
+ }
+
+ return defaultValue;
+ }
+
+}
diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
new file mode 100644
index 0000000..e3778b1
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 android.view;
+
+import com.android.layoutlib.bridge.android.BridgeWindow;
+import com.android.layoutlib.bridge.android.BridgeWindowSession;
+
+import android.os.Handler;
+import android.view.View.AttachInfo;
+
+public class AttachInfo_Accessor {
+
+ public static void setAttachInfo(View view) {
+ AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
+ new Handler(), null);
+ info.mHasWindowFocus = true;
+ info.mWindowVisibility = View.VISIBLE;
+ info.mInTouchMode = false; // this is so that we can display selections.
+ info.mHardwareAccelerated = false;
+ view.dispatchAttachedToWindow(info, 0);
+ }
+
+ public static void dispatchOnPreDraw(View view) {
+ view.mAttachInfo.mTreeObserver.dispatchOnPreDraw();
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
new file mode 100644
index 0000000..941f1ce6
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 android.view;
+
+import com.android.ide.common.rendering.api.IProjectCallback;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.MergeCookie;
+import com.android.ide.common.rendering.api.ResourceReference;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+import com.android.layoutlib.bridge.impl.ParserFactory;
+import com.android.resources.ResourceType;
+import com.android.util.Pair;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.InflateException;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.io.File;
+
+/**
+ * Custom implementation of {@link LayoutInflater} to handle custom views.
+ */
+public final class BridgeInflater extends LayoutInflater {
+
+ private final IProjectCallback mProjectCallback;
+ private boolean mIsInMerge = false;
+ private ResourceReference mResourceReference;
+
+ /**
+ * List of class prefixes which are tried first by default.
+ * <p/>
+ * This should match the list in com.android.internal.policy.impl.PhoneLayoutInflater.
+ */
+ private static final String[] sClassPrefixList = {
+ "android.widget.",
+ "android.webkit."
+ };
+
+ protected BridgeInflater(LayoutInflater original, Context newContext) {
+ super(original, newContext);
+ mProjectCallback = null;
+ }
+
+ /**
+ * Instantiate a new BridgeInflater with an {@link IProjectCallback} object.
+ *
+ * @param context The Android application context.
+ * @param projectCallback the {@link IProjectCallback} object.
+ */
+ public BridgeInflater(Context context, IProjectCallback projectCallback) {
+ super(context);
+ mProjectCallback = projectCallback;
+ mConstructorArgs[0] = context;
+ }
+
+ @Override
+ public View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {
+ View view = null;
+
+ try {
+ // First try to find a class using the default Android prefixes
+ for (String prefix : sClassPrefixList) {
+ try {
+ view = createView(name, prefix, attrs);
+ if (view != null) {
+ break;
+ }
+ } catch (ClassNotFoundException e) {
+ // Ignore. We'll try again using the base class below.
+ }
+ }
+
+ // Next try using the parent loader. This will most likely only work for
+ // fully-qualified class names.
+ try {
+ if (view == null) {
+ view = super.onCreateView(name, attrs);
+ }
+ } catch (ClassNotFoundException e) {
+ // Ignore. We'll try again using the custom view loader below.
+ }
+
+ // Finally try again using the custom view loader
+ try {
+ if (view == null) {
+ view = loadCustomView(name, attrs);
+ }
+ } catch (ClassNotFoundException e) {
+ // If the class was not found, we throw the exception directly, because this
+ // method is already expected to throw it.
+ throw e;
+ }
+ } catch (Exception e) {
+ // Wrap the real exception in a ClassNotFoundException, so that the calling method
+ // can deal with it.
+ ClassNotFoundException exception = new ClassNotFoundException("onCreateView", e);
+ throw exception;
+ }
+
+ setupViewInContext(view, attrs);
+
+ return view;
+ }
+
+ @Override
+ public View createViewFromTag(View parent, String name, AttributeSet attrs) {
+ View view = null;
+ try {
+ view = super.createViewFromTag(parent, name, attrs);
+ } catch (InflateException e) {
+ // try to load the class from using the custom view loader
+ try {
+ view = loadCustomView(name, attrs);
+ } catch (Exception e2) {
+ // Wrap the real exception in an InflateException so that the calling
+ // method can deal with it.
+ InflateException exception = new InflateException();
+ if (e2.getClass().equals(ClassNotFoundException.class) == false) {
+ exception.initCause(e2);
+ } else {
+ exception.initCause(e);
+ }
+ throw exception;
+ }
+ }
+
+ setupViewInContext(view, attrs);
+
+ return view;
+ }
+
+ @Override
+ public View inflate(int resource, ViewGroup root) {
+ Context context = getContext();
+ if (context instanceof BridgeContext) {
+ BridgeContext bridgeContext = (BridgeContext)context;
+
+ ResourceValue value = null;
+
+ Pair<ResourceType, String> layoutInfo = Bridge.resolveResourceId(resource);
+ if (layoutInfo != null) {
+ value = bridgeContext.getRenderResources().getFrameworkResource(
+ ResourceType.LAYOUT, layoutInfo.getSecond());
+ } else {
+ layoutInfo = mProjectCallback.resolveResourceId(resource);
+
+ if (layoutInfo != null) {
+ value = bridgeContext.getRenderResources().getProjectResource(
+ ResourceType.LAYOUT, layoutInfo.getSecond());
+ }
+ }
+
+ if (value != null) {
+ File f = new File(value.getValue());
+ if (f.isFile()) {
+ try {
+ XmlPullParser parser = ParserFactory.create(f);
+
+ BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
+ parser, bridgeContext, false);
+
+ return inflate(bridgeParser, root);
+ } catch (Exception e) {
+ Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
+ "Failed to parse file " + f.getAbsolutePath(), e, null /*data*/);
+
+ return null;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private View loadCustomView(String name, AttributeSet attrs) throws ClassNotFoundException,
+ Exception{
+ if (mProjectCallback != null) {
+ // first get the classname in case it's not the node name
+ if (name.equals("view")) {
+ name = attrs.getAttributeValue(null, "class");
+ }
+
+ mConstructorArgs[1] = attrs;
+
+ Object customView = mProjectCallback.loadView(name, mConstructorSignature,
+ mConstructorArgs);
+
+ if (customView instanceof View) {
+ return (View)customView;
+ }
+ }
+
+ return null;
+ }
+
+ private void setupViewInContext(View view, AttributeSet attrs) {
+ if (getContext() instanceof BridgeContext) {
+ BridgeContext bc = (BridgeContext) getContext();
+ if (attrs instanceof BridgeXmlBlockParser) {
+ BridgeXmlBlockParser parser = (BridgeXmlBlockParser) attrs;
+
+ // get the view key
+ Object viewKey = parser.getViewCookie();
+
+ if (viewKey == null) {
+ int currentDepth = parser.getDepth();
+
+ // test whether we are in an included file or in a adapter binding view.
+ BridgeXmlBlockParser previousParser = bc.getPreviousParser();
+ if (previousParser != null) {
+ // looks like we inside an embedded layout.
+ // only apply the cookie of the calling node (<include>) if we are at the
+ // top level of the embedded layout. If there is a merge tag, then
+ // skip it and look for the 2nd level
+ int testDepth = mIsInMerge ? 2 : 1;
+ if (currentDepth == testDepth) {
+ viewKey = previousParser.getViewCookie();
+ // if we are in a merge, wrap the cookie in a MergeCookie.
+ if (viewKey != null && mIsInMerge) {
+ viewKey = new MergeCookie(viewKey);
+ }
+ }
+ } else if (mResourceReference != null && currentDepth == 1) {
+ // else if there's a resource reference, this means we are in an adapter
+ // binding case. Set the resource ref as the view cookie only for the top
+ // level view.
+ viewKey = mResourceReference;
+ }
+ }
+
+ if (viewKey != null) {
+ bc.addViewKey(view, viewKey);
+ }
+ }
+ }
+ }
+
+ public void setIsInMerge(boolean isInMerge) {
+ mIsInMerge = isInMerge;
+ }
+
+ public void setResourceReference(ResourceReference reference) {
+ mResourceReference = reference;
+ }
+
+ @Override
+ public LayoutInflater cloneInContext(Context newContext) {
+ return new BridgeInflater(this, newContext);
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
index 83f9cc2..9732530 100644
--- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
@@ -46,31 +46,17 @@ public class Display_Delegate {
}
@LayoutlibDelegate
- /** @hide Returns the actual screen size, not including any decor. */
- /*package*/ static int getRealWidth(Display theDisplay) {
- // always dynamically query for the current window manager
- return RenderAction.getCurrentContext().getIWindowManager().getMetrics().widthPixels;
- }
-
- @LayoutlibDelegate
- /** @hide Returns the actual screen size, not including any decor. */
- /*package*/ static int getRealHeight(Display theDisplay) {
- // always dynamically query for the current window manager
- return RenderAction.getCurrentContext().getIWindowManager().getMetrics().heightPixels;
- }
-
- @LayoutlibDelegate
/** @hide special for when we are faking the screen size. */
/*package*/ static int getRawWidth(Display theDisplay) {
// same as real since we're not faking compatibility mode.
- return getRealWidth(theDisplay);
+ return RenderAction.getCurrentContext().getIWindowManager().getMetrics().widthPixels;
}
@LayoutlibDelegate
/** @hide special for when we are faking the screen size. */
/*package*/ static int getRawHeight(Display theDisplay) {
// same as real since we're not faking compatibility mode.
- return getRealHeight(theDisplay);
+ return RenderAction.getCurrentContext().getIWindowManager().getMetrics().heightPixels;
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
index 64efa7e..3db3a1b 100644
--- a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
@@ -16,7 +16,6 @@
package android.view;
-import com.android.layoutlib.bridge.android.BridgeInflater;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java b/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java
new file mode 100644
index 0000000..01db34e
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 android.view;
+
+public class ViewConfiguration_Accessor {
+
+ public static void clearConfigurations() {
+ // clear the stored ViewConfiguration since the map is per density and not per context.
+ ViewConfiguration.sConfigurations.clear();
+ }
+
+}
diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java
new file mode 100644
index 0000000..875336a
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 android.view.inputmethod;
+
+public class InputMethodManager_Accessor {
+
+ public static void resetInstance() {
+ InputMethodManager.mInstance = null;
+ }
+}