summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GenerationCache.h245
-rw-r--r--api/current.txt17
-rw-r--r--core/java/android/app/Activity.java1
-rw-r--r--core/java/android/text/BoringLayout.java44
-rw-r--r--core/java/android/text/TextLine.java7
-rw-r--r--core/java/android/util/NtpTrustedTime.java96
-rw-r--r--core/java/android/util/TrustedTime.java55
-rw-r--r--core/java/android/view/GLES20Canvas.java5
-rw-r--r--core/java/android/view/GLES20Layer.java81
-rw-r--r--core/java/android/view/GLES20RenderLayer.java91
-rw-r--r--core/java/android/view/GLES20TextureLayer.java76
-rw-r--r--core/java/android/view/HardwareLayer.java12
-rw-r--r--core/java/android/view/HardwareRenderer.java52
-rw-r--r--core/java/android/view/TextureView.java296
-rw-r--r--core/java/android/webkit/WebSettings.java13
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java20
-rw-r--r--core/java/com/android/internal/util/Protocol.java37
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuPresenter.java20
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java48
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp22
-rw-r--r--core/res/res/layout/screen_action_bar.xml3
-rw-r--r--core/res/res/layout/screen_action_bar_overlay.xml3
-rw-r--r--core/res/res/values-w480dp/bools.xml1
-rwxr-xr-xcore/res/res/values/attrs.xml5
-rw-r--r--core/res/res/values/bools.xml1
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--core/res/res/values/themes.xml13
-rw-r--r--docs/html/guide/topics/ui/declaring-layout.jd4
-rw-r--r--graphics/java/android/renderscript/RenderScript.java10
-rw-r--r--graphics/java/android/renderscript/Script.java29
-rw-r--r--graphics/jni/android_renderscript_RenderScript.cpp20
-rw-r--r--libs/gui/Android.mk4
-rw-r--r--libs/gui/tests/Android.mk3
-rw-r--r--libs/hwui/Layer.h18
-rw-r--r--libs/hwui/LayerCache.cpp2
-rw-r--r--libs/hwui/LayerRenderer.cpp47
-rw-r--r--libs/hwui/LayerRenderer.h3
-rw-r--r--libs/hwui/OpenGLRenderer.cpp57
-rw-r--r--libs/hwui/OpenGLRenderer.h13
-rw-r--r--libs/hwui/ProgramCache.cpp34
-rw-r--r--libs/hwui/ProgramCache.h5
-rw-r--r--libs/rs/rs.spec12
-rw-r--r--libs/rs/rsHandcode.h87
-rw-r--r--libs/rs/rsScript.cpp10
-rw-r--r--libs/rs/rsThreadIO.cpp2
-rw-r--r--libs/rs/rsg_generator.c91
-rw-r--r--location/java/android/location/LocationManager.java6
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java15
-rw-r--r--services/input/InputWindow.h5
-rw-r--r--services/java/com/android/server/ThrottleService.java183
-rwxr-xr-xservices/java/com/android/server/location/ComprehensiveCountryDetector.java30
-rwxr-xr-xservices/java/com/android/server/location/LocationBasedCountryDetector.java88
-rw-r--r--services/tests/servicestests/Android.mk4
-rw-r--r--services/tests/servicestests/AndroidManifest.xml4
-rw-r--r--services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java400
-rwxr-xr-xservices/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java105
-rw-r--r--telephony/java/com/android/internal/telephony/cat/CatService.java9
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java4
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java4
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java2
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java18
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml14
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java87
-rw-r--r--tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs2
-rw-r--r--tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs2
-rw-r--r--tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs2
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs2
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/rslist.rs2
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java115
69 files changed, 2124 insertions, 696 deletions
diff --git a/GenerationCache.h b/GenerationCache.h
deleted file mode 100644
index 42e6d9bb8cda..000000000000
--- a/GenerationCache.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_HWUI_GENERATION_CACHE_H
-#define ANDROID_HWUI_GENERATION_CACHE_H
-
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-
-namespace android {
-namespace uirenderer {
-
-template<typename EntryKey, typename EntryValue>
-class OnEntryRemoved {
-public:
- virtual ~OnEntryRemoved() { };
- virtual void operator()(EntryKey& key, EntryValue& value) = 0;
-}; // class OnEntryRemoved
-
-template<typename EntryKey, typename EntryValue>
-struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > {
- Entry() { }
- Entry(const Entry<EntryKey, EntryValue>& e):
- key(e.key), value(e.value), parent(e.parent), child(e.child) { }
- Entry(sp<Entry<EntryKey, EntryValue> > e):
- key(e->key), value(e->value), parent(e->parent), child(e->child) { }
-
- EntryKey key;
- EntryValue value;
-
- sp<Entry<EntryKey, EntryValue> > parent;
- sp<Entry<EntryKey, EntryValue> > child;
-}; // struct Entry
-
-template<typename K, typename V>
-class GenerationCache {
-public:
- GenerationCache(uint32_t maxCapacity);
- virtual ~GenerationCache();
-
- enum Capacity {
- kUnlimitedCapacity,
- };
-
- void setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener);
-
- void clear();
-
- bool contains(K key) const;
- V get(K key);
- K getKeyAt(uint32_t index) const;
- bool put(K key, V value);
- V remove(K key);
- V removeOldest();
- V getValueAt(uint32_t index) const;
-
- uint32_t size() const;
-
- void addToCache(sp<Entry<K, V> > entry, K key, V value);
- void attachToCache(sp<Entry<K, V> > entry);
- void detachFromCache(sp<Entry<K, V> > entry);
-
- V removeAt(ssize_t index);
-
- KeyedVector<K, sp<Entry<K, V> > > mCache;
- uint32_t mMaxCapacity;
-
- OnEntryRemoved<K, V>* mListener;
-
- sp<Entry<K, V> > mOldest;
- sp<Entry<K, V> > mYoungest;
-}; // class GenerationCache
-
-template<typename K, typename V>
-GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) {
-};
-
-template<typename K, typename V>
-GenerationCache<K, V>::~GenerationCache() {
- clear();
-};
-
-template<typename K, typename V>
-uint32_t GenerationCache<K, V>::size() const {
- return mCache.size();
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
- mListener = listener;
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::clear() {
- if (mListener) {
- for (uint32_t i = 0; i < mCache.size(); i++) {
- sp<Entry<K, V> > entry = mCache.valueAt(i);
- if (mListener) {
- (*mListener)(entry->key, entry->value);
- }
- }
- }
- mCache.clear();
- mYoungest.clear();
- mOldest.clear();
-}
-
-template<typename K, typename V>
-bool GenerationCache<K, V>::contains(K key) const {
- return mCache.indexOfKey(key) >= 0;
-}
-
-template<typename K, typename V>
-K GenerationCache<K, V>::getKeyAt(uint32_t index) const {
- return mCache.keyAt(index);
-}
-
-template<typename K, typename V>
-V GenerationCache<K, V>::getValueAt(uint32_t index) const {
- return mCache.valueAt(index)->value;
-}
-
-template<typename K, typename V>
-V GenerationCache<K, V>::get(K key) {
- ssize_t index = mCache.indexOfKey(key);
- if (index >= 0) {
- sp<Entry<K, V> > entry = mCache.valueAt(index);
- if (entry.get()) {
- detachFromCache(entry);
- attachToCache(entry);
- return entry->value;
- }
- }
-
- return NULL;
-}
-
-template<typename K, typename V>
-bool GenerationCache<K, V>::put(K key, V value) {
- if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) {
- removeOldest();
- }
-
- ssize_t index = mCache.indexOfKey(key);
- if (index < 0) {
- sp<Entry<K, V> > entry = new Entry<K, V>;
- addToCache(entry, key, value);
- return true;
- }
-
- return false;
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::addToCache(sp<Entry<K, V> > entry, K key, V value) {
- entry->key = key;
- entry->value = value;
- mCache.add(key, entry);
- attachToCache(entry);
-}
-
-template<typename K, typename V>
-V GenerationCache<K, V>::remove(K key) {
- ssize_t index = mCache.indexOfKey(key);
- if (index >= 0) {
- return removeAt(index);
- }
-
- return NULL;
-}
-
-template<typename K, typename V>
-V GenerationCache<K, V>::removeAt(ssize_t index) {
- sp<Entry<K, V> > entry = mCache.valueAt(index);
- if (mListener) {
- (*mListener)(entry->key, entry->value);
- }
- mCache.removeItemsAt(index, 1);
- detachFromCache(entry);
-
- return entry->value;
-}
-
-template<typename K, typename V>
-V GenerationCache<K, V>::removeOldest() {
- if (mOldest.get()) {
- ssize_t index = mCache.indexOfKey(mOldest->key);
- if (index >= 0) {
- return removeAt(index);
- }
- }
-
- return NULL;
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::attachToCache(sp<Entry<K, V> > entry) {
- if (!mYoungest.get()) {
- mYoungest = mOldest = entry;
- } else {
- entry->parent = mYoungest;
- mYoungest->child = entry;
- mYoungest = entry;
- }
-}
-
-template<typename K, typename V>
-void GenerationCache<K, V>::detachFromCache(sp<Entry<K, V> > entry) {
- if (entry->parent.get()) {
- entry->parent->child = entry->child;
- }
-
- if (entry->child.get()) {
- entry->child->parent = entry->parent;
- }
-
- if (mOldest == entry) {
- mOldest = entry->child;
- }
-
- if (mYoungest == entry) {
- mYoungest = entry->parent;
- }
-
- entry->parent.clear();
- entry->child.clear();
-}
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_GENERATION_CACHE_H
diff --git a/api/current.txt b/api/current.txt
index 4b3918e6adba..a98ffae88899 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1490,9 +1490,11 @@ package android {
field public static final int Theme_Holo_Light_Dialog_NoActionBar_MinWidth = 16973942; // 0x1030076
field public static final int Theme_Holo_Light_NoActionBar = 16974064; // 0x10300f0
field public static final int Theme_Holo_Light_Panel = 16973948; // 0x103007c
+ field public static final int Theme_Holo_Light_SplitActionBarWhenNarrow = 16974067; // 0x10300f3
field public static final int Theme_Holo_NoActionBar = 16973932; // 0x103006c
field public static final int Theme_Holo_NoActionBar_Fullscreen = 16973933; // 0x103006d
field public static final int Theme_Holo_Panel = 16973947; // 0x103007b
+ field public static final int Theme_Holo_SplitActionBarWhenNarrow = 16974066; // 0x10300f2
field public static final int Theme_Holo_Wallpaper = 16973949; // 0x103007d
field public static final int Theme_Holo_Wallpaper_NoTitleBar = 16973950; // 0x103007e
field public static final int Theme_InputMethod = 16973908; // 0x1030054
@@ -21010,6 +21012,21 @@ package android.view {
method public void setZOrderOnTop(boolean);
}
+ public class TextureView extends android.view.View {
+ ctor public TextureView(android.content.Context);
+ ctor public TextureView(android.content.Context, android.util.AttributeSet);
+ ctor public TextureView(android.content.Context, android.util.AttributeSet, int);
+ method public final void draw(android.graphics.Canvas);
+ method public android.graphics.SurfaceTexture getSurfaceTexture();
+ method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
+ method protected final void onDraw(android.graphics.Canvas);
+ method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener);
+ }
+
+ public static abstract interface TextureView.SurfaceTextureListener {
+ method public abstract void onSurfaceTextureAvailable(android.graphics.SurfaceTexture);
+ }
+
public class TouchDelegate {
ctor public TouchDelegate(android.graphics.Rect, android.view.View);
method public boolean onTouchEvent(android.view.MotionEvent);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f5849c24e59a..02b6619dfaf9 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2482,6 +2482,7 @@ public class Activity extends ContextThemeWrapper
break;
case Window.FEATURE_ACTION_BAR:
+ initActionBar();
mActionBar.dispatchMenuVisibilityChanged(false);
break;
}
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 9309b05c6fda..757a8c3db075 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -234,18 +234,17 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
* provided Metrics object (or a new one if the provided one was null)
* if boring.
*/
- public static Metrics isBoring(CharSequence text, TextPaint paint,
- Metrics metrics) {
+ public static Metrics isBoring(CharSequence text, TextPaint paint, Metrics metrics) {
char[] temp = TextUtils.obtain(500);
- int len = text.length();
+ int length = text.length();
boolean boring = true;
outer:
- for (int i = 0; i < len; i += 500) {
+ for (int i = 0; i < length; i += 500) {
int j = i + 500;
- if (j > len)
- j = len;
+ if (j > length)
+ j = length;
TextUtils.getChars(text, i, j, temp, 0);
@@ -265,7 +264,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
if (boring && text instanceof Spanned) {
Spanned sp = (Spanned) text;
- Object[] styles = sp.getSpans(0, text.length(), ParagraphStyle.class);
+ Object[] styles = sp.getSpans(0, length, ParagraphStyle.class);
if (styles.length > 0) {
boring = false;
}
@@ -278,7 +277,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
}
TextLine line = TextLine.obtain();
- line.set(paint, text, 0, text.length(), Layout.DIR_LEFT_TO_RIGHT,
+ line.set(paint, text, 0, length, Layout.DIR_LEFT_TO_RIGHT,
Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null);
fm.width = (int) FloatMath.ceil(line.metrics(fm));
TextLine.recycle(line);
@@ -289,52 +288,63 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
}
}
- @Override public int getHeight() {
+ @Override
+ public int getHeight() {
return mBottom;
}
- @Override public int getLineCount() {
+ @Override
+ public int getLineCount() {
return 1;
}
- @Override public int getLineTop(int line) {
+ @Override
+ public int getLineTop(int line) {
if (line == 0)
return 0;
else
return mBottom;
}
- @Override public int getLineDescent(int line) {
+ @Override
+ public int getLineDescent(int line) {
return mDesc;
}
- @Override public int getLineStart(int line) {
+ @Override
+ public int getLineStart(int line) {
if (line == 0)
return 0;
else
return getText().length();
}
- @Override public int getParagraphDirection(int line) {
+ @Override
+ public int getParagraphDirection(int line) {
return DIR_LEFT_TO_RIGHT;
}
- @Override public boolean getLineContainsTab(int line) {
+ @Override
+ public boolean getLineContainsTab(int line) {
return false;
}
- @Override public float getLineMax(int line) {
+ @Override
+ public float getLineMax(int line) {
return mMax;
}
- @Override public final Directions getLineDirections(int line) {
+ @Override
+ public final Directions getLineDirections(int line) {
return Layout.DIRS_ALL_LEFT_TO_RIGHT;
}
+ @Override
public int getTopPadding() {
return mTopPadding;
}
+ @Override
public int getBottomPadding() {
return mBottomPadding;
}
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 1b7f2f310c9f..0f8097a948a6 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -815,6 +815,13 @@ class TextLine {
int limit, boolean runIsRtl, Canvas c, float x, int top, int y,
int bottom, FontMetricsInt fmi, boolean needWidth) {
+ // Case of an empty line, make sure we update fmi according to mPaint
+ if (start == measureLimit) {
+ TextPaint wp = mWorkPaint;
+ wp.set(mPaint);
+ return handleText(wp, 0, 0, 0, 0, runIsRtl, c, x, top, y, bottom, fmi, needWidth);
+ }
+
// Shaping needs to take into account context up to metric boundaries,
// but rendering needs to take into account character style boundaries.
// So we iterate through metric runs to get metric bounds,
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
new file mode 100644
index 000000000000..729c5064204e
--- /dev/null
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.net.SntpClient;
+import android.os.SystemClock;
+
+/**
+ * {@link TrustedTime} that connects with a remote NTP server as its remote
+ * trusted time source.
+ *
+ * @hide
+ */
+public class NtpTrustedTime implements TrustedTime {
+ private String mNtpServer;
+ private long mNtpTimeout;
+
+ private boolean mHasCache;
+ private long mCachedNtpTime;
+ private long mCachedNtpElapsedRealtime;
+ private long mCachedNtpCertainty;
+
+ public NtpTrustedTime() {
+ }
+
+ public void setNtpServer(String server, long timeout) {
+ mNtpServer = server;
+ mNtpTimeout = timeout;
+ }
+
+ /** {@inheritDoc} */
+ public boolean forceRefresh() {
+ if (mNtpServer == null) {
+ throw new IllegalStateException("Missing NTP server");
+ }
+
+ final SntpClient client = new SntpClient();
+ if (client.requestTime(mNtpServer, (int) mNtpTimeout)) {
+ mHasCache = true;
+ mCachedNtpTime = client.getNtpTime();
+ mCachedNtpElapsedRealtime = client.getNtpTimeReference();
+ mCachedNtpCertainty = client.getRoundTripTime() / 2;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public boolean hasCache() {
+ return mHasCache;
+ }
+
+ /** {@inheritDoc} */
+ public long getCacheAge() {
+ if (mHasCache) {
+ return SystemClock.elapsedRealtime() - mCachedNtpElapsedRealtime;
+ } else {
+ return Long.MAX_VALUE;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public long getCacheCertainty() {
+ if (mHasCache) {
+ return mCachedNtpCertainty;
+ } else {
+ return Long.MAX_VALUE;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public long currentTimeMillis() {
+ if (!mHasCache) {
+ throw new IllegalStateException("Missing authoritative time source");
+ }
+
+ // current time is age after the last ntp cache; callers who
+ // want fresh values will hit makeAuthoritative() first.
+ return mCachedNtpTime + getCacheAge();
+ }
+}
diff --git a/core/java/android/util/TrustedTime.java b/core/java/android/util/TrustedTime.java
new file mode 100644
index 000000000000..263d7821a085
--- /dev/null
+++ b/core/java/android/util/TrustedTime.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+/**
+ * Interface that provides trusted time information, possibly coming from an NTP
+ * server. Implementations may cache answers until {@link #forceRefresh()}.
+ *
+ * @hide
+ */
+public interface TrustedTime {
+ /**
+ * Force update with an external trusted time source, returning {@code true}
+ * when successful.
+ */
+ public boolean forceRefresh();
+
+ /**
+ * Check if this instance has cached a response from a trusted time source.
+ */
+ public boolean hasCache();
+
+ /**
+ * Return time since last trusted time source contact, or
+ * {@link Long#MAX_VALUE} if never contacted.
+ */
+ public long getCacheAge();
+
+ /**
+ * Return certainty of cached trusted time in milliseconds, or
+ * {@link Long#MAX_VALUE} if never contacted. Smaller values are more
+ * precise.
+ */
+ public long getCacheCertainty();
+
+ /**
+ * Return current time similar to {@link System#currentTimeMillis()},
+ * possibly using a cached authoritative time source.
+ */
+ public long currentTimeMillis();
+}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index b8c5c2acadc8..cdf8954f5b2f 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -160,8 +160,11 @@ class GLES20Canvas extends HardwareCanvas {
// Hardware layers
///////////////////////////////////////////////////////////////////////////
+ static native int nCreateTextureLayer(int[] layerInfo);
static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo);
+ static native void nUpdateTextureLayer(int layerId, int width, int height,
+ float[] textureTransform);
static native void nDestroyLayer(int layerId);
static native void nDestroyLayerDeferred(int layerId);
@@ -272,7 +275,7 @@ class GLES20Canvas extends HardwareCanvas {
}
private static native void nDrawLayer(int renderer, int layer, float x, float y, int paint);
-
+
void interrupt() {
nInterrupt(mRenderer);
}
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
index 6000a4a53bff..bc191a6fae9b 100644
--- a/core/java/android/view/GLES20Layer.java
+++ b/core/java/android/view/GLES20Layer.java
@@ -14,39 +14,21 @@
* limitations under the License.
*/
-package android.view;
-import android.graphics.Canvas;
+package android.view;
/**
* An OpenGL ES 2.0 implementation of {@link HardwareLayer}.
*/
-class GLES20Layer extends HardwareLayer {
- private int mLayer;
-
- private int mLayerWidth;
- private int mLayerHeight;
-
- private final GLES20Canvas mCanvas;
+abstract class GLES20Layer extends HardwareLayer {
+ int mLayer;
+ Finalizer mFinalizer;
- @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
- private final Finalizer mFinalizer;
-
- GLES20Layer(int width, int height, boolean isOpaque) {
- super(width, height, isOpaque);
-
- int[] layerInfo = new int[2];
- mLayer = GLES20Canvas.nCreateLayer(width, height, isOpaque, layerInfo);
- if (mLayer != 0) {
- mLayerWidth = layerInfo[0];
- mLayerHeight = layerInfo[1];
+ GLES20Layer() {
+ }
- mCanvas = new GLES20Canvas(mLayer, !isOpaque);
- mFinalizer = new Finalizer(mLayer);
- } else {
- mCanvas = null;
- mFinalizer = null;
- }
+ GLES20Layer(int width, int height, boolean opaque) {
+ super(width, height, opaque);
}
/**
@@ -58,55 +40,14 @@ class GLES20Layer extends HardwareLayer {
return mLayer;
}
- @Override
- boolean isValid() {
- return mLayer != 0 && mLayerWidth > 0 && mLayerHeight > 0;
- }
-
- @Override
- void resize(int width, int height) {
- if (!isValid() || width <= 0 || height <= 0) return;
-
- mWidth = width;
- mHeight = height;
-
- if (width != mLayerWidth || height != mLayerHeight) {
- int[] layerInfo = new int[2];
-
- GLES20Canvas.nResizeLayer(mLayer, width, height, layerInfo);
-
- mLayerWidth = layerInfo[0];
- mLayerHeight = layerInfo[1];
- }
- }
-
- @Override
- HardwareCanvas getCanvas() {
- return mCanvas;
- }
-
- @Override
- void end(Canvas currentCanvas) {
- if (currentCanvas instanceof GLES20Canvas) {
- ((GLES20Canvas) currentCanvas).resume();
- }
- }
-
- @Override
- HardwareCanvas start(Canvas currentCanvas) {
- if (currentCanvas instanceof GLES20Canvas) {
- ((GLES20Canvas) currentCanvas).interrupt();
- }
- return getCanvas();
- }
-
+
@Override
void destroy() {
- mFinalizer.destroy();
+ if (mFinalizer != null) mFinalizer.destroy();
mLayer = 0;
}
- private static class Finalizer {
+ static class Finalizer {
private int mLayerId;
public Finalizer(int layerId) {
diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
new file mode 100644
index 000000000000..7adac1ce3e3f
--- /dev/null
+++ b/core/java/android/view/GLES20RenderLayer.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.graphics.Canvas;
+
+/**
+ * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This
+ * implementation can be used a rendering target. It generates a
+ * {@link Canvas} that can be used to render into an FBO using OpenGL.
+ */
+class GLES20RenderLayer extends GLES20Layer {
+
+ private int mLayerWidth;
+ private int mLayerHeight;
+
+ private final GLES20Canvas mCanvas;
+
+ GLES20RenderLayer(int width, int height, boolean isOpaque) {
+ super(width, height, isOpaque);
+
+ int[] layerInfo = new int[2];
+ mLayer = GLES20Canvas.nCreateLayer(width, height, isOpaque, layerInfo);
+ if (mLayer != 0) {
+ mLayerWidth = layerInfo[0];
+ mLayerHeight = layerInfo[1];
+
+ mCanvas = new GLES20Canvas(mLayer, !isOpaque);
+ mFinalizer = new Finalizer(mLayer);
+ } else {
+ mCanvas = null;
+ mFinalizer = null;
+ }
+ }
+
+ @Override
+ boolean isValid() {
+ return mLayer != 0 && mLayerWidth > 0 && mLayerHeight > 0;
+ }
+
+ @Override
+ void resize(int width, int height) {
+ if (!isValid() || width <= 0 || height <= 0) return;
+
+ mWidth = width;
+ mHeight = height;
+
+ if (width != mLayerWidth || height != mLayerHeight) {
+ int[] layerInfo = new int[2];
+
+ GLES20Canvas.nResizeLayer(mLayer, width, height, layerInfo);
+
+ mLayerWidth = layerInfo[0];
+ mLayerHeight = layerInfo[1];
+ }
+ }
+
+ @Override
+ HardwareCanvas getCanvas() {
+ return mCanvas;
+ }
+
+ @Override
+ void end(Canvas currentCanvas) {
+ if (currentCanvas instanceof GLES20Canvas) {
+ ((GLES20Canvas) currentCanvas).resume();
+ }
+ }
+
+ @Override
+ HardwareCanvas start(Canvas currentCanvas) {
+ if (currentCanvas instanceof GLES20Canvas) {
+ ((GLES20Canvas) currentCanvas).interrupt();
+ }
+ return getCanvas();
+ }
+}
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
new file mode 100644
index 000000000000..21fbdfcf6af3
--- /dev/null
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.graphics.Canvas;
+import android.graphics.SurfaceTexture;
+
+/**
+ * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This
+ * implementation can be used as a texture. Rendering into this
+ * layer is not controlled by a {@link HardwareCanvas}.
+ */
+class GLES20TextureLayer extends GLES20Layer {
+ private int mTexture;
+ private SurfaceTexture mSurface;
+
+ GLES20TextureLayer() {
+ int[] layerInfo = new int[2];
+ mLayer = GLES20Canvas.nCreateTextureLayer(layerInfo);
+
+ if (mLayer != 0) {
+ mTexture = layerInfo[0];
+ mFinalizer = new Finalizer(mLayer);
+ } else {
+ mFinalizer = null;
+ }
+ }
+
+ @Override
+ boolean isValid() {
+ return mLayer != 0 && mTexture != 0;
+ }
+
+ @Override
+ void resize(int width, int height) {
+ }
+
+ @Override
+ HardwareCanvas getCanvas() {
+ return null;
+ }
+
+ @Override
+ HardwareCanvas start(Canvas currentCanvas) {
+ return null;
+ }
+
+ @Override
+ void end(Canvas currentCanvas) {
+ }
+
+ SurfaceTexture getSurfaceTexture() {
+ if (mSurface == null) {
+ mSurface = new SurfaceTexture(mTexture);
+ }
+ return mSurface;
+ }
+
+ void update(int width, int height, float[] textureTransform) {
+ GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, textureTransform);
+ }
+}
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index d01b8ce37854..86dec3f16eff 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -26,12 +26,24 @@ import android.graphics.Canvas;
* drawn several times.
*/
abstract class HardwareLayer {
+ /**
+ * Indicates an unknown dimension (width or height.)
+ */
+ static final int DIMENSION_UNDEFINED = -1;
+
int mWidth;
int mHeight;
final boolean mOpaque;
/**
+ * Creates a new hardware layer with undefined dimensions.
+ */
+ HardwareLayer() {
+ this(DIMENSION_UNDEFINED, DIMENSION_UNDEFINED, false);
+ }
+
+ /**
* Creates a new hardware layer at least as large as the supplied
* dimensions.
*
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 66f37f29b0bd..5b2983d548a1 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -20,6 +20,7 @@ package android.view;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
+import android.graphics.SurfaceTexture;
import android.os.*;
import android.util.EventLog;
import android.util.Log;
@@ -166,6 +167,14 @@ public abstract class HardwareRenderer {
abstract DisplayList createDisplayList(View v);
/**
+ * Creates a new hardware layer. A hardware layer built by calling this
+ * method will be treated as a texture layer, instead of as a render target.
+ *
+ * @return A hardware layer
+ */
+ abstract HardwareLayer createHardwareLayer();
+
+ /**
* Creates a new hardware layer.
*
* @param width The minimum width of the layer
@@ -175,6 +184,29 @@ public abstract class HardwareRenderer {
* @return A hardware layer
*/
abstract HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque);
+
+ /**
+ * Creates a new {@link SurfaceTexture} that can be used to render into the
+ * specified hardware layer.
+ *
+ *
+ * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture}
+ *
+ * @return A {@link SurfaceTexture}
+ */
+ abstract SurfaceTexture createSuraceTexture(HardwareLayer layer);
+
+ /**
+ * Updates the specified layer.
+ *
+ * @param layer The hardware layer to update
+ * @param width The layer's width
+ * @param height The layer's height
+ * @param textureTransform A 4x4 column-first transform matrix to apply to
+ * texture coordinates
+ */
+ abstract void updateTextureLayer(HardwareLayer layer, int width, int height,
+ float[] textureTransform);
/**
* Initializes the hardware renderer for the specified surface and setup the
@@ -856,10 +888,26 @@ public abstract class HardwareRenderer {
DisplayList createDisplayList(View v) {
return new GLES20DisplayList(v);
}
-
+
+ @Override
+ HardwareLayer createHardwareLayer() {
+ return new GLES20TextureLayer();
+ }
+
@Override
HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) {
- return new GLES20Layer(width, height, isOpaque);
+ return new GLES20RenderLayer(width, height, isOpaque);
+ }
+
+ @Override
+ SurfaceTexture createSuraceTexture(HardwareLayer layer) {
+ return ((GLES20TextureLayer) layer).getSurfaceTexture();
+ }
+
+ @Override
+ void updateTextureLayer(HardwareLayer layer, int width, int height,
+ float[] textureTransform) {
+ ((GLES20TextureLayer) layer).update(width, height, textureTransform);
}
static HardwareRenderer create(boolean translucent) {
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
new file mode 100644
index 000000000000..6380e1b5c7bd
--- /dev/null
+++ b/core/java/android/view/TextureView.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.SurfaceTexture;
+import android.util.AttributeSet;
+import android.util.Log;
+
+/**
+ * <p>A TextureView can be used to display a content stream. Such a content
+ * stream can for instance be a video or an OpenGL scene. The content stream
+ * can come from the application's process as well as a remote process.</p>
+ *
+ * <p>TextureView can only be used in a hardware accelerated window. When
+ * rendered in software, TextureView will draw nothing.</p>
+ *
+ * <p>Unlike {@link SurfaceView}, TextureView does not create a separate
+ * window but behaves as a regular View. This key difference allows a
+ * TextureView to be moved, transformed, animated, etc. For instance, you
+ * can make a TextureView semi-translucent by calling
+ * <code>myView.setAlpha(0.5f)</code>.</p>
+ *
+ * <p>Using a TextureView is simple: all you need to do is get its
+ * {@link SurfaceTexture}. The {@link SurfaceTexture} can then be used to
+ * render content. The following example demonstrates how to render the
+ * camera preview into a TextureView:</p>
+ *
+ * <pre>
+ * public class LiveCameraActivity extends Activity implements TextureView.SurfaceTextureListener {
+ * private Camera mCamera;
+ * private TextureView mTextureView;
+ *
+ * protected void onCreate(Bundle savedInstanceState) {
+ * super.onCreate(savedInstanceState);
+ *
+ * mTextureView = new TextureView(this);
+ * mTextureView.setSurfaceTextureListener(this);
+ *
+ * setContentView(mTextureView);
+ * }
+ *
+ * protected void onDestroy() {
+ * super.onDestroy();
+ *
+ * mCamera.stopPreview();
+ * mCamera.release();
+ * }
+ *
+ * public void onSurfaceTextureAvailable(SurfaceTexture surface) {
+ * mCamera = Camera.open();
+ *
+ * try {
+ * mCamera.setPreviewTexture(surface);
+ * mCamera.startPreview();
+ * } catch (IOException ioe) {
+ * // Something bad happened
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * <p>A TextureView's SurfaceTexture can be obtained either by invoking
+ * {@link #getSurfaceTexture()} or by using a {@link SurfaceTextureListener}.
+ * It is important to know that a SurfaceTexture is available only after the
+ * TextureView is attached to a window (and {@link #onAttachedToWindow()} has
+ * been invoked.) It is therefore highly recommended you use a listener to
+ * be notified when the SurfaceTexture becomes available.</p>
+ *
+ * @see SurfaceView
+ * @see SurfaceTexture
+ */
+public class TextureView extends View {
+ private HardwareLayer mLayer;
+ private SurfaceTexture mSurface;
+ private SurfaceTextureListener mListener;
+
+ private final float[] mTextureTransform = new float[16];
+
+ private final Runnable mUpdateLayerAction = new Runnable() {
+ @Override
+ public void run() {
+ updateLayer();
+ }
+ };
+
+ /**
+ * Creates a new TextureView.
+ *
+ * @param context The context to associate this view with.
+ */
+ public TextureView(Context context) {
+ super(context);
+ init();
+ }
+
+ /**
+ * Creates a new TextureView.
+ *
+ * @param context The context to associate this view with.
+ * @param attrs The attributes of the XML tag that is inflating the view.
+ */
+ @SuppressWarnings({"UnusedDeclaration"})
+ public TextureView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ /**
+ * Creates a new TextureView.
+ *
+ * @param context The context to associate this view with.
+ * @param attrs The attributes of the XML tag that is inflating the view.
+ * @param defStyle The default style to apply to this view. If 0, no style
+ * will be applied (beyond what is included in the theme). This may
+ * either be an attribute resource, whose value will be retrieved
+ * from the current theme, or an explicit style resource.
+ */
+ @SuppressWarnings({"UnusedDeclaration"})
+ public TextureView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ private void init() {
+ mLayerPaint = new Paint();
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ if (!isHardwareAccelerated()) {
+ Log.w("TextureView", "A TextureView or a subclass can only be "
+ + "used with hardware acceleration enabled.");
+ }
+ }
+
+ /**
+ * The layer type of a TextureView is ignored since a TextureView is always
+ * considered to act as a hardware layer. The optional paint supplied to this
+ * method will however be taken into account when rendering the content of
+ * this TextureView.
+ *
+ * @param layerType The ype of layer to use with this view, must be one of
+ * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
+ * {@link #LAYER_TYPE_HARDWARE}
+ * @param paint The paint used to compose the layer. This argument is optional
+ * and can be null. It is ignored when the layer type is
+ * {@link #LAYER_TYPE_NONE}
+ */
+ @Override
+ public void setLayerType(int layerType, Paint paint) {
+ if (paint != mLayerPaint) {
+ mLayerPaint = paint;
+ invalidate();
+ }
+ }
+
+ /**
+ * Always returns {@link #LAYER_TYPE_HARDWARE}.
+ */
+ @Override
+ public int getLayerType() {
+ return LAYER_TYPE_HARDWARE;
+ }
+
+ /**
+ * Calling this method has no effect.
+ */
+ @Override
+ public void buildLayer() {
+ }
+
+ /**
+ * Subclasses of TextureView cannot do their own rendering
+ * with the {@link Canvas} object.
+ *
+ * @param canvas The Canvas to which the View is rendered.
+ */
+ @Override
+ public final void draw(Canvas canvas) {
+ super.draw(canvas);
+ }
+
+ /**
+ * Subclasses of TextureView cannot do their own rendering
+ * with the {@link Canvas} object.
+ *
+ * @param canvas The Canvas to which the View is rendered.
+ */
+ @Override
+ protected final void onDraw(Canvas canvas) {
+ }
+
+ @Override
+ HardwareLayer getHardwareLayer() {
+ if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+ return null;
+ }
+
+ if (mLayer == null) {
+ mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer();
+ mSurface = mAttachInfo.mHardwareRenderer.createSuraceTexture(mLayer);
+
+ mSurface.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
+ @Override
+ public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+ // Per SurfaceTexture's documentation, the callback may be invoked
+ // from an arbitrary thread
+ post(mUpdateLayerAction);
+ }
+ });
+
+ if (mListener != null) {
+ mListener.onSurfaceTextureAvailable(mSurface);
+ }
+ }
+
+ return mLayer;
+ }
+
+ private void updateLayer() {
+ if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+ return;
+ }
+
+ mSurface.updateTexImage();
+ mSurface.getTransformMatrix(mTextureTransform);
+
+ mAttachInfo.mHardwareRenderer.updateTextureLayer(mLayer, getWidth(), getHeight(),
+ mTextureTransform);
+
+ invalidate();
+ }
+
+ /**
+ * Returns the {@link SurfaceTexture} used by this view. This method
+ * may return null if the view is not attached to a window.
+ */
+ public SurfaceTexture getSurfaceTexture() {
+ return mSurface;
+ }
+
+ /**
+ * Returns the {@link SurfaceTextureListener} currently associated with this
+ * texture view.
+ *
+ * @see #setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener)
+ * @see SurfaceTextureListener
+ */
+ public SurfaceTextureListener getSurfaceTextureListener() {
+ return mListener;
+ }
+
+ /**
+ * Sets the {@link SurfaceTextureListener} used to listen to surface
+ * texture events.
+ *
+ * @see #getSurfaceTextureListener()
+ * @see SurfaceTextureListener
+ */
+ public void setSurfaceTextureListener(SurfaceTextureListener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * This listener can be used to be notified when the surface texture
+ * associated with this texture view is available.
+ */
+ public static interface SurfaceTextureListener {
+ /**
+ * Invoked when a {@link TextureView}'s SurfaceTexture is ready for use.
+ *
+ * @param surface The surface returned by
+ * {@link android.view.TextureView#getSurfaceTexture()}
+ */
+ public void onSurfaceTextureAvailable(SurfaceTexture surface);
+ }
+}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 3e11197df764..4755362537f5 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -19,7 +19,6 @@ package android.webkit;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
@@ -137,6 +136,9 @@ public class WebSettings {
OFF
}
+ // TODO: Keep this up to date
+ private static final String PREVIOUS_VERSION = "3.1";
+
// WebView associated with this WebSettings.
private WebView mWebView;
// BrowserFrame used to access the native frame pointer.
@@ -470,7 +472,14 @@ public class WebSettings {
// Add version
final String version = Build.VERSION.RELEASE;
if (version.length() > 0) {
- buffer.append(version);
+ if (Character.isDigit(version.charAt(0))) {
+ // Release is a version, eg "3.1"
+ buffer.append(version);
+ } else {
+ // Release is a codename, eg "Honeycomb"
+ // In this case, use the previous release's version
+ buffer.append(PREVIOUS_VERSION);
+ }
} else {
// default to "1.0"
buffer.append("1.0");
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index dccfa6c537fb..57df259acca9 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -71,7 +71,7 @@ public class ActionBarImpl extends ActionBar {
private ActionBarContainer mContainerView;
private ActionBarView mActionView;
private ActionBarContextView mUpperContextView;
- private LinearLayout mLowerContextView;
+ private LinearLayout mLowerView;
private View mContentView;
private ViewGroup mExternalTabView;
@@ -106,8 +106,8 @@ public class ActionBarImpl extends ActionBar {
new AnimatorListenerAdapter() { // NORMAL_VIEW
@Override
public void onAnimationEnd(Animator animation) {
- if (mLowerContextView != null) {
- mLowerContextView.removeAllViews();
+ if (mLowerView != null) {
+ mLowerView.removeAllViews();
}
mCurrentModeAnim = null;
hideAllExcept(NORMAL_VIEW);
@@ -162,7 +162,7 @@ public class ActionBarImpl extends ActionBar {
mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
mUpperContextView = (ActionBarContextView) decor.findViewById(
com.android.internal.R.id.action_context_bar);
- mLowerContextView = (LinearLayout) decor.findViewById(
+ mLowerView = (LinearLayout) decor.findViewById(
com.android.internal.R.id.lower_action_context_bar);
mContainerView = (ActionBarContainer) decor.findViewById(
com.android.internal.R.id.action_bar_container);
@@ -173,8 +173,8 @@ public class ActionBarImpl extends ActionBar {
}
mActionView.setContextView(mUpperContextView);
- mContextDisplayMode = mLowerContextView == null ?
- CONTEXT_DISPLAY_NORMAL : CONTEXT_DISPLAY_SPLIT;
+ mContextDisplayMode = mActionView.isSplitActionBar() ?
+ CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
if (!mActionView.hasEmbeddedTabs()) {
HorizontalScrollView tabScroller = new HorizontalScrollView(mContext);
@@ -348,9 +348,9 @@ public class ActionBarImpl extends ActionBar {
mode.invalidate();
mUpperContextView.initForMode(mode);
animateTo(CONTEXT_VIEW);
- if (mLowerContextView != null) {
+ if (mLowerView != null) {
// TODO animate this
- mLowerContextView.setVisibility(View.VISIBLE);
+ mLowerView.setVisibility(View.VISIBLE);
}
mActionMode = mode;
return mode;
@@ -616,9 +616,9 @@ public class ActionBarImpl extends ActionBar {
// Clear out the context mode views after the animation finishes
mUpperContextView.closeMode();
- if (mLowerContextView != null && mLowerContextView.getVisibility() != View.GONE) {
+ if (mLowerView != null && mLowerView.getVisibility() != View.GONE) {
// TODO Animate this
- mLowerContextView.setVisibility(View.GONE);
+ mLowerView.setVisibility(View.GONE);
}
mActionMode = null;
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
new file mode 100644
index 000000000000..2689f09c518e
--- /dev/null
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -0,0 +1,37 @@
+/*
+ * 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.internal.util;
+
+/**
+ * This class defines Message.what base addresses for various protocols that are recognized
+ * to be unique by any {@link com.android.internal.util.Statemachine} implementation. This
+ * allows for interaction between different StateMachine implementations without a conflict
+ * of message codes.
+ *
+ * As an example, all messages in {@link android.net.wifi.WifiStateMachine} will have message
+ * codes with Message.what starting at Protocol.WIFI + 1 and less than or equal to Protocol.WIFI +
+ * Protocol.MAX_MESSAGE
+ *
+ * {@hide}
+ */
+public class Protocol {
+ public static final int MAX_MESSAGE = 0x0000FFFF;
+
+ public static final int BASE_WIFI = 0x00010000;
+ public static final int BASE_DHCP = 0x00020000;
+ //TODO: define all used protocols
+}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index a05fa53e425a..e210b78c268f 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -73,10 +73,11 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
int width = mWidthLimit;
if (mReserveOverflow) {
- OverflowMenuButton button = new OverflowMenuButton(mContext);
- mOverflowButton = button;
- final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- mOverflowButton.measure(spec, spec);
+ if (mOverflowButton == null) {
+ mOverflowButton = new OverflowMenuButton(mContext);
+ final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ mOverflowButton.measure(spec, spec);
+ }
width -= mOverflowButton.getMeasuredWidth();
} else {
mOverflowButton = null;
@@ -88,6 +89,17 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
mScrapActionButtonView = null;
}
+ public void setWidthLimit(int width) {
+ if (mReserveOverflow) {
+ width -= mOverflowButton.getMeasuredWidth();
+ }
+ mActionItemWidthLimit = width;
+ }
+
+ public void setItemLimit(int itemCount) {
+ mMaxItems = itemCount;
+ }
+
@Override
public MenuView getMenuView(ViewGroup root) {
MenuView result = super.getMenuView(root);
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index a572e1168372..0c13f7bfbe60 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -110,7 +110,7 @@ public class ActionBarView extends ViewGroup {
private int mProgressStyle;
private int mIndeterminateProgressStyle;
- private boolean mShowMenu;
+ private boolean mSplitActionBar;
private boolean mUserTitle;
private boolean mIncludeTabs;
@@ -119,6 +119,7 @@ public class ActionBarView extends ViewGroup {
private ActionMenuPresenter mActionMenuPresenter;
private ActionBarContextView mContextView;
+ private ViewGroup mSplitView;
private ActionMenuItem mLogoNavItem;
@@ -245,6 +246,26 @@ public class ActionBarView extends ViewGroup {
addView(mIndeterminateProgressView);
}
+ public void setSplitActionBar(boolean splitActionBar) {
+ if (mSplitActionBar != splitActionBar) {
+ if (mMenuView != null) {
+ if (splitActionBar) {
+ removeView(mMenuView);
+ if (mSplitView != null) {
+ mSplitView.addView(mMenuView);
+ }
+ } else {
+ addView(mMenuView);
+ }
+ }
+ mSplitActionBar = splitActionBar;
+ }
+ }
+
+ public boolean isSplitActionBar() {
+ return mSplitActionBar;
+ }
+
public boolean hasEmbeddedTabs() {
return mIncludeTabs;
}
@@ -284,10 +305,29 @@ public class ActionBarView extends ViewGroup {
final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.MATCH_PARENT);
menuView.setLayoutParams(layoutParams);
- addView(menuView);
+ if (!mSplitActionBar) {
+ addView(menuView);
+ } else {
+ // Allow full screen width in split mode.
+ mActionMenuPresenter.setWidthLimit(
+ getContext().getResources().getDisplayMetrics().widthPixels);
+ // No limit to the item count; use whatever will fit.
+ mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
+ if (mSplitView != null) {
+ mSplitView.addView(menuView);
+ } // We'll add this later if we missed it this time.
+ }
mMenuView = menuView;
}
+ public void setSplitView(ViewGroup splitView) {
+ mSplitView = splitView;
+ splitView.setVisibility(VISIBLE);
+ if (mMenuView != null) {
+ splitView.addView(mMenuView);
+ }
+ }
+
public boolean showOverflowMenu() {
if (mActionMenuPresenter != null) {
return mActionMenuPresenter.showOverflowMenu();
@@ -718,7 +758,7 @@ public class ActionBarView extends ViewGroup {
leftOfCenter -= homeWidth;
}
- if (mMenuView != null) {
+ if (mMenuView != null && mMenuView.getParent() == this) {
availableWidth = measureChildView(mMenuView, availableWidth,
childSpecHeight, 0);
rightOfCenter -= mMenuView.getMeasuredWidth();
@@ -880,7 +920,7 @@ public class ActionBarView extends ViewGroup {
}
int menuLeft = r - l - getPaddingRight();
- if (mMenuView != null) {
+ if (mMenuView != null && mMenuView.getParent() == this) {
positionChildInverse(mMenuView, menuLeft, y, contentHeight);
menuLeft -= mMenuView.getMeasuredWidth();
}
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 314c2ee3b176..af7639a541d8 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -539,6 +539,19 @@ static OpenGLRenderer* android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env
return NULL;
}
+static Layer* android_view_GLES20Canvas_createTextureLayer(JNIEnv* env, jobject clazz,
+ jintArray layerInfo) {
+ Layer* layer = LayerRenderer::createTextureLayer();
+
+ if (layer) {
+ jint* storage = env->GetIntArrayElements(layerInfo, NULL);
+ storage[0] = layer->texture;
+ env->ReleaseIntArrayElements(layerInfo, storage, 0);
+ }
+
+ return layer;
+}
+
static Layer* android_view_GLES20Canvas_createLayer(JNIEnv* env, jobject clazz,
jint width, jint height, jboolean isOpaque, jintArray layerInfo) {
Layer* layer = LayerRenderer::createLayer(width, height, isOpaque);
@@ -563,6 +576,13 @@ static void android_view_GLES20Canvas_resizeLayer(JNIEnv* env, jobject clazz,
env->ReleaseIntArrayElements(layerInfo, storage, 0);
}
+static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject clazz,
+ Layer* layer, jint width, jint height, jfloatArray texTransform) {
+ jfloat* transform = env->GetFloatArrayElements(texTransform, NULL);
+ LayerRenderer::updateTextureLayer(layer, width, height, transform);
+ env->ReleaseFloatArrayElements(texTransform, transform, 0);
+}
+
static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, Layer* layer) {
LayerRenderer::destroyLayer(layer);
}
@@ -696,6 +716,8 @@ static JNINativeMethod gMethods[] = {
{ "nCreateLayerRenderer", "(I)I", (void*) android_view_GLES20Canvas_createLayerRenderer },
{ "nCreateLayer", "(IIZ[I)I", (void*) android_view_GLES20Canvas_createLayer },
{ "nResizeLayer", "(III[I)V" , (void*) android_view_GLES20Canvas_resizeLayer },
+ { "nCreateTextureLayer", "([I)I", (void*) android_view_GLES20Canvas_createTextureLayer },
+ { "nUpdateTextureLayer", "(III[F)V" , (void*) android_view_GLES20Canvas_updateTextureLayer },
{ "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer },
{ "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred },
{ "nDrawLayer", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawLayer },
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index 70af26519ea6..14af446abf20 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -47,5 +47,6 @@ This is an optimized layout for a screen with the Action Bar enabled.
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?android:attr/actionBarStyle"
- android:visibility="gone" />
+ android:visibility="gone"
+ android:gravity="center"/>
</LinearLayout>
diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml
index cfa335e51d47..aebbe411566f 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -51,5 +51,6 @@ the Action Bar enabled overlaying application content.
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
style="?android:attr/actionBarStyle"
- android:visibility="gone" />
+ android:visibility="gone"
+ android:gravity="center"/>
</RelativeLayout>
diff --git a/core/res/res/values-w480dp/bools.xml b/core/res/res/values-w480dp/bools.xml
index c202d90d403b..8206e792dbe5 100644
--- a/core/res/res/values-w480dp/bools.xml
+++ b/core/res/res/values-w480dp/bools.xml
@@ -19,4 +19,5 @@
<resources>
<bool name="allow_action_menu_item_text_with_icon">true</bool>
<bool name="action_bar_embed_tabs">true</bool>
+ <bool name="split_action_bar_is_narrow">false</bool>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3a44e4f73a82..dac3bd24aa22 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -299,6 +299,10 @@
when there is not reserved space for their UI (such as an Action Bar). -->
<attr name="windowActionModeOverlay" format="boolean" />
+ <!-- Flag indicating that the action bar should be split to provide more
+ room for elements. -->
+ <attr name="windowSplitActionBar" format="boolean" />
+
<!-- Defines the default soft input state that this window would
like when it is displayed. -->
<attr name="windowSoftInputMode">
@@ -1429,6 +1433,7 @@
<attr name="windowActionBar" />
<attr name="windowActionModeOverlay" />
<attr name="windowActionBarOverlay" />
+ <attr name="windowSplitActionBar" />
<attr name="windowEnableSplitTouch" />
<attr name="windowCloseOnTouchOutside" />
<!-- The minimum width the window is allowed to be, along the major
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index 6eb006f32f03..8e27be4a904d 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -19,4 +19,5 @@
<resources>
<bool name="allow_action_menu_item_text_with_icon">false</bool>
<bool name="action_bar_embed_tabs">false</bool>
+ <bool name="split_action_bar_is_narrow">true</bool>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 501d4784632a..7ca5e98a9873 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1660,6 +1660,8 @@
<public type="style" name="Theme.Holo.Light.NoActionBar" />
<public type="style" name="TextAppearance.SuggestionHighlight" />
+ <public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" />
+ <public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" />
<public type="attr" name="textSuggestionsWindowStyle" />
<public type="attr" name="textEditSuggestionsBottomWindowLayout" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index be7b42fa61fc..cdfdd11a6492 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -1538,4 +1538,17 @@
<item name="android:windowNoTitle">true</item>
</style>
+ <!-- Variant of the holographic (dark) theme with an action bar that
+ splits across the top and bottom of the activity when constrained
+ for horizontal space. -->
+ <style name="Theme.Holo.SplitActionBarWhenNarrow">
+ <item name="android:windowSplitActionBar">@android:bool/split_action_bar_is_narrow</item>
+ </style>
+
+ <!-- Variant of the holographic (light) theme with an action bar that
+ splits across the top and bottom of the activity when constrained
+ for horizontal space. -->
+ <style name="Theme.Holo.Light.SplitActionBarWhenNarrow">
+ <item name="android:windowSplitActionBar">@android:bool/split_action_bar_is_narrow</item>
+ </style>
</resources>
diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd
index 2da022c3c58e..4a574be82244 100644
--- a/docs/html/guide/topics/ui/declaring-layout.jd
+++ b/docs/html/guide/topics/ui/declaring-layout.jd
@@ -295,7 +295,9 @@ Available Resources</a> document.</p>
{@link android.view.ViewGroup.MarginLayoutParams} for further information.
</p>
-<p>For more information about dimensions, see <a href="{@docRoot}guide/topics/resources/available-resources.html#dimension">Dimension Values</a>.</p>
+ <p>For more information about dimensions, see
+ <a href="{@docRoot}guide/topics/resources/more-resources.html#Dimension">Dimension Values</a>.
+ </p>
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 754ebfb2953a..4c505ec95e1d 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -420,6 +420,16 @@ public class RenderScript {
validate();
rsnScriptInvoke(mContext, id, slot);
}
+ native void rsnScriptForEach(int con, int id, int slot, int ain, int aout, byte[] params);
+ native void rsnScriptForEach(int con, int id, int slot, int ain, int aout);
+ synchronized void nScriptForEach(int id, int slot, int ain, int aout, byte[] params) {
+ validate();
+ if (params == null) {
+ rsnScriptForEach(mContext, id, slot, ain, aout);
+ } else {
+ rsnScriptForEach(mContext, id, slot, ain, aout, params);
+ }
+ }
native void rsnScriptInvokeV(int con, int id, int slot, byte[] params);
synchronized void nScriptInvokeV(int id, int slot, byte[] params) {
validate();
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index 56abba51a836..11aa13476bff 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -43,6 +43,35 @@ public class Script extends BaseObj {
}
}
+ /**
+ * @hide
+ * Only intended for use by generated reflected code.
+ *
+ * @param slot
+ * @param ain
+ * @param aout
+ * @param v
+ */
+ protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v) {
+ if (ain == null && aout == null) {
+ throw new RSIllegalArgumentException(
+ "At least one of ain or aout is required to be non-null.");
+ }
+ int in_id = 0;
+ if (ain != null) {
+ in_id = ain.getID();
+ }
+ int out_id = 0;
+ if (aout != null) {
+ out_id = aout.getID();
+ }
+ byte[] params = null;
+ if (v != null) {
+ params = v.getData();
+ }
+ mRS.nScriptForEach(getID(), slot, in_id, out_id, params);
+ }
+
Script(int id, RenderScript rs) {
super(id, rs);
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index c3f2360e99bb..3f6f8c366694 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -866,6 +866,24 @@ nScriptInvokeV(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slo
_env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
}
+static void
+nScriptForEach(JNIEnv *_env, jobject _this, RsContext con,
+ jint script, jint slot, jint ain, jint aout)
+{
+ LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
+ rsScriptForEach(con, (RsScript)script, slot, (RsAllocation)ain, (RsAllocation)aout, NULL, 0);
+}
+static void
+nScriptForEachV(JNIEnv *_env, jobject _this, RsContext con,
+ jint script, jint slot, jint ain, jint aout, jbyteArray params)
+{
+ LOG_API("nScriptForEach, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
+ jint len = _env->GetArrayLength(params);
+ jbyte *ptr = _env->GetByteArrayElements(params, NULL);
+ rsScriptForEach(con, (RsScript)script, slot, (RsAllocation)ain, (RsAllocation)aout, ptr, len);
+ _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
+}
+
// -----------------------------------
@@ -1235,6 +1253,8 @@ static JNINativeMethod methods[] = {
{"rsnScriptSetTimeZone", "(II[B)V", (void*)nScriptSetTimeZone },
{"rsnScriptInvoke", "(III)V", (void*)nScriptInvoke },
{"rsnScriptInvokeV", "(III[B)V", (void*)nScriptInvokeV },
+{"rsnScriptForEach", "(IIIII)V", (void*)nScriptForEach },
+{"rsnScriptForEach", "(IIIII[B)V", (void*)nScriptForEachV },
{"rsnScriptSetVarI", "(IIII)V", (void*)nScriptSetVarI },
{"rsnScriptSetVarJ", "(IIIJ)V", (void*)nScriptSetVarJ },
{"rsnScriptSetVarF", "(IIIF)V", (void*)nScriptSetVarF },
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 58bb0d31f4e2..b5737ffff18f 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -38,3 +38,7 @@ ifeq ($(TARGET_SIMULATOR),true)
endif
include $(BUILD_SHARED_LIBRARY)
+
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk
index ecd09951153e..8d3a9b5ebafa 100644
--- a/libs/gui/tests/Android.mk
+++ b/libs/gui/tests/Android.mk
@@ -36,9 +36,6 @@ LOCAL_C_INCLUDES := \
include $(BUILD_EXECUTABLE)
-# Build the manual test programs.
-include $(call all-subdir-makefiles)
-
endif
# Include subdirectory makefiles
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 6c4a2a9a972d..16566b80164d 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -45,6 +45,8 @@ struct Layer {
mesh = NULL;
meshIndices = NULL;
meshElementCount = 0;
+ isCacheable = true;
+ isTextureLayer = false;
}
~Layer() {
@@ -137,6 +139,22 @@ struct Layer {
TextureVertex* mesh;
uint16_t* meshIndices;
GLsizei meshElementCount;
+
+ /**
+ * If set to true (by default), the layer can be reused.
+ */
+ bool isCacheable;
+
+ /**
+ * When set to true, this layer must be treated as a texture
+ * layer.
+ */
+ bool isTextureLayer;
+
+ /**
+ * Optional texture coordinates transform.
+ */
+ mat4 texTransform;
}; // struct Layer
}; // namespace uirenderer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index a9710ad6adbf..b2d795f3516b 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -154,6 +154,8 @@ bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t heigh
}
bool LayerCache::put(Layer* layer) {
+ if (!layer->isCacheable) return false;
+
const uint32_t size = layer->width * layer->height * 4;
// Don't even try to cache a layer that's bigger than the cache
if (size < mMaxSize) {
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index ca1e7ae0027b..e167336c8657 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -20,6 +20,7 @@
#include "LayerCache.h"
#include "LayerRenderer.h"
+#include "Matrix.h"
#include "Properties.h"
#include "Rect.h"
@@ -165,6 +166,40 @@ void LayerRenderer::generateMesh() {
// Layers management
///////////////////////////////////////////////////////////////////////////////
+Layer* LayerRenderer::createTextureLayer() {
+ LAYER_RENDERER_LOGD("Creating new texture layer");
+
+ Layer* layer = new Layer(0, 0);
+ layer->isCacheable = false;
+ layer->isTextureLayer = true;
+ layer->blend = true;
+ layer->empty = true;
+ layer->fbo = 0;
+ layer->colorFilter = NULL;
+ layer->fbo = 0;
+ layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
+ layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f);
+ layer->alpha = 255;
+ layer->mode = SkXfermode::kSrcOver_Mode;
+ layer->colorFilter = NULL;
+ layer->region.clear();
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glGenTextures(1, &layer->texture);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, layer->texture);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ return layer;
+}
+
Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height);
@@ -244,6 +279,18 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
return true;
}
+void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
+ float* transform) {
+ if (layer) {
+ layer->width = width;
+ layer->height = height;
+ layer->layer.set(0.0f, 0.0f, width, height);
+ layer->region.set(width, height);
+ layer->regionRect.set(0.0f, 0.0f, width, height);
+ layer->texTransform.load(transform);
+ }
+}
+
void LayerRenderer::destroyLayer(Layer* layer) {
if (layer) {
LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo);
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index d2f565e4f307..b3cd5db4fbe2 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -53,8 +53,11 @@ public:
Region* getRegion();
GLint getTargetFbo();
+ static Layer* createTextureLayer();
static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
+ static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
+ float* transform);
static void destroyLayer(Layer* layer);
static void destroyLayerDeferred(Layer* layer);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index ea4283897273..34d8fd31e206 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -633,15 +633,43 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
}
}
+void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
+ float alpha = layer->alpha / 255.0f;
+
+ setupDraw();
+ setupDrawWithExternalTexture();
+ setupDrawColor(alpha, alpha, alpha, alpha);
+ setupDrawColorFilter();
+ setupDrawBlending(layer->blend, layer->mode);
+ setupDrawProgram();
+ setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom);
+ setupDrawPureColorUniforms();
+ setupDrawColorFilterUniforms();
+ setupDrawExternalTexture(layer->texture);
+ setupDrawTextureTransform(layer->texTransform);
+ setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+
+ finishDrawTexture();
+}
+
void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
- const Rect& texCoords = layer->texCoords;
- resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom);
+ if (!layer->isTextureLayer) {
+ const Rect& texCoords = layer->texCoords;
+ resetDrawTextureTexCoords(texCoords.left, texCoords.top,
+ texCoords.right, texCoords.bottom);
- drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
- layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
- &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, swap, swap);
+ drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
+ layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
+ &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, swap, swap);
- resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+ resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+ } else {
+ resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
+ drawTextureLayer(layer, rect);
+ resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+ }
}
void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
@@ -882,6 +910,10 @@ void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
mDescription.hasAlpha8Texture = isAlpha8;
}
+void OpenGLRenderer::setupDrawWithExternalTexture() {
+ mDescription.hasExternalTexture = true;
+}
+
void OpenGLRenderer::setupDrawAALine() {
mDescription.hasWidth = true;
}
@@ -1055,6 +1087,19 @@ void OpenGLRenderer::setupDrawTexture(GLuint texture) {
glEnableVertexAttribArray(mTexCoordsSlot);
}
+void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) {
+ bindExternalTexture(texture);
+ glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++);
+
+ mTexCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
+ glEnableVertexAttribArray(mTexCoordsSlot);
+}
+
+void OpenGLRenderer::setupDrawTextureTransform(mat4& transform) {
+ glUniformMatrix4fv(mCaches.currentProgram->getUniform("mainTextureTransform"), 1,
+ GL_FALSE, &transform.data[0]);
+}
+
void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) {
if (!vertices) {
mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 918e1fb4178d..0ffd70b4ef99 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -248,6 +248,8 @@ private:
*/
void composeLayerRect(Layer* layer, const Rect& rect, bool swap = false);
+ void drawTextureLayer(Layer* layer, const Rect& rect);
+
/**
* Mark the layer as dirty at the specified coordinates. The coordinates
* are transformed with the supplied matrix.
@@ -387,6 +389,14 @@ private:
}
/**
+ * Binds the specified EGLImage texture. The texture unit must have been selected
+ * prior to calling this method.
+ */
+ inline void bindExternalTexture(GLuint texture) {
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
+ }
+
+ /**
* Sets the wrap modes for the specified texture. The wrap modes are modified
* only when needed.
*/
@@ -425,6 +435,7 @@ private:
* Various methods to setup OpenGL rendering.
*/
void setupDrawWithTexture(bool isAlpha8 = false);
+ void setupDrawWithExternalTexture();
void setupDrawAALine();
void setupDrawPoint(float pointSize);
void setupDrawColor(int color);
@@ -453,6 +464,8 @@ private:
void setupDrawColorFilterUniforms();
void setupDrawSimpleMesh();
void setupDrawTexture(GLuint texture);
+ void setupDrawExternalTexture(GLuint texture);
+ void setupDrawTextureTransform(mat4& transform);
void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0);
void setupDrawVertices(GLvoid* vertices);
void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, float strokeWidth);
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 80b1917809ca..62ac2baaf7b6 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -41,6 +41,8 @@ const char* gVS_Header_Attributes_TexCoords =
"attribute vec2 texCoords;\n";
const char* gVS_Header_Attributes_Distance =
"attribute float vtxDistance;\n";
+const char* gVS_Header_Uniforms_TextureTransform =
+ "uniform mat4 mainTextureTransform;\n";
const char* gVS_Header_Uniforms =
"uniform mat4 transform;\n";
const char* gVS_Header_Uniforms_IsPoint =
@@ -76,6 +78,8 @@ const char* gVS_Main =
"\nvoid main(void) {\n";
const char* gVS_Main_OutTexCoords =
" outTexCoords = texCoords;\n";
+const char* gVS_Main_OutTransformedTexCoords =
+ " outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n";
const char* gVS_Main_OutGradient[3] = {
// Linear
" linear = vec2((screenSpace * position).x, 0.5);\n",
@@ -103,6 +107,8 @@ const char* gVS_Footer =
const char* gFS_Header_Extension_FramebufferFetch =
"#extension GL_NV_shader_framebuffer_fetch : enable\n\n";
+const char* gFS_Header_Extension_ExternalTexture =
+ "#extension GL_OES_EGL_image_external : require\n\n";
const char* gFS_Header =
"precision mediump float;\n\n";
const char* gFS_Uniforms_Color =
@@ -116,6 +122,8 @@ const char* gFS_Header_Uniforms_PointHasBitmap =
"uniform float pointSize;\n";
const char* gFS_Uniforms_TextureSampler =
"uniform sampler2D sampler;\n";
+const char* gFS_Uniforms_ExternalTextureSampler =
+ "uniform samplerExternalOES sampler;\n";
const char* gFS_Uniforms_GradientSampler[3] = {
// Linear
"uniform sampler2D gradientSampler;\n",
@@ -369,7 +377,7 @@ Program* ProgramCache::generateProgram(const ProgramDescription& description, pr
String8 ProgramCache::generateVertexShader(const ProgramDescription& description) {
// Add attributes
String8 shader(gVS_Header_Attributes);
- if (description.hasTexture) {
+ if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Header_Attributes_TexCoords);
}
if (description.hasWidth) {
@@ -377,6 +385,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
}
// Uniforms
shader.append(gVS_Header_Uniforms);
+ if (description.hasExternalTexture) {
+ shader.append(gVS_Header_Uniforms_TextureTransform);
+ }
if (description.hasGradient) {
shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]);
}
@@ -387,7 +398,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
shader.append(gVS_Header_Uniforms_IsPoint);
}
// Varyings
- if (description.hasTexture) {
+ if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Header_Varyings_HasTexture);
}
if (description.hasWidth) {
@@ -407,6 +418,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
if (description.hasTexture) {
shader.append(gVS_Main_OutTexCoords);
}
+ if (description.hasExternalTexture) {
+ shader.append(gVS_Main_OutTransformedTexCoords);
+ }
if (description.hasWidth) {
shader.append(gVS_Main_Width);
}
@@ -440,11 +454,14 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
if (blendFramebuffer) {
shader.append(gFS_Header_Extension_FramebufferFetch);
}
+ if (description.hasExternalTexture) {
+ shader.append(gFS_Header_Extension_ExternalTexture);
+ }
shader.append(gFS_Header);
// Varyings
- if (description.hasTexture) {
+ if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Header_Varyings_HasTexture);
}
if (description.hasWidth) {
@@ -461,7 +478,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
// Uniforms
int modulateOp = MODULATE_OP_NO_MODULATE;
- const bool singleColor = !description.hasTexture &&
+ const bool singleColor = !description.hasTexture && !description.hasExternalTexture &&
!description.hasGradient && !description.hasBitmap;
if (description.modulate || singleColor) {
@@ -471,6 +488,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
if (description.hasTexture) {
shader.append(gFS_Uniforms_TextureSampler);
}
+ if (description.hasExternalTexture) {
+ shader.append(gFS_Uniforms_ExternalTextureSampler);
+ }
if (description.hasWidth) {
shader.append(gFS_Uniforms_Width);
}
@@ -487,11 +507,11 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
bool fast = false;
const bool noShader = !description.hasGradient && !description.hasBitmap;
- const bool singleTexture = description.hasTexture &&
+ const bool singleTexture = (description.hasTexture || description.hasExternalTexture) &&
!description.hasAlpha8Texture && noShader;
const bool singleA8Texture = description.hasTexture &&
description.hasAlpha8Texture && noShader;
- const bool singleGradient = !description.hasTexture &&
+ const bool singleGradient = !description.hasTexture && !description.hasExternalTexture &&
description.hasGradient && !description.hasBitmap &&
description.gradientType == ProgramDescription::kGradientLinear;
@@ -554,7 +574,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
// Begin the shader
shader.append(gFS_Main); {
// Stores the result in fragColor directly
- if (description.hasTexture) {
+ if (description.hasTexture || description.hasExternalTexture) {
if (description.hasAlpha8Texture) {
if (!description.hasGradient && !description.hasBitmap) {
shader.append(gFS_Main_FetchA8Texture[modulateOp]);
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 18d98cb05e10..70909fd622bf 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -77,6 +77,8 @@ namespace uirenderer {
#define PROGRAM_HAS_WIDTH_SHIFT 37
+#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
+
///////////////////////////////////////////////////////////////////////////////
// Types
///////////////////////////////////////////////////////////////////////////////
@@ -113,6 +115,7 @@ struct ProgramDescription {
// Texturing
bool hasTexture;
bool hasAlpha8Texture;
+ bool hasExternalTexture;
// Modulate, this should only be set when setColor() return true
bool modulate;
@@ -151,6 +154,7 @@ struct ProgramDescription {
void reset() {
hasTexture = false;
hasAlpha8Texture = false;
+ hasExternalTexture = false;
hasWidth = false;
@@ -240,6 +244,7 @@ struct ProgramDescription {
if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT;
if (hasWidth) key |= programid(0x1) << PROGRAM_HAS_WIDTH_SHIFT;
+ if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
return key;
}
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 998296ba3f08..6310cf6b36ab 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -188,7 +188,6 @@ AllocationCopyToBitmap {
Allocation1DData {
- handcodeApi
param RsAllocation va
param uint32_t xoff
param uint32_t lod
@@ -197,7 +196,6 @@ Allocation1DData {
}
Allocation1DElementData {
- handcodeApi
param RsAllocation va
param uint32_t x
param uint32_t lod
@@ -290,12 +288,19 @@ ScriptInvoke {
}
ScriptInvokeV {
- handcodeApi
param RsScript s
param uint32_t slot
param const void * data
}
+ScriptForEach {
+ param RsScript s
+ param uint32_t slot
+ param RsAllocation ain
+ param RsAllocation aout
+ param const void * usr
+}
+
ScriptSetVarI {
param RsScript s
param uint32_t slot
@@ -327,7 +332,6 @@ ScriptSetVarD {
}
ScriptSetVarV {
- handcodeApi
param RsScript s
param uint32_t slot
param const void * data
diff --git a/libs/rs/rsHandcode.h b/libs/rs/rsHandcode.h
index da51d95b4e27..e6b722cb0704 100644
--- a/libs/rs/rsHandcode.h
+++ b/libs/rs/rsHandcode.h
@@ -7,90 +7,3 @@ static inline void rsHCAPI_ContextFinish (RsContext rsc) {
io->mToCore.commitSync(RS_CMD_ID_ContextFinish, size);
}
-static inline void rsHCAPI_ScriptInvokeV (RsContext rsc, RsScript va, uint32_t slot, const void * data, size_t sizeBytes) {
- ThreadIO *io = &((Context *)rsc)->mIO;
- uint32_t size = sizeof(RS_CMD_ScriptInvokeV);
- if (sizeBytes < DATA_SYNC_SIZE) {
- size += (sizeBytes + 3) & ~3;
- }
- RS_CMD_ScriptInvokeV *cmd = static_cast<RS_CMD_ScriptInvokeV *>(io->mToCore.reserve(size));
- cmd->s = va;
- cmd->slot = slot;
- cmd->data_length = sizeBytes;
- cmd->data = data;
- if (sizeBytes < DATA_SYNC_SIZE) {
- cmd->data = (void *)(cmd+1);
- memcpy(cmd+1, data, sizeBytes);
- io->mToCore.commit(RS_CMD_ID_ScriptInvokeV, size);
- } else {
- io->mToCore.commitSync(RS_CMD_ID_ScriptInvokeV, size);
- }
-}
-
-
-static inline void rsHCAPI_ScriptSetVarV (RsContext rsc, RsScript va, uint32_t slot, const void * data, size_t sizeBytes) {
- ThreadIO *io = &((Context *)rsc)->mIO;
- uint32_t size = sizeof(RS_CMD_ScriptSetVarV);
- if (sizeBytes < DATA_SYNC_SIZE) {
- size += (sizeBytes + 3) & ~3;
- }
- RS_CMD_ScriptSetVarV *cmd = static_cast<RS_CMD_ScriptSetVarV *>(io->mToCore.reserve(size));
- cmd->s = va;
- cmd->slot = slot;
- cmd->data_length = sizeBytes;
- cmd->data = data;
- if (sizeBytes < DATA_SYNC_SIZE) {
- cmd->data = (void *)(cmd+1);
- memcpy(cmd+1, data, sizeBytes);
- io->mToCore.commit(RS_CMD_ID_ScriptSetVarV, size);
- } else {
- io->mToCore.commitSync(RS_CMD_ID_ScriptSetVarV, size);
- }
-}
-
-static inline void rsHCAPI_Allocation1DData (RsContext rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
- uint32_t count, const void * data, size_t sizeBytes) {
- ThreadIO *io = &((Context *)rsc)->mIO;
- uint32_t size = sizeof(RS_CMD_Allocation1DData);
- if (sizeBytes < DATA_SYNC_SIZE) {
- size += (sizeBytes + 3) & ~3;
- }
- RS_CMD_Allocation1DData *cmd = static_cast<RS_CMD_Allocation1DData *>(io->mToCore.reserve(size));
- cmd->va = va;
- cmd->xoff = xoff;
- cmd->lod = lod;
- cmd->count = count;
- cmd->data = data;
- cmd->data_length = sizeBytes;
- if (sizeBytes < DATA_SYNC_SIZE) {
- cmd->data = (void *)(cmd+1);
- memcpy(cmd+1, data, sizeBytes);
- io->mToCore.commit(RS_CMD_ID_Allocation1DData, size);
- } else {
- io->mToCore.commitSync(RS_CMD_ID_Allocation1DData, size);
- }
-}
-
-static inline void rsHCAPI_Allocation1DElementData (RsContext rsc, RsAllocation va, uint32_t x, uint32_t lod,
- const void * data, size_t sizeBytes, uint32_t comp_offset) {
- ThreadIO *io = &((Context *)rsc)->mIO;
- uint32_t size = sizeof(RS_CMD_Allocation1DElementData);
- if (sizeBytes < DATA_SYNC_SIZE) {
- size += (sizeBytes + 3) & ~3;
- }
- RS_CMD_Allocation1DElementData *cmd = static_cast<RS_CMD_Allocation1DElementData *>(io->mToCore.reserve(size));
- cmd->va = va;
- cmd->x = x;
- cmd->lod = lod;
- cmd->data = data;
- cmd->comp_offset = comp_offset;
- cmd->data_length = sizeBytes;
- if (sizeBytes < DATA_SYNC_SIZE) {
- cmd->data = (void *)(cmd+1);
- memcpy(cmd+1, data, sizeBytes);
- io->mToCore.commit(RS_CMD_ID_Allocation1DElementData, size);
- } else {
- io->mToCore.commitSync(RS_CMD_ID_Allocation1DElementData, size);
- }
-}
-
diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp
index b84014fa31d4..7641cab03c27 100644
--- a/libs/rs/rsScript.cpp
+++ b/libs/rs/rsScript.cpp
@@ -87,6 +87,16 @@ void rsi_ScriptSetTimeZone(Context * rsc, RsScript vs, const char * timeZone, ui
s->mEnviroment.mTimeZone = timeZone;
}
+void rsi_ScriptForEach(Context *rsc, RsScript vs, uint32_t slot,
+ RsAllocation vain, RsAllocation vaout,
+ const void *params, uint32_t paramLen) {
+ Script *s = static_cast<Script *>(vs);
+ s->runForEach(rsc,
+ static_cast<const Allocation *>(vain), static_cast<Allocation *>(vaout),
+ params, paramLen);
+
+}
+
void rsi_ScriptInvoke(Context *rsc, RsScript vs, uint32_t slot) {
Script *s = static_cast<Script *>(vs);
s->Invoke(rsc, slot, NULL, 0);
diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp
index 6cf07de7920b..6e959a74d129 100644
--- a/libs/rs/rsThreadIO.cpp
+++ b/libs/rs/rsThreadIO.cpp
@@ -58,7 +58,7 @@ bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) {
LOGE("playCoreCommands error con %p, cmd %i", con, cmdID);
mToCore.printDebugData();
}
- gPlaybackFuncs[cmdID](con, data);
+ gPlaybackFuncs[cmdID](con, data, cmdSize << 2);
mToCore.next();
}
return ret;
diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c
index 14b380a34312..0059f1924589 100644
--- a/libs/rs/rsg_generator.c
+++ b/libs/rs/rsg_generator.c
@@ -53,6 +53,10 @@ void printVarType(FILE *f, const VarType *vt) {
fprintf(f, "*");
}
}
+}
+
+void printVarTypeAndName(FILE *f, const VarType *vt) {
+ printVarType(f, vt);
if (vt->name[0]) {
fprintf(f, " %s", vt->name);
@@ -65,7 +69,7 @@ void printArgList(FILE *f, const ApiEntry * api, int assumePrevious) {
if (ct || assumePrevious) {
fprintf(f, ", ");
}
- printVarType(f, &api->params[ct]);
+ printVarTypeAndName(f, &api->params[ct]);
}
}
@@ -86,7 +90,7 @@ void printStructures(FILE *f) {
for (ct2=0; ct2 < api->paramCount; ct2++) {
fprintf(f, " ");
- printVarType(f, &api->params[ct2]);
+ printVarTypeAndName(f, &api->params[ct2]);
fprintf(f, ";\n");
}
fprintf(f, "};\n\n");
@@ -94,7 +98,7 @@ void printStructures(FILE *f) {
}
void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext) {
- printVarType(f, &api->ret);
+ printVarTypeAndName(f, &api->ret);
fprintf(f, " %s%s (", prefix, api->name);
if (!api->nocontext) {
if (addContext) {
@@ -127,6 +131,32 @@ void printPlaybackFuncs(FILE *f, const char *prefix) {
}
}
+static int hasInlineDataPointers(const ApiEntry * api) {
+ int ret = 0;
+ int ct;
+ if (api->sync || api->ret.typeName[0]) {
+ return 0;
+ }
+ for (ct=0; ct < api->paramCount; ct++) {
+ const VarType *vt = &api->params[ct];
+
+ if (!vt->isConst && vt->ptrLevel) {
+ // Non-const pointers cannot be inlined.
+ return 0;
+ }
+ if (vt->ptrLevel > 1) {
+ // not handled yet.
+ return 0;
+ }
+
+ if (vt->isConst && vt->ptrLevel) {
+ // Non-const pointers cannot be inlined.
+ ret = 1;
+ }
+ }
+ return ret;
+}
+
void printApiCpp(FILE *f) {
int ct;
int ct2;
@@ -161,28 +191,62 @@ void printApiCpp(FILE *f) {
fprintf(f, ");\n");
} else {
fprintf(f, " ThreadIO *io = &((Context *)rsc)->mIO;\n");
+ fprintf(f, " uint32_t size = sizeof(RS_CMD_%s);\n", api->name);
+ if (hasInlineDataPointers(api)) {
+ fprintf(f, " uint32_t dataSize = 0;\n");
+ for (ct2=0; ct2 < api->paramCount; ct2++) {
+ const VarType *vt = &api->params[ct2];
+ if (vt->isConst && vt->ptrLevel) {
+ fprintf(f, " dataSize += %s_length;\n", vt->name);
+ }
+ }
+ }
+
//fprintf(f, " LOGE(\"add command %s\\n\");\n", api->name);
fprintf(f, " RS_CMD_%s *cmd = static_cast<RS_CMD_%s *>(io->mToCore.reserve(sizeof(RS_CMD_%s)));\n", api->name, api->name, api->name);
- fprintf(f, " uint32_t size = sizeof(RS_CMD_%s);\n", api->name);
+ if (hasInlineDataPointers(api)) {
+ fprintf(f, " uint8_t *payload = (uint8_t *)&cmd[1];\n");
+ }
for (ct2=0; ct2 < api->paramCount; ct2++) {
const VarType *vt = &api->params[ct2];
needFlush += vt->ptrLevel;
- fprintf(f, " cmd->%s = %s;\n", vt->name, vt->name);
+ if (vt->ptrLevel && hasInlineDataPointers(api)) {
+ fprintf(f, " if (dataSize < 1024) {\n");
+ fprintf(f, " memcpy(payload, %s, %s_length);\n", vt->name, vt->name);
+ fprintf(f, " cmd->%s = (", vt->name);
+ printVarType(f, vt);
+ fprintf(f, ")payload;\n");
+ fprintf(f, " payload += %s_length;\n", vt->name);
+ fprintf(f, " } else {\n");
+ fprintf(f, " cmd->%s = %s;\n", vt->name, vt->name);
+ fprintf(f, " }\n");
+
+ } else {
+ fprintf(f, " cmd->%s = %s;\n", vt->name, vt->name);
+ }
}
if (api->ret.typeName[0]) {
needFlush = 1;
}
- fprintf(f, " io->mToCore.commit");
- if (needFlush) {
- fprintf(f, "Sync");
+ if (hasInlineDataPointers(api)) {
+ fprintf(f, " if (dataSize < 1024) {\n");
+ fprintf(f, " io->mToCore.commit(RS_CMD_ID_%s, size + dataSize);\n", api->name);
+ fprintf(f, " } else {\n");
+ fprintf(f, " io->mToCore.commitSync(RS_CMD_ID_%s, size);\n", api->name);
+ fprintf(f, " }\n");
+ } else {
+ fprintf(f, " io->mToCore.commit");
+ if (needFlush) {
+ fprintf(f, "Sync");
+ }
+ fprintf(f, "(RS_CMD_ID_%s, size);\n", api->name);
}
- fprintf(f, "(RS_CMD_ID_%s, size);\n", api->name);
if (api->ret.typeName[0]) {
fprintf(f, " return reinterpret_cast<");
- printVarType(f, &api->ret);
+ printVarTypeAndName(f, &api->ret);
fprintf(f, ">(io->mToCoreRet);\n");
}
}
@@ -212,11 +276,12 @@ void printPlaybackCpp(FILE *f) {
continue;
}
- fprintf(f, "void rsp_%s(Context *con, const void *vp)\n", api->name);
+ fprintf(f, "void rsp_%s(Context *con, const void *vp, size_t cmdSizeBytes)\n", api->name);
fprintf(f, "{\n");
//fprintf(f, " LOGE(\"play command %s\\n\");\n", api->name);
fprintf(f, " const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
+
fprintf(f, " ");
if (api->ret.typeName[0]) {
fprintf(f, "con->mIO.mToCoreRet = (intptr_t)");
@@ -246,6 +311,8 @@ void printPlaybackCpp(FILE *f) {
fprintf(f, "};\n");
}
+void yylex();
+
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "usage: %s commandFile outFile\n", argv[0]);
@@ -280,7 +347,7 @@ int main(int argc, char **argv) {
printStructures(f);
printFuncDecls(f, "rsi_", 1);
printPlaybackFuncs(f, "rsp_");
- fprintf(f, "\n\ntypedef void (*RsPlaybackFunc)(Context *, const void *);\n");
+ fprintf(f, "\n\ntypedef void (*RsPlaybackFunc)(Context *, const void *, size_t sizeBytes);\n");
fprintf(f, "extern RsPlaybackFunc gPlaybackFuncs[%i];\n", apiCount + 1);
fprintf(f, "}\n");
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index cc689bbd798c..2817df8ebabc 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1310,7 +1310,7 @@ public class LocationManager {
* @param listener GPS status listener object to register
*
* @return true if the listener was successfully added
- *
+ *
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
*/
public boolean addGpsStatusListener(GpsStatus.Listener listener) {
@@ -1434,7 +1434,7 @@ public class LocationManager {
return false;
}
}
-
+
/**
* Used by NetInitiatedActivity to report user response
* for network initiated GPS fix requests.
@@ -1449,5 +1449,5 @@ public class LocationManager {
return false;
}
}
-
+
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 73003c855f84..27b7e1c87419 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2587,6 +2587,21 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if ((localFeatures & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
mActionBar.initIndeterminateProgress();
}
+
+ final boolean splitActionBar = getWindowStyle().getBoolean(
+ com.android.internal.R.styleable.Window_windowSplitActionBar, false);
+ if (splitActionBar) {
+ final ViewGroup splitView = (ViewGroup) findViewById(
+ com.android.internal.R.id.lower_action_context_bar);
+ if (splitView != null) {
+ mActionBar.setSplitActionBar(splitActionBar);
+ mActionBar.setSplitView(splitView);
+ } else {
+ Log.e(TAG, "Window style requested split action bar with " +
+ "incompatible window decor! Ignoring request.");
+ }
+ }
+
// Post the panel invalidate for later; avoid application onCreateOptionsMenu
// being called in the middle of onCreate or similar.
mDecor.post(new Runnable() {
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
index 9c43067363a9..f04fb020fff7 100644
--- a/services/input/InputWindow.h
+++ b/services/input/InputWindow.h
@@ -114,10 +114,11 @@ struct InputWindow {
TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
- TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+14,
+ TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
TYPE_DRAG = FIRST_SYSTEM_WINDOW+16,
- TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+17,
+ TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17,
+ TYPE_POINTER = FIRST_SYSTEM_WINDOW+18,
LAST_SYSTEM_WINDOW = 2999,
};
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index d841cb3a7766..02332b7aa918 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -16,6 +16,9 @@
package com.android.server;
+import com.android.internal.R;
+import com.android.internal.telephony.TelephonyProperties;
+
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -30,7 +33,6 @@ import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.INetworkManagementEventObserver;
import android.net.IThrottleManager;
-import android.net.SntpClient;
import android.net.ThrottleManager;
import android.os.Binder;
import android.os.Environment;
@@ -47,10 +49,9 @@ import android.os.SystemProperties;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.NtpTrustedTime;
import android.util.Slog;
-
-import com.android.internal.R;
-import com.android.internal.telephony.TelephonyProperties;
+import android.util.TrustedTime;
import java.io.BufferedWriter;
import java.io.File;
@@ -60,11 +61,11 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
import java.util.GregorianCalendar;
import java.util.Properties;
import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
// TODO - add comments - reference the ThrottleManager for public API
public class ThrottleService extends IThrottleManager.Stub {
@@ -84,6 +85,11 @@ public class ThrottleService extends IThrottleManager.Stub {
private static final int TESTING_RESET_PERIOD_SEC = 60 * 10;
private static final long TESTING_THRESHOLD = 1 * 1024 * 1024;
+ private static final long MAX_NTP_CACHE_AGE = 24 * 60 * 60 * 1000;
+ private static final long MAX_NTP_FETCH_WAIT = 20 * 1000;
+
+ private long mMaxNtpCacheAge = MAX_NTP_CACHE_AGE;
+
private int mPolicyPollPeriodSec;
private AtomicLong mPolicyThreshold;
private AtomicInteger mPolicyThrottleValue;
@@ -121,10 +127,24 @@ public class ThrottleService extends IThrottleManager.Stub {
private static final int THROTTLE_INDEX_UNTHROTTLED = 0;
private static final String PROPERTIES_FILE = "/etc/gps.conf";
- private String mNtpServer;
- private boolean mNtpActive;
+
+ private Intent mPollStickyBroadcast;
+
+ private TrustedTime mTime;
+
+ private static INetworkManagementService getNetworkManagementService() {
+ final IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ return INetworkManagementService.Stub.asInterface(b);
+ }
public ThrottleService(Context context) {
+ // TODO: move to using cached NtpTrustedTime
+ this(context, getNetworkManagementService(), new NtpTrustedTime(),
+ context.getResources().getString(R.string.config_datause_iface));
+ }
+
+ public ThrottleService(Context context, INetworkManagementService nmService, TrustedTime time,
+ String iface) {
if (VDBG) Slog.v(TAG, "Starting ThrottleService");
mContext = context;
@@ -132,17 +152,15 @@ public class ThrottleService extends IThrottleManager.Stub {
mPolicyThrottleValue = new AtomicInteger();
mThrottleIndex = new AtomicInteger();
- mNtpActive = false;
-
- mIface = mContext.getResources().getString(R.string.config_datause_iface);
+ mIface = iface;
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
Intent pollIntent = new Intent(ACTION_POLL, null);
mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
Intent resetIntent = new Intent(ACTION_RESET, null);
mPendingResetIntent = PendingIntent.getBroadcast(mContext, RESET_REQUEST, resetIntent, 0);
- IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
- mNMService = INetworkManagementService.Stub.asInterface(b);
+ mNMService = nmService;
+ mTime = time;
mNotificationManager = (NotificationManager)mContext.getSystemService(
Context.NOTIFICATION_SERVICE);
@@ -189,7 +207,7 @@ public class ThrottleService extends IThrottleManager.Stub {
mMsg = msg;
}
- void observe(Context context) {
+ void register(Context context) {
ContentResolver resolver = context.getContentResolver();
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.THROTTLE_POLLING_SEC), false, this);
@@ -207,6 +225,11 @@ public class ThrottleService extends IThrottleManager.Stub {
Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC), false, this);
}
+ void unregister(Context context) {
+ final ContentResolver resolver = context.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ }
+
@Override
public void onChange(boolean selfChange) {
mHandler.obtainMessage(mMsg).sendToTarget();
@@ -220,7 +243,9 @@ public class ThrottleService extends IThrottleManager.Stub {
}
private long ntpToWallTime(long ntpTime) {
- long bestNow = getBestTime(true); // do it quickly
+ // get time quickly without worrying about trusted state
+ long bestNow = mTime.hasCache() ? mTime.currentTimeMillis()
+ : System.currentTimeMillis();
long localNow = System.currentTimeMillis();
return localNow + (ntpTime - bestNow);
}
@@ -300,7 +325,7 @@ public class ThrottleService extends IThrottleManager.Stub {
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- mHandler.obtainMessage(EVENT_POLL_ALARM).sendToTarget();
+ dispatchPoll();
}
}, new IntentFilter(ACTION_POLL));
@@ -308,7 +333,7 @@ public class ThrottleService extends IThrottleManager.Stub {
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget();
+ dispatchReset();
}
}, new IntentFilter(ACTION_RESET));
@@ -318,7 +343,10 @@ public class ThrottleService extends IThrottleManager.Stub {
File file = new File(PROPERTIES_FILE);
stream = new FileInputStream(file);
properties.load(stream);
- mNtpServer = properties.getProperty("NTP_SERVER", null);
+ final String ntpServer = properties.getProperty("NTP_SERVER", null);
+ if (mTime instanceof NtpTrustedTime) {
+ ((NtpTrustedTime) mTime).setNtpServer(ntpServer, MAX_NTP_FETCH_WAIT);
+ }
} catch (IOException e) {
Slog.e(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
} finally {
@@ -343,9 +371,33 @@ public class ThrottleService extends IThrottleManager.Stub {
}
mSettingsObserver = new SettingsObserver(mHandler, EVENT_POLICY_CHANGED);
- mSettingsObserver.observe(mContext);
+ mSettingsObserver.register(mContext);
+ }
+
+ void shutdown() {
+ // TODO: eventually connect with ShutdownThread to persist stats during
+ // graceful shutdown.
+
+ if (mThread != null) {
+ mThread.quit();
+ }
+
+ if (mSettingsObserver != null) {
+ mSettingsObserver.unregister(mContext);
+ }
+
+ if (mPollStickyBroadcast != null) {
+ mContext.removeStickyBroadcast(mPollStickyBroadcast);
+ }
}
+ void dispatchPoll() {
+ mHandler.obtainMessage(EVENT_POLL_ALARM).sendToTarget();
+ }
+
+ void dispatchReset() {
+ mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget();
+ }
private static final int EVENT_REBOOT_RECOVERY = 0;
private static final int EVENT_POLICY_CHANGED = 1;
@@ -440,15 +492,17 @@ public class ThrottleService extends IThrottleManager.Stub {
mPolicyNotificationsAllowedMask = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.THROTTLE_NOTIFICATION_TYPE, defaultNotificationType);
- mMaxNtpCacheAgeSec = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC, MAX_NTP_CACHE_AGE_SEC);
+ final int maxNtpCacheAgeSec = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC,
+ (int) (MAX_NTP_CACHE_AGE / 1000));
+ mMaxNtpCacheAge = maxNtpCacheAgeSec * 1000;
if (VDBG || (mPolicyThreshold.get() != 0)) {
Slog.d(TAG, "onPolicyChanged testing=" + testing +", period=" +
mPolicyPollPeriodSec + ", threshold=" + mPolicyThreshold.get() +
", value=" + mPolicyThrottleValue.get() + ", resetDay=" + mPolicyResetDay +
- ", noteType=" + mPolicyNotificationsAllowedMask + ", maxNtpCacheAge=" +
- mMaxNtpCacheAgeSec);
+ ", noteType=" + mPolicyNotificationsAllowedMask + ", mMaxNtpCacheAge=" +
+ mMaxNtpCacheAge);
}
// force updates
@@ -464,9 +518,15 @@ public class ThrottleService extends IThrottleManager.Stub {
private void onPollAlarm() {
long now = SystemClock.elapsedRealtime();
- long next = now + mPolicyPollPeriodSec*1000;
+ long next = now + mPolicyPollPeriodSec * 1000;
- checkForAuthoritativeTime();
+ // when trusted cache outdated, try refreshing
+ if (mTime.getCacheAge() > mMaxNtpCacheAge) {
+ if (mTime.forceRefresh()) {
+ if (VDBG) Slog.d(TAG, "updated trusted time, reseting alarm");
+ dispatchReset();
+ }
+ }
long incRead = 0;
long incWrite = 0;
@@ -509,6 +569,7 @@ public class ThrottleService extends IThrottleManager.Stub {
broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_START, getPeriodStartTime(mIface));
broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_END, getResetTime(mIface));
mContext.sendStickyBroadcast(broadcast);
+ mPollStickyBroadcast = broadcast;
mAlarmManager.cancel(mPendingPollIntent);
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
@@ -538,7 +599,8 @@ public class ThrottleService extends IThrottleManager.Stub {
// have we spoken with an ntp server yet?
// this is controversial, but we'd rather err towards not throttling
- if ((mNtpServer != null) && !mNtpActive) {
+ if (!mTime.hasCache()) {
+ Slog.w(TAG, "missing trusted time, skipping throttle check");
return;
}
@@ -697,9 +759,15 @@ public class ThrottleService extends IThrottleManager.Stub {
" bytes read and " + mRecorder.getPeriodTx(0) + " written");
}
- long now = getBestTime(false);
+ // when trusted cache outdated, try refreshing
+ if (mTime.getCacheAge() > mMaxNtpCacheAge) {
+ mTime.forceRefresh();
+ }
- if (mNtpActive || (mNtpServer == null)) {
+ // as long as we have a trusted time cache, we always reset alarms,
+ // even if the refresh above failed.
+ if (mTime.hasCache()) {
+ final long now = mTime.currentTimeMillis();
Calendar end = calculatePeriodEnd(now);
Calendar start = calculatePeriodStart(end);
@@ -714,56 +782,11 @@ public class ThrottleService extends IThrottleManager.Stub {
SystemClock.elapsedRealtime() + offset,
mPendingResetIntent);
} else {
- if (VDBG) Slog.d(TAG, "no authoritative time - not resetting period");
+ if (VDBG) Slog.d(TAG, "no trusted time, not resetting period");
}
}
}
- private void checkForAuthoritativeTime() {
- if (mNtpActive || (mNtpServer == null)) return;
-
- // will try to get the ntp time and switch to it if found.
- // will also cache the time so we don't fetch it repeatedly.
- getBestTime(false);
- }
-
- private static final int MAX_NTP_CACHE_AGE_SEC = 60 * 60 * 24; // 1 day
- private static final int MAX_NTP_FETCH_WAIT = 20 * 1000;
- private int mMaxNtpCacheAgeSec = MAX_NTP_CACHE_AGE_SEC;
- private long cachedNtp;
- private long cachedNtpTimestamp;
-
- // if the request is tied to UI and ANR's are a danger, request a fast result
- // the regular polling should have updated the cached time recently using the
- // slower method (!fast)
- private long getBestTime(boolean fast) {
- if (mNtpServer != null) {
- if (mNtpActive) {
- long ntpAge = SystemClock.elapsedRealtime() - cachedNtpTimestamp;
- if (ntpAge < mMaxNtpCacheAgeSec * 1000 || fast) {
- if (VDBG) Slog.v(TAG, "using cached time");
- return cachedNtp + ntpAge;
- }
- }
- SntpClient client = new SntpClient();
- if (client.requestTime(mNtpServer, MAX_NTP_FETCH_WAIT)) {
- cachedNtp = client.getNtpTime();
- cachedNtpTimestamp = SystemClock.elapsedRealtime();
- if (!mNtpActive) {
- mNtpActive = true;
- if (VDBG) Slog.d(TAG, "found Authoritative time - reseting alarm");
- mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget();
- }
- if (VDBG) Slog.v(TAG, "using Authoritative time: " + cachedNtp);
- return cachedNtp;
- }
- }
- long time = System.currentTimeMillis();
- if (VDBG) Slog.v(TAG, "using User time: " + time);
- mNtpActive = false;
- return time;
- }
-
// records bytecount data for a given time and accumulates it into larger time windows
// for logging and other purposes
//
@@ -929,7 +952,7 @@ public class ThrottleService extends IThrottleManager.Stub {
private void checkAndDeleteLRUDataFile(File dir) {
File[] files = dir.listFiles();
- if (files.length <= MAX_SIMS_SUPPORTED) return;
+ if (files == null || files.length <= MAX_SIMS_SUPPORTED) return;
if (DBG) Slog.d(TAG, "Too many data files");
do {
File oldest = null;
@@ -949,9 +972,11 @@ public class ThrottleService extends IThrottleManager.Stub {
File newest = null;
File[] files = dir.listFiles();
- for (File f : files) {
- if ((newest == null) || (newest.lastModified() < f.lastModified())) {
- newest = f;
+ if (files != null) {
+ for (File f : files) {
+ if ((newest == null) || (newest.lastModified() < f.lastModified())) {
+ newest = f;
+ }
}
}
if (newest == null) {
@@ -1126,7 +1151,7 @@ public class ThrottleService extends IThrottleManager.Stub {
" seconds.");
pw.println("Polling every " + mPolicyPollPeriodSec + " seconds");
pw.println("Current Throttle Index is " + mThrottleIndex.get());
- pw.println("Max NTP Cache Age is " + mMaxNtpCacheAgeSec);
+ pw.println("mMaxNtpCacheAge=" + mMaxNtpCacheAge);
for (int i = 0; i < mRecorder.getPeriodCount(); i++) {
pw.println(" Period[" + i + "] - read:" + mRecorder.getPeriodRx(i) + ", written:" +
diff --git a/services/java/com/android/server/location/ComprehensiveCountryDetector.java b/services/java/com/android/server/location/ComprehensiveCountryDetector.java
index e9ce3ce3ccf7..bb9e60f6e072 100755
--- a/services/java/com/android/server/location/ComprehensiveCountryDetector.java
+++ b/services/java/com/android/server/location/ComprehensiveCountryDetector.java
@@ -56,6 +56,7 @@ import java.util.TimerTask;
public class ComprehensiveCountryDetector extends CountryDetectorBase {
private final static String TAG = "ComprehensiveCountryDetector";
+ /* package */ static final boolean DEBUG = false;
/**
* The refresh interval when the location based country was used
@@ -90,7 +91,9 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
* The listener for receiving the notification from LocationBasedCountryDetector.
*/
private CountryListener mLocationBasedCountryDetectionListener = new CountryListener() {
+ @Override
public void onCountryDetected(Country country) {
+ if (DEBUG) Slog.d(TAG, "Country detected via LocationBasedCountryDetector");
mCountryFromLocation = country;
// Don't start the LocationBasedCountryDetector.
detectCountry(true, false);
@@ -206,6 +209,7 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
protected void runAfterDetectionAsync(final Country country, final Country detectedCountry,
final boolean notifyChange, final boolean startLocationBasedDetection) {
mHandler.post(new Runnable() {
+ @Override
public void run() {
runAfterDetection(
country, detectedCountry, notifyChange, startLocationBasedDetection);
@@ -233,9 +237,20 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
if (notifyChange) {
notifyIfCountryChanged(country, detectedCountry);
}
+ if (DEBUG) {
+ Slog.d(TAG, "startLocationBasedDetection=" + startLocationBasedDetection
+ + " detectCountry=" + (detectedCountry == null ? null :
+ "(source: " + detectedCountry.getSource()
+ + ", countryISO: " + detectedCountry.getCountryIso() + ")")
+ + " isAirplaneModeOff()=" + isAirplaneModeOff()
+ + " mListener=" + mListener
+ + " isGeoCoderImplemnted()=" + isGeoCoderImplemented());
+ }
+
if (startLocationBasedDetection && (detectedCountry == null
|| detectedCountry.getSource() > Country.COUNTRY_SOURCE_LOCATION)
&& isAirplaneModeOff() && mListener != null && isGeoCoderImplemented()) {
+ if (DEBUG) Slog.d(TAG, "run startLocationBasedDetector()");
// Start finding location when the source is less reliable than the
// location and the airplane mode is off (as geocoder will not
// work).
@@ -266,12 +281,20 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
if (mLocationBasedCountryDetector != null) {
return;
}
+ if (DEBUG) {
+ Slog.d(TAG, "starts LocationBasedDetector to detect Country code via Location info "
+ + "(e.g. GPS)");
+ }
mLocationBasedCountryDetector = createLocationBasedCountryDetector();
mLocationBasedCountryDetector.setCountryListener(listener);
mLocationBasedCountryDetector.detectCountry();
}
private synchronized void stopLocationBasedDetector() {
+ if (DEBUG) {
+ Slog.d(TAG, "tries to stop LocationBasedDetector "
+ + "(current detector: " + mLocationBasedCountryDetector + ")");
+ }
if (mLocationBasedCountryDetector != null) {
mLocationBasedCountryDetector.stop();
mLocationBasedCountryDetector = null;
@@ -305,10 +328,17 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
*/
private synchronized void scheduleLocationRefresh() {
if (mLocationRefreshTimer != null) return;
+ if (DEBUG) {
+ Slog.d(TAG, "start periodic location refresh timer. Interval: "
+ + LOCATION_REFRESH_INTERVAL);
+ }
mLocationRefreshTimer = new Timer();
mLocationRefreshTimer.schedule(new TimerTask() {
@Override
public void run() {
+ if (DEBUG) {
+ Slog.d(TAG, "periodic location refresh event. Starts detecting Country code");
+ }
mLocationRefreshTimer = null;
detectCountry(false, true);
}
diff --git a/services/java/com/android/server/location/LocationBasedCountryDetector.java b/services/java/com/android/server/location/LocationBasedCountryDetector.java
index 139f05d211fd..d4fb8ee5abb0 100755
--- a/services/java/com/android/server/location/LocationBasedCountryDetector.java
+++ b/services/java/com/android/server/location/LocationBasedCountryDetector.java
@@ -16,12 +16,6 @@
package com.android.server.location;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Timer;
-import java.util.TimerTask;
-
import android.content.Context;
import android.location.Address;
import android.location.Country;
@@ -32,6 +26,12 @@ import android.location.LocationManager;
import android.os.Bundle;
import android.util.Slog;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
/**
* This class detects which country the user currently is in through the enabled
* location providers and the GeoCoder
@@ -86,24 +86,23 @@ public class LocationBasedCountryDetector extends CountryDetectorBase {
return country;
}
+ protected boolean isAcceptableProvider(String provider) {
+ // We don't want to actively initiate a location fix here (with gps or network providers).
+ return LocationManager.PASSIVE_PROVIDER.equals(provider);
+ }
+
/**
- * Register the listeners with the location providers
+ * Register a listener with a provider name
*/
- protected void registerEnabledProviders(List<LocationListener> listeners) {
- int total = listeners.size();
- for (int i = 0; i< total; i++) {
- mLocationManager.requestLocationUpdates(
- mEnabledProviders.get(i), 0, 0, listeners.get(i));
- }
+ protected void registerListener(String provider, LocationListener listener) {
+ mLocationManager.requestLocationUpdates(provider, 0, 0, listener);
}
/**
- * Unregister the listeners with the location providers
+ * Unregister an already registered listener
*/
- protected void unregisterProviders(List<LocationListener> listeners) {
- for (LocationListener listener : listeners) {
- mLocationManager.removeUpdates(listener);
- }
+ protected void unregisterListener(LocationListener listener) {
+ mLocationManager.removeUpdates(listener);
}
/**
@@ -130,14 +129,11 @@ public class LocationBasedCountryDetector extends CountryDetectorBase {
return QUERY_LOCATION_TIMEOUT;
}
- /**
- * @return the total number of enabled location providers
- */
- protected int getTotalEnabledProviders() {
+ protected List<String> getEnabledProviders() {
if (mEnabledProviders == null) {
mEnabledProviders = mLocationManager.getProviders(true);
}
- return mEnabledProviders.size();
+ return mEnabledProviders;
}
/**
@@ -152,27 +148,36 @@ public class LocationBasedCountryDetector extends CountryDetectorBase {
throw new IllegalStateException();
}
// Request the location from all enabled providers.
- int totalProviders = getTotalEnabledProviders();
+ List<String> enabledProviders = getEnabledProviders();
+ int totalProviders = enabledProviders.size();
if (totalProviders > 0) {
mLocationListeners = new ArrayList<LocationListener>(totalProviders);
for (int i = 0; i < totalProviders; i++) {
- LocationListener listener = new LocationListener () {
- public void onLocationChanged(Location location) {
- if (location != null) {
- LocationBasedCountryDetector.this.stop();
- queryCountryCode(location);
+ String provider = enabledProviders.get(i);
+ if (isAcceptableProvider(provider)) {
+ LocationListener listener = new LocationListener () {
+ @Override
+ public void onLocationChanged(Location location) {
+ if (location != null) {
+ LocationBasedCountryDetector.this.stop();
+ queryCountryCode(location);
+ }
}
- }
- public void onProviderDisabled(String provider) {
- }
- public void onProviderEnabled(String provider) {
- }
- public void onStatusChanged(String provider, int status, Bundle extras) {
- }
- };
- mLocationListeners.add(listener);
+ @Override
+ public void onProviderDisabled(String provider) {
+ }
+ @Override
+ public void onProviderEnabled(String provider) {
+ }
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
+ };
+ mLocationListeners.add(listener);
+ registerListener(provider, listener);
+ }
}
- registerEnabledProviders(mLocationListeners);
+
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
@Override
@@ -197,7 +202,9 @@ public class LocationBasedCountryDetector extends CountryDetectorBase {
@Override
public synchronized void stop() {
if (mLocationListeners != null) {
- unregisterProviders(mLocationListeners);
+ for (LocationListener listener : mLocationListeners) {
+ unregisterListener(listener);
+ }
mLocationListeners = null;
}
if (mTimer != null) {
@@ -216,6 +223,7 @@ public class LocationBasedCountryDetector extends CountryDetectorBase {
}
if (mQueryThread != null) return;
mQueryThread = new Thread(new Runnable() {
+ @Override
public void run() {
String countryIso = null;
if (location != null) {
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 186b3490e502..295f324f9582 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -7,7 +7,9 @@ LOCAL_MODULE_TAGS := tests
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := easymocklib
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ easymocklib \
+ guava
LOCAL_JAVA_LIBRARIES := android.test.runner services
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 2fcce785178c..f8d14265217c 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -20,6 +20,10 @@
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
new file mode 100644
index 000000000000..6f55f4600dcd
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
@@ -0,0 +1,400 @@
+/*
+ * 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.server;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.AbstractFuture;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.INetworkManagementEventObserver;
+import android.net.ThrottleManager;
+import android.os.INetworkManagementService;
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+import android.text.format.DateUtils;
+import android.util.TrustedTime;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.Future;
+
+/**
+ * Tests for {@link ThrottleService}.
+ */
+public class ThrottleServiceTest extends AndroidTestCase {
+ private static final String TAG = "ThrottleServiceTest";
+
+ private static final long MB_IN_BYTES = 1024 * 1024;
+
+ private static final int TEST_KBITPS = 222;
+ private static final int TEST_RESET_DAY = 11;
+
+ private static final String TEST_IFACE = "test0";
+
+ private WatchingContext mWatchingContext;
+ private INetworkManagementService mMockNMService;
+ private TrustedTime mMockTime;
+
+ private ThrottleService mThrottleService;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mWatchingContext = new WatchingContext(getContext());
+
+ mMockNMService = createMock(INetworkManagementService.class);
+ mMockTime = createMock(TrustedTime.class);
+
+ mThrottleService = new ThrottleService(
+ mWatchingContext, mMockNMService, mMockTime, TEST_IFACE);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mWatchingContext = null;
+ mMockNMService = null;
+
+ mThrottleService.shutdown();
+ mThrottleService = null;
+
+ clearThrottlePolicy();
+
+ super.tearDown();
+ }
+
+ public void testNoPolicyNotThrottled() throws Exception {
+ expectTimeCurrent();
+ expectSystemReady();
+
+ // provide stats without policy, verify not throttled
+ expectGetInterfaceCounter(1 * MB_IN_BYTES, 2 * MB_IN_BYTES);
+ expectSetInterfaceThrottle(-1, -1);
+
+ replay(mMockTime, mMockNMService);
+ systemReady();
+ verify(mMockTime, mMockNMService);
+ }
+
+ public void testUnderLimitNotThrottled() throws Exception {
+ setThrottlePolicy(200 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
+
+ expectTimeCurrent();
+ expectSystemReady();
+
+ // provide stats under limits, and verify not throttled
+ expectGetInterfaceCounter(1 * MB_IN_BYTES, 2 * MB_IN_BYTES);
+ expectSetInterfaceThrottle(-1, -1);
+
+ replay(mMockTime, mMockNMService);
+ systemReady();
+ verify(mMockTime, mMockNMService);
+ }
+
+ public void testOverLimitThrottled() throws Exception {
+ setThrottlePolicy(200 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
+
+ expectTimeCurrent();
+ expectSystemReady();
+
+ // provide stats over limits, and verify throttled
+ expectGetInterfaceCounter(500 * MB_IN_BYTES, 600 * MB_IN_BYTES);
+ expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS);
+
+ replay(mMockTime, mMockNMService);
+ systemReady();
+ verify(mMockTime, mMockNMService);
+ }
+
+ public void testUnderThenOverLimitThrottled() throws Exception {
+ setThrottlePolicy(201 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
+
+ expectTimeCurrent();
+ expectSystemReady();
+
+ // provide stats right under 201MB limit, verify not throttled
+ expectGetInterfaceCounter(100 * MB_IN_BYTES, 100 * MB_IN_BYTES);
+ expectSetInterfaceThrottle(-1, -1);
+
+ replay(mMockTime, mMockNMService);
+ systemReady();
+ verify(mMockTime, mMockNMService);
+ reset(mMockTime, mMockNMService);
+
+ expectTimeCurrent();
+
+ // adjust usage to bump over limit, verify throttle kicks in
+ expectGetInterfaceCounter(105 * MB_IN_BYTES, 100 * MB_IN_BYTES);
+ expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS);
+
+ // and kick poll event which should throttle
+ replay(mMockTime, mMockNMService);
+ forceServicePoll();
+ verify(mMockTime, mMockNMService);
+ }
+
+ public void testUpdatedPolicyThrottled() throws Exception {
+ setThrottlePolicy(500 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
+
+ expectTimeCurrent();
+ expectSystemReady();
+
+ // provide stats under limit, verify not throttled
+ expectGetInterfaceCounter(50 * MB_IN_BYTES, 50 * MB_IN_BYTES);
+ expectSetInterfaceThrottle(-1, -1);
+
+ replay(mMockTime, mMockNMService);
+ systemReady();
+ verify(mMockTime, mMockNMService);
+ reset(mMockTime, mMockNMService);
+
+ expectTimeCurrent();
+
+ // provide same stats, but verify that modified policy will throttle
+ expectGetInterfaceCounter(50 * MB_IN_BYTES, 50 * MB_IN_BYTES);
+ expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS);
+
+ replay(mMockTime, mMockNMService);
+
+ // now adjust policy to bump usage over limit
+ setThrottlePolicy(5 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
+
+ // and wait for policy updated broadcast
+ mWatchingContext.nextBroadcastIntent(ThrottleManager.POLICY_CHANGED_ACTION).get();
+
+ verify(mMockTime, mMockNMService);
+ }
+
+ public void testWithPolicyOverLimitThrottledAndRemovedAfterCycle() throws Exception {
+ setThrottlePolicy(90 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
+
+ final long baseTime = System.currentTimeMillis();
+
+ expectTime(baseTime);
+ expectSystemReady();
+
+ // provide stats over limit, verify throttle kicks in
+ expectGetInterfaceCounter(50 * MB_IN_BYTES, 50 * MB_IN_BYTES);
+ expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS);
+
+ replay(mMockTime, mMockNMService);
+ systemReady();
+ verify(mMockTime, mMockNMService);
+ reset(mMockTime, mMockNMService);
+
+ // pretend that time has jumped forward two months
+ expectTime(baseTime + DateUtils.WEEK_IN_MILLIS * 8);
+
+ // provide slightly updated stats, but verify throttle is removed
+ expectGetInterfaceCounter(60 * MB_IN_BYTES, 60 * MB_IN_BYTES);
+ expectSetInterfaceThrottle(-1, -1);
+
+ // and kick poll event which should throttle
+ replay(mMockTime, mMockNMService);
+ forceServiceReset();
+ verify(mMockTime, mMockNMService);
+ }
+
+ /**
+ * Persist the given {@link ThrottleService} policy into {@link Settings}.
+ */
+ public void setThrottlePolicy(long thresholdBytes, int valueKbitps, int resetDay) {
+ final ContentResolver resolver = getContext().getContentResolver();
+ Settings.Secure.putLong(resolver, Settings.Secure.THROTTLE_THRESHOLD_BYTES, thresholdBytes);
+ Settings.Secure.putInt(resolver, Settings.Secure.THROTTLE_VALUE_KBITSPS, valueKbitps);
+ Settings.Secure.putInt(resolver, Settings.Secure.THROTTLE_RESET_DAY, resetDay);
+ }
+
+ /**
+ * Clear any {@link ThrottleService} policy from {@link Settings}.
+ */
+ public void clearThrottlePolicy() {
+ final ContentResolver resolver = getContext().getContentResolver();
+ Settings.Secure.putString(resolver, Settings.Secure.THROTTLE_THRESHOLD_BYTES, null);
+ Settings.Secure.putString(resolver, Settings.Secure.THROTTLE_VALUE_KBITSPS, null);
+ Settings.Secure.putString(resolver, Settings.Secure.THROTTLE_RESET_DAY, null);
+ }
+
+ /**
+ * Expect any {@link TrustedTime} mock calls, and respond with
+ * {@link System#currentTimeMillis()}.
+ */
+ public void expectTimeCurrent() throws Exception {
+ expectTime(System.currentTimeMillis());
+ }
+
+ /**
+ * Expect any {@link TrustedTime} mock calls, and respond with the given
+ * time in response to {@link TrustedTime#currentTimeMillis()}.
+ */
+ public void expectTime(long currentTime) throws Exception {
+ expect(mMockTime.forceRefresh()).andReturn(false).anyTimes();
+ expect(mMockTime.hasCache()).andReturn(true).anyTimes();
+ expect(mMockTime.currentTimeMillis()).andReturn(currentTime).anyTimes();
+ expect(mMockTime.getCacheAge()).andReturn(0L).anyTimes();
+ expect(mMockTime.getCacheCertainty()).andReturn(0L).anyTimes();
+ }
+
+ /**
+ * Expect {@link ThrottleService#systemReady()} generated calls, such as
+ * connecting with {@link NetworkManagementService} mock.
+ */
+ public void expectSystemReady() throws Exception {
+ mMockNMService.registerObserver(isA(INetworkManagementEventObserver.class));
+ expectLastCall().atLeastOnce();
+ }
+
+ /**
+ * Expect {@link NetworkManagementService#getInterfaceRxCounter} mock calls,
+ * responding with the given counter values.
+ */
+ public void expectGetInterfaceCounter(long rx, long tx) throws Exception {
+ expect(mMockNMService.getInterfaceRxCounter(isA(String.class))).andReturn(rx).atLeastOnce();
+ expect(mMockNMService.getInterfaceTxCounter(isA(String.class))).andReturn(tx).atLeastOnce();
+ }
+
+ /**
+ * Expect {@link NetworkManagementService#setInterfaceThrottle} mock call
+ * with the specified parameters.
+ */
+ public void expectSetInterfaceThrottle(int rx, int tx) throws Exception {
+ mMockNMService.setInterfaceThrottle(isA(String.class), eq(rx), eq(tx));
+ expectLastCall().atLeastOnce();
+ }
+
+ /**
+ * Dispatch {@link ThrottleService#systemReady()} and block until finished.
+ */
+ public void systemReady() throws Exception {
+ final Future<Intent> policyChanged = mWatchingContext.nextBroadcastIntent(
+ ThrottleManager.POLICY_CHANGED_ACTION);
+ final Future<Intent> pollAction = mWatchingContext.nextBroadcastIntent(
+ ThrottleManager.THROTTLE_POLL_ACTION);
+
+ mThrottleService.systemReady();
+
+ // wait for everything to settle; for policy to update and for first poll
+ policyChanged.get();
+ pollAction.get();
+ }
+
+ /**
+ * Dispatch {@link ThrottleService#dispatchPoll()} and block until finished.
+ */
+ public void forceServicePoll() throws Exception {
+ // during systemReady() service already pushed a sticky broadcast, so we
+ // need to skip the immediate and wait for the updated sticky.
+ final Future<Intent> pollAction = mWatchingContext.nextBroadcastIntent(
+ ThrottleManager.THROTTLE_POLL_ACTION);
+
+ mThrottleService.dispatchPoll();
+
+ pollAction.get();
+ }
+
+ /**
+ * Dispatch {@link ThrottleService#dispatchReset()} and block until finished.
+ */
+ public void forceServiceReset() throws Exception {
+ // during systemReady() service already pushed a sticky broadcast, so we
+ // need to skip the immediate and wait for the updated sticky.
+ final Future<Intent> pollAction = mWatchingContext.nextBroadcastIntent(
+ ThrottleManager.THROTTLE_POLL_ACTION);
+
+ mThrottleService.dispatchReset();
+
+ pollAction.get();
+ }
+
+
+ /**
+ * {@link ContextWrapper} that can attach listeners for upcoming
+ * {@link Context#sendBroadcast(Intent)}.
+ */
+ private static class WatchingContext extends ContextWrapper {
+ private List<LocalBroadcastReceiver> mReceivers = Lists.newArrayList();
+
+ public class LocalBroadcastReceiver extends AbstractFuture<Intent> {
+ private IntentFilter mFilter;
+
+ public LocalBroadcastReceiver(IntentFilter filter) {
+ mFilter = filter;
+ }
+
+ public boolean dispatchBroadcast(Intent intent) {
+ if (mFilter.match(getContentResolver(), intent, false, TAG) > 0) {
+ set(intent);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public WatchingContext(Context base) {
+ super(base);
+ }
+
+ public Future<Intent> nextBroadcastIntent(String action) {
+ return nextBroadcastIntent(new IntentFilter(action));
+ }
+
+ public Future<Intent> nextBroadcastIntent(IntentFilter filter) {
+ final LocalBroadcastReceiver receiver = new LocalBroadcastReceiver(filter);
+ synchronized (mReceivers) {
+ mReceivers.add(receiver);
+ }
+ return receiver;
+ }
+
+ @Override
+ public void sendBroadcast(Intent intent) {
+ synchronized (mReceivers) {
+ final Iterator<LocalBroadcastReceiver> i = mReceivers.iterator();
+ while (i.hasNext()) {
+ final LocalBroadcastReceiver receiver = i.next();
+ if (receiver.dispatchBroadcast(intent)) {
+ i.remove();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void sendStickyBroadcast(Intent intent) {
+ sendBroadcast(intent);
+ }
+
+ @Override
+ public void removeStickyBroadcast(Intent intent) {
+ // ignored
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java b/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java
index 71e8e2a62623..60677dff0d8d 100755
--- a/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java
@@ -15,17 +15,25 @@
*/
package com.android.server.location;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Timer;
-
import android.location.Country;
import android.location.CountryListener;
import android.location.Location;
import android.location.LocationListener;
+import android.location.LocationManager;
import android.test.AndroidTestCase;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.Timer;
+
public class LocationBasedCountryDetectorTest extends AndroidTestCase {
+ private static final List<String> sEnabledProviders = Arrays.asList(
+ LocationManager.GPS_PROVIDER, LocationManager.PASSIVE_PROVIDER);
private class TestCountryDetector extends LocationBasedCountryDetector {
public static final int TOTAL_PROVIDERS = 2;
protected Object countryFoundLocker = new Object();
@@ -33,7 +41,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
private final Location mLocation;
private final String mCountry;
private final long mQueryLocationTimeout;
- private List<LocationListener> mListeners;
+ private Map<String, LocationListener> mListeners;
public TestCountryDetector(String country, String provider) {
this(country, provider, 1000 * 60 * 5);
@@ -44,7 +52,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
mCountry = country;
mLocation = new Location(provider);
mQueryLocationTimeout = queryLocationTimeout;
- mListeners = new ArrayList<LocationListener>();
+ mListeners = new HashMap<String, LocationListener>();
}
@Override
@@ -69,16 +77,40 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
return mLocation;
}
+ private Set<String> mAcceptableProviders;
+
+ public void setAcceptableProvider(Set<String> acceptableProviders) {
+ mAcceptableProviders = acceptableProviders;
+ }
+
+ @Override
+ protected boolean isAcceptableProvider(String provider) {
+ if (mAcceptableProviders != null) {
+ return mAcceptableProviders.contains(provider);
+ } else {
+ return true;
+ }
+ }
+
@Override
- protected void registerEnabledProviders(List<LocationListener> listeners) {
- mListeners.addAll(listeners);
+ protected void registerListener(String provider, LocationListener listener) {
+ assertNotNull(provider);
+ mListeners.put(provider, listener);
}
@Override
- protected void unregisterProviders(List<LocationListener> listeners) {
- for (LocationListener listener : mLocationListeners) {
- assertTrue(mListeners.remove(listener));
+ protected void unregisterListener(LocationListener listener) {
+ for (Entry<String, LocationListener> entry : mListeners.entrySet()) {
+ if (entry.getValue().equals(listener)) {
+ mListeners.remove(entry.getKey());
+ return;
+ }
}
+ fail("Not registered");
+ }
+
+ public Map<String, LocationListener> getListeners() {
+ return mListeners;
}
@Override
@@ -87,8 +119,8 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
}
@Override
- protected int getTotalEnabledProviders() {
- return TOTAL_PROVIDERS;
+ protected List<String> getEnabledProviders() {
+ return sEnabledProviders;
}
public void notifyLocationFound() {
@@ -140,16 +172,39 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
}
public void testFindingCountry() {
+ testFindingCountryCommon(null);
+ }
+
+ public void testFindingCountryWithAcceptableProvider() {
+ testFindingCountryCommon(new HashSet<String>(Arrays.asList("passive")));
+ }
+
+ private void testFindingCountryCommon(Set<String> acceptableProviders) {
final String country = "us";
final String provider = "Good";
CountryListenerImpl countryListener = new CountryListenerImpl();
TestCountryDetector detector = new TestCountryDetector(country, provider);
+
+ if (acceptableProviders != null) {
+ detector.setAcceptableProvider(acceptableProviders);
+ }
+
detector.setCountryListener(countryListener);
detector.detectCountry();
- assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
+
+ if (acceptableProviders != null) {
+ assertEquals(acceptableProviders.size(), detector.getListenersCount());
+ Map<String, LocationListener> listeners = detector.getListeners();
+ for (String acceptableProvider : acceptableProviders) {
+ assertTrue(listeners.containsKey(acceptableProvider));
+ }
+ } else {
+ assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
+ }
+
detector.notifyLocationFound();
// All listeners should be unregistered
- assertEquals(detector.getListenersCount(), 0);
+ assertEquals(0, detector.getListenersCount());
assertNull(detector.getTimer());
Thread queryThread = waitForQueryThreadLaunched(detector);
detector.notifyCountryFound();
@@ -168,10 +223,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
TestCountryDetector detector = new TestCountryDetector(country, provider);
detector.setCountryListener(countryListener);
detector.detectCountry();
- assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
+ assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
detector.notifyLocationFound();
// All listeners should be unregistered
- assertEquals(detector.getListenersCount(), 0);
+ assertEquals(0, detector.getListenersCount());
// The time should be stopped
assertNull(detector.getTimer());
Thread queryThread = waitForQueryThreadLaunched(detector);
@@ -193,10 +248,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
TestCountryDetector detector = new TestCountryDetector(country, provider);
detector.setCountryListener(countryListener);
detector.detectCountry();
- assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
+ assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
detector.stop();
// All listeners should be unregistered
- assertEquals(detector.getListenersCount(), 0);
+ assertEquals(0, detector.getListenersCount());
// The time should be stopped
assertNull(detector.getTimer());
// QueryThread should still be NULL
@@ -217,10 +272,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
CountryListenerImpl countryListener = new CountryListenerImpl();
detector.setCountryListener(countryListener);
detector.detectCountry();
- assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
+ assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
waitForTimerReset(detector);
// All listeners should be unregistered
- assertEquals(detector.getListenersCount(), 0);
+ assertEquals(0, detector.getListenersCount());
// QueryThread should still be NULL
assertNull(detector.getQueryThread());
assertTrue(countryListener.notified());
@@ -248,10 +303,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
CountryListenerImpl countryListener = new CountryListenerImpl();
detector.setCountryListener(countryListener);
detector.detectCountry();
- assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
+ assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
detector.notifyLocationFound();
// All listeners should be unregistered
- assertEquals(detector.getListenersCount(), 0);
+ assertEquals(0, detector.getListenersCount());
assertNull(detector.getTimer());
Thread queryThread = waitForQueryThreadLaunched(detector);
detector.notifyCountryFound();
@@ -272,10 +327,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase {
CountryListenerImpl countryListener = new CountryListenerImpl();
detector.setCountryListener(countryListener);
detector.detectCountry();
- assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS);
+ assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount());
waitForTimerReset(detector);
// All listeners should be unregistered
- assertEquals(detector.getListenersCount(), 0);
+ assertEquals(0, detector.getListenersCount());
Thread queryThread = waitForQueryThreadLaunched(detector);
detector.notifyCountryFound();
// Wait for query thread ending
diff --git a/telephony/java/com/android/internal/telephony/cat/CatService.java b/telephony/java/com/android/internal/telephony/cat/CatService.java
index 5217ecd49c7c..33cc97ed12d6 100644
--- a/telephony/java/com/android/internal/telephony/cat/CatService.java
+++ b/telephony/java/com/android/internal/telephony/cat/CatService.java
@@ -134,6 +134,7 @@ public class CatService extends Handler implements AppInterface {
static final int MSG_ID_CALL_SETUP = 4;
static final int MSG_ID_REFRESH = 5;
static final int MSG_ID_RESPONSE = 6;
+ static final int MSG_ID_SIM_READY = 7;
static final int MSG_ID_RIL_MSG_DECODED = 10;
@@ -171,9 +172,11 @@ public class CatService extends Handler implements AppInterface {
mIccRecords = ir;
// Register for SIM ready event.
+ mCmdIf.registerForSIMReady(this, MSG_ID_SIM_READY, null);
+ mCmdIf.registerForRUIMReady(this, MSG_ID_SIM_READY, null);
+ mCmdIf.registerForNVReady(this, MSG_ID_SIM_READY, null);
mIccRecords.registerForRecordsLoaded(this, MSG_ID_ICC_RECORDS_LOADED, null);
- mCmdIf.reportStkServiceIsRunning(null);
CatLog.d(this, "Is running");
}
@@ -587,6 +590,10 @@ public class CatService extends Handler implements AppInterface {
case MSG_ID_RESPONSE:
handleCmdResponse((CatResponseMessage) msg.obj);
break;
+ case MSG_ID_SIM_READY:
+ CatLog.d(this, "SIM ready. Reporting STK service running now...");
+ mCmdIf.reportStkServiceIsRunning(null);
+ break;
default:
throw new AssertionError("Unrecognized CAT command: " + msg.what);
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index cd585cfcba63..e299d4a8b8a1 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -99,9 +99,9 @@ public class CdmaDataConnection extends DataConnection {
@Override
protected boolean isDnsOk(String[] domainNameServers) {
- if ((NULL_IP.equals(domainNameServers[0])
+ if (NULL_IP.equals(domainNameServers[0])
&& NULL_IP.equals(domainNameServers[1])
- && !((CDMAPhone) phone).isDnsCheckDisabled())) {
+ && !phone.isDnsCheckDisabled()) {
return false;
} else {
return true;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index 109daf03c642..f019487aa2bc 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -424,8 +424,8 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
: -1;
if (networkType == ServiceState.RADIO_TECHNOLOGY_LTE) {
lteRssi = (ints[offset + 5] >= 0) ? ints[offset + 5] : 99;
- lteRsrp = (ints[offset + 6] > 0) ? -ints[offset + 7] : -1;
- lteCqi = (ints[offset + 7] >= 0) ? ints[offset + 6] : 99;
+ lteRsrp = (ints[offset + 6] < 0) ? ints[offset + 6] : -1;
+ lteCqi = (ints[offset + 7] >= 0) ? ints[offset + 7] : 99;
}
if (networkType != ServiceState.RADIO_TECHNOLOGY_LTE) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index 8a11ae3a3253..545ad8af6b3c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -130,7 +130,7 @@ public class GsmDataConnection extends DataConnection {
@Override
protected boolean isDnsOk(String[] domainNameServers) {
if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1])
- && !((GSMPhone) phone).isDnsCheckDisabled()) {
+ && !phone.isDnsCheckDisabled()) {
// Work around a race condition where QMI does not fill in DNS:
// Deactivate PDP and let DataConnectionTracker retry.
// Do not apply the race condition workaround for MMS APN
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 223c8adc644d..8e675fc3f4f9 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -115,6 +115,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn");
static final String APN_ID = "apn_id";
private boolean canSetPreferApn = false;
+ private boolean mRadioAvailable = false;
@Override
protected void onActionIntentReconnectAlarm(Intent intent) {
@@ -519,6 +520,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} else {
if (DBG) log("return APN_ALREADY_INACTIVE");
apnContext.setEnabled(false);
+ apnContext.setDataConnection(null);
return Phone.APN_ALREADY_INACTIVE;
}
@@ -1267,6 +1269,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (!apnContext.getDataConnection().isRetryNeeded()) {
if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)){
// if no more retries on a secondary APN attempt, tell the world and revert.
+ apnContext.setDataConnection(null);
notifyDataConnection(Phone.REASON_APN_FAILED);
return;
}
@@ -1323,6 +1326,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void onRecordsLoaded() {
if (DBG) log("onRecordsLoaded: createAllApnList");
createAllApnList();
+ if (mRadioAvailable) {
+ if (DBG) log("onRecordsLoaded, notifying data availability");
+ notifyDataAvailability(null);
+ }
setupDataOnReadyApns(Phone.REASON_SIM_LOADED);
}
@@ -1434,6 +1441,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
protected void onRadioAvailable() {
+
+ mRadioAvailable = true;
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
@@ -1461,6 +1470,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
dc.resetRetryCount();
}
mReregisterOnReconnectFailure = false;
+ mRadioAvailable = false;
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
@@ -1470,6 +1480,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (DBG) log("Radio is off and clean up all connection");
cleanUpAllConnections(false, Phone.REASON_RADIO_TURNED_OFF);
}
+ notifyDataAvailability(null);
}
@Override
@@ -1562,6 +1573,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
log("onDataSetupComplete: All APN's had permanent failures, stop retrying");
}
apnContext.setState(State.FAILED);
+ apnContext.setDataConnection(null);
notifyDataConnection(Phone.REASON_APN_FAILED);
} else {
if (DBG) log("onDataSetupComplete: Not all permanent failures, retry");
@@ -1600,6 +1612,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE) {
apnContext.setEnabled(false);
apnContext.setPendingAction(ApnContext.PENDING_ACTION_NONE);
+ apnContext.setDataConnection(null);
}
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
@@ -1618,7 +1631,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_RECONNECT) {
apnContext.setPendingAction(ApnContext.PENDING_ACTION_NONE);
}
- trySetupData(apnContext);
+ // Wait a bit before trying the next APN, so that
+ // we're not tying up the RIL command channel.
+ // This also helps in any external dependency to turn off the context.
+ sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext),APN_DELAY_MILLIS);
}
}
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 31b2ddd27b50..c5c3f708b0d0 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -18,6 +18,11 @@
package="com.android.test.hwui">
<uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.CAMERA" />
+
+ <uses-feature android:name="android.hardware.camera" />
+ <uses-feature android:name="android.hardware.camera.autofocus" />
+
<uses-sdk android:minSdkVersion="11" />
<application
@@ -25,6 +30,15 @@
android:hardwareAccelerated="true">
<activity
+ android:name="TextureViewActivity"
+ android:label="_TextureView">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="BitmapMeshActivity"
android:label="_BitmapMesh">
<intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
new file mode 100644
index 000000000000..4726672cad84
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
@@ -0,0 +1,87 @@
+/*
+ * 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.test.hwui;
+
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.app.Activity;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.TextureView;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.io.IOException;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class TextureViewActivity extends Activity implements TextureView.SurfaceTextureListener {
+ private Camera mCamera;
+ private TextureView mTextureView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mTextureView = new TextureView(this);
+ mTextureView.setSurfaceTextureListener(this);
+
+ setContentView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER));
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ mCamera.stopPreview();
+ mCamera.release();
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface) {
+ mCamera = Camera.open();
+
+ try {
+ mCamera.setPreviewTexture(surface);
+ } catch (IOException t) {
+ android.util.Log.e("TextureView", "Cannot set preview texture target!", t);
+ }
+
+ mCamera.startPreview();
+
+ mTextureView.setCameraDistance(5000);
+
+ ObjectAnimator animator = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
+ animator.setRepeatMode(ObjectAnimator.REVERSE);
+ animator.setRepeatCount(ObjectAnimator.INFINITE);
+ animator.setDuration(4000);
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ ((View) mTextureView.getParent()).invalidate();
+ }
+ });
+ animator.start();
+
+ animator = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f);
+ animator.setRepeatMode(ObjectAnimator.REVERSE);
+ animator.setRepeatCount(ObjectAnimator.INFINITE);
+ animator.setDuration(4000);
+ animator.start();
+ }
+}
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs
index 31dd3e94ce34..d44fd2beff9d 100644
--- a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs
+++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs
@@ -184,7 +184,7 @@ static void drawOffscreenResult(int posX, int posY) {
startX + width, startY, 0, 1, 1);
}
-int root(int launchID) {
+int root(void) {
rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
rsgClearDepth(1.0f);
diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs
index 36790686feca..f04695260f41 100644
--- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs
+++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs
@@ -46,7 +46,7 @@ void init() {
gRotate = 0.0f;
}
-int root(int launchID) {
+int root(void) {
gGroup->transforms[1].w += 0.5f;
gGroup->isDirty = 1;
diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs
index 4c38745574c4..809f02cecc0f 100644
--- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs
+++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs
@@ -130,7 +130,7 @@ void drawDescription() {
rsgDrawText(gTextAlloc, 2 -left, height - 2 + bottom);
}
-int root(int launchID) {
+int root(void) {
rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
rsgClearDepth(1.0f);
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
index a663d3525176..3fc59fcfdd64 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
@@ -776,7 +776,7 @@ static void drawOffscreenResult(int posX, int posY, int width, int height) {
startX + width, startY, 0, 1, 1);
}
-int root(int launchID) {
+int root(void) {
gRenderSurfaceW = rsgGetWidth();
gRenderSurfaceH = rsgGetHeight();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/rslist.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/rslist.rs
index 67c2b8623c61..aeae13ff1331 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/rslist.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/rslist.rs
@@ -35,7 +35,7 @@ void init() {
int textPos = 0;
-int root(int launchID) {
+int root(void) {
rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
rsgClearDepth(1.0f);
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 16611d88851f..33d4e1fc489b 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -73,6 +73,7 @@ import android.util.LruCache;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -165,95 +166,97 @@ public class WifiStateMachine extends StateMachine {
private static final int EVENTLOG_WIFI_EVENT_HANDLED = 50022;
private static final int EVENTLOG_SUPPLICANT_STATE_CHANGED = 50023;
+ /* The base for wifi message types */
+ static final int BASE = Protocol.BASE_WIFI;
/* Load the driver */
- static final int CMD_LOAD_DRIVER = 1;
+ static final int CMD_LOAD_DRIVER = BASE + 1;
/* Unload the driver */
- static final int CMD_UNLOAD_DRIVER = 2;
+ static final int CMD_UNLOAD_DRIVER = BASE + 2;
/* Indicates driver load succeeded */
- static final int CMD_LOAD_DRIVER_SUCCESS = 3;
+ static final int CMD_LOAD_DRIVER_SUCCESS = BASE + 3;
/* Indicates driver load failed */
- static final int CMD_LOAD_DRIVER_FAILURE = 4;
+ static final int CMD_LOAD_DRIVER_FAILURE = BASE + 4;
/* Indicates driver unload succeeded */
- static final int CMD_UNLOAD_DRIVER_SUCCESS = 5;
+ static final int CMD_UNLOAD_DRIVER_SUCCESS = BASE + 5;
/* Indicates driver unload failed */
- static final int CMD_UNLOAD_DRIVER_FAILURE = 6;
+ static final int CMD_UNLOAD_DRIVER_FAILURE = BASE + 6;
/* Start the supplicant */
- static final int CMD_START_SUPPLICANT = 11;
+ static final int CMD_START_SUPPLICANT = BASE + 11;
/* Stop the supplicant */
- static final int CMD_STOP_SUPPLICANT = 12;
+ static final int CMD_STOP_SUPPLICANT = BASE + 12;
/* Start the driver */
- static final int CMD_START_DRIVER = 13;
+ static final int CMD_START_DRIVER = BASE + 13;
/* Start the driver */
- static final int CMD_STOP_DRIVER = 14;
+ static final int CMD_STOP_DRIVER = BASE + 14;
/* Indicates DHCP succeded */
- static final int CMD_IP_CONFIG_SUCCESS = 15;
+ static final int CMD_IP_CONFIG_SUCCESS = BASE + 15;
/* Indicates DHCP failed */
- static final int CMD_IP_CONFIG_FAILURE = 16;
+ static final int CMD_IP_CONFIG_FAILURE = BASE + 16;
/* Start the soft access point */
- static final int CMD_START_AP = 21;
+ static final int CMD_START_AP = BASE + 21;
/* Stop the soft access point */
- static final int CMD_STOP_AP = 22;
+ static final int CMD_STOP_AP = BASE + 22;
- static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = 23;
+ static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 23;
/* Supplicant events */
/* Connection to supplicant established */
- static final int SUP_CONNECTION_EVENT = 31;
+ static final int SUP_CONNECTION_EVENT = BASE + 31;
/* Connection to supplicant lost */
- static final int SUP_DISCONNECTION_EVENT = 32;
+ static final int SUP_DISCONNECTION_EVENT = BASE + 32;
/* Driver start completed */
- static final int DRIVER_START_EVENT = 33;
+ static final int DRIVER_START_EVENT = BASE + 33;
/* Driver stop completed */
- static final int DRIVER_STOP_EVENT = 34;
+ static final int DRIVER_STOP_EVENT = BASE + 34;
/* Network connection completed */
- static final int NETWORK_CONNECTION_EVENT = 36;
+ static final int NETWORK_CONNECTION_EVENT = BASE + 36;
/* Network disconnection completed */
- static final int NETWORK_DISCONNECTION_EVENT = 37;
+ static final int NETWORK_DISCONNECTION_EVENT = BASE + 37;
/* Scan results are available */
- static final int SCAN_RESULTS_EVENT = 38;
+ static final int SCAN_RESULTS_EVENT = BASE + 38;
/* Supplicate state changed */
- static final int SUPPLICANT_STATE_CHANGE_EVENT = 39;
+ static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 39;
/* Password failure and EAP authentication failure */
- static final int AUTHENTICATION_FAILURE_EVENT = 40;
+ static final int AUTHENTICATION_FAILURE_EVENT = BASE + 40;
/* WPS overlap detected */
- static final int WPS_OVERLAP_EVENT = 41;
+ static final int WPS_OVERLAP_EVENT = BASE + 41;
/* Supplicant commands */
/* Is supplicant alive ? */
- static final int CMD_PING_SUPPLICANT = 51;
+ static final int CMD_PING_SUPPLICANT = BASE + 51;
/* Add/update a network configuration */
- static final int CMD_ADD_OR_UPDATE_NETWORK = 52;
+ static final int CMD_ADD_OR_UPDATE_NETWORK = BASE + 52;
/* Delete a network */
- static final int CMD_REMOVE_NETWORK = 53;
+ static final int CMD_REMOVE_NETWORK = BASE + 53;
/* Enable a network. The device will attempt a connection to the given network. */
- static final int CMD_ENABLE_NETWORK = 54;
+ static final int CMD_ENABLE_NETWORK = BASE + 54;
/* Enable all networks */
- static final int CMD_ENABLE_ALL_NETWORKS = 55;
+ static final int CMD_ENABLE_ALL_NETWORKS = BASE + 55;
/* Disable a network. The device does not attempt a connection to the given network. */
- static final int CMD_DISABLE_NETWORK = 56;
+ static final int CMD_DISABLE_NETWORK = BASE + 56;
/* Blacklist network. De-prioritizes the given BSSID for connection. */
- static final int CMD_BLACKLIST_NETWORK = 57;
+ static final int CMD_BLACKLIST_NETWORK = BASE + 57;
/* Clear the blacklist network list */
- static final int CMD_CLEAR_BLACKLIST = 58;
+ static final int CMD_CLEAR_BLACKLIST = BASE + 58;
/* Save configuration */
- static final int CMD_SAVE_CONFIG = 59;
+ static final int CMD_SAVE_CONFIG = BASE + 59;
/* Supplicant commands after driver start*/
/* Initiate a scan */
- static final int CMD_START_SCAN = 71;
+ static final int CMD_START_SCAN = BASE + 71;
/* Set scan mode. CONNECT_MODE or SCAN_ONLY_MODE */
- static final int CMD_SET_SCAN_MODE = 72;
+ static final int CMD_SET_SCAN_MODE = BASE + 72;
/* Set scan type. SCAN_ACTIVE or SCAN_PASSIVE */
- static final int CMD_SET_SCAN_TYPE = 73;
+ static final int CMD_SET_SCAN_TYPE = BASE + 73;
/* Disconnect from a network */
- static final int CMD_DISCONNECT = 74;
+ static final int CMD_DISCONNECT = BASE + 74;
/* Reconnect to a network */
- static final int CMD_RECONNECT = 75;
+ static final int CMD_RECONNECT = BASE + 75;
/* Reassociate to a network */
- static final int CMD_REASSOCIATE = 76;
+ static final int CMD_REASSOCIATE = BASE + 76;
/* Controls power mode and suspend mode optimizations
*
* When high perf mode is enabled, power mode is set to
@@ -267,19 +270,19 @@ public class WifiStateMachine extends StateMachine {
* - turn off roaming
* - DTIM wake up settings
*/
- static final int CMD_SET_HIGH_PERF_MODE = 77;
+ static final int CMD_SET_HIGH_PERF_MODE = BASE + 77;
/* Set the country code */
- static final int CMD_SET_COUNTRY_CODE = 80;
+ static final int CMD_SET_COUNTRY_CODE = BASE + 80;
/* Request connectivity manager wake lock before driver stop */
- static final int CMD_REQUEST_CM_WAKELOCK = 81;
+ static final int CMD_REQUEST_CM_WAKELOCK = BASE + 81;
/* Enables RSSI poll */
- static final int CMD_ENABLE_RSSI_POLL = 82;
+ static final int CMD_ENABLE_RSSI_POLL = BASE + 82;
/* RSSI poll */
- static final int CMD_RSSI_POLL = 83;
+ static final int CMD_RSSI_POLL = BASE + 83;
/* Set up packet filtering */
- static final int CMD_START_PACKET_FILTERING = 84;
+ static final int CMD_START_PACKET_FILTERING = BASE + 84;
/* Clear packet filter */
- static final int CMD_STOP_PACKET_FILTERING = 85;
+ static final int CMD_STOP_PACKET_FILTERING = BASE + 85;
/* Connect to a specified network (network id
* or WifiConfiguration) This involves increasing
* the priority of the network, enabling the network
@@ -288,33 +291,33 @@ public class WifiStateMachine extends StateMachine {
* an existing network. All the networks get enabled
* upon a successful connection or a failure.
*/
- static final int CMD_CONNECT_NETWORK = 86;
+ static final int CMD_CONNECT_NETWORK = BASE + 86;
/* Save the specified network. This involves adding
* an enabled network (if new) and updating the
* config and issuing a save on supplicant config.
*/
- static final int CMD_SAVE_NETWORK = 87;
+ static final int CMD_SAVE_NETWORK = BASE + 87;
/* Delete the specified network. This involves
* removing the network and issuing a save on
* supplicant config.
*/
- static final int CMD_FORGET_NETWORK = 88;
+ static final int CMD_FORGET_NETWORK = BASE + 88;
/* Start Wi-Fi protected setup */
- static final int CMD_START_WPS = 89;
+ static final int CMD_START_WPS = BASE + 89;
/* Set the frequency band */
- static final int CMD_SET_FREQUENCY_BAND = 90;
+ static final int CMD_SET_FREQUENCY_BAND = BASE + 90;
/* Enable background scan for configured networks */
- static final int CMD_ENABLE_BACKGROUND_SCAN = 91;
+ static final int CMD_ENABLE_BACKGROUND_SCAN = BASE + 91;
/* Commands from/to the SupplicantStateTracker */
/* Reset the supplicant state tracker */
- static final int CMD_RESET_SUPPLICANT_STATE = 111;
+ static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111;
/* Commands/events reported by WpsStateMachine */
/* Indicates the completion of WPS activity */
- static final int WPS_COMPLETED_EVENT = 121;
+ static final int WPS_COMPLETED_EVENT = BASE + 121;
/* Reset the WPS state machine */
- static final int CMD_RESET_WPS_STATE = 122;
+ static final int CMD_RESET_WPS_STATE = BASE + 122;
private static final int CONNECT_MODE = 1;
private static final int SCAN_ONLY_MODE = 2;