summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/text/StaticLayout.java2
-rw-r--r--core/java/android/view/VolumePanel.java2
-rw-r--r--core/java/android/webkit/CookieManager.java16
-rw-r--r--core/java/com/android/internal/service/wallpaper/ImageWallpaper.java2
-rw-r--r--core/jni/android/graphics/Path.cpp3
-rw-r--r--data/sounds/effects/ogg/Effect_Tick.oggbin4825 -> 4348 bytes
-rw-r--r--data/sounds/effects/ogg/KeypressSpacebar.oggbin4204 -> 7470 bytes
-rw-r--r--data/sounds/effects/ogg/KeypressStandard.oggbin4196 -> 6442 bytes
-rw-r--r--data/sounds/effects/ogg/Lock.oggbin26740 -> 20013 bytes
-rw-r--r--data/sounds/effects/ogg/Unlock.oggbin29712 -> 21885 bytes
-rw-r--r--docs/html/guide/publishing/licensing.jd13
-rw-r--r--docs/html/guide/topics/fundamentals/index.jd45
-rw-r--r--libs/gui/SurfaceTexture.cpp3
-rw-r--r--libs/hwui/DisplayListRenderer.cpp17
-rw-r--r--libs/hwui/DisplayListRenderer.h9
-rw-r--r--libs/hwui/OpenGLRenderer.cpp13
-rw-r--r--libs/hwui/ResourceCache.cpp35
-rw-r--r--libs/hwui/ResourceCache.h4
-rw-r--r--libs/hwui/Snapshot.h4
-rw-r--r--libs/rs/rsScriptC_Lib.cpp2
-rw-r--r--media/java/android/media/AudioManager.java34
-rw-r--r--media/java/android/media/AudioService.java16
-rwxr-xr-xmedia/java/android/media/videoeditor/MediaProperties.java5
-rwxr-xr-xmedia/java/android/media/videoeditor/MediaVideoItem.java5
-rwxr-xr-xmedia/jni/mediaeditor/Android.mk3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java7
-rw-r--r--services/java/com/android/server/WindowManagerService.java4
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml9
-rw-r--r--tests/HwAccelerationTest/res/anim/accelerate_interpolator_2.xml21
-rw-r--r--tests/HwAccelerationTest/res/anim/slide_off_left.xml20
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/MarqueeActivity.java68
-rw-r--r--tools/layoutlib/bridge/Android.mk2
-rw-r--r--tools/layoutlib/bridge/resources/bars/action_bar.xml11
-rw-r--r--tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.pngbin0 -> 3900 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.pngbin0 -> 3991 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.pngbin0 -> 3140 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.pngbin0 -> 885 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/phone_system_bar.xml12
-rw-r--r--tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml20
-rw-r--r--tools/layoutlib/bridge/resources/bars/title_bar.xml7
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java29
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java14
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java10
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java78
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java212
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java47
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java42
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java45
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java46
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java323
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java71
52 files changed, 1094 insertions, 239 deletions
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index ac3df795c760..13ea13f32097 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -500,7 +500,7 @@ public class StaticLayout extends Layout
choosehtv, fm, hasTabOrEmoji,
needMultiply, paraStart, chdirs, dir, easy,
paraEnd == bufend, includepad, trackpad,
- chs, widths, here - paraStart,
+ chs, widths, paraStart,
ellipsize, ellipsizedWidth, w, paint);
}
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index 2aa94dc65c44..3bab29fcc27f 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -190,6 +190,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
mDialog.setOnDismissListener(new OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
mActiveStreamType = -1;
+ mAudioManager.forceVolumeControlStream(mActiveStreamType);
}
});
// Change some window properties
@@ -483,6 +484,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
}
if (!mDialog.isShowing()) {
+ mAudioManager.forceVolumeControlStream(streamType);
mDialog.setContentView(mView);
// Showing dialog - use collapsed state
collapse();
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 1fea65adf074..9b0d4e0eaa27 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -519,11 +519,17 @@ public final class CookieManager {
}
}
- synchronized void waitForCookieOperationsToComplete() {
- while (pendingCookieOperations > 0) {
- try {
- wait();
- } catch (InterruptedException e) { }
+ /**
+ * Waits for pending operations to completed.
+ * {@hide} Too late to release publically.
+ */
+ public void waitForCookieOperationsToComplete() {
+ synchronized (this) {
+ while (pendingCookieOperations > 0) {
+ try {
+ wait();
+ } catch (InterruptedException e) { }
+ }
}
}
diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
index 38ec9c86e646..85095cf04322 100644
--- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
+++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
@@ -129,7 +129,7 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
- onDesiredSizeChanged(desiredWidth, desiredHeight);
+ super.onDesiredSizeChanged(desiredWidth, desiredHeight);
SurfaceHolder surfaceHolder = getSurfaceHolder();
if (surfaceHolder != null) {
updateSurfaceSize(surfaceHolder);
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index 90c4dd453c2e..eb9e004c9861 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -36,7 +36,8 @@ public:
static void finalizer(JNIEnv* env, jobject clazz, SkPath* obj) {
#ifdef USE_OPENGL_RENDERER
if (android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().pathCache.removeDeferred(obj);
+ android::uirenderer::Caches::getInstance().resourceCache.destructor(obj);
+ return;
}
#endif
delete obj;
diff --git a/data/sounds/effects/ogg/Effect_Tick.ogg b/data/sounds/effects/ogg/Effect_Tick.ogg
index b3790199b8b1..a997fe164ee4 100644
--- a/data/sounds/effects/ogg/Effect_Tick.ogg
+++ b/data/sounds/effects/ogg/Effect_Tick.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressSpacebar.ogg b/data/sounds/effects/ogg/KeypressSpacebar.ogg
index 1776762e51d2..0d0fbf122577 100644
--- a/data/sounds/effects/ogg/KeypressSpacebar.ogg
+++ b/data/sounds/effects/ogg/KeypressSpacebar.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressStandard.ogg b/data/sounds/effects/ogg/KeypressStandard.ogg
index a261975bbb8e..5878135e1574 100644
--- a/data/sounds/effects/ogg/KeypressStandard.ogg
+++ b/data/sounds/effects/ogg/KeypressStandard.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Lock.ogg b/data/sounds/effects/ogg/Lock.ogg
index a24df3deba71..2e57d9e716a7 100644
--- a/data/sounds/effects/ogg/Lock.ogg
+++ b/data/sounds/effects/ogg/Lock.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Unlock.ogg b/data/sounds/effects/ogg/Unlock.ogg
index 114df939cd08..490f98e526e1 100644
--- a/data/sounds/effects/ogg/Unlock.ogg
+++ b/data/sounds/effects/ogg/Unlock.ogg
Binary files differ
diff --git a/docs/html/guide/publishing/licensing.jd b/docs/html/guide/publishing/licensing.jd
index e099413e23d8..55513843019e 100644
--- a/docs/html/guide/publishing/licensing.jd
+++ b/docs/html/guide/publishing/licensing.jd
@@ -2123,7 +2123,7 @@ returned by the Android Market server in a license response.</p>
<tr>
<td>LICENSED</td>
<td>The application is licensed to the user. The user has purchased the
-application or the application is free.</td>
+application or the application only exists as a draft.</td>
<td>Yes</td>
<td><code>VT</code>,&nbsp;<code>GT</code>, <code>GR</code></td>
<td><em>Allow access according to Policy constraints.</em></td>
@@ -2201,6 +2201,17 @@ implementation.</p>
</table>
+<p class="note"><strong>Note:</strong> As documented in <a href="#test-env">
+Setting Up The Testing Environment</a>, the response code can be manually
+overridden for the application developer and any registered test users via the
+Android Market publisher site.
+<br/><br/>
+Additionally, as noted above, applications that are in draft mode (in other
+words, applicaitons that have been uploaded but have <em>never</em> been
+published) will return LICENSED for all users, even if not listed as a test
+user. Since the application has never been offered for download, it is assumed
+that any users running it must have obtained it from an authorized channel for
+testing purposes.</p>
<h2 id="extras">Server Response Extras</h2>
diff --git a/docs/html/guide/topics/fundamentals/index.jd b/docs/html/guide/topics/fundamentals/index.jd
index de2e31249aaa..f427a927daaf 100644
--- a/docs/html/guide/topics/fundamentals/index.jd
+++ b/docs/html/guide/topics/fundamentals/index.jd
@@ -180,9 +180,7 @@ instance, it might initiate a service to perform some work based on the event.
<p>A broadcast receiver is implemented as a subclass of {@link android.content.BroadcastReceiver}
and each broadcast is delivered as an {@link android.content.Intent} object. For more information,
-see the <a
-href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
-developer guide.</p>
+see the {@link android.content.BroadcastReceiver} class.</p>
</dd>
</dl>
@@ -220,35 +218,56 @@ Intents bind individual components to each other at runtime (you can think of th
as the messengers that request an action from other components), whether the component belongs
to your application or another.</p>
-<p>An intent is defined by an {@link android.content.Intent} object, which defines a message to
+<p>An intent is created with an {@link android.content.Intent} object, which defines a message to
activate either a specific component or a specific <em>type</em> of component&mdash;an intent
can be either explicit or implicit, respectively.</p>
<p>For activities and services, an intent defines the action to perform (for example, to "view" or
"send" something) and may specify the URI of the data to act on (among other things that the
component being started might need to know). For example, an intent might convey a request for an
-activity to present an image to the user or to open a web page. In some cases, you can start a
-component in order to receive a result, in which case, the component that is started also returns
-the result in an {@link android.content.Intent} object (for example, you can issue an intent to let
+activity to show an image or to open a web page. In some cases, you can start an
+activity to receive a result, in which case, the activity also returns
+the result in an {@link android.content.Intent} (for example, you can issue an intent to let
the user pick a personal contact and have it returned to you&mdash;the return intent includes a
-URI pointing to the chosen contact). For broadcast receivers, the intent simply defines the
+URI pointing to the chosen contact).</p>
+
+<p>For broadcast receivers, the intent simply defines the
announcement being broadcast (for example, a broadcast to indicate the device battery is low
includes only a known action string that indicates "battery is low").</p>
-<p>The remaining type of component, content provider, is not activated by intents. Rather, it is
+<p>The other component type, content provider, is not activated by intents. Rather, it is
activated when targeted by a request from a {@link android.content.ContentResolver}. The content
resolver handles all direct transactions with the content provider so that the component that's
performing transactions with the provider doesn't need to and instead calls methods on the {@link
android.content.ContentResolver} object. This leaves a layer of abstraction between the content
provider and the component requesting information (for security).</p>
+<p>There are separate methods for activiting each type of component:</p>
+<ul>
+ <li>You can start an activity (or give it something new to do) by
+passing an {@link android.content.Intent} to {@link android.content.Context#startActivity
+startActivity()} or {@link android.app.Activity#startActivityForResult startActivityForResult()}
+(when you want the activity to return a result).</li>
+ <li>You can start a service (or give new instructions to an ongoing service) by
+passing an {@link android.content.Intent} to {@link android.content.Context#startService
+startService()}. Or you can bind to the service by passing an {@link android.content.Intent} to
+{@link android.content.Context#bindService bindService()}.</li>
+ <li>You can initiate a broadcast by passing an {@link android.content.Intent} to methods like
+{@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}, {@link
+android.content.Context#sendOrderedBroadcast(Intent, String) sendOrderedBroadcast()}, or {@link
+android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</li>
+ <li>You can perform a query to a content provider by calling {@link
+android.content.ContentProvider#query query()} on a {@link android.content.ContentResolver}.</li>
+</ul>
+
<p>For more information about using intents, see the <a
href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and
Intent Filters</a> document. More information about activating specific components is also provided
-in the <a href="{@docRoot}guide/topics/fundamentals/activities.html">Activities</a>, <a
-href="{@docRoot}guide/topics/fundamentals/services.html">Services</a>, and <a
-href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> developer
-guides.</p>
+in the following documents: <a
+href="{@docRoot}guide/topics/fundamentals/activities.html">Activities</a>, <a
+href="{@docRoot}guide/topics/fundamentals/services.html">Services</a>, {@link
+android.content.BroadcastReceiver} and <a
+href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.</p>
<h2 id="Manifest">The Manifest File</h2>
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 3c4b565d466b..d6cc8ce03443 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -77,7 +77,8 @@ static void mtxMul(float out[16], const float a[16], const float b[16]);
SurfaceTexture::SurfaceTexture(GLuint tex) :
mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT),
- mLastQueued(INVALID_BUFFER_SLOT), mTexName(tex) {
+ mCurrentTransform(0), mLastQueued(INVALID_BUFFER_SLOT),
+ mLastQueuedTransform(0), mNextTransform(0), mTexName(tex) {
LOGV("SurfaceTexture::SurfaceTexture");
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 2df52ae65e12..d5d2ba07154c 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -95,6 +95,10 @@ void DisplayList::clearResources() {
delete mPaths.itemAt(i);
}
mPaths.clear();
+ for (size_t i = 0; i < mOriginalPaths.size(); i++) {
+ caches.resourceCache.decrementRefcount(mOriginalPaths.itemAt(i));
+ }
+ mOriginalPaths.clear();
for (size_t i = 0; i < mMatrices.size(); i++) {
delete mMatrices.itemAt(i);
@@ -146,6 +150,13 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde
mPaths.add(paths.itemAt(i));
}
+ const Vector<SkPath*> &originalPaths = recorder.getOriginalPaths();
+ for (size_t i = 0; i < originalPaths.size(); i++) {
+ SkPath* path = originalPaths.itemAt(i);
+ mOriginalPaths.add(path);
+ caches.resourceCache.incrementRefcount(path);
+ }
+
const Vector<SkMatrix*> &matrices = recorder.getMatrices();
for (size_t i = 0; i < matrices.size(); i++) {
mMatrices.add(matrices.itemAt(i));
@@ -519,6 +530,12 @@ void DisplayListRenderer::reset() {
}
mBitmapResources.clear();
+ for (size_t i = 0; i < mOriginalPaths.size(); i++) {
+ SkPath* resource = mOriginalPaths.itemAt(i);
+ caches.resourceCache.decrementRefcount(resource);
+ }
+ mOriginalPaths.clear();
+
for (size_t i = 0; i < mShaders.size(); i++) {
caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 2d0e30a48e05..f39f37f860eb 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -190,6 +190,7 @@ private:
Vector<SkPaint*> mPaints;
Vector<SkPath*> mPaths;
+ Vector<SkPath*> mOriginalPaths;
Vector<SkMatrix*> mMatrices;
Vector<SkiaShader*> mShaders;
@@ -293,6 +294,10 @@ public:
return mPaths;
}
+ const Vector<SkPath*>& getOriginalPaths() const {
+ return mOriginalPaths;
+ }
+
const Vector<SkMatrix*>& getMatrices() const {
return mMatrices;
}
@@ -371,6 +376,9 @@ private:
if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) {
if (pathCopy == NULL) {
pathCopy = path;
+ mOriginalPaths.add(path);
+ Caches& caches = Caches::getInstance();
+ caches.resourceCache.incrementRefcount(path);
} else {
pathCopy = new SkPath(*path);
mPaths.add(pathCopy);
@@ -452,6 +460,7 @@ private:
Vector<SkPaint*> mPaints;
DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
+ Vector<SkPath*> mOriginalPaths;
Vector<SkPath*> mPaths;
DefaultKeyedVector<SkPath*, SkPath*> mPathMap;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 90d6ea1bc1f0..8ee7ec3f60cd 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1217,17 +1217,18 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int
#if RENDER_LAYERS_AS_REGIONS
// Mark the current layer dirty where we are going to draw the patch
if (hasLayer() && mesh->hasEmptyQuads) {
+ const float offsetX = left + mSnapshot->transform->getTranslateX();
+ const float offsetY = top + mSnapshot->transform->getTranslateY();
const size_t count = mesh->quads.size();
for (size_t i = 0; i < count; i++) {
const Rect& bounds = mesh->quads.itemAt(i);
if (pureTranslate) {
- const float x = (int) floorf(bounds.left + 0.5f);
- const float y = (int) floorf(bounds.top + 0.5f);
- dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
- *mSnapshot->transform);
+ const float x = (int) floorf(bounds.left + offsetX + 0.5f);
+ const float y = (int) floorf(bounds.top + offsetY + 0.5f);
+ dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight());
} else {
- dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
- *mSnapshot->transform);
+ dirtyLayer(left + bounds.left, top + bounds.top,
+ left + bounds.right, top + bounds.bottom, *mSnapshot->transform);
}
}
}
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 70d117a3622b..87fdfb5212a1 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -65,6 +65,10 @@ void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
incrementRefcount((void*)bitmapResource, kBitmap);
}
+void ResourceCache::incrementRefcount(SkPath* pathResource) {
+ incrementRefcount((void*)pathResource, kPath);
+}
+
void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
shaderResource->getSkShader()->safeRef();
incrementRefcount((void*) shaderResource, kShader);
@@ -94,6 +98,10 @@ void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
decrementRefcount((void*) bitmapResource);
}
+void ResourceCache::decrementRefcount(SkPath* pathResource) {
+ decrementRefcount((void*) pathResource);
+}
+
void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
shaderResource->getSkShader()->safeUnref();
decrementRefcount((void*) shaderResource);
@@ -122,6 +130,24 @@ void ResourceCache::recycle(SkBitmap* resource) {
}
}
+void ResourceCache::destructor(SkPath* resource) {
+ Mutex::Autolock _l(mLock);
+ ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
+ if (ref == NULL) {
+ // If we're not tracking this resource, just delete it
+ if (Caches::hasInstance()) {
+ Caches::getInstance().pathCache.removeDeferred(resource);
+ }
+ delete resource;
+ return;
+ }
+ ref->destroyed = true;
+ if (ref->refCount == 0) {
+ deleteResourceReference(resource, ref);
+ return;
+ }
+}
+
void ResourceCache::destructor(SkBitmap* resource) {
Mutex::Autolock _l(mLock);
ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
@@ -192,6 +218,15 @@ void ResourceCache::deleteResourceReference(void* resource, ResourceReference* r
delete bitmap;
}
break;
+ case kPath:
+ {
+ SkPath* path = (SkPath*)resource;
+ if (Caches::hasInstance()) {
+ Caches::getInstance().pathCache.removeDeferred(path);
+ }
+ delete path;
+ }
+ break;
case kShader:
{
SkiaShader* shader = (SkiaShader*)resource;
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 1bb4390f82d9..2a38910951c4 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -32,6 +32,7 @@ enum ResourceType {
kBitmap,
kShader,
kColorFilter,
+ kPath,
};
class ResourceReference {
@@ -53,15 +54,18 @@ class ResourceCache {
public:
ResourceCache();
~ResourceCache();
+ void incrementRefcount(SkPath* resource);
void incrementRefcount(SkBitmap* resource);
void incrementRefcount(SkiaShader* resource);
void incrementRefcount(SkiaColorFilter* resource);
void incrementRefcount(const void* resource, ResourceType resourceType);
void decrementRefcount(void* resource);
void decrementRefcount(SkBitmap* resource);
+ void decrementRefcount(SkPath* resource);
void decrementRefcount(SkiaShader* resource);
void decrementRefcount(SkiaColorFilter* resource);
void recycle(SkBitmap* resource);
+ void destructor(SkPath* resource);
void destructor(SkBitmap* resource);
void destructor(SkiaShader* resource);
void destructor(SkiaColorFilter* resource);
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 595ad4e92e3b..bd7031927b5e 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -150,6 +150,10 @@ public:
break;
case SkRegion::kIntersect_Op:
clipped = clipRect->intersect(r);
+ if (!clipped) {
+ clipRect->setEmpty();
+ clipped = true;
+ }
break;
case SkRegion::kUnion_Op:
clipped = clipRect->unionWith(r);
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 8a85f6ed5308..80da8aeed8af 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -856,6 +856,8 @@ static ScriptCState::SymbolTable_t gSyms[] = {
{ "__modsi3", (void *)&SC_modsi3, true },
{ "__udivsi3", (void *)&SC_udivsi3, true },
{ "__umodsi3", (void *)&SC_umodsi3, true },
+ { "memset", (void *)&memset, true },
+ { "memcpy", (void *)&memcpy, true },
// allocation
{ "_Z19rsAllocationGetDimX13rs_allocation", (void *)&SC_allocGetDimX, true },
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 051a0fc21760..5a59ef6ac809 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -48,7 +48,7 @@ public class AudioManager {
private final Context mContext;
private final Handler mHandler;
private long mVolumeKeyUpTime;
-
+ private int mVolumeControlStream = -1;
private static String TAG = "AudioManager";
private static boolean DEBUG = false;
private static boolean localLOGV = DEBUG || android.util.Config.LOGV;
@@ -263,6 +263,13 @@ public class AudioManager {
public static final int FLAG_VIBRATE = 1 << 4;
/**
+ * forces use of specified stream
+ * @hide
+ */
+ public static final int FLAG_FORCE_STREAM = 1 << 5;
+
+
+ /**
* Ringer mode that will be silent and will not vibrate. (This overrides the
* vibrate setting.)
*
@@ -392,12 +399,17 @@ public class AudioManager {
* Adjust the volume in on key down since it is more
* responsive to the user.
*/
+ int flags = FLAG_SHOW_UI | FLAG_VIBRATE;
+ if (mVolumeControlStream != -1) {
+ stream = mVolumeControlStream;
+ flags |= FLAG_FORCE_STREAM;
+ }
adjustSuggestedStreamVolume(
keyCode == KeyEvent.KEYCODE_VOLUME_UP
? ADJUST_RAISE
: ADJUST_LOWER,
stream,
- FLAG_SHOW_UI | FLAG_VIBRATE);
+ flags);
break;
case KeyEvent.KEYCODE_VOLUME_MUTE:
// TODO: Actually handle MUTE.
@@ -416,10 +428,15 @@ public class AudioManager {
* Play a sound. This is done on key up since we don't want the
* sound to play when a user holds down volume down to mute.
*/
+ int flags = FLAG_PLAY_SOUND;
+ if (mVolumeControlStream != -1) {
+ stream = mVolumeControlStream;
+ flags |= FLAG_FORCE_STREAM;
+ }
adjustSuggestedStreamVolume(
ADJUST_SAME,
stream,
- FLAG_PLAY_SOUND);
+ flags);
mVolumeKeyUpTime = SystemClock.uptimeMillis();
break;
@@ -683,6 +700,17 @@ public class AudioManager {
}
/**
+ * forces the stream controlled by hard volume keys
+ * specifying streamType == -1 releases control to the
+ * logic.
+ *
+ * @hide
+ */
+ public void forceVolumeControlStream(int streamType) {
+ mVolumeControlStream = streamType;
+ }
+
+ /**
* Returns whether a particular type should vibrate according to user
* settings and the current ringer mode.
* <p>
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index e18220ac0f4b..6c85490bb1c5 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -417,6 +417,9 @@ public class AudioService extends IAudioService.Stub {
(1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)|
(1 << AudioSystem.STREAM_MUSIC)));
+ if (!mVoiceCapable) {
+ mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
+ }
mMuteAffectedStreams = System.getInt(cr,
System.MUTE_STREAMS_AFFECTED,
((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM)));
@@ -461,7 +464,12 @@ public class AudioService extends IAudioService.Stub {
/** @see AudioManager#adjustVolume(int, int, int) */
public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
- int streamType = getActiveStreamType(suggestedStreamType);
+ int streamType;
+ if ((flags & AudioManager.FLAG_FORCE_STREAM) != 0) {
+ streamType = suggestedStreamType;
+ } else {
+ streamType = getActiveStreamType(suggestedStreamType);
+ }
// Don't play sound on other streams
if (streamType != AudioSystem.STREAM_RING && (flags & AudioManager.FLAG_PLAY_SOUND) != 0) {
@@ -1940,7 +1948,7 @@ public class AudioService extends IAudioService.Stub {
// Force creation of new IAudioflinger interface
if (!mMediaServerOk) {
Log.e(TAG, "Media server died.");
- AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0);
+ AudioSystem.isMicrophoneMuted();
sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SHARED_MSG, SENDMSG_NOOP, 0, 0,
null, 500);
}
@@ -2025,6 +2033,10 @@ public class AudioService extends IAudioService.Stub {
int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver,
Settings.System.MODE_RINGER_STREAMS_AFFECTED,
0);
+ if (!mVoiceCapable) {
+ ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
+ }
+
if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
/*
* Ensure all stream types that should be affected by ringer mode
diff --git a/media/java/android/media/videoeditor/MediaProperties.java b/media/java/android/media/videoeditor/MediaProperties.java
index a2e01f6f7817..34186e98de02 100755
--- a/media/java/android/media/videoeditor/MediaProperties.java
+++ b/media/java/android/media/videoeditor/MediaProperties.java
@@ -198,6 +198,11 @@ public class MediaProperties {
public static final int FILE_UNSUPPORTED = 255;
/**
+ * Undefined video codec profiles
+ */
+ public static final int UNDEFINED_VIDEO_PROFILE = 255;
+
+ /**
* The array of the supported file formats
*/
private static final int[] SUPPORTED_VIDEO_FILE_FORMATS = new int[] {
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index bbadd621fab9..d35058496b8b 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -139,6 +139,11 @@ public class MediaVideoItem extends MediaItem {
throw new IllegalArgumentException("Unsupported Video Codec Format in Input File");
}
+ /* Check if the profile is unsupported. */
+ if (properties.profileAndLevel == MediaProperties.UNDEFINED_VIDEO_PROFILE) {
+ throw new IllegalArgumentException("Unsupported Video Codec Profile in Input File");
+ }
+
mWidth = properties.width;
mHeight = properties.height;
mAspectRatio = mMANativeHelper.getAspectRatio(properties.width,
diff --git a/media/jni/mediaeditor/Android.mk b/media/jni/mediaeditor/Android.mk
index 9c21e5e32b72..6a7116ca2505 100755
--- a/media/jni/mediaeditor/Android.mk
+++ b/media/jni/mediaeditor/Android.mk
@@ -66,8 +66,7 @@ LOCAL_CFLAGS += \
-DUSE_STAGEFRIGHT_AUDIOENC \
-DUSE_STAGEFRIGHT_VIDEOENC \
-DUSE_STAGEFRIGHT_READERS \
- -DUSE_STAGEFRIGHT_3GPP_READER \
- -DUSE_SOFTWARE_DECODER
+ -DUSE_STAGEFRIGHT_3GPP_READER
LOCAL_LDFLAGS += -fuse-ld=bfd
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index 76c05d2a16b8..bb326fef461f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -20,11 +20,13 @@ import java.util.ArrayList;
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.LocationManager;
+import android.provider.Settings;
import android.util.Slog;
import android.view.View;
import android.widget.ImageView;
@@ -83,10 +85,15 @@ public class LocationController extends BroadcastReceiver {
try {
if (visible) {
+ Intent gpsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+ gpsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, gpsIntent, 0);
+
Notification n = new Notification.Builder(mContext)
.setSmallIcon(iconId)
.setContentTitle(mContext.getText(textResId))
.setOngoing(true)
+ .setContentIntent(pendingIntent)
.getNotification();
// Notification.Builder will helpfully fill these out for you no matter what you do
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index d144dbacda0d..2efb4449eb90 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -692,7 +692,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean changed = setRotationUncheckedLocked(
WindowManagerPolicy.USE_LAST_ROTATION, 0, false);
if (changed) {
- sendNewConfiguration();
+ mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
}
@@ -11075,7 +11075,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean changed = setRotationUncheckedLocked(
WindowManagerPolicy.USE_LAST_ROTATION, 0, false);
if (changed) {
- sendNewConfiguration();
+ mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
}
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 353580910c4d..f72de127d338 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -32,6 +32,15 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+
+ <activity
+ android:name="MarqueeActivity"
+ android:label="_Marquee">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
<activity
android:name="ShapesActivity"
diff --git a/tests/HwAccelerationTest/res/anim/accelerate_interpolator_2.xml b/tests/HwAccelerationTest/res/anim/accelerate_interpolator_2.xml
new file mode 100644
index 000000000000..e4a8d480a28b
--- /dev/null
+++ b/tests/HwAccelerationTest/res/anim/accelerate_interpolator_2.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<accelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:factor="2.0"/>
diff --git a/tests/HwAccelerationTest/res/anim/slide_off_left.xml b/tests/HwAccelerationTest/res/anim/slide_off_left.xml
new file mode 100644
index 000000000000..f05de3937586
--- /dev/null
+++ b/tests/HwAccelerationTest/res/anim/slide_off_left.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<translate xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fromXDelta="0%"
+ android:toXDelta="-100%"
+ android:interpolator="@anim/accelerate_interpolator_2"
+ android:duration="600"/> \ No newline at end of file
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MarqueeActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MarqueeActivity.java
new file mode 100644
index 000000000000..715cdbb226cb
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MarqueeActivity.java
@@ -0,0 +1,68 @@
+/*
+ * 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 com.android.test.hwui;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class MarqueeActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final LinearLayout linearLayout = new LinearLayout(this);
+ linearLayout.setOrientation(LinearLayout.VERTICAL);
+
+ final TextView text1 = new TextView(this);
+ text1.setText("This is a marquee inside a TextView");
+ text1.setSingleLine(true);
+ text1.setHorizontalFadingEdgeEnabled(true);
+ text1.setEllipsize(TextUtils.TruncateAt.MARQUEE);
+ linearLayout.addView(text1, new LinearLayout.LayoutParams(
+ 100, LinearLayout.LayoutParams.WRAP_CONTENT));
+
+ final TextView text2 = new TextView(this);
+ text2.setText("This is a marquee inside a TextView");
+ text2.setSingleLine(true);
+ text2.setHorizontalFadingEdgeEnabled(true);
+ text2.setEllipsize(TextUtils.TruncateAt.MARQUEE);
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ 100, LinearLayout.LayoutParams.WRAP_CONTENT);
+ linearLayout.addView(text2, params);
+
+ setContentView(linearLayout);
+
+ getWindow().getDecorView().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ text2.setVisibility(View.INVISIBLE);
+ Animation animation = AnimationUtils.loadAnimation(text2.getContext(),
+ R.anim.slide_off_left);
+ animation.setFillEnabled(true);
+ animation.setFillAfter(true);
+ text2.startAnimation(animation);
+ }
+ }, 1000);
+ }
+}
diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk
index 3d4c76a36c60..ca7db8ccd63e 100644
--- a/tools/layoutlib/bridge/Android.mk
+++ b/tools/layoutlib/bridge/Android.mk
@@ -17,6 +17,8 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_JAVA_RESOURCE_DIRS := resources
+
LOCAL_JAVA_LIBRARIES := \
kxml2-2.3.0 \
diff --git a/tools/layoutlib/bridge/resources/bars/action_bar.xml b/tools/layoutlib/bridge/resources/bars/action_bar.xml
new file mode 100644
index 000000000000..cd99a096d07c
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/action_bar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
new file mode 100644
index 000000000000..4bcd2be5cb86
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
new file mode 100644
index 000000000000..cfeba3e5e7f0
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
new file mode 100644
index 000000000000..1d97e0581c59
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 000000000000..c629387c20b8
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
new file mode 100644
index 000000000000..29df90906fcf
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text=" "/>
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml b/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
new file mode 100644
index 000000000000..8a3b87ae48c0
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/resources/bars/title_bar.xml b/tools/layoutlib/bridge/resources/bars/title_bar.xml
new file mode 100644
index 000000000000..29fcc4b40b7f
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/title_bar.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
index 993c30543e32..ee60eb4a002d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
@@ -18,6 +18,9 @@ package android.graphics;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeResources.NinePatchInputStream;
+import com.android.ninepatch.NinePatch;
+import com.android.ninepatch.NinePatchChunk;
import com.android.resources.Density;
import android.content.res.AssetManager;
@@ -438,6 +441,8 @@ public class BitmapFactory {
return null;
}
+ boolean isNinePatch = is instanceof NinePatchInputStream;
+
// we need mark/reset to work properly
if (!is.markSupported()) {
@@ -466,7 +471,29 @@ public class BitmapFactory {
if (opts != null) {
density = Density.getEnum(opts.inDensity);
}
- bm = Bitmap_Delegate.createBitmap(is, true, density);
+
+ if (isNinePatch) {
+ // load the bitmap as a nine patch
+ NinePatch ninePatch = NinePatch.load(is, true /*is9Patch*/, false /*convert*/);
+
+ // get the bitmap and chunk objects.
+ bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/,
+ density);
+ NinePatchChunk chunk = ninePatch.getChunk();
+
+ // put the chunk in the bitmap
+ bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk));
+
+ // read the padding
+ int[] padding = chunk.getPadding();
+ outPadding.left = padding[0];
+ outPadding.top = padding[1];
+ outPadding.right = padding[2];
+ outPadding.bottom = padding[3];
+ } else {
+ // load the bitmap directly.
+ bm = Bitmap_Delegate.createBitmap(is, true, density);
+ }
} catch (IOException e) {
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 93c81d18013d..65f6bedeb818 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -21,7 +21,7 @@ import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
import com.android.ide.common.rendering.api.Capability;
import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderParams;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.android.layoutlib.bridge.android.BridgeAssetManager;
@@ -293,15 +293,15 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
/**
* Starts a layout session by inflating and rendering it. The method returns a
- * {@link ILayoutScene} on which further actions can be taken.
+ * {@link RenderSession} on which further actions can be taken.
*
- * @param params the {@link SceneParams} object with all the information necessary to create
+ * @param params the {@link RenderParams} object with all the information necessary to create
* the scene.
- * @return a new {@link ILayoutScene} object that contains the result of the layout.
+ * @return a new {@link RenderSession} object that contains the result of the layout.
* @since 5
*/
@Override
- public RenderSession createSession(Params params) {
+ public RenderSession createSession(RenderParams params) {
try {
Result lastResult = SUCCESS.createResult();
RenderSessionImpl scene = new RenderSessionImpl(params);
@@ -331,10 +331,6 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
}
}
- /*
- * (non-Javadoc)
- * @see com.android.layoutlib.api.ILayoutLibBridge#clearCaches(java.lang.Object)
- */
@Override
public void clearCaches(Object projectKey) {
if (projectKey != null) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
index 0c6fa20fc977..765fd990483e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
@@ -18,7 +18,7 @@ package com.android.layoutlib.bridge;
import com.android.ide.common.rendering.api.IAnimationListener;
import com.android.ide.common.rendering.api.ILayoutPullParser;
-import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderParams;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.ViewInfo;
@@ -128,7 +128,7 @@ public class BridgeRenderSession extends RenderSession {
boolean isFrameworkAnimation, IAnimationListener listener) {
try {
Bridge.prepareThread();
- mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+ mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
if (mLastResult.isSuccess()) {
mLastResult = mSession.animate(targetObject, animationName, isFrameworkAnimation,
listener);
@@ -150,7 +150,7 @@ public class BridgeRenderSession extends RenderSession {
try {
Bridge.prepareThread();
- mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+ mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
if (mLastResult.isSuccess()) {
mLastResult = mSession.insertChild((ViewGroup) parentView, childXml, index,
listener);
@@ -176,7 +176,7 @@ public class BridgeRenderSession extends RenderSession {
try {
Bridge.prepareThread();
- mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+ mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
if (mLastResult.isSuccess()) {
mLastResult = mSession.moveChild((ViewGroup) parentView, (View) childView, index,
layoutParams, listener);
@@ -197,7 +197,7 @@ public class BridgeRenderSession extends RenderSession {
try {
Bridge.prepareThread();
- mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+ mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
if (mLastResult.isSuccess()) {
mLastResult = mSession.removeChild((View) childView, listener);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
index 5ea0a8df10f9..d31fcc8422d6 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
@@ -22,6 +22,7 @@ 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.impl.ResourceHelper;
+import com.android.ninepatch.NinePatch;
import com.android.resources.ResourceType;
import com.android.util.Pair;
@@ -58,6 +59,18 @@ public final class BridgeResources extends Resources {
private boolean[] mPlatformResourceFlag = new boolean[1];
/**
+ * Simpler wrapper around FileInputStream. This is used when the input stream represent
+ * not a normal bitmap but a nine patch.
+ * This is useful when the InputStream is created in a method but used in another that needs
+ * to know whether this is 9-patch or not, such as BitmapFactory.
+ */
+ public class NinePatchInputStream extends FileInputStream {
+ public NinePatchInputStream(File file) throws FileNotFoundException {
+ super(file);
+ }
+ }
+
+ /**
* This initializes the static field {@link Resources#mSystem} which is used
* by methods who get global resources using {@link Resources#getSystem()}.
* <p/>
@@ -129,7 +142,7 @@ public final class BridgeResources extends Resources {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
- return ResourceHelper.getDrawable(value, mContext, value.isFramework());
+ return ResourceHelper.getDrawable(value, mContext);
}
// id was not found or not resolved. Throw a NotFoundException.
@@ -165,44 +178,9 @@ public final class BridgeResources extends Resources {
ResourceValue resValue = getResourceValue(id, mPlatformResourceFlag);
if (resValue != null) {
- String value = resValue.getValue();
- if (value != null) {
- // first check if the value is a file (xml most likely)
- File f = new File(value);
- if (f.isFile()) {
- try {
- // let the framework inflate the ColorStateList from the XML file, by
- // providing an XmlPullParser
- KXmlParser parser = new KXmlParser();
- parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
- parser.setInput(new FileReader(f));
-
- return ColorStateList.createFromXml(this,
- new BridgeXmlBlockParser(parser, mContext, resValue.isFramework()));
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value, e, null /*data*/);
- // we'll return null below.
- } catch (Exception e) {
- // this is an error and not warning since the file existence is
- // checked before attempting to parse it.
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed to parse file " + value, e, null /*data*/);
-
- return null;
- }
- } else {
- // try to load the color state list from an int
- try {
- int color = ResourceHelper.getColor(value);
- return ColorStateList.valueOf(color);
- } catch (NumberFormatException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
- "Failed to convert " + value + " into a ColorStateList", e,
- null /*data*/);
- return null;
- }
- }
+ ColorStateList stateList = ResourceHelper.getColorStateList(resValue, mContext);
+ if (stateList != null) {
+ return stateList;
}
}
@@ -562,13 +540,19 @@ public final class BridgeResources extends Resources {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
- String v = value.getValue();
+ String path = value.getValue();
- if (v != null) {
+ if (path != null) {
// check this is a file
- File f = new File(value.getValue());
+ File f = new File(path);
if (f.isFile()) {
try {
+ // if it's a nine-patch return a custom input stream so that
+ // other methods (mainly bitmap factory) can detect it's a 9-patch
+ // and actually load it as a 9-patch instead of a normal bitmap
+ if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) {
+ return new NinePatchInputStream(f);
+ }
return new FileInputStream(f);
} catch (FileNotFoundException e) {
NotFoundException newE = new NotFoundException();
@@ -590,9 +574,17 @@ public final class BridgeResources extends Resources {
public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
getValue(id, value, true);
- File f = new File(value.string.toString());
+ String path = value.string.toString();
+
+ File f = new File(path);
if (f.isFile()) {
try {
+ // if it's a nine-patch return a custom input stream so that
+ // other methods (mainly bitmap factory) can detect it's a 9-patch
+ // and actually load it as a 9-patch instead of a normal bitmap
+ if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) {
+ return new NinePatchInputStream(f);
+ }
return new FileInputStream(f);
} catch (FileNotFoundException e) {
NotFoundException exception = new NotFoundException();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index cf2c0ff8947f..c226b8b54f91 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -690,7 +690,7 @@ public final class BridgeTypedArray extends TypedArray {
return null;
}
- return ResourceHelper.getDrawable(value, mContext, mResourceData[index].isFramework());
+ return ResourceHelper.getDrawable(value, mContext);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
new file mode 100644
index 000000000000..f03999405592
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -0,0 +1,212 @@
+/*
+ * 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 com.android.layoutlib.bridge.bars;
+
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.StyleResourceValue;
+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.ResourceHelper;
+import com.android.resources.Density;
+
+import org.kxml2.io.KXmlParser;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap_Delegate;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Base "bar" class for the window decor around the the edited layout.
+ * This is basically an horizontal layout that loads a given layout on creation (it is read
+ * through {@link Class#getResourceAsStream(String)}).
+ *
+ * The given layout should be a merge layout so that all the children belong to this class directly.
+ *
+ * It also provides a few utility methods to configure the content of the layout.
+ */
+abstract class CustomBar extends LinearLayout {
+
+ protected abstract TextView getStyleableTextView();
+
+ protected CustomBar(Context context, Density density, String layoutPath)
+ throws XmlPullParserException {
+ super(context);
+ setOrientation(LinearLayout.HORIZONTAL);
+ setBackgroundColor(0xFF000000);
+
+ LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+
+ KXmlParser parser = new KXmlParser();
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+ parser.setInput(
+ getClass().getResourceAsStream(layoutPath),
+ "UTF8");
+
+ BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
+ parser, (BridgeContext) context, false);
+
+ inflater.inflate(bridgeParser, this, true);
+ }
+
+ protected void loadIcon(int index, String iconName, Density density) {
+ View child = getChildAt(index);
+ if (child instanceof ImageView) {
+ ImageView imageView = (ImageView) child;
+
+ // bitmap url relative to this class
+ String path = "/bars/" + density.getResourceValue() + "/" + iconName;
+
+ // create a bitmap
+ Bitmap bitmap = Bridge.getCachedBitmap(path, true /*isFramework*/);
+
+ if (bitmap == null) {
+ InputStream stream = getClass().getResourceAsStream(path);
+
+ if (stream != null) {
+ try {
+ bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density);
+ Bridge.setCachedBitmap(path, bitmap, true /*isFramework*/);
+ } catch (IOException e) {
+ return;
+ }
+ }
+ }
+
+ if (bitmap != null) {
+ BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), bitmap);
+ imageView.setBackgroundDrawable(drawable);
+ }
+ }
+ }
+
+ protected void loadIcon(int index, String iconReference) {
+ ResourceValue value = getResourceValue(iconReference);
+ if (value != null) {
+ View child = getChildAt(index);
+ if (child instanceof ImageView) {
+ ImageView imageView = (ImageView) child;
+
+ Drawable drawable = ResourceHelper.getDrawable(
+ value, (BridgeContext) mContext);
+ if (drawable != null) {
+ imageView.setBackgroundDrawable(drawable);
+ }
+ }
+ }
+ }
+
+ protected TextView setText(int index, String stringReference) {
+ View child = getChildAt(index);
+ if (child instanceof TextView) {
+ TextView textView = (TextView) child;
+ ResourceValue value = getResourceValue(stringReference);
+ if (value != null) {
+ textView.setText(value.getValue());
+ } else {
+ textView.setText(stringReference);
+ }
+ return textView;
+ }
+
+ return null;
+ }
+
+ protected void setStyle(String themeEntryName) {
+
+ BridgeContext bridgeContext = (BridgeContext) mContext;
+ RenderResources res = bridgeContext.getRenderResources();
+
+ ResourceValue value = res.findItemInTheme(themeEntryName);
+ value = res.resolveResValue(value);
+
+ if (value instanceof StyleResourceValue == false) {
+ return;
+ }
+
+ StyleResourceValue style = (StyleResourceValue) value;
+
+ // get the background
+ ResourceValue backgroundValue = res.findItemInStyle(style, "background");
+ backgroundValue = res.resolveResValue(backgroundValue);
+ if (backgroundValue != null) {
+ Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext);
+ if (d != null) {
+ setBackgroundDrawable(d);
+ }
+ }
+
+ TextView textView = getStyleableTextView();
+ if (textView != null) {
+ // get the text style
+ ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle");
+ textStyleValue = res.resolveResValue(textStyleValue);
+ if (textStyleValue instanceof StyleResourceValue) {
+ StyleResourceValue textStyle = (StyleResourceValue) textStyleValue;
+
+ ResourceValue textSize = res.findItemInStyle(textStyle, "textSize");
+ textSize = res.resolveResValue(textSize);
+
+ if (textSize != null) {
+ TypedValue out = new TypedValue();
+ if (ResourceHelper.stringToFloat(textSize.getValue(), out)) {
+ textView.setTextSize(
+ out.getDimension(bridgeContext.getResources().mMetrics));
+ }
+ }
+
+
+ ResourceValue textColor = res.findItemInStyle(textStyle, "textColor");
+ textColor = res.resolveResValue(textColor);
+ if (textColor != null) {
+ ColorStateList stateList = ResourceHelper.getColorStateList(
+ textColor, bridgeContext);
+ if (stateList != null) {
+ textView.setTextColor(stateList);
+ }
+ }
+ }
+ }
+ }
+
+ private ResourceValue getResourceValue(String reference) {
+ BridgeContext bridgeContext = (BridgeContext) mContext;
+ RenderResources res = bridgeContext.getRenderResources();
+
+ // find the resource
+ ResourceValue value = res.findResValue(reference, false /*isFramework*/);
+
+ // resolve it if needed
+ return res.resolveResValue(value);
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
new file mode 100644
index 000000000000..3af4e3ada18b
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
@@ -0,0 +1,47 @@
+/*
+ * 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 com.android.layoutlib.bridge.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class FakeActionBar extends CustomBar {
+
+ private TextView mTextView;
+
+ public FakeActionBar(Context context, Density density, String label, String icon)
+ throws XmlPullParserException {
+ super(context, density, "/bars/action_bar.xml");
+
+ // Cannot access the inside items through id because no R.id values have been
+ // created for them.
+ // We do know the order though.
+ loadIcon(0, icon);
+ mTextView = setText(1, label);
+
+ setStyle("actionBarStyle");
+ }
+
+ @Override
+ protected TextView getStyleableTextView() {
+ return mTextView;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
new file mode 100644
index 000000000000..92615dc260d5
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
@@ -0,0 +1,42 @@
+/*
+ * 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 com.android.layoutlib.bridge.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class PhoneSystemBar extends CustomBar {
+
+ public PhoneSystemBar(Context context, Density density) throws XmlPullParserException {
+ super(context, density, "/bars/tablet_system_bar.xml");
+
+ // Cannot access the inside items through id because no R.id values have been
+ // created for them.
+ // We do know the order though.
+ // 0 is the spacer
+ loadIcon(1, "stat_sys_wifi_signal_4_fully.png", density);
+ }
+
+ @Override
+ protected TextView getStyleableTextView() {
+ return null;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
new file mode 100644
index 000000000000..bc61799b3bd2
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
@@ -0,0 +1,45 @@
+/*
+ * 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 com.android.layoutlib.bridge.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class TabletSystemBar extends CustomBar {
+
+ public TabletSystemBar(Context context, Density density) throws XmlPullParserException {
+ super(context, density, "/bars/tablet_system_bar.xml");
+
+ // Cannot access the inside items through id because no R.id values have been
+ // created for them.
+ // We do know the order though.
+ loadIcon(0, "ic_sysbar_back_default.png", density);
+ loadIcon(1, "ic_sysbar_home_default.png", density);
+ loadIcon(2, "ic_sysbar_recent_default.png", density);
+ // 3 is the spacer
+ loadIcon(4, "stat_sys_wifi_signal_4_fully.png", density);
+ }
+
+ @Override
+ protected TextView getStyleableTextView() {
+ return null;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
new file mode 100644
index 000000000000..d7401d960128
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
@@ -0,0 +1,46 @@
+/*
+ * 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 com.android.layoutlib.bridge.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class TitleBar extends CustomBar {
+
+ private TextView mTextView;
+
+ public TitleBar(Context context, Density density, String label)
+ throws XmlPullParserException {
+ super(context, density, "/bars/title_bar.xml");
+
+ // Cannot access the inside items through id because no R.id values have been
+ // created for them.
+ // We do know the order though.
+ mTextView = setText(0, label);
+
+ setStyle("windowTitleBackgroundStyle");
+ }
+
+ @Override
+ protected TextView getStyleableTextView() {
+ return mTextView;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index c8ad1d6c968a..0aa2e6d4ea56 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -29,14 +29,13 @@ import com.android.ide.common.rendering.api.IAnimationListener;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderParams;
import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.StyleResourceValue;
import com.android.ide.common.rendering.api.ViewInfo;
-import com.android.ide.common.rendering.api.Params.RenderingMode;
+import com.android.ide.common.rendering.api.RenderParams.RenderingMode;
import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider;
import com.android.ide.common.rendering.api.Result.Status;
import com.android.internal.util.XmlUtils;
@@ -47,11 +46,16 @@ import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
import com.android.layoutlib.bridge.android.BridgeWindow;
import com.android.layoutlib.bridge.android.BridgeWindowSession;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.resources.Density;
+import com.android.layoutlib.bridge.bars.FakeActionBar;
+import com.android.layoutlib.bridge.bars.PhoneSystemBar;
+import com.android.layoutlib.bridge.bars.TabletSystemBar;
+import com.android.layoutlib.bridge.bars.TitleBar;
import com.android.resources.ResourceType;
import com.android.resources.ScreenSize;
import com.android.util.Pair;
+import org.xmlpull.v1.XmlPullParserException;
+
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.LayoutTransition;
@@ -105,7 +109,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
*/
private static BridgeContext sCurrentContext = null;
- private final Params mParams;
+ private final RenderParams mParams;
// scene state
private RenderSession mScene;
@@ -113,17 +117,18 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
private BridgeXmlBlockParser mBlockParser;
private BridgeInflater mInflater;
private ResourceValue mWindowBackground;
- private FrameLayout mViewRoot;
+ private ViewGroup mViewRoot;
+ private FrameLayout mContentRoot;
private Canvas mCanvas;
private int mMeasuredScreenWidth = -1;
private int mMeasuredScreenHeight = -1;
- private boolean mIsAlphaChannelImage = true;
+ private boolean mIsAlphaChannelImage;
+ private boolean mWindowIsFloating;
private int mStatusBarSize;
- private int mTopBarSize;
private int mSystemBarSize;
- private int mTopOffset;
- private int mTotalBarSize;
+ private int mTitleBarSize;
+ private int mActionBarSize;
// information being returned through the API
@@ -146,9 +151,9 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
*
* @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
*/
- public RenderSessionImpl(Params params) {
+ public RenderSessionImpl(RenderParams params) {
// copy the params.
- mParams = new Params(params);
+ mParams = new RenderParams(params);
}
/**
@@ -172,8 +177,8 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
// setup the display Metrics.
DisplayMetrics metrics = new DisplayMetrics();
- metrics.densityDpi = mParams.getDensity();
- metrics.density = mParams.getDensity() / (float) DisplayMetrics.DENSITY_DEFAULT;
+ metrics.densityDpi = mParams.getDensity().getDpiValue();
+ metrics.density = metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
metrics.scaledDensity = metrics.density;
metrics.widthPixels = mParams.getScreenWidth();
metrics.heightPixels = mParams.getScreenHeight();
@@ -190,17 +195,16 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
mIsAlphaChannelImage = getBooleanThemeValue(resources,
"windowIsFloating", true /*defaultValue*/);
+ mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating",
+ true /*defaultValue*/);
setUp();
findBackground(resources);
findStatusBar(resources, metrics);
- findTopBar(resources, metrics);
+ findActionBar(resources, metrics);
findSystemBar(resources, metrics);
- mTopOffset = mStatusBarSize + mTopBarSize;
- mTotalBarSize = mTopOffset + mSystemBarSize;
-
// build the inflater and parser.
mInflater = new BridgeInflater(mContext, mParams.getProjectCallback());
mContext.setBridgeInflater(mInflater);
@@ -353,13 +357,100 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
try {
- mViewRoot = new FrameLayout(mContext);
+ if (mWindowIsFloating || mParams.isForceNoDecor()) {
+ mViewRoot = mContentRoot = new FrameLayout(mContext);
+ } else {
+ /*
+ * we're creating the following layout
+ *
+ +-------------------------------------------------+
+ | System bar (only in phone UI) |
+ +-------------------------------------------------+
+ | Title/Action bar (optional) |
+ +-------------------------------------------------+
+ | Content, vertical extending |
+ | |
+ +-------------------------------------------------+
+ | System bar (only in tablet UI) |
+ +-------------------------------------------------+
+
+ */
+
+ LinearLayout topLayout = new LinearLayout(mContext);
+ mViewRoot = topLayout;
+ topLayout.setOrientation(LinearLayout.VERTICAL);
+
+ if (mStatusBarSize > 0) {
+ // system bar
+ try {
+ PhoneSystemBar systemBar = new PhoneSystemBar(mContext,
+ mParams.getDensity());
+ systemBar.setLayoutParams(
+ new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, mStatusBarSize));
+ topLayout.addView(systemBar);
+ } catch (XmlPullParserException e) {
+
+ }
+ }
+
+ // if the theme says no title/action bar, then the size will be 0
+ if (mActionBarSize > 0) {
+ try {
+ FakeActionBar actionBar = new FakeActionBar(mContext,
+ mParams.getDensity(),
+ mParams.getAppLabel(), mParams.getAppIcon());
+ actionBar.setLayoutParams(
+ new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, mActionBarSize));
+ topLayout.addView(actionBar);
+ } catch (XmlPullParserException e) {
+
+ }
+ } else if (mTitleBarSize > 0) {
+ try {
+ TitleBar titleBar = new TitleBar(mContext,
+ mParams.getDensity(), mParams.getAppLabel());
+ titleBar.setLayoutParams(
+ new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, mTitleBarSize));
+ topLayout.addView(titleBar);
+ } catch (XmlPullParserException e) {
+
+ }
+ }
+
+
+ // content frame
+ mContentRoot = new FrameLayout(mContext);
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ params.weight = 1;
+ mContentRoot.setLayoutParams(params);
+ topLayout.addView(mContentRoot);
+
+ if (mSystemBarSize > 0) {
+ // system bar
+ try {
+ TabletSystemBar systemBar = new TabletSystemBar(mContext,
+ mParams.getDensity());
+ systemBar.setLayoutParams(
+ new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, mSystemBarSize));
+ topLayout.addView(systemBar);
+ } catch (XmlPullParserException e) {
+
+ }
+ }
+
+ }
+
// Sets the project callback (custom view loader) to the fragment delegate so that
// it can instantiate the custom Fragment.
Fragment_Delegate.setProjectCallback(mParams.getProjectCallback());
- View view = mInflater.inflate(mBlockParser, mViewRoot);
+ View view = mInflater.inflate(mBlockParser, mContentRoot);
Fragment_Delegate.setProjectCallback(null);
@@ -377,9 +468,8 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
// get the background drawable
if (mWindowBackground != null) {
- Drawable d = ResourceHelper.getDrawable(mWindowBackground,
- mContext, true /* isFramework */);
- mViewRoot.setBackgroundDrawable(d);
+ Drawable d = ResourceHelper.getDrawable(mWindowBackground, mContext);
+ mContentRoot.setBackgroundDrawable(d);
}
return SUCCESS.createResult();
@@ -408,8 +498,8 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
- * @see SceneParams#getRenderingMode()
- * @see LayoutScene#render(long)
+ * @see RenderParams#getRenderingMode()
+ * @see RenderSession#render(long)
*/
public Result render(boolean freshRender) {
checkLock();
@@ -428,7 +518,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
if (mMeasuredScreenWidth == -1) {
newRenderSize = true;
mMeasuredScreenWidth = mParams.getScreenWidth();
- mMeasuredScreenHeight = mParams.getScreenHeight() - mTotalBarSize;
+ mMeasuredScreenHeight = mParams.getScreenHeight();
if (renderingMode != RenderingMode.NORMAL) {
// measure the full size needed by the layout.
@@ -476,11 +566,11 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
if (mParams.getImageFactory() != null) {
mImage = mParams.getImageFactory().getImage(
mMeasuredScreenWidth,
- mMeasuredScreenHeight + mTotalBarSize);
+ mMeasuredScreenHeight);
} else {
mImage = new BufferedImage(
mMeasuredScreenWidth,
- mMeasuredScreenHeight + mTotalBarSize,
+ mMeasuredScreenHeight,
BufferedImage.TYPE_INT_ARGB);
newImage = true;
}
@@ -491,46 +581,26 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
Graphics2D gc = mImage.createGraphics();
gc.setColor(new Color(mParams.getOverrideBgColor(), true));
gc.setComposite(AlphaComposite.Src);
- gc.fillRect(0, 0, mMeasuredScreenWidth,
- mMeasuredScreenHeight + mTotalBarSize);
+ gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
gc.dispose();
}
// create an Android bitmap around the BufferedImage
Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
- true /*isMutable*/,
- Density.getEnum(mParams.getDensity()));
+ true /*isMutable*/, mParams.getDensity());
// create a Canvas around the Android bitmap
mCanvas = new Canvas(bitmap);
- mCanvas.setDensity(mParams.getDensity());
- mCanvas.translate(0, mTopOffset);
+ mCanvas.setDensity(mParams.getDensity().getDpiValue());
}
if (freshRender && newImage == false) {
Graphics2D gc = mImage.createGraphics();
gc.setComposite(AlphaComposite.Src);
- if (mStatusBarSize > 0) {
- gc.setColor(new Color(0xFF3C3C3C, true));
- gc.fillRect(0, 0, mMeasuredScreenWidth, mStatusBarSize);
- }
-
- if (mTopBarSize > 0) {
- gc.setColor(new Color(0xFF7F7F7F, true));
- gc.fillRect(0, mStatusBarSize, mMeasuredScreenWidth, mTopOffset);
- }
-
- // erase the rest
gc.setColor(new Color(0x00000000, true));
- gc.fillRect(0, mTopOffset,
- mMeasuredScreenWidth, mMeasuredScreenHeight + mTopOffset);
-
- if (mSystemBarSize > 0) {
- gc.setColor(new Color(0xFF3C3C3C, true));
- gc.fillRect(0, mMeasuredScreenHeight + mTopOffset,
- mMeasuredScreenWidth, mMeasuredScreenHeight + mTotalBarSize);
- }
+ gc.fillRect(0, 0,
+ mMeasuredScreenWidth, mMeasuredScreenHeight);
// done
gc.dispose();
@@ -538,7 +608,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
mViewRoot.draw(mCanvas);
- mViewInfoList = visitAllChildren((ViewGroup)mViewRoot, mContext, mTopOffset);
+ mViewInfoList = startVisitingViews(mViewRoot, 0);
// success!
return SUCCESS.createResult();
@@ -561,7 +631,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
- * @see LayoutScene#animate(Object, String, boolean, IAnimationListener)
+ * @see RenderSession#animate(Object, String, boolean, IAnimationListener)
*/
public Result animate(Object targetObject, String animationName,
boolean isFrameworkAnimation, IAnimationListener listener) {
@@ -617,7 +687,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
- * @see LayoutScene#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
+ * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
*/
public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
final int index, IAnimationListener listener) {
@@ -696,7 +766,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
- * @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener)
+ * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener)
*/
public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
Map<String, String> layoutParamsMap, final IAnimationListener listener) {
@@ -892,7 +962,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
- * @see LayoutScene#removeChild(Object, IAnimationListener)
+ * @see RenderSession#removeChild(Object, IAnimationListener)
*/
public Result removeChild(final View childView, IAnimationListener listener) {
checkLock();
@@ -989,40 +1059,12 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
return mParams.getConfigScreenSize() == ScreenSize.XLARGE;
}
- private boolean isHCApp() {
- RenderResources resources = mContext.getRenderResources();
-
- // the app must say it targets 11+ and the theme name must extend Theme.Holo or
- // Theme.Holo.Light (which does not extend Theme.Holo, but Theme.Light)
- if (mParams.getTargetSdkVersion() < 11) {
- return false;
- }
-
- StyleResourceValue currentTheme = resources.getCurrentTheme();
- StyleResourceValue holoTheme = resources.getTheme("Theme.Holo", true /*frameworkTheme*/);
-
- if (currentTheme == holoTheme ||
- resources.themeIsParentOf(holoTheme, currentTheme)) {
- return true;
- }
-
- StyleResourceValue holoLightTheme = resources.getTheme("Theme.Holo.Light",
- true /*frameworkTheme*/);
-
- if (currentTheme == holoLightTheme ||
- resources.themeIsParentOf(holoLightTheme, currentTheme)) {
- return true;
- }
-
- return false;
- }
-
private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
if (isTabletUi() == false) {
boolean windowFullscreen = getBooleanThemeValue(resources,
"windowFullscreen", false /*defaultValue*/);
- if (windowFullscreen == false) {
+ if (windowFullscreen == false && mWindowIsFloating == false) {
// default value
mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
@@ -1041,20 +1083,11 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
}
}
- private void findTopBar(RenderResources resources, DisplayMetrics metrics) {
- boolean windowIsFloating = getBooleanThemeValue(resources,
- "windowIsFloating", true /*defaultValue*/);
-
- if (windowIsFloating == false) {
- if (isHCApp()) {
- findActionBar(resources, metrics);
- } else {
- findTitleBar(resources, metrics);
- }
+ private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
+ if (mWindowIsFloating) {
+ return;
}
- }
- private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
boolean windowActionBar = getBooleanThemeValue(resources,
"windowActionBar", true /*defaultValue*/);
@@ -1062,7 +1095,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
if (windowActionBar) {
// default size of the window title bar
- mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT;
+ mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
// get value from the theme.
ResourceValue value = resources.findItemInTheme("actionBarSize");
@@ -1075,44 +1108,43 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
if (typedValue != null) {
// compute the pixel value based on the display metrics
- mTopBarSize = (int)typedValue.getDimension(metrics);
+ mActionBarSize = (int)typedValue.getDimension(metrics);
}
}
- }
- }
-
- private void findTitleBar(RenderResources resources, DisplayMetrics metrics) {
- boolean windowNoTitle = getBooleanThemeValue(resources,
- "windowNoTitle", false /*defaultValue*/);
+ } else {
+ // action bar overrides title bar so only look for this one if action bar is hidden
+ boolean windowNoTitle = getBooleanThemeValue(resources,
+ "windowNoTitle", false /*defaultValue*/);
- if (windowNoTitle == false) {
+ if (windowNoTitle == false) {
- // default size of the window title bar
- mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT;
+ // default size of the window title bar
+ mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
- // get value from the theme.
- ResourceValue value = resources.findItemInTheme("windowTitleSize");
+ // get value from the theme.
+ ResourceValue value = resources.findItemInTheme("windowTitleSize");
- // resolve it
- value = resources.resolveResValue(value);
+ // resolve it
+ value = resources.resolveResValue(value);
- if (value != null) {
- // get the numerical value, if available
- TypedValue typedValue = ResourceHelper.getValue(value.getValue());
- if (typedValue != null) {
- // compute the pixel value based on the display metrics
- mTopBarSize = (int)typedValue.getDimension(metrics);
+ if (value != null) {
+ // get the numerical value, if available
+ TypedValue typedValue = ResourceHelper.getValue(value.getValue());
+ if (typedValue != null) {
+ // compute the pixel value based on the display metrics
+ mTitleBarSize = (int)typedValue.getDimension(metrics);
+ }
}
}
+
}
}
private void findSystemBar(RenderResources resources, DisplayMetrics metrics) {
- if (isTabletUi() && getBooleanThemeValue(
- resources, "windowIsFloating", true /*defaultValue*/) == false) {
+ if (isTabletUi() && mWindowIsFloating == false) {
// default value
- mSystemBarSize = 56; // ??
+ mSystemBarSize = 48; // ??
// get the real value
ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
@@ -1244,40 +1276,71 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
}
}
+ private List<ViewInfo> startVisitingViews(View view, int offset) {
+ if (view == null) {
+ return null;
+ }
+
+ // adjust the offset to this view.
+ offset += view.getTop();
+
+ if (view == mContentRoot) {
+ return visitAllChildren(mContentRoot, offset);
+ }
+
+ // otherwise, look for mContentRoot in the children
+ if (view instanceof ViewGroup) {
+ ViewGroup group = ((ViewGroup) view);
+
+ for (int i = 0; i < group.getChildCount(); i++) {
+ List<ViewInfo> list = startVisitingViews(group.getChildAt(i), offset);
+ if (list != null) {
+ return list;
+ }
+ }
+ }
+
+ return null;
+ }
/**
* Visits a View and its children and generate a {@link ViewInfo} containing the
* bounds of all the views.
* @param view the root View
- * @param context the context.
+ * @param offset an offset for the view bounds.
*/
- private ViewInfo visit(View view, BridgeContext context, int offset) {
+ private ViewInfo visit(View view, int offset) {
if (view == null) {
return null;
}
ViewInfo result = new ViewInfo(view.getClass().getName(),
- context.getViewKey(view),
+ mContext.getViewKey(view),
view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset,
view, view.getLayoutParams());
if (view instanceof ViewGroup) {
ViewGroup group = ((ViewGroup) view);
- result.setChildren(visitAllChildren(group, context, 0 /*offset*/));
+ result.setChildren(visitAllChildren(group, 0 /*offset*/));
}
return result;
}
- private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, BridgeContext context,
- int offset) {
+ /**
+ * Visits all the children of a given ViewGroup generate a list of {@link ViewInfo}
+ * containing the bounds of all the views.
+ * @param view the root View
+ * @param offset an offset for the view bounds.
+ */
+ private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset) {
if (viewGroup == null) {
return null;
}
List<ViewInfo> children = new ArrayList<ViewInfo>();
for (int i = 0; i < viewGroup.getChildCount(); i++) {
- children.add(visit(viewGroup.getChildAt(i), context, offset));
+ children.add(visit(viewGroup.getChildAt(i), offset));
}
return children;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 25bb81c43735..cea7cf360ce2 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -18,6 +18,7 @@ package com.android.layoutlib.bridge.impl;
import com.android.ide.common.rendering.api.DensityBasedResourceValue;
import com.android.ide.common.rendering.api.LayoutLog;
+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.android.BridgeContext;
@@ -28,7 +29,9 @@ import com.android.resources.Density;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
import android.graphics.NinePatch_Delegate;
@@ -108,19 +111,63 @@ public final class ResourceHelper {
throw new NumberFormatException();
}
+ public static ColorStateList getColorStateList(ResourceValue resValue, BridgeContext context) {
+ String value = resValue.getValue();
+ if (value != null) {
+ // first check if the value is a file (xml most likely)
+ File f = new File(value);
+ if (f.isFile()) {
+ try {
+ // let the framework inflate the ColorStateList from the XML file, by
+ // providing an XmlPullParser
+ KXmlParser parser = new KXmlParser();
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+ parser.setInput(new FileReader(f));
+
+ return ColorStateList.createFromXml(context.getResources(),
+ new BridgeXmlBlockParser(parser, context, resValue.isFramework()));
+ } catch (XmlPullParserException e) {
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "Failed to configure parser for " + value, e, null /*data*/);
+ // we'll return null below.
+ } catch (Exception e) {
+ // this is an error and not warning since the file existence is
+ // checked before attempting to parse it.
+ Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
+ "Failed to parse file " + value, e, null /*data*/);
+
+ return null;
+ }
+ } else {
+ // try to load the color state list from an int
+ try {
+ int color = ResourceHelper.getColor(value);
+ return ColorStateList.valueOf(color);
+ } catch (NumberFormatException e) {
+ Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
+ "Failed to convert " + value + " into a ColorStateList", e,
+ null /*data*/);
+ return null;
+ }
+ }
+ }
+
+ return null;
+ }
+
/**
* Returns a drawable from the given value.
* @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable,
* or an hexadecimal color
- * @param context
- * @param isFramework indicates whether the resource is a framework resources.
- * Framework resources are cached, and loaded only once.
+ * @param context the current context
*/
- public static Drawable getDrawable(ResourceValue value, BridgeContext context,
- boolean isFramework) {
+ public static Drawable getDrawable(ResourceValue value, BridgeContext context) {
Drawable d = null;
String stringValue = value.getValue();
+ if (RenderResources.REFERENCE_NULL.equals(stringValue)) {
+ return null;
+ }
String lowerCaseValue = stringValue.toLowerCase();
@@ -129,9 +176,9 @@ public final class ResourceHelper {
if (file.isFile()) {
// see if we still have both the chunk and the bitmap in the caches
NinePatchChunk chunk = Bridge.getCached9Patch(stringValue,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
Bitmap bitmap = Bridge.getCachedBitmap(stringValue,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
// if either chunk or bitmap is null, then we reload the 9-patch file.
if (chunk == null || bitmap == null) {
@@ -143,7 +190,7 @@ public final class ResourceHelper {
chunk = ninePatch.getChunk();
Bridge.setCached9Patch(stringValue, chunk,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
}
if (bitmap == null) {
@@ -158,7 +205,7 @@ public final class ResourceHelper {
density);
Bridge.setCachedBitmap(stringValue, bitmap,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
}
}
} catch (MalformedURLException e) {
@@ -192,7 +239,7 @@ public final class ResourceHelper {
parser.setInput(new FileReader(f));
d = Drawable.createFromXml(context.getResources(),
- new BridgeXmlBlockParser(parser, context, isFramework));
+ new BridgeXmlBlockParser(parser, context, value.isFramework()));
return d;
} catch (Exception e) {
// this is an error and not warning since the file existence is checked before
@@ -212,7 +259,7 @@ public final class ResourceHelper {
if (bmpFile.isFile()) {
try {
Bitmap bitmap = Bridge.getCachedBitmap(stringValue,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
if (bitmap == null) {
Density density = Density.MEDIUM;
@@ -223,7 +270,7 @@ public final class ResourceHelper {
bitmap = Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/,
density);
Bridge.setCachedBitmap(stringValue, bitmap,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
}
return new BitmapDrawable(context.getResources(), bitmap);