diff options
40 files changed, 303 insertions, 107 deletions
diff --git a/api/current.xml b/api/current.xml index 504dab4..bf5c8a0 100644 --- a/api/current.xml +++ b/api/current.xml @@ -1949,7 +1949,7 @@ type="int" transient="false" volatile="false" - value="16843554" + value="16843555" static="true" final="true" deprecated="not deprecated" @@ -1960,7 +1960,7 @@ type="int" transient="false" volatile="false" - value="16843553" + value="16843554" static="true" final="true" deprecated="not deprecated" @@ -1971,7 +1971,7 @@ type="int" transient="false" volatile="false" - value="16843555" + value="16843556" static="true" final="true" deprecated="not deprecated" @@ -9396,7 +9396,7 @@ type="int" transient="false" volatile="false" - value="16843557" + value="16843558" static="true" final="true" deprecated="not deprecated" @@ -9407,7 +9407,7 @@ type="int" transient="false" volatile="false" - value="16843556" + value="16843557" static="true" final="true" deprecated="not deprecated" @@ -9898,6 +9898,17 @@ visibility="public" > </field> +<field name="useIntrinsicSizeAsMinimum" + type="int" + transient="false" + volatile="false" + value="16843553" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="useLevel" type="int" transient="false" @@ -246052,7 +246063,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="t" type="T"> +<parameter name="arg0" type="T"> </parameter> </method> </interface> diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java index 65adef9..ff769ad 100644 --- a/core/java/android/provider/Downloads.java +++ b/core/java/android/provider/Downloads.java @@ -375,6 +375,13 @@ public final class Downloads { */ public static final String COLUMN_MEDIA_SCANNED = "scanned"; + /** + * The column with errorMsg for a failed downloaded. + * Used only for debugging purposes. + * <P>Type: TEXT</P> + */ + public static final String COLUMN_ERROR_MSG = "errorMsg"; + /* * Lists the destinations that an application can specify for a download. */ diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java index ec8f031..01a6b94 100644 --- a/core/java/android/server/BluetoothService.java +++ b/core/java/android/server/BluetoothService.java @@ -2508,44 +2508,42 @@ public class BluetoothService extends IBluetooth.Stub { // dump pw.println("\n--Headset Service--"); if (mBluetoothHeadset != null) { - List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices(); - if (deviceList.size() == 0) { - pw.println("\n--No headsets connected--"); - } - BluetoothDevice device = deviceList.get(0); - - switch (mBluetoothHeadset.getConnectionState(device)) { - case BluetoothHeadset.STATE_DISCONNECTED: - pw.println("getConnectionState() = STATE_DISCONNECTED"); - break; - case BluetoothHeadset.STATE_CONNECTING: - pw.println("getConnectionState() = STATE_CONNECTING"); - break; - case BluetoothHeadset.STATE_CONNECTED: - pw.println("getConnectionState() = STATE_CONNECTED"); - break; - case BluetoothHeadset.STATE_DISCONNECTING: - pw.println("getConnectionState() = STATE_DISCONNECTING"); - break; - case BluetoothHeadset.STATE_AUDIO_CONNECTED: - pw.println("getConnectionState() = STATE_AUDIO_CONNECTED"); - break; + List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices(); + if (deviceList.size() == 0) { + pw.println("\n--No headsets connected--"); + } else { + BluetoothDevice device = deviceList.get(0); + pw.println("\ngetConnectedDevices[0] = " + device); + + switch (mBluetoothHeadset.getConnectionState(device)) { + case BluetoothHeadset.STATE_CONNECTING: + pw.println("getConnectionState() = STATE_CONNECTING"); + break; + case BluetoothHeadset.STATE_CONNECTED: + pw.println("getConnectionState() = STATE_CONNECTED"); + break; + case BluetoothHeadset.STATE_DISCONNECTING: + pw.println("getConnectionState() = STATE_DISCONNECTING"); + break; + case BluetoothHeadset.STATE_AUDIO_CONNECTED: + pw.println("getConnectionState() = STATE_AUDIO_CONNECTED"); + break; + } + pw.println("getBatteryUsageHint() = " + + mBluetoothHeadset.getBatteryUsageHint(device)); } deviceList.clear(); deviceList = mBluetoothHeadset.getDevicesMatchingConnectionStates(new int[] { BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED}); pw.println("\n--Connected and Disconnected Headsets"); - for (BluetoothDevice dev: deviceList) { + for (BluetoothDevice device: deviceList) { pw.println(device); if (mBluetoothHeadset.isAudioConnected(device)) { pw.println("SCO audio connected to device:" + device); } } - pw.println("\ngetCurrentHeadset() = " + device); - pw.println("getBatteryUsageHint() = " + - mBluetoothHeadset.getBatteryUsageHint(device)); mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); } diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp index abe33f4..90c4dd4 100644 --- a/core/jni/android/graphics/Path.cpp +++ b/core/jni/android/graphics/Path.cpp @@ -36,7 +36,7 @@ public: static void finalizer(JNIEnv* env, jobject clazz, SkPath* obj) { #ifdef USE_OPENGL_RENDERER if (android::uirenderer::Caches::hasInstance()) { - android::uirenderer::Caches::getInstance().pathCache.remove(obj); + android::uirenderer::Caches::getInstance().pathCache.removeDeferred(obj); } #endif delete obj; diff --git a/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png Binary files differnew file mode 100644 index 0000000..192df6d --- /dev/null +++ b/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png b/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png Binary files differnew file mode 100644 index 0000000..223416d --- /dev/null +++ b/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png Binary files differnew file mode 100644 index 0000000..1a59124 --- /dev/null +++ b/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png b/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png Binary files differnew file mode 100644 index 0000000..f119c6a --- /dev/null +++ b/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png diff --git a/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png Binary files differnew file mode 100644 index 0000000..3c6c5ed --- /dev/null +++ b/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png b/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png Binary files differnew file mode 100644 index 0000000..cab3888 --- /dev/null +++ b/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png Binary files differnew file mode 100644 index 0000000..316af64 --- /dev/null +++ b/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png b/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png Binary files differnew file mode 100644 index 0000000..e286136 --- /dev/null +++ b/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png Binary files differnew file mode 100644 index 0000000..0502669 --- /dev/null +++ b/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png b/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png Binary files differnew file mode 100644 index 0000000..1ba9e34 --- /dev/null +++ b/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png Binary files differnew file mode 100644 index 0000000..a2fe2b3 --- /dev/null +++ b/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png b/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png Binary files differnew file mode 100644 index 0000000..3b264ab --- /dev/null +++ b/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png diff --git a/core/res/res/drawable/progress_horizontal_holo_dark.xml b/core/res/res/drawable/progress_horizontal_holo_dark.xml new file mode 100644 index 0000000..ff270b3 --- /dev/null +++ b/core/res/res/drawable/progress_horizontal_holo_dark.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + + <item android:id="@android:id/background" + android:drawable="@android:drawable/progress_bg_holo_dark" /> + + <item android:id="@android:id/secondaryProgress"> + <scale android:scaleWidth="100%" + android:drawable="@android:drawable/progress_secondary_holo_dark" /> + </item> + + <item android:id="@android:id/progress"> + <scale android:scaleWidth="100%" + android:drawable="@android:drawable/progress_primary_holo_dark" /> + </item> + +</layer-list> diff --git a/core/res/res/drawable/progress_horizontal_holo_light.xml b/core/res/res/drawable/progress_horizontal_holo_light.xml new file mode 100644 index 0000000..4935185 --- /dev/null +++ b/core/res/res/drawable/progress_horizontal_holo_light.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + + <item android:id="@android:id/background" + android:drawable="@android:drawable/progress_bg_holo_light" /> + + <item android:id="@android:id/secondaryProgress"> + <scale android:scaleWidth="100%" + android:drawable="@android:drawable/progress_secondary_holo_light" /> + </item> + + <item android:id="@android:id/progress"> + <scale android:scaleWidth="100%" + android:drawable="@android:drawable/progress_primary_holo_light" /> + </item> + +</layer-list> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 5d3dc03..115e59d 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3021,6 +3021,10 @@ </attr> <!-- Reference to a drawable resource to draw with the specified scale. --> <attr name="drawable" /> + <!-- Use the drawable's intrinsic width and height as minimum size values. + Useful if the target drawable is a 9-patch or otherwise should not be scaled + down beyond a minimum size. --> + <attr name="useIntrinsicSizeAsMinimum" format="boolean" /> </declare-styleable> <declare-styleable name="ClipDrawable"> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index ff12e8f..a1b9dc9 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1364,6 +1364,7 @@ <public type="attr" name="exitFadeDuration" /> <public type="attr" name="selectableItemBackground" /> <public type="attr" name="autoAdvanceViewId" /> + <public type="attr" name="useIntrinsicSizeAsMinimum" /> <public type="anim" name="animator_fade_in" /> <public type="anim" name="animator_fade_out" /> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index f63805b..457175b 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1359,6 +1359,9 @@ </style> <style name="Widget.Holo.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal"> + <item name="android:progressDrawable">@android:drawable/progress_horizontal_holo_dark</item> + <item name="android:minHeight">16dip</item> + <item name="android:maxHeight">16dip</item> </style> <style name="Widget.Holo.ProgressBar.Small" parent="Widget.ProgressBar.Horizontal"> @@ -1383,8 +1386,8 @@ <item name="android:indeterminateOnly">false</item> <item name="android:progressDrawable">@android:drawable/scrubber_progress_horizontal_holo_dark</item> <item name="android:indeterminateDrawable">@android:drawable/scrubber_progress_horizontal_holo_dark</item> - <item name="android:minHeight">16dip</item> - <item name="android:maxHeight">16dip</item> + <item name="android:minHeight">6dip</item> + <item name="android:maxHeight">6dip</item> <item name="android:thumb">@android:drawable/scrubber_control_holo</item> <item name="android:thumbOffset">16dip</item> <item name="android:focusable">true</item> @@ -1646,6 +1649,7 @@ </style> <style name="Widget.Holo.Light.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal"> + <item name="android:progressDrawable">@android:drawable/progress_horizontal_holo_light</item> </style> <style name="Widget.Holo.Light.ProgressBar.Small" parent="Widget.ProgressBar.Small"> diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index 501cca9..b6cce7e 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -21,7 +21,10 @@ import org.xmlpull.v1.XmlPullParserException; import android.content.res.Resources; import android.content.res.TypedArray; -import android.graphics.*; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.PixelFormat; +import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java index b623d80..dcaf20b 100644 --- a/graphics/java/android/graphics/drawable/ScaleDrawable.java +++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java @@ -95,6 +95,8 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { float sw = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleWidth); float sh = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleHeight); int g = a.getInt(com.android.internal.R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT); + boolean min = a.getBoolean( + com.android.internal.R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false); Drawable dr = a.getDrawable(com.android.internal.R.styleable.ScaleDrawable_drawable); a.recycle(); @@ -116,6 +118,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { mScaleState.mScaleWidth = sw; mScaleState.mScaleHeight = sh; mScaleState.mGravity = g; + mScaleState.mUseIntrinsicSizeAsMin = min; if (dr != null) { dr.setCallback(this); } @@ -206,15 +209,16 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { @Override protected void onBoundsChange(Rect bounds) { final Rect r = mTmpRect; + final boolean min = mScaleState.mUseIntrinsicSizeAsMin; int level = getLevel(); int w = bounds.width(); - final int iw = 0; //mScaleState.mDrawable.getIntrinsicWidth(); if (mScaleState.mScaleWidth > 0) { + final int iw = min ? mScaleState.mDrawable.getIntrinsicWidth() : 0; w -= (int) ((w - iw) * (10000 - level) * mScaleState.mScaleWidth / 10000); } int h = bounds.height(); - final int ih = 0; //mScaleState.mDrawable.getIntrinsicHeight(); if (mScaleState.mScaleHeight > 0) { + final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0; h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000); } Gravity.apply(mScaleState.mGravity, w, h, bounds, r); @@ -258,6 +262,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { float mScaleWidth; float mScaleHeight; int mGravity; + boolean mUseIntrinsicSizeAsMin; private boolean mCheckedConstantState; private boolean mCanConstantState; @@ -273,6 +278,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { mScaleWidth = orig.mScaleWidth; mScaleHeight = orig.mScaleHeight; mGravity = orig.mGravity; + mUseIntrinsicSizeAsMin = orig.mUseIntrinsicSizeAsMin; mCheckedConstantState = mCanConstantState = true; } } diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 2b498c6..40dd117 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -95,6 +95,16 @@ void Caches::dumpMemoryUsage() { } /////////////////////////////////////////////////////////////////////////////// +// Memory management +/////////////////////////////////////////////////////////////////////////////// + +void Caches::clearGarbage() { + textureCache.clearGarbage(); + gradientCache.clearGarbage(); + pathCache.clearGarbage(); +} + +/////////////////////////////////////////////////////////////////////////////// // VBO /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index 2779dfd..e8ced9c 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -101,6 +101,12 @@ public: } /** + * Call this on each frame to ensure that garbage is deleted from + * GPU memory. + */ + void clearGarbage(); + + /** * Binds the VBO used to render simple textured quads. */ void bindMeshBuffer(); diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index d08df44..77d628a 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -153,13 +153,13 @@ DisplayList::~DisplayList() { mPaints.clear(); for (size_t i = 0; i < mMatrices.size(); i++) { - delete mMatrices.itemAt(i); + delete mMatrices.itemAt(i); } mMatrices.clear(); if (mPathHeap) { for (int i = 0; i < mPathHeap->count(); i++) { - caches.pathCache.remove(&(*mPathHeap)[i]); + caches.pathCache.removeDeferred(&(*mPathHeap)[i]); } mPathHeap->safeUnref(); } diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index 97f4cb4..a37964e 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -54,7 +54,6 @@ GradientCache::GradientCache(uint32_t maxByteSize): } GradientCache::~GradientCache() { - Mutex::Autolock _l(mLock); mCache.clear(); } @@ -63,17 +62,14 @@ GradientCache::~GradientCache() { /////////////////////////////////////////////////////////////////////////////// uint32_t GradientCache::getSize() { - Mutex::Autolock _l(mLock); return mSize; } uint32_t GradientCache::getMaxSize() { - Mutex::Autolock _l(mLock); return mMaxSize; } void GradientCache::setMaxSize(uint32_t maxSize) { - Mutex::Autolock _l(mLock); mMaxSize = maxSize; while (mSize > mMaxSize) { mCache.removeOldest(); @@ -102,17 +98,28 @@ void GradientCache::operator()(SkShader*& shader, Texture*& texture) { /////////////////////////////////////////////////////////////////////////////// Texture* GradientCache::get(SkShader* shader) { - Mutex::Autolock _l(mLock); return mCache.get(shader); } void GradientCache::remove(SkShader* shader) { - Mutex::Autolock _l(mLock); mCache.remove(shader); } -void GradientCache::clear() { +void GradientCache::removeDeferred(SkShader* shader) { Mutex::Autolock _l(mLock); + mGarbage.push(shader); +} + +void GradientCache::clearGarbage() { + Mutex::Autolock _l(mLock); + size_t count = mGarbage.size(); + for (size_t i = 0; i < count; i++) { + mCache.remove(mGarbage.itemAt(i)); + } + mGarbage.clear(); +} + +void GradientCache::clear() { mCache.clear(); } @@ -138,21 +145,17 @@ Texture* GradientCache::addLinearGradient(SkShader* shader, uint32_t* colors, canvas.drawRectCoords(0.0f, 0.0f, bitmap.width(), 1.0f, p); - mLock.lock(); // Asume the cache is always big enough const uint32_t size = bitmap.rowBytes() * bitmap.height(); while (mSize + size > mMaxSize) { mCache.removeOldest(); } - mLock.unlock(); Texture* texture = new Texture; generateTexture(&bitmap, texture); - mLock.lock(); mSize += size; mCache.put(shader, texture); - mLock.unlock(); return texture; } diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h index c9553f4..30da462 100644 --- a/libs/hwui/GradientCache.h +++ b/libs/hwui/GradientCache.h @@ -19,6 +19,8 @@ #include <SkShader.h> +#include <utils/Vector.h> + #include "Texture.h" #include "utils/GenerationCache.h" @@ -53,11 +55,20 @@ public: */ Texture* get(SkShader* shader); /** - * Removes the texture associated with the specified shader. Returns NULL - * if the texture cannot be found. Upon remove the texture is freed. + * Removes the texture associated with the specified shader. + * Upon remove the texture is freed. */ void remove(SkShader* shader); /** + * Removes the texture associated with the specified shader. This is meant + * to be called from threads that are not the EGL context thread. + */ + void removeDeferred(SkShader* shader); + /** + * Process deferred removals. + */ + void clearGarbage(); + /** * Clears the cache. This causes all textures to be deleted. */ void clear(); @@ -83,10 +94,7 @@ private: uint32_t mSize; uint32_t mMaxSize; - /** - * Used to access mCache and mSize. All methods are accessed from a single - * thread except for remove(). - */ + Vector<SkShader*> mGarbage; mutable Mutex mLock; }; // class GradientCache diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index acce1a2..ad72584 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -135,6 +135,8 @@ void OpenGLRenderer::setViewport(int width, int height) { } void OpenGLRenderer::prepare(bool opaque) { + mCaches.clearGarbage(); + mSnapshot = new Snapshot(mFirstSnapshot, SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); mSaveCount = 1; diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index 7ff26dc..8740a64 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -53,7 +53,6 @@ PathCache::PathCache(uint32_t maxByteSize): } PathCache::~PathCache() { - Mutex::Autolock _l(mLock); mCache.clear(); } @@ -72,17 +71,14 @@ void PathCache::init() { /////////////////////////////////////////////////////////////////////////////// uint32_t PathCache::getSize() { - Mutex::Autolock _l(mLock); return mSize; } uint32_t PathCache::getMaxSize() { - Mutex::Autolock _l(mLock); return mMaxSize; } void PathCache::setMaxSize(uint32_t maxSize) { - Mutex::Autolock _l(mLock); mMaxSize = maxSize; while (mSize > mMaxSize) { mCache.removeOldest(); @@ -94,6 +90,14 @@ void PathCache::setMaxSize(uint32_t maxSize) { /////////////////////////////////////////////////////////////////////////////// void PathCache::operator()(PathCacheEntry& path, PathTexture*& texture) { + removeTexture(texture); +} + +/////////////////////////////////////////////////////////////////////////////// +// Caching +/////////////////////////////////////////////////////////////////////////////// + +void PathCache::removeTexture(PathTexture* texture) { if (texture) { const uint32_t size = texture->width * texture->height; mSize -= size; @@ -109,39 +113,46 @@ void PathCache::operator()(PathCacheEntry& path, PathTexture*& texture) { } } -/////////////////////////////////////////////////////////////////////////////// -// Caching -/////////////////////////////////////////////////////////////////////////////// - void PathCache::remove(SkPath* path) { - Mutex::Autolock _l(mLock); - // TODO: Linear search... Vector<uint32_t> pathsToRemove; for (uint32_t i = 0; i < mCache.size(); i++) { if (mCache.getKeyAt(i).path == path) { pathsToRemove.push(i); + removeTexture(mCache.getValueAt(i)); } } + mCache.setOnEntryRemovedListener(NULL); for (size_t i = 0; i < pathsToRemove.size(); i++) { mCache.removeAt(pathsToRemove.itemAt(i)); } + mCache.setOnEntryRemovedListener(this); +} + +void PathCache::removeDeferred(SkPath* path) { + Mutex::Autolock _l(mLock); + mGarbage.push(path); +} + +void PathCache::clearGarbage() { + Mutex::Autolock _l(mLock); + size_t count = mGarbage.size(); + for (size_t i = 0; i < count; i++) { + remove(mGarbage.itemAt(i)); + } + mGarbage.clear(); } PathTexture* PathCache::get(SkPath* path, SkPaint* paint) { PathCacheEntry entry(path, paint); - mLock.lock(); PathTexture* texture = mCache.get(entry); - mLock.unlock(); if (!texture) { texture = addTexture(entry, path, paint); } else if (path->getGenerationID() != texture->generation) { - mLock.lock(); mCache.remove(entry); - mLock.unlock(); texture = addTexture(entry, path, paint); } @@ -167,11 +178,9 @@ PathTexture* PathCache::addTexture(const PathCacheEntry& entry, const uint32_t size = width * height; // Don't even try to cache a bitmap that's bigger than the cache if (size < mMaxSize) { - mLock.lock(); while (mSize + size > mMaxSize) { mCache.removeOldest(); } - mLock.unlock(); } PathTexture* texture = new PathTexture; @@ -200,7 +209,6 @@ PathTexture* PathCache::addTexture(const PathCacheEntry& entry, generateTexture(bitmap, texture); if (size < mMaxSize) { - mLock.lock(); mSize += size; PATH_LOGD("PathCache::get: create path: name, size, mSize = %d, %d, %d", texture->id, size, mSize); @@ -208,7 +216,6 @@ PathTexture* PathCache::addTexture(const PathCacheEntry& entry, LOGD("Path created, size = %d", size); } mCache.put(entry, texture); - mLock.unlock(); } else { texture->cleanup = true; } @@ -217,7 +224,6 @@ PathTexture* PathCache::addTexture(const PathCacheEntry& entry, } void PathCache::clear() { - Mutex::Autolock _l(mLock); mCache.clear(); } diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h index 0193f43..ae2e55d 100644 --- a/libs/hwui/PathCache.h +++ b/libs/hwui/PathCache.h @@ -21,6 +21,8 @@ #include <SkPaint.h> #include <SkPath.h> +#include <utils/Vector.h> + #include "Debug.h" #include "Texture.h" #include "utils/Compare.h" @@ -146,6 +148,15 @@ public: * Removes an entry. */ void remove(SkPath* path); + /** + * Removes the specified path. This is meant to be called from threads + * that are not the EGL context thread. + */ + void removeDeferred(SkPath* path); + /** + * Process deferred removals. + */ + void clearGarbage(); /** * Sets the maximum size of the cache in bytes. @@ -166,6 +177,8 @@ private: */ void generateTexture(SkBitmap& bitmap, Texture* texture); + void removeTexture(PathTexture* texture); + PathTexture* addTexture(const PathCacheEntry& entry, const SkPath *path, const SkPaint* paint); void init(); @@ -178,10 +191,7 @@ private: bool mDebugEnabled; - /** - * Used to access mCache and mSize. All methods are accessed from a single - * thread except for remove(). - */ + Vector<SkPath*> mGarbage; mutable Mutex mLock; }; // class PathCache diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp index 47c5d48..5ebd2c0 100644 --- a/libs/hwui/ResourceCache.cpp +++ b/libs/hwui/ResourceCache.cpp @@ -37,14 +37,17 @@ void ResourceCache::logCache() { } ResourceCache::ResourceCache() { + Mutex::Autolock _l(mLock); mCache = new KeyedVector<void *, ResourceReference *>(); } ResourceCache::~ResourceCache() { + Mutex::Autolock _l(mLock); delete mCache; } void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) { + Mutex::Autolock _l(mLock); for (size_t i = 0; i < mCache->size(); ++i) { void* ref = mCache->valueAt(i); } @@ -73,6 +76,7 @@ void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) { } void ResourceCache::decrementRefcount(void* resource) { + Mutex::Autolock _l(mLock); ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; if (ref == NULL) { // Should not get here - shouldn't get a call to decrement if we're not yet tracking it @@ -101,6 +105,7 @@ void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) { } void ResourceCache::recycle(SkBitmap* resource) { + Mutex::Autolock _l(mLock); if (mCache->indexOfKey(resource) < 0) { // not tracking this resource; just recycle the pixel data resource->setPixels(NULL, NULL); @@ -110,6 +115,7 @@ void ResourceCache::recycle(SkBitmap* resource) { } void ResourceCache::recycle(void* resource) { + Mutex::Autolock _l(mLock); ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL; if (ref == NULL) { // Should not get here - shouldn't get a call to recycle if we're not yet tracking it @@ -122,11 +128,12 @@ void ResourceCache::recycle(void* resource) { } void ResourceCache::destructor(SkBitmap* 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().textureCache.remove(resource); + Caches::getInstance().textureCache.removeDeferred(resource); } delete resource; return; @@ -139,11 +146,12 @@ void ResourceCache::destructor(SkBitmap* resource) { } void ResourceCache::destructor(SkiaShader* 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().gradientCache.remove(resource->getSkShader()); + Caches::getInstance().gradientCache.removeDeferred(resource->getSkShader()); } delete resource; return; @@ -156,6 +164,7 @@ void ResourceCache::destructor(SkiaShader* resource) { } void ResourceCache::destructor(SkiaColorFilter* 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 @@ -169,6 +178,10 @@ void ResourceCache::destructor(SkiaColorFilter* resource) { } } +/** + * This method should only be called while the mLock mutex is held (that mutex is grabbed + * by the various destructor() and recycle() methods which call this method). + */ void ResourceCache::deleteResourceReference(void* resource, ResourceReference* ref) { if (ref->recycled && ref->resourceType == kBitmap) { ((SkBitmap*) resource)->setPixels(NULL, NULL); @@ -179,7 +192,7 @@ void ResourceCache::deleteResourceReference(void* resource, ResourceReference* r { SkBitmap* bitmap = (SkBitmap*)resource; if (Caches::hasInstance()) { - Caches::getInstance().textureCache.remove(bitmap); + Caches::getInstance().textureCache.removeDeferred(bitmap); } delete bitmap; } @@ -188,7 +201,7 @@ void ResourceCache::deleteResourceReference(void* resource, ResourceReference* r { SkiaShader* shader = (SkiaShader*)resource; if (Caches::hasInstance()) { - Caches::getInstance().gradientCache.remove(shader->getSkShader()); + Caches::getInstance().gradientCache.removeDeferred(shader->getSkShader()); } delete shader; } diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h index 2256fd1..b0abe2c 100644 --- a/libs/hwui/ResourceCache.h +++ b/libs/hwui/ResourceCache.h @@ -70,6 +70,13 @@ private: void deleteResourceReference(void* resource, ResourceReference* ref); void incrementRefcount(void* resource, ResourceType resourceType); void logCache(); + + /** + * Used to increment, decrement, and destroy. Incrementing is generally accessed on the UI + * thread, but destroying resources may be called from the GC thread, the finalizer thread, + * or a reference queue finalization thread. + */ + mutable Mutex mLock; }; }; // namespace uirenderer diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 1be6868..ebecebe 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -53,7 +53,6 @@ TextureCache::TextureCache(uint32_t maxByteSize): } TextureCache::~TextureCache() { - Mutex::Autolock _l(mLock); mCache.clear(); } @@ -71,17 +70,14 @@ void TextureCache::init() { /////////////////////////////////////////////////////////////////////////////// uint32_t TextureCache::getSize() { - Mutex::Autolock _l(mLock); return mSize; } uint32_t TextureCache::getMaxSize() { - Mutex::Autolock _l(mLock); return mMaxSize; } void TextureCache::setMaxSize(uint32_t maxSize) { - Mutex::Autolock _l(mLock); mMaxSize = maxSize; while (mSize > mMaxSize) { mCache.removeOldest(); @@ -111,9 +107,7 @@ void TextureCache::operator()(SkBitmap*& bitmap, Texture*& texture) { /////////////////////////////////////////////////////////////////////////////// Texture* TextureCache::get(SkBitmap* bitmap) { - mLock.lock(); Texture* texture = mCache.get(bitmap); - mLock.unlock(); if (!texture) { if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) { @@ -124,11 +118,9 @@ Texture* TextureCache::get(SkBitmap* bitmap) { const uint32_t size = bitmap->rowBytes() * bitmap->height(); // Don't even try to cache a bitmap that's bigger than the cache if (size < mMaxSize) { - mLock.lock(); while (mSize + size > mMaxSize) { mCache.removeOldest(); } - mLock.unlock(); } texture = new Texture; @@ -136,7 +128,6 @@ Texture* TextureCache::get(SkBitmap* bitmap) { generateTexture(bitmap, texture, false); if (size < mMaxSize) { - mLock.lock(); mSize += size; TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d", bitmap, texture->id, size, mSize); @@ -144,7 +135,6 @@ Texture* TextureCache::get(SkBitmap* bitmap) { LOGD("Texture created, size = %d", size); } mCache.put(bitmap, texture); - mLock.unlock(); } else { texture->cleanup = true; } @@ -156,12 +146,24 @@ Texture* TextureCache::get(SkBitmap* bitmap) { } void TextureCache::remove(SkBitmap* bitmap) { - Mutex::Autolock _l(mLock); mCache.remove(bitmap); } -void TextureCache::clear() { +void TextureCache::removeDeferred(SkBitmap* bitmap) { Mutex::Autolock _l(mLock); + mGarbage.push(bitmap); +} + +void TextureCache::clearGarbage() { + Mutex::Autolock _l(mLock); + size_t count = mGarbage.size(); + for (size_t i = 0; i < count; i++) { + mCache.remove(mGarbage.itemAt(i)); + } + mGarbage.clear(); +} + +void TextureCache::clear() { mCache.clear(); TEXTURE_LOGD("TextureCache:clear(), miSize = %d", mSize); } diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index 27693df..f7707f7 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -19,6 +19,8 @@ #include <SkBitmap.h> +#include <utils/Vector.h> + #include "Debug.h" #include "Texture.h" #include "utils/GenerationCache.h" @@ -64,11 +66,21 @@ public: */ Texture* get(SkBitmap* bitmap); /** - * Removes the texture associated with the specified bitmap. Returns NULL - * if the texture cannot be found. Upon remove the texture is freed. + * Removes the texture associated with the specified bitmap. + * Upon remove the texture is freed. */ void remove(SkBitmap* bitmap); /** + * Removes the texture associated with the specified bitmap. This is meant + * to be called from threads that are not the EGL context thread. + */ + void removeDeferred(SkBitmap* bitmap); + /** + * Process deferred removals. + */ + void clearGarbage(); + + /** * Clears the cache. This causes all textures to be deleted. */ void clear(); @@ -109,10 +121,7 @@ private: bool mDebugEnabled; - /** - * Used to access mCache and mSize. All methods are accessed from a single - * thread except for remove(). - */ + Vector<SkBitmap*> mGarbage; mutable Mutex mLock; }; // class TextureCache diff --git a/libs/hwui/utils/GenerationCache.h b/libs/hwui/utils/GenerationCache.h index 2e76236..42e6d9b 100644 --- a/libs/hwui/utils/GenerationCache.h +++ b/libs/hwui/utils/GenerationCache.h @@ -130,7 +130,7 @@ K GenerationCache<K, V>::getKeyAt(uint32_t index) const { template<typename K, typename V> V GenerationCache<K, V>::getValueAt(uint32_t index) const { - return mCache.valueAt(index); + return mCache.valueAt(index)->value; } template<typename K, typename V> diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 4e1969b..f084e28 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -564,6 +564,12 @@ bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) { return false; } +void AwesomePlayer::ensureCacheIsFetching_l() { + if (mCachedSource != NULL) { + mCachedSource->resumeFetchingIfNecessary(); + } +} + void AwesomePlayer::onBufferingUpdate() { Mutex::Autolock autoLock(mLock); if (!mBufferingEventPending) { @@ -606,6 +612,7 @@ void AwesomePlayer::onBufferingUpdate() { kLowWaterMarkBytes); mFlags |= CACHE_UNDERRUN; pause_l(); + ensureCacheIsFetching_l(); notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { if (mFlags & CACHE_UNDERRUN) { @@ -627,12 +634,16 @@ void AwesomePlayer::onBufferingUpdate() { int64_t cachedDurationUs; bool eos; if (getCachedDuration_l(&cachedDurationUs, &eos)) { + LOGV("cachedDurationUs = %.2f secs, eos=%d", + cachedDurationUs / 1E6, eos); + if ((mFlags & PLAYING) && !eos && (cachedDurationUs < kLowWaterMarkUs)) { LOGI("cache is running low (%.2f secs) , pausing.", cachedDurationUs / 1E6); mFlags |= CACHE_UNDERRUN; pause_l(); + ensureCacheIsFetching_l(); notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); } else if (eos || cachedDurationUs > kHighWaterMarkUs) { if (mFlags & CACHE_UNDERRUN) { diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp index a69c396..4a2402b 100644 --- a/media/libstagefright/NuCachedSource2.cpp +++ b/media/libstagefright/NuCachedSource2.cpp @@ -325,15 +325,17 @@ void NuCachedSource2::onRead(const sp<AMessage> &msg) { mCondition.signal(); } -void NuCachedSource2::restartPrefetcherIfNecessary_l() { +void NuCachedSource2::restartPrefetcherIfNecessary_l( + bool ignoreLowWaterThreshold) { static const size_t kGrayArea = 256 * 1024; if (mFetching || mFinalStatus != OK) { return; } - if (mCacheOffset + mCache->totalSize() - mLastAccessPos - >= kLowWaterThreshold) { + if (!ignoreLowWaterThreshold + && mCacheOffset + mCache->totalSize() - mLastAccessPos + >= kLowWaterThreshold) { return; } @@ -510,6 +512,12 @@ void NuCachedSource2::onSuspend() { mSuspended = true; } +void NuCachedSource2::resumeFetchingIfNecessary() { + Mutex::Autolock autoLock(mLock); + + restartPrefetcherIfNecessary_l(true /* ignore low water threshold */); +} + DecryptHandle* NuCachedSource2::DrmInitialization(DrmManagerClient* client) { return mSource->DrmInitialization(client); } diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index a0a7436..302a1ba 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -274,6 +274,7 @@ private: bool getBitrate(int64_t *bitrate); void finishSeekIfNecessary(int64_t videoTimeUs); + void ensureCacheIsFetching_l(); AwesomePlayer(const AwesomePlayer &); AwesomePlayer &operator=(const AwesomePlayer &); diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h index 4067585..8cd7d4b 100644 --- a/media/libstagefright/include/NuCachedSource2.h +++ b/media/libstagefright/include/NuCachedSource2.h @@ -47,6 +47,8 @@ struct NuCachedSource2 : public DataSource { void suspend(); void clearCacheAndResume(); + void resumeFetchingIfNecessary(); + protected: virtual ~NuCachedSource2(); @@ -96,7 +98,7 @@ private: status_t seekInternal_l(off_t offset); size_t approxDataRemaining_l(bool *eos); - void restartPrefetcherIfNecessary_l(); + void restartPrefetcherIfNecessary_l(bool ignoreLowWaterThreshold = false); DISALLOW_EVIL_CONSTRUCTORS(NuCachedSource2); }; |
