summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--GenerationCache.h245
-rw-r--r--api/current.txt18
-rw-r--r--cmds/dumpstate/dumpstate.c3
-rw-r--r--core/java/android/app/Activity.java1
-rw-r--r--core/java/android/app/Dialog.java2
-rw-r--r--core/java/android/net/DhcpInfoInternal.java25
-rw-r--r--core/java/android/net/DhcpStateMachine.java353
-rw-r--r--core/java/android/net/LinkProperties.java44
-rw-r--r--core/java/android/net/NetworkUtils.java10
-rw-r--r--core/java/android/net/RouteInfo.aidl19
-rw-r--r--core/java/android/net/RouteInfo.java162
-rw-r--r--core/java/android/text/BoringLayout.java44
-rw-r--r--core/java/android/text/Layout.java2
-rw-r--r--core/java/android/text/SpannableStringBuilder.java55
-rw-r--r--core/java/android/text/TextLine.java7
-rw-r--r--core/java/android/text/TextUtils.java12
-rw-r--r--core/java/android/text/method/MultiTapKeyListener.java8
-rw-r--r--core/java/android/text/style/DrawableMarginSpan.java3
-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.java4
-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.java233
-rw-r--r--core/java/android/view/TextureView.java334
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java10
-rw-r--r--core/java/android/view/accessibility/AccessibilityRecord.java10
-rw-r--r--core/java/android/webkit/WebSettings.java13
-rw-r--r--core/java/android/widget/AdapterView.java2
-rw-r--r--core/java/android/widget/LinearLayout.java9
-rw-r--r--core/java/android/widget/ListView.java14
-rw-r--r--core/java/android/widget/PopupWindow.java4
-rw-r--r--core/java/android/widget/ProgressBar.java88
-rw-r--r--core/java/android/widget/ScrollView.java6
-rw-r--r--core/java/android/widget/TextView.java146
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java117
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java2
-rw-r--r--core/java/com/android/internal/util/AsyncChannel.java174
-rw-r--r--core/java/com/android/internal/util/Protocol.java46
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuPresenter.java36
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuView.java122
-rw-r--r--core/java/com/android/internal/view/menu/MenuBuilder.java2
-rw-r--r--core/java/com/android/internal/widget/AbsActionBarView.java211
-rw-r--r--core/java/com/android/internal/widget/ActionBarContainer.java7
-rw-r--r--core/java/com/android/internal/widget/ActionBarContextView.java86
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java139
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android/graphics/Movie.cpp5
-rw-r--r--core/jni/android_net_NetUtils.cpp62
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp27
-rw-r--r--core/jni/android_view_TextureView.cpp50
-rw-r--r--core/jni/com_google_android_gles_jni_EGLImpl.cpp33
-rw-r--r--core/res/res/layout/action_bar_title_item.xml3
-rw-r--r--core/res/res/layout/screen_action_bar.xml5
-rw-r--r--core/res/res/layout/screen_action_bar_overlay.xml5
-rw-r--r--core/res/res/values-ca/strings.xml2
-rw-r--r--core/res/res/values-de/strings.xml4
-rw-r--r--core/res/res/values-es/strings.xml2
-rw-r--r--core/res/res/values-in/strings.xml2
-rw-r--r--core/res/res/values-ro/strings.xml4
-rw-r--r--core/res/res/values-sk/strings.xml2
-rw-r--r--core/res/res/values-w480dp/bools.xml1
-rw-r--r--core/res/res/values-zh-rTW/strings.xml2
-rwxr-xr-xcore/res/res/values/attrs.xml5
-rw-r--r--core/res/res/values/bools.xml1
-rwxr-xr-xcore/res/res/values/config.xml4
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--core/res/res/values/themes.xml13
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java3
-rw-r--r--core/tests/coretests/AndroidManifest.xml7
-rw-r--r--core/tests/coretests/src/android/net/LinkPropertiesTest.java33
-rw-r--r--core/tests/coretests/src/android/text/TextUtilsTest.java46
-rw-r--r--core/tests/coretests/src/android/util/ScrollViewScenario.java19
-rw-r--r--core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPadding.java38
-rw-r--r--core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPaddingTest.java68
-rw-r--r--docs/html/guide/topics/resources/providing-resources.jd4
-rw-r--r--docs/html/guide/topics/ui/declaring-layout.jd4
-rw-r--r--graphics/java/android/graphics/Movie.java11
-rw-r--r--graphics/java/android/graphics/SurfaceTexture.java19
-rw-r--r--graphics/java/android/graphics/drawable/BitmapDrawable.java4
-rw-r--r--graphics/jni/android_renderscript_RenderScript.cpp8
-rw-r--r--include/drm/drm_framework_common.h19
-rw-r--r--include/media/IMediaPlayer.h2
-rw-r--r--include/media/MediaPlayerInterface.h2
-rw-r--r--include/media/mediaplayer.h3
-rw-r--r--include/media/stagefright/MediaErrors.h12
-rw-r--r--include/private/opengles/gl_context.h18
-rw-r--r--include/ui/Region.h23
-rw-r--r--libs/gui/Android.mk4
-rw-r--r--libs/gui/tests/Android.mk3
-rw-r--r--libs/hwui/Caches.h4
-rw-r--r--libs/hwui/Layer.h24
-rw-r--r--libs/hwui/LayerCache.cpp2
-rw-r--r--libs/hwui/LayerRenderer.cpp46
-rw-r--r--libs/hwui/LayerRenderer.h3
-rw-r--r--libs/hwui/OpenGLRenderer.cpp162
-rw-r--r--libs/hwui/OpenGLRenderer.h17
-rw-r--r--libs/hwui/ProgramCache.cpp97
-rw-r--r--libs/hwui/ProgramCache.h17
-rw-r--r--libs/hwui/Vertex.h19
-rw-r--r--libs/rs/Android.mk11
-rw-r--r--libs/rs/driver/rsdCore.cpp21
-rw-r--r--libs/rs/driver/rsdGL.cpp11
-rw-r--r--libs/rs/driver/rsdGL.h5
-rw-r--r--libs/rs/driver/rsdMesh.cpp60
-rw-r--r--libs/rs/driver/rsdMesh.h32
-rw-r--r--libs/rs/driver/rsdMeshObj.cpp178
-rw-r--r--libs/rs/driver/rsdMeshObj.h63
-rw-r--r--libs/rs/driver/rsdProgram.cpp95
-rw-r--r--libs/rs/driver/rsdProgramFragment.h32
-rw-r--r--libs/rs/driver/rsdProgramVertex.h31
-rw-r--r--libs/rs/driver/rsdRuntimeMath.cpp2
-rw-r--r--libs/rs/driver/rsdRuntimeStubs.cpp2
-rw-r--r--libs/rs/driver/rsdShader.cpp468
-rw-r--r--libs/rs/driver/rsdShader.h104
-rw-r--r--libs/rs/driver/rsdShaderCache.cpp (renamed from libs/rs/rsShaderCache.cpp)78
-rw-r--r--libs/rs/driver/rsdShaderCache.h (renamed from libs/rs/rsShaderCache.h)61
-rw-r--r--libs/rs/driver/rsdVertexArray.cpp (renamed from libs/rs/rsVertexArray.cpp)48
-rw-r--r--libs/rs/driver/rsdVertexArray.h (renamed from libs/rs/rsVertexArray.h)39
-rw-r--r--libs/rs/rs.spec8
-rw-r--r--libs/rs/rsAllocation.cpp56
-rw-r--r--libs/rs/rsContext.cpp43
-rw-r--r--libs/rs/rsContext.h6
-rw-r--r--libs/rs/rsDevice.cpp11
-rw-r--r--libs/rs/rsFont.cpp29
-rw-r--r--libs/rs/rsFont.h4
-rw-r--r--libs/rs/rsMesh.cpp316
-rw-r--r--libs/rs/rsMesh.h64
-rw-r--r--libs/rs/rsProgram.cpp420
-rw-r--r--libs/rs/rsProgram.h81
-rw-r--r--libs/rs/rsProgramFragment.cpp106
-rw-r--r--libs/rs/rsProgramFragment.h5
-rw-r--r--libs/rs/rsProgramStore.h4
-rw-r--r--libs/rs/rsProgramVertex.cpp100
-rw-r--r--libs/rs/rsProgramVertex.h6
-rw-r--r--libs/rs/rsScriptC_LibGL.cpp16
-rw-r--r--libs/rs/rsType.cpp9
-rw-r--r--libs/rs/rsType.h3
-rw-r--r--libs/rs/rs_hal.h22
-rw-r--r--libs/rs/rsg_generator.c116
-rw-r--r--location/java/android/location/LocationManager.java6
-rw-r--r--media/java/android/media/MediaPlayer.java78
-rw-r--r--media/java/android/media/MediaScanner.java66
-rw-r--r--media/jni/android_media_MediaPlayer.cpp35
-rw-r--r--media/libmedia/IMediaPlayer.cpp39
-rw-r--r--media/libmedia/MediaScanner.cpp7
-rw-r--r--media/libmedia/mediaplayer.cpp22
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp14
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h2
-rw-r--r--media/libmediaplayerservice/MidiFile.h7
-rw-r--r--media/libmediaplayerservice/StagefrightPlayer.cpp10
-rw-r--r--media/libmediaplayerservice/StagefrightPlayer.h2
-rw-r--r--media/libmediaplayerservice/TestPlayerStub.h6
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp8
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.h2
-rw-r--r--media/libstagefright/AwesomePlayer.cpp11
-rw-r--r--media/libstagefright/DRMExtractor.cpp8
-rw-r--r--media/libstagefright/include/AwesomePlayer.h3
-rw-r--r--media/tests/players/invoke_mock_media_player.cpp3
-rw-r--r--opengl/java/com/google/android/gles_jni/EGLImpl.java18
-rw-r--r--opengl/libagl/egl.cpp114
-rw-r--r--opengl/libagl2/src/egl.cpp3304
-rw-r--r--policy/src/com/android/internal/policy/impl/GlobalActions.java7
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java31
-rw-r--r--services/input/InputWindow.h5
-rw-r--r--services/java/com/android/server/ConnectivityService.java20
-rw-r--r--services/java/com/android/server/ThrottleService.java183
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java15
-rwxr-xr-xservices/java/com/android/server/location/ComprehensiveCountryDetector.java30
-rwxr-xr-xservices/java/com/android/server/location/LocationBasedCountryDetector.java88
-rw-r--r--services/surfaceflinger/TextureManager.cpp2
-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/android/telephony/JapanesePhoneNumberFormatter.java8
-rw-r--r--telephony/java/com/android/internal/telephony/ApnContext.java18
-rw-r--r--telephony/java/com/android/internal/telephony/DataCallState.java5
-rw-r--r--telephony/java/com/android/internal/telephony/DataConnection.java330
-rw-r--r--telephony/java/com/android/internal/telephony/DataConnectionAc.java288
-rw-r--r--telephony/java/com/android/internal/telephony/DataConnectionTracker.java128
-rw-r--r--telephony/java/com/android/internal/telephony/IccUtils.java1
-rw-r--r--telephony/java/com/android/internal/telephony/RIL.java5
-rw-r--r--telephony/java/com/android/internal/telephony/cat/CatService.java9
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java5
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java39
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java68
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java47
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java3
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java390
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml23
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java274
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java101
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java92
-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/WifiConfigStore.java61
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java389
204 files changed, 9068 insertions, 4868 deletions
diff --git a/GenerationCache.h b/GenerationCache.h
deleted file mode 100644
index 42e6d9b..0000000
--- 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 4b3918e..a7f0368 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,22 @@ 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);
+ method public abstract void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int);
+ }
+
public class TouchDelegate {
ctor public TouchDelegate(android.graphics.Rect, android.view.View);
method public boolean onTouchEvent(android.view.MotionEvent);
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index df7037c..53cae41 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -109,7 +109,10 @@ static void dumpstate() {
run_command("NETWORK INTERFACES", 10, "su", "root", "netcfg", NULL);
dump_file("NETWORK ROUTES", "/proc/net/route");
+ dump_file("NETWORK ROUTES IPV6", "/proc/net/ipv6_route");
dump_file("ARP CACHE", "/proc/net/arp");
+ run_command("IPTABLES", 10, "su", "root", "iptables", "-L", NULL);
+ run_command("IPTABLE NAT", 10, "su", "root", "iptables", "-t", "nat", "-L", NULL);
run_command("WIFI NETWORKS", 20,
"su", "root", "wpa_cli", "list_networks", NULL);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f5849c2..02b6619 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/app/Dialog.java b/core/java/android/app/Dialog.java
index 087753b..82186dd 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -931,7 +931,7 @@ public class Dialog implements DialogInterface, Window.Callback,
// associate search with owner activity
final ComponentName appName = getAssociatedActivity();
- if (appName != null) {
+ if (appName != null && searchManager.getSearchableInfo(appName) != null) {
searchManager.startSearch(null, false, appName, null, false);
dismiss();
return true;
diff --git a/core/java/android/net/DhcpInfoInternal.java b/core/java/android/net/DhcpInfoInternal.java
index 7396669..860da0a 100644
--- a/core/java/android/net/DhcpInfoInternal.java
+++ b/core/java/android/net/DhcpInfoInternal.java
@@ -22,6 +22,8 @@ import android.util.Log;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
/**
* A simple object for retrieving the results of a DHCP request.
@@ -31,7 +33,6 @@ import java.net.UnknownHostException;
public class DhcpInfoInternal {
private final static String TAG = "DhcpInfoInternal";
public String ipAddress;
- public String gateway;
public int prefixLength;
public String dns1;
@@ -40,7 +41,14 @@ public class DhcpInfoInternal {
public String serverAddress;
public int leaseDuration;
+ private Collection<RouteInfo> routes;
+
public DhcpInfoInternal() {
+ routes = new ArrayList<RouteInfo>();
+ }
+
+ public void addRoute(RouteInfo routeInfo) {
+ routes.add(routeInfo);
}
private int convertToInt(String addr) {
@@ -58,7 +66,12 @@ public class DhcpInfoInternal {
public DhcpInfo makeDhcpInfo() {
DhcpInfo info = new DhcpInfo();
info.ipAddress = convertToInt(ipAddress);
- info.gateway = convertToInt(gateway);
+ for (RouteInfo route : routes) {
+ if (route.isDefaultRoute()) {
+ info.gateway = convertToInt(route.getGateway().getHostAddress());
+ break;
+ }
+ }
try {
InetAddress inetAddress = NetworkUtils.numericToInetAddress(ipAddress);
info.netmask = NetworkUtils.prefixLengthToNetmaskInt(prefixLength);
@@ -81,8 +94,8 @@ public class DhcpInfoInternal {
public LinkProperties makeLinkProperties() {
LinkProperties p = new LinkProperties();
p.addLinkAddress(makeLinkAddress());
- if (TextUtils.isEmpty(gateway) == false) {
- p.addGateway(NetworkUtils.numericToInetAddress(gateway));
+ for (RouteInfo route : routes) {
+ p.addRoute(route);
}
if (TextUtils.isEmpty(dns1) == false) {
p.addDns(NetworkUtils.numericToInetAddress(dns1));
@@ -98,8 +111,10 @@ public class DhcpInfoInternal {
}
public String toString() {
+ String routeString = "";
+ for (RouteInfo route : routes) routeString += route.toString() + " | ";
return "addr: " + ipAddress + "/" + prefixLength +
- " gateway: " + gateway +
+ " routes: " + routeString +
" dns: " + dns1 + "," + dns2 +
" dhcpServer: " + serverAddress +
" leaseDuration: " + leaseDuration;
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
new file mode 100644
index 0000000..eaf087f
--- /dev/null
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -0,0 +1,353 @@
+/*
+ * 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.net;
+
+import com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.DhcpInfoInternal;
+import android.net.NetworkUtils;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Log;
+
+/**
+ * StateMachine that interacts with the native DHCP client and can talk to
+ * a controller that also needs to be a StateMachine
+ *
+ * The Dhcp state machine provides the following features:
+ * - Wakeup and renewal using the native DHCP client (which will not renew
+ * on its own when the device is in suspend state and this can lead to device
+ * holding IP address beyond expiry)
+ * - A notification right before DHCP request or renewal is started. This
+ * can be used for any additional setup before DHCP. For example, wifi sets
+ * BT-Wifi coex settings right before DHCP is initiated
+ *
+ * @hide
+ */
+public class DhcpStateMachine extends StateMachine {
+
+ private static final String TAG = "DhcpStateMachine";
+ private static final boolean DBG = false;
+
+
+ /* A StateMachine that controls the DhcpStateMachine */
+ private StateMachine mController;
+
+ private Context mContext;
+ private BroadcastReceiver mBroadcastReceiver;
+ private AlarmManager mAlarmManager;
+ private PendingIntent mDhcpRenewalIntent;
+ private PowerManager.WakeLock mDhcpRenewWakeLock;
+ private static final String WAKELOCK_TAG = "DHCP";
+
+ private static final int DHCP_RENEW = 0;
+ private static final String ACTION_DHCP_RENEW = "android.net.wifi.DHCP_RENEW";
+
+ private enum DhcpAction {
+ START,
+ RENEW
+ };
+
+ private String mInterfaceName;
+ private boolean mRegisteredForPreDhcpNotification = false;
+
+ private static final int BASE = Protocol.BASE_DHCP;
+
+ /* Commands from controller to start/stop DHCP */
+ public static final int CMD_START_DHCP = BASE + 1;
+ public static final int CMD_STOP_DHCP = BASE + 2;
+ public static final int CMD_RENEW_DHCP = BASE + 3;
+
+ /* Notification from DHCP state machine prior to DHCP discovery/renewal */
+ public static final int CMD_PRE_DHCP_ACTION = BASE + 4;
+ /* Notification from DHCP state machine post DHCP discovery/renewal. Indicates
+ * success/failure */
+ public static final int CMD_POST_DHCP_ACTION = BASE + 5;
+
+ /* Command from controller to indicate DHCP discovery/renewal can continue
+ * after pre DHCP action is complete */
+ public static final int CMD_PRE_DHCP_ACTION_COMPLETE = BASE + 6;
+
+ /* Message.arg1 arguments to CMD_POST_DHCP notification */
+ public static final int DHCP_SUCCESS = 1;
+ public static final int DHCP_FAILURE = 2;
+
+ private State mDefaultState = new DefaultState();
+ private State mStoppedState = new StoppedState();
+ private State mWaitBeforeStartState = new WaitBeforeStartState();
+ private State mRunningState = new RunningState();
+ private State mWaitBeforeRenewalState = new WaitBeforeRenewalState();
+
+ private DhcpStateMachine(Context context, StateMachine controller, String intf) {
+ super(TAG);
+
+ mContext = context;
+ mController = controller;
+ mInterfaceName = intf;
+
+ mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
+ Intent dhcpRenewalIntent = new Intent(ACTION_DHCP_RENEW, null);
+ mDhcpRenewalIntent = PendingIntent.getBroadcast(mContext, DHCP_RENEW, dhcpRenewalIntent, 0);
+
+ PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+ mDhcpRenewWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
+
+ mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ //DHCP renew
+ if (DBG) Log.d(TAG, "Sending a DHCP renewal " + this);
+ //acquire a 40s wakelock to finish DHCP renewal
+ mDhcpRenewWakeLock.acquire(40000);
+ sendMessage(CMD_RENEW_DHCP);
+ }
+ };
+ mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_DHCP_RENEW));
+
+ addState(mDefaultState);
+ addState(mStoppedState, mDefaultState);
+ addState(mWaitBeforeStartState, mDefaultState);
+ addState(mRunningState, mDefaultState);
+ addState(mWaitBeforeRenewalState, mDefaultState);
+
+ setInitialState(mStoppedState);
+ }
+
+ public static DhcpStateMachine makeDhcpStateMachine(Context context, StateMachine controller,
+ String intf) {
+ DhcpStateMachine dsm = new DhcpStateMachine(context, controller, intf);
+ dsm.start();
+ return dsm;
+ }
+
+ /**
+ * This sends a notification right before DHCP request/renewal so that the
+ * controller can do certain actions before DHCP packets are sent out.
+ * When the controller is ready, it sends a CMD_PRE_DHCP_ACTION_COMPLETE message
+ * to indicate DHCP can continue
+ *
+ * This is used by Wifi at this time for the purpose of doing BT-Wifi coex
+ * handling during Dhcp
+ */
+ public void registerForPreDhcpNotification() {
+ mRegisteredForPreDhcpNotification = true;
+ }
+
+ class DefaultState extends State {
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_RENEW_DHCP:
+ Log.e(TAG, "Error! Failed to handle a DHCP renewal on " + mInterfaceName);
+ break;
+ case SM_QUIT_CMD:
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ //let parent kill the state machine
+ return NOT_HANDLED;
+ default:
+ Log.e(TAG, "Error! unhandled message " + message);
+ break;
+ }
+ return HANDLED;
+ }
+ }
+
+
+ class StoppedState extends State {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ boolean retValue = HANDLED;
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_START_DHCP:
+ if (mRegisteredForPreDhcpNotification) {
+ /* Notify controller before starting DHCP */
+ mController.sendMessage(CMD_PRE_DHCP_ACTION);
+ transitionTo(mWaitBeforeStartState);
+ } else {
+ if (runDhcp(DhcpAction.START)) {
+ transitionTo(mRunningState);
+ }
+ }
+ break;
+ case CMD_STOP_DHCP:
+ //ignore
+ break;
+ default:
+ retValue = NOT_HANDLED;
+ break;
+ }
+ return retValue;
+ }
+ }
+
+ class WaitBeforeStartState extends State {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ boolean retValue = HANDLED;
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_PRE_DHCP_ACTION_COMPLETE:
+ if (runDhcp(DhcpAction.START)) {
+ transitionTo(mRunningState);
+ } else {
+ transitionTo(mStoppedState);
+ }
+ break;
+ case CMD_STOP_DHCP:
+ transitionTo(mStoppedState);
+ break;
+ case CMD_START_DHCP:
+ //ignore
+ break;
+ default:
+ retValue = NOT_HANDLED;
+ break;
+ }
+ return retValue;
+ }
+ }
+
+ class RunningState extends State {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ boolean retValue = HANDLED;
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_STOP_DHCP:
+ mAlarmManager.cancel(mDhcpRenewalIntent);
+ if (!NetworkUtils.stopDhcp(mInterfaceName)) {
+ Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName);
+ }
+ transitionTo(mStoppedState);
+ break;
+ case CMD_RENEW_DHCP:
+ if (mRegisteredForPreDhcpNotification) {
+ /* Notify controller before starting DHCP */
+ mController.sendMessage(CMD_PRE_DHCP_ACTION);
+ transitionTo(mWaitBeforeRenewalState);
+ } else {
+ if (!runDhcp(DhcpAction.RENEW)) {
+ transitionTo(mStoppedState);
+ }
+ }
+ break;
+ case CMD_START_DHCP:
+ //ignore
+ break;
+ default:
+ retValue = NOT_HANDLED;
+ }
+ return retValue;
+ }
+ }
+
+ class WaitBeforeRenewalState extends State {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ boolean retValue = HANDLED;
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch (message.what) {
+ case CMD_STOP_DHCP:
+ mAlarmManager.cancel(mDhcpRenewalIntent);
+ if (!NetworkUtils.stopDhcp(mInterfaceName)) {
+ Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName);
+ }
+ transitionTo(mStoppedState);
+ break;
+ case CMD_PRE_DHCP_ACTION_COMPLETE:
+ if (runDhcp(DhcpAction.RENEW)) {
+ transitionTo(mRunningState);
+ } else {
+ transitionTo(mStoppedState);
+ }
+ break;
+ case CMD_START_DHCP:
+ //ignore
+ break;
+ default:
+ retValue = NOT_HANDLED;
+ break;
+ }
+ return retValue;
+ }
+ }
+
+ private boolean runDhcp(DhcpAction dhcpAction) {
+ boolean success = false;
+ DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
+
+ if (dhcpAction == DhcpAction.START) {
+ Log.d(TAG, "DHCP request on " + mInterfaceName);
+ success = NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal);
+ } else if (dhcpAction == DhcpAction.RENEW) {
+ Log.d(TAG, "DHCP renewal on " + mInterfaceName);
+ success = NetworkUtils.runDhcpRenew(mInterfaceName, dhcpInfoInternal);
+ }
+
+ if (success) {
+ Log.d(TAG, "DHCP succeeded on " + mInterfaceName);
+ //Do it a bit earlier than half the lease duration time
+ //to beat the native DHCP client and avoid extra packets
+ //48% for one hour lease time = 29 minutes
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() +
+ dhcpInfoInternal.leaseDuration * 480, //in milliseconds
+ mDhcpRenewalIntent);
+
+ mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpInfoInternal)
+ .sendToTarget();
+ } else {
+ Log.d(TAG, "DHCP failed on " + mInterfaceName + ": " +
+ NetworkUtils.getDhcpError());
+ NetworkUtils.stopDhcp(mInterfaceName);
+ mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0)
+ .sendToTarget();
+ }
+ return success;
+ }
+}
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index e88292f..61acf2b 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -54,7 +54,7 @@ public class LinkProperties implements Parcelable {
String mIfaceName;
private Collection<LinkAddress> mLinkAddresses;
private Collection<InetAddress> mDnses;
- private Collection<InetAddress> mGateways;
+ private Collection<RouteInfo> mRoutes;
private ProxyProperties mHttpProxy;
public LinkProperties() {
@@ -67,7 +67,7 @@ public class LinkProperties implements Parcelable {
mIfaceName = source.getInterfaceName();
mLinkAddresses = source.getLinkAddresses();
mDnses = source.getDnses();
- mGateways = source.getGateways();
+ mRoutes = source.getRoutes();
mHttpProxy = new ProxyProperties(source.getHttpProxy());
}
}
@@ -104,11 +104,11 @@ public class LinkProperties implements Parcelable {
return Collections.unmodifiableCollection(mDnses);
}
- public void addGateway(InetAddress gateway) {
- if (gateway != null) mGateways.add(gateway);
+ public void addRoute(RouteInfo route) {
+ if (route != null) mRoutes.add(route);
}
- public Collection<InetAddress> getGateways() {
- return Collections.unmodifiableCollection(mGateways);
+ public Collection<RouteInfo> getRoutes() {
+ return Collections.unmodifiableCollection(mRoutes);
}
public void setHttpProxy(ProxyProperties proxy) {
@@ -122,7 +122,7 @@ public class LinkProperties implements Parcelable {
mIfaceName = null;
mLinkAddresses = new ArrayList<LinkAddress>();
mDnses = new ArrayList<InetAddress>();
- mGateways = new ArrayList<InetAddress>();
+ mRoutes = new ArrayList<RouteInfo>();
mHttpProxy = null;
}
@@ -146,12 +146,12 @@ public class LinkProperties implements Parcelable {
for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
dns += "] ";
- String gateways = "Gateways: [";
- for (InetAddress gw : mGateways) gateways += gw.getHostAddress() + ",";
- gateways += "] ";
+ String routes = "Routes: [";
+ for (RouteInfo route : mRoutes) routes += route.toString() + ",";
+ routes += "] ";
String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
- return ifaceName + linkAddresses + gateways + dns + proxy;
+ return ifaceName + linkAddresses + routes + dns + proxy;
}
@@ -177,7 +177,7 @@ public class LinkProperties implements Parcelable {
boolean sameAddresses;
boolean sameDnses;
- boolean sameGateways;
+ boolean sameRoutes;
LinkProperties target = (LinkProperties) obj;
@@ -190,12 +190,12 @@ public class LinkProperties implements Parcelable {
sameDnses = (mDnses.size() == targetDnses.size()) ?
mDnses.containsAll(targetDnses) : false;
- Collection<InetAddress> targetGateways = target.getGateways();
- sameGateways = (mGateways.size() == targetGateways.size()) ?
- mGateways.containsAll(targetGateways) : false;
+ Collection<RouteInfo> targetRoutes = target.getRoutes();
+ sameRoutes = (mRoutes.size() == targetRoutes.size()) ?
+ mRoutes.containsAll(targetRoutes) : false;
return
- sameAddresses && sameDnses && sameGateways
+ sameAddresses && sameDnses && sameRoutes
&& TextUtils.equals(getInterfaceName(), target.getInterfaceName())
&& (getHttpProxy() == null ? target.getHttpProxy() == null :
getHttpProxy().equals(target.getHttpProxy()));
@@ -211,7 +211,7 @@ public class LinkProperties implements Parcelable {
return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
+ mLinkAddresses.size() * 31
+ mDnses.size() * 37
- + mGateways.size() * 41
+ + mRoutes.size() * 41
+ ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()));
}
@@ -231,9 +231,9 @@ public class LinkProperties implements Parcelable {
dest.writeByteArray(d.getAddress());
}
- dest.writeInt(mGateways.size());
- for(InetAddress gw : mGateways) {
- dest.writeByteArray(gw.getAddress());
+ dest.writeInt(mRoutes.size());
+ for(RouteInfo route : mRoutes) {
+ dest.writeParcelable(route, flags);
}
if (mHttpProxy != null) {
@@ -272,9 +272,7 @@ public class LinkProperties implements Parcelable {
}
addressCount = in.readInt();
for (int i=0; i<addressCount; i++) {
- try {
- netProp.addGateway(InetAddress.getByAddress(in.createByteArray()));
- } catch (UnknownHostException e) { }
+ netProp.addRoute((RouteInfo)in.readParcelable(null));
}
if (in.readByte() == 1) {
netProp.setHttpProxy((ProxyProperties)in.readParcelable(null));
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index b3f3988..823d10f 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -80,6 +80,16 @@ public class NetworkUtils {
public native static boolean runDhcp(String interfaceName, DhcpInfoInternal ipInfo);
/**
+ * Initiate renewal on the Dhcp client daemon. This call blocks until it obtains
+ * a result (either success or failure) from the daemon.
+ * @param interfaceName the name of the interface to configure
+ * @param ipInfo if the request succeeds, this object is filled in with
+ * the IP address information.
+ * @return {@code true} for success, {@code false} for failure
+ */
+ public native static boolean runDhcpRenew(String interfaceName, DhcpInfoInternal ipInfo);
+
+ /**
* Shut down the DHCP client daemon.
* @param interfaceName the name of the interface for which the daemon
* should be stopped
diff --git a/core/java/android/net/RouteInfo.aidl b/core/java/android/net/RouteInfo.aidl
new file mode 100644
index 0000000..2296a57
--- /dev/null
+++ b/core/java/android/net/RouteInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.net;
+
+parcelable RouteInfo;
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
new file mode 100644
index 0000000..5b10531
--- /dev/null
+++ b/core/java/android/net/RouteInfo.java
@@ -0,0 +1,162 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.net.UnknownHostException;
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+/**
+ * A simple container for route information.
+ *
+ * @hide
+ */
+public class RouteInfo implements Parcelable {
+ /**
+ * The IP destination address for this route.
+ */
+ private final LinkAddress mDestination;
+
+ /**
+ * The gateway address for this route.
+ */
+ private final InetAddress mGateway;
+
+ private final boolean mIsDefault;
+
+ public RouteInfo(LinkAddress destination, InetAddress gateway) {
+ if (destination == null) {
+ try {
+ if ((gateway != null) && (gateway instanceof Inet4Address)) {
+ destination = new LinkAddress(InetAddress.getByName("0.0.0.0"), 32);
+ } else {
+ destination = new LinkAddress(InetAddress.getByName("::0"), 128);
+ }
+ } catch (Exception e) {}
+ }
+ mDestination = destination;
+ mGateway = gateway;
+ mIsDefault = isDefault();
+ }
+
+ public RouteInfo(InetAddress gateway) {
+ LinkAddress destination = null;
+ try {
+ if ((gateway != null) && (gateway instanceof Inet4Address)) {
+ destination = new LinkAddress(InetAddress.getByName("0.0.0.0"), 32);
+ } else {
+ destination = new LinkAddress(InetAddress.getByName("::0"), 128);
+ }
+ } catch (Exception e) {}
+ mDestination = destination;
+ mGateway = gateway;
+ mIsDefault = isDefault();
+ }
+
+ private boolean isDefault() {
+ boolean val = false;
+ if (mGateway != null) {
+ if (mGateway instanceof Inet4Address) {
+ val = (mDestination == null || mDestination.getNetworkPrefixLength() == 32);
+ } else {
+ val = (mDestination == null || mDestination.getNetworkPrefixLength() == 128);
+ }
+ }
+ return val;
+ }
+
+ public LinkAddress getDestination() {
+ return mDestination;
+ }
+
+ public InetAddress getGateway() {
+ return mGateway;
+ }
+
+ public boolean isDefaultRoute() {
+ return mIsDefault;
+ }
+
+ public String toString() {
+ String val = "";
+ if (mDestination != null) val = mDestination.toString();
+ if (mGateway != null) val += " -> " + mGateway.getHostAddress();
+ return val;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mDestination == null) {
+ dest.writeByte((byte) 0);
+ } else {
+ dest.writeByte((byte) 1);
+ dest.writeByteArray(mDestination.getAddress().getAddress());
+ dest.writeInt(mDestination.getNetworkPrefixLength());
+ }
+
+ if (mGateway == null) {
+ dest.writeByte((byte) 0);
+ } else {
+ dest.writeByte((byte) 1);
+ dest.writeByteArray(mGateway.getAddress());
+ }
+ }
+
+ public static final Creator<RouteInfo> CREATOR =
+ new Creator<RouteInfo>() {
+ public RouteInfo createFromParcel(Parcel in) {
+ InetAddress destAddr = null;
+ int prefix = 0;
+ InetAddress gateway = null;
+
+ if (in.readByte() == 1) {
+ byte[] addr = in.createByteArray();
+ prefix = in.readInt();
+
+ try {
+ destAddr = InetAddress.getByAddress(addr);
+ } catch (UnknownHostException e) {}
+ }
+
+ if (in.readByte() == 1) {
+ byte[] addr = in.createByteArray();
+
+ try {
+ gateway = InetAddress.getByAddress(addr);
+ } catch (UnknownHostException e) {}
+ }
+
+ LinkAddress dest = null;
+
+ if (destAddr != null) {
+ dest = new LinkAddress(destAddr, prefix);
+ }
+
+ return new RouteInfo(dest, gateway);
+ }
+
+ public RouteInfo[] newArray(int size) {
+ return new RouteInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 9309b05..757a8c3 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/Layout.java b/core/java/android/text/Layout.java
index 1e4cca9..4107c5a 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1170,7 +1170,7 @@ public abstract class Layout {
if (h2 < 0.5f)
h2 = 0.5f;
- if (h1 == h2) {
+ if (Float.compare(h1, h2) == 0) {
dest.moveTo(h1, top);
dest.lineTo(h1, bottom);
} else {
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 6b2d8e4..6bde802 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -20,6 +20,7 @@ import com.android.internal.util.ArrayUtils;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.text.style.SuggestionSpan;
import java.lang.reflect.Array;
@@ -277,8 +278,7 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
TextWatcher[] recipients = null;
if (notify)
- recipients = sendTextWillChange(start, end - start,
- tbend - tbstart);
+ recipients = sendTextWillChange(start, end - start, tbend - tbstart);
for (int i = mSpanCount - 1; i >= 0; i--) {
if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) {
@@ -353,6 +353,7 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
// no need for span fixup on pure insertion
if (tbend > tbstart && end - start == 0) {
if (notify) {
+ removeSuggestionSpans(start, end);
sendTextChange(recipients, start, end - start, tbend - tbstart);
sendTextHasChanged(recipients);
}
@@ -384,20 +385,10 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
}
// remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE
- // XXX send notification on removal
-
if (mSpanEnds[i] < mSpanStarts[i]) {
- System.arraycopy(mSpans, i + 1,
- mSpans, i, mSpanCount - (i + 1));
- System.arraycopy(mSpanStarts, i + 1,
- mSpanStarts, i, mSpanCount - (i + 1));
- System.arraycopy(mSpanEnds, i + 1,
- mSpanEnds, i, mSpanCount - (i + 1));
- System.arraycopy(mSpanFlags, i + 1,
- mSpanFlags, i, mSpanCount - (i + 1));
-
- mSpanCount--;
+ removeSpan(i);
}
+ removeSuggestionSpans(start, end);
}
if (notify) {
@@ -408,6 +399,32 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
return ret;
}
+ /**
+ * Removes the SuggestionSpan that overlap the [start, end] range, and that would
+ * not make sense anymore after the change.
+ */
+ private void removeSuggestionSpans(int start, int end) {
+ for (int i = mSpanCount - 1; i >= 0; i--) {
+ final int spanEnd = mSpanEnds[i];
+ final int spanSpart = mSpanStarts[i];
+ if ((mSpans[i] instanceof SuggestionSpan) && (
+ (spanSpart < start && spanEnd > start) ||
+ (spanSpart < end && spanEnd > end))) {
+ removeSpan(i);
+ }
+ }
+ }
+
+ private void removeSpan(int i) {
+ // XXX send notification on removal
+ System.arraycopy(mSpans, i + 1, mSpans, i, mSpanCount - (i + 1));
+ System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, mSpanCount - (i + 1));
+ System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, mSpanCount - (i + 1));
+ System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, mSpanCount - (i + 1));
+
+ mSpanCount--;
+ }
+
// Documentation from interface
public SpannableStringBuilder replace(int start, int end, CharSequence tb) {
return replace(start, end, tb, 0, tb.length());
@@ -465,16 +482,15 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
mGapStart++;
mGapLength--;
- if (mGapLength < 1)
+ if (mGapLength < 1) {
new Exception("mGapLength < 1").printStackTrace();
+ }
int oldlen = (end + 1) - start;
- int inserted = change(false, start + 1, start + 1,
- tb, tbstart, tbend);
+ int inserted = change(false, start + 1, start + 1, tb, tbstart, tbend);
change(false, start, start + 1, "", 0, 0);
- change(false, start + inserted, start + inserted + oldlen - 1,
- "", 0, 0);
+ change(false, start + inserted, start + inserted + oldlen - 1, "", 0, 0);
/*
* Special case to keep the cursor in the same position
@@ -1274,7 +1290,6 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
private int[] mSpanFlags;
private int mSpanCount;
- private static final int MARK = 1;
private static final int POINT = 2;
private static final int PARAGRAPH = 3;
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 1b7f2f3..0f8097a 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/text/TextUtils.java b/core/java/android/text/TextUtils.java
index ac5db62..6741059 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -629,10 +629,16 @@ public class TextUtils {
public CharSequence createFromParcel(Parcel p) {
int kind = p.readInt();
- if (kind == 1)
- return p.readString();
+ String string = p.readString();
+ if (string == null) {
+ return null;
+ }
+
+ if (kind == 1) {
+ return string;
+ }
- SpannableString sp = new SpannableString(p.readString());
+ SpannableString sp = new SpannableString(string);
while (true) {
kind = p.readInt();
diff --git a/core/java/android/text/method/MultiTapKeyListener.java b/core/java/android/text/method/MultiTapKeyListener.java
index 6d94788..2a739fa 100644
--- a/core/java/android/text/method/MultiTapKeyListener.java
+++ b/core/java/android/text/method/MultiTapKeyListener.java
@@ -116,7 +116,7 @@ public class MultiTapKeyListener extends BaseKeyListener
content.replace(selStart, selEnd,
String.valueOf(current).toUpperCase());
removeTimeouts(content);
- Timeout t = new Timeout(content);
+ new Timeout(content); // for its side effects
return true;
}
@@ -124,7 +124,7 @@ public class MultiTapKeyListener extends BaseKeyListener
content.replace(selStart, selEnd,
String.valueOf(current).toLowerCase());
removeTimeouts(content);
- Timeout t = new Timeout(content);
+ new Timeout(content); // for its side effects
return true;
}
@@ -140,7 +140,7 @@ public class MultiTapKeyListener extends BaseKeyListener
content.replace(selStart, selEnd, val, ix, ix + 1);
removeTimeouts(content);
- Timeout t = new Timeout(content);
+ new Timeout(content); // for its side effects
return true;
}
@@ -206,7 +206,7 @@ public class MultiTapKeyListener extends BaseKeyListener
}
removeTimeouts(content);
- Timeout t = new Timeout(content);
+ new Timeout(content); // for its side effects
// Set up the callback so we can remove the timeout if the
// cursor moves.
diff --git a/core/java/android/text/style/DrawableMarginSpan.java b/core/java/android/text/style/DrawableMarginSpan.java
index 3c471a5..c2564d5 100644
--- a/core/java/android/text/style/DrawableMarginSpan.java
+++ b/core/java/android/text/style/DrawableMarginSpan.java
@@ -50,9 +50,6 @@ implements LeadingMarginSpan, LineHeightSpan
int dw = mDrawable.getIntrinsicWidth();
int dh = mDrawable.getIntrinsicHeight();
- if (dir < 0)
- x -= dw;
-
// XXX What to do about Paint?
mDrawable.setBounds(ix, itop, ix+dw, itop+dh);
mDrawable.draw(c);
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
new file mode 100644
index 0000000..729c506
--- /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 0000000..263d782
--- /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 b8c5c2a..984102a 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -160,8 +160,10 @@ 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, int surface);
static native void nDestroyLayer(int layerId);
static native void nDestroyLayerDeferred(int layerId);
@@ -272,7 +274,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 6000a4a..bc191a6 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 0000000..7adac1c
--- /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 0000000..fcf421b
--- /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, int surface) {
+ GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, surface);
+ }
+}
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index d01b8ce..86dec3f 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 66f37f2..7ca6e09 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,28 @@ 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 surface The surface to update
+ */
+ abstract void updateTextureLayer(HardwareLayer layer, int width, int height,
+ SurfaceTexture surface);
/**
* Initializes the hardware renderer for the specified surface and setup the
@@ -257,9 +288,10 @@ public abstract class HardwareRenderer {
@SuppressWarnings({"deprecation"})
static abstract class GlRenderer extends HardwareRenderer {
// These values are not exposed in our EGL APIs
- private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
- private static final int EGL_SURFACE_TYPE = 0x3033;
- private static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
+ static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+ static final int EGL_SURFACE_TYPE = 0x3033;
+ static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
+ static final int EGL_OPENGL_ES2_BIT = 4;
private static final int SURFACE_STATE_ERROR = 0;
private static final int SURFACE_STATE_SUCCESS = 1;
@@ -427,13 +459,12 @@ public abstract class HardwareRenderer {
getEGLErrorString(sEgl.eglGetError()));
}
- sEglConfig = getConfigChooser(mGlVersion).chooseConfig(sEgl, sEglDisplay);
+ sEglConfig = chooseEglConfig();
if (sEglConfig == null) {
// We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
if (mDirtyRegions) {
mDirtyRegions = false;
-
- sEglConfig = getConfigChooser(mGlVersion).chooseConfig(sEgl, sEglDisplay);
+ sEglConfig = chooseEglConfig();
if (sEglConfig == null) {
throw new RuntimeException("eglConfig not initialized");
}
@@ -449,6 +480,21 @@ public abstract class HardwareRenderer {
sEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
}
+ private EGLConfig chooseEglConfig() {
+ int[] configsCount = new int[1];
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] configSpec = getConfig(mDirtyRegions);
+ if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) {
+ throw new IllegalArgumentException("eglChooseConfig failed " +
+ getEGLErrorString(sEgl.eglGetError()));
+ } else if (configsCount[0] > 0) {
+ return configs[0];
+ }
+ return null;
+ }
+
+ abstract int[] getConfig(boolean dirtyRegions);
+
GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException {
// Check preconditions.
if (sEgl == null) {
@@ -560,15 +606,6 @@ public abstract class HardwareRenderer {
void onPostDraw() {
}
-
- /**
- * Defines the EGL configuration for this renderer.
- *
- * @return An {@link android.view.HardwareRenderer.GlRenderer.EglConfigChooser}.
- */
- EglConfigChooser getConfigChooser(int glVersion) {
- return new ComponentSizeChooser(glVersion, 8, 8, 8, 8, 0, 0, mDirtyRegions);
- }
@Override
void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
@@ -681,134 +718,6 @@ public abstract class HardwareRenderer {
}
return SURFACE_STATE_SUCCESS;
}
-
- static abstract class EglConfigChooser {
- final int[] mConfigSpec;
- private final int mGlVersion;
-
- EglConfigChooser(int glVersion, int[] configSpec) {
- mGlVersion = glVersion;
- mConfigSpec = filterConfigSpec(configSpec);
- }
-
- EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
- int[] index = new int[1];
- if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, index)) {
- throw new IllegalArgumentException("eglChooseConfig failed "
- + getEGLErrorString(egl.eglGetError()));
- }
-
- int numConfigs = index[0];
- if (numConfigs <= 0) {
- throw new IllegalArgumentException("No configs match configSpec");
- }
-
- EGLConfig[] configs = new EGLConfig[numConfigs];
- if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, index)) {
- throw new IllegalArgumentException("eglChooseConfig failed "
- + getEGLErrorString(egl.eglGetError()));
- }
-
- EGLConfig config = chooseConfig(egl, display, configs);
- if (config == null) {
- throw new IllegalArgumentException("No config chosen");
- }
-
- return config;
- }
-
- abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs);
-
- private int[] filterConfigSpec(int[] configSpec) {
- if (mGlVersion != 2) {
- return configSpec;
- }
- /* We know none of the subclasses define EGL_RENDERABLE_TYPE.
- * And we know the configSpec is well formed.
- */
- int len = configSpec.length;
- int[] newConfigSpec = new int[len + 2];
- System.arraycopy(configSpec, 0, newConfigSpec, 0, len - 1);
- newConfigSpec[len - 1] = EGL10.EGL_RENDERABLE_TYPE;
- newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */
- newConfigSpec[len + 1] = EGL10.EGL_NONE;
- return newConfigSpec;
- }
- }
-
- /**
- * Choose a configuration with exactly the specified r,g,b,a sizes,
- * and at least the specified depth and stencil sizes.
- */
- static class ComponentSizeChooser extends EglConfigChooser {
- private int[] mValue;
-
- private final int mRedSize;
- private final int mGreenSize;
- private final int mBlueSize;
- private final int mAlphaSize;
- private final int mDepthSize;
- private final int mStencilSize;
- private final boolean mDirtyRegions;
-
- ComponentSizeChooser(int glVersion, int redSize, int greenSize, int blueSize,
- int alphaSize, int depthSize, int stencilSize, boolean dirtyRegions) {
- super(glVersion, new int[] {
- EGL10.EGL_RED_SIZE, redSize,
- EGL10.EGL_GREEN_SIZE, greenSize,
- EGL10.EGL_BLUE_SIZE, blueSize,
- EGL10.EGL_ALPHA_SIZE, alphaSize,
- EGL10.EGL_DEPTH_SIZE, depthSize,
- EGL10.EGL_STENCIL_SIZE, stencilSize,
- EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT |
- (dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
- EGL10.EGL_NONE });
- mValue = new int[1];
- mRedSize = redSize;
- mGreenSize = greenSize;
- mBlueSize = blueSize;
- mAlphaSize = alphaSize;
- mDepthSize = depthSize;
- mStencilSize = stencilSize;
- mDirtyRegions = dirtyRegions;
- }
-
- @Override
- EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
- for (EGLConfig config : configs) {
- int d = findConfigAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE, 0);
- int s = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0);
- if (d >= mDepthSize && s >= mStencilSize) {
- int r = findConfigAttrib(egl, display, config, EGL10.EGL_RED_SIZE, 0);
- int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0);
- int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);
- int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);
- boolean backBuffer;
- if (mDirtyRegions) {
- int surfaceType = findConfigAttrib(egl, display, config,
- EGL_SURFACE_TYPE, 0);
- backBuffer = (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) != 0;
- } else {
- backBuffer = true;
- }
- if (r >= mRedSize && g >= mGreenSize && b >= mBlueSize && a >= mAlphaSize
- && backBuffer) {
- return config;
- }
- }
- }
- return null;
- }
-
- private int findConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config,
- int attribute, int defaultValue) {
- if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
- return mValue[0];
- }
-
- return defaultValue;
- }
- }
}
/**
@@ -825,7 +734,23 @@ public abstract class HardwareRenderer {
GLES20Canvas createCanvas() {
return mGlCanvas = new GLES20Canvas(mTranslucent);
}
-
+
+ @Override
+ int[] getConfig(boolean dirtyRegions) {
+ return new int[] {
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL10.EGL_RED_SIZE, 8,
+ EGL10.EGL_GREEN_SIZE, 8,
+ EGL10.EGL_BLUE_SIZE, 8,
+ EGL10.EGL_ALPHA_SIZE, 8,
+ EGL10.EGL_DEPTH_SIZE, 0,
+ EGL10.EGL_STENCIL_SIZE, 0,
+ EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT |
+ (dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
+ EGL10.EGL_NONE
+ };
+ }
+
@Override
boolean canDraw() {
return super.canDraw() && mGlCanvas != null;
@@ -856,10 +781,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,
+ SurfaceTexture surface) {
+ ((GLES20TextureLayer) layer).update(width, height, surface.mSurfaceTexture);
}
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 0000000..755ecf5
--- /dev/null
+++ b/core/java/android/view/TextureView.java
@@ -0,0 +1,334 @@
+/*
+ * 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
+ * }
+ * }
+ *
+ * public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ * // Ignored, Camera does all the work for us
+ * }
+ * }
+ * </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 Runnable mUpdateLayerAction = new Runnable() {
+ @Override
+ public void run() {
+ updateLayer();
+ }
+ };
+ private SurfaceTexture.OnFrameAvailableListener mUpdateListener;
+
+ /**
+ * 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
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ if (mSurface != null) {
+ nSetDefaultBufferSize(mSurface.mSurfaceTexture, getWidth(), getHeight());
+ }
+ }
+
+ @Override
+ HardwareLayer getHardwareLayer() {
+ if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+ return null;
+ }
+
+ if (mLayer == null) {
+ mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer();
+ mSurface = mAttachInfo.mHardwareRenderer.createSuraceTexture(mLayer);
+ nSetDefaultBufferSize(mSurface.mSurfaceTexture, getWidth(), getHeight());
+
+ mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() {
+ @Override
+ public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+ // Per SurfaceTexture's documentation, the callback may be invoked
+ // from an arbitrary thread
+ post(mUpdateLayerAction);
+ }
+ };
+ mSurface.setOnFrameAvailableListener(mUpdateListener);
+
+ if (mListener != null) {
+ mListener.onSurfaceTextureAvailable(mSurface);
+ }
+ }
+
+ return mLayer;
+ }
+
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+
+ if (mSurface != null) {
+ // When the view becomes invisible, stop updating it, it's a waste of CPU
+ // To cancel updates, the easiest thing to do is simply to remove the
+ // updates listener
+ if (visibility == VISIBLE) {
+ mSurface.setOnFrameAvailableListener(mUpdateListener);
+ updateLayer();
+ } else {
+ mSurface.setOnFrameAvailableListener(null);
+ }
+ }
+ }
+
+ private void updateLayer() {
+ if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+ return;
+ }
+
+ mAttachInfo.mHardwareRenderer.updateTextureLayer(mLayer, getWidth(), getHeight(), mSurface);
+
+ 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);
+
+ /**
+ * Invoked when the {@link SurfaceTexture}'s buffers size changed.
+ *
+ * @param surface The surface returned by
+ * {@link android.view.TextureView#getSurfaceTexture()}
+ * @param width The new width of the surface
+ * @param height The new height of the surface
+ */
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height);
+ }
+
+ private static native void nSetDefaultBufferSize(int surfaceTexture, int width, int height);
+}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 11c9392..5e18f55 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -253,7 +253,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
private static final int MAX_POOL_SIZE = 10;
- private static final Object mPoolLock = new Object();
+ private static final Object sPoolLock = new Object();
private static AccessibilityEvent sPool;
private static int sPoolSize;
@@ -375,7 +375,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* @return An instance.
*/
public static AccessibilityEvent obtain() {
- synchronized (mPoolLock) {
+ synchronized (sPoolLock) {
if (sPool != null) {
AccessibilityEvent event = sPool;
sPool = sPool.mNext;
@@ -392,14 +392,16 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* Return an instance back to be reused.
* <p>
* <b>Note: You must not touch the object after calling this function.</b>
+ *
+ * @throws IllegalStateException If the event is already recycled.
*/
@Override
public void recycle() {
if (mIsInPool) {
- return;
+ throw new IllegalStateException("Event already recycled!");
}
clear();
- synchronized (mPoolLock) {
+ synchronized (sPoolLock) {
if (sPoolSize <= MAX_POOL_SIZE) {
mNext = sPool;
sPool = this;
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index e095f43..fecf9df 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -39,7 +39,7 @@ public class AccessibilityRecord {
private static final int PROPERTY_FULL_SCREEN = 0x00000080;
private static final int MAX_POOL_SIZE = 10;
- private static final Object mPoolLock = new Object();
+ private static final Object sPoolLock = new Object();
private static AccessibilityRecord sPool;
private static int sPoolSize;
@@ -342,7 +342,7 @@ public class AccessibilityRecord {
* @return An instance.
*/
protected static AccessibilityRecord obtain() {
- synchronized (mPoolLock) {
+ synchronized (sPoolLock) {
if (sPool != null) {
AccessibilityRecord record = sPool;
sPool = sPool.mNext;
@@ -359,13 +359,15 @@ public class AccessibilityRecord {
* Return an instance back to be reused.
* <p>
* <b>Note: You must not touch the object after calling this function.</b>
+ *
+ * @throws IllegalStateException If the record is already recycled.
*/
public void recycle() {
if (mIsInPool) {
- return;
+ throw new IllegalStateException("Record already recycled!");
}
clear();
- synchronized (mPoolLock) {
+ synchronized (sPoolLock) {
if (sPoolSize <= MAX_POOL_SIZE) {
mNext = sPool;
sPool = this;
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 3e11197..4755362 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/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 060f1a9..7fbfcbb 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -899,6 +899,8 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup {
@Override
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+
View selectedView = getSelectedView();
if (selectedView != null) {
event.setEnabled(selectedView.isEnabled());
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index dbe9288..7838ec0 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -254,6 +254,15 @@ public class LinearLayout extends ViewGroup {
return mDividerPadding;
}
+ /**
+ * Get the width of the current divider drawable.
+ *
+ * @hide Used internally by framework.
+ */
+ public int getDividerWidth() {
+ return mDividerWidth;
+ }
+
@Override
protected void onDraw(Canvas canvas) {
if (mDivider == null) {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 5618dbe..d115364 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2009,16 +2009,12 @@ public class ListView extends AbsListView {
ListAdapter adapter = getAdapter();
if (adapter != null) {
final int count = adapter.getCount();
- if (count < 15) {
- for (int i = 0; i < count; i++) {
- if (adapter.isEnabled(i)) {
- itemCount++;
- } else if (i <= currentItemIndex) {
- currentItemIndex--;
- }
+ for (int i = 0; i < count; i++) {
+ if (adapter.isEnabled(i)) {
+ itemCount++;
+ } else if (i <= currentItemIndex) {
+ currentItemIndex--;
}
- } else {
- itemCount = count;
}
}
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 72b70bc..de32c2b 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1489,6 +1489,10 @@ public class PopupWindow {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+ if (getKeyDispatcherState() == null) {
+ return super.dispatchKeyEvent(event);
+ }
+
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0) {
KeyEvent.DispatcherState state = getKeyDispatcherState();
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 96d41a0..c4ba270 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -66,15 +66,16 @@ import android.widget.RemoteViews.RemoteView;
*
* <p>
* A progress bar can also be made indeterminate. In indeterminate mode, the
- * progress bar shows a cyclic animation. This mode is used by applications
- * when the length of the task is unknown.
+ * progress bar shows a cyclic animation without an indication of progress. This mode is used by
+ * applications when the length of the task is unknown. The indeterminate progress bar can be either
+ * a spinning wheel or a horizontal bar.
* </p>
*
* <p>The following code example shows how a progress bar can be used from
* a worker thread to update the user interface to notify the user of progress:
* </p>
*
- * <pre class="prettyprint">
+ * <pre>
* public class MyActivity extends Activity {
* private static final int PROGRESS = 0x1;
*
@@ -93,7 +94,7 @@ import android.widget.RemoteViews.RemoteView;
* // Start lengthy operation in a background thread
* new Thread(new Runnable() {
* public void run() {
- * while (mProgressStatus < 100) {
+ * while (mProgressStatus &lt; 100) {
* mProgressStatus = doWork();
*
* // Update the progress bar
@@ -106,8 +107,61 @@ import android.widget.RemoteViews.RemoteView;
* }
* }).start();
* }
- * }
- * </pre>
+ * }</pre>
+ *
+ * <p>To add a progress bar to a layout file, you can use the {@code &lt;ProgressBar&gt;} element.
+ * By default, the progress bar is a spinning wheel (an indeterminate indicator). To change to a
+ * horizontal progress bar, apply the {@link android.R.style#Widget_ProgressBar_Horizontal
+ * Widget.ProgressBar.Horizontal} style, like so:</p>
+ *
+ * <pre>
+ * &lt;ProgressBar
+ * style="@android:style/Widget.ProgressBar.Horizontal"
+ * ... /&gt;</pre>
+ *
+ * <p>If you will use the progress bar to show real progress, you must use the horizontal bar. You
+ * can then increment the progress with {@link #incrementProgressBy incrementProgressBy()} or
+ * {@link #setProgress setProgress()}. By default, the progress bar is full when it reaches 100. If
+ * necessary, you can adjust the maximum value (the value for a full bar) using the {@link
+ * android.R.styleable#ProgressBar_max android:max} attribute. Other attributes available are listed
+ * below.</p>
+ *
+ * <p>Another common style to apply to the progress bar is {@link
+ * android.R.style#Widget_ProgressBar_Small Widget.ProgressBar.Small}, which shows a smaller
+ * version of the spinning wheel&mdash;useful when waiting for content to load.
+ * For example, you can insert this kind of progress bar into your default layout for
+ * a view that will be populated by some content fetched from the Internet&mdash;the spinning wheel
+ * appears immediately and when your application receives the content, it replaces the progress bar
+ * with the loaded content. For example:</p>
+ *
+ * <pre>
+ * &lt;LinearLayout
+ * android:orientation="horizontal"
+ * ... &gt;
+ * &lt;ProgressBar
+ * android:layout_width="wrap_content"
+ * android:layout_height="wrap_content"
+ * style="@android:style/Widget.ProgressBar.Small"
+ * android:layout_marginRight="5dp" /&gt;
+ * &lt;TextView
+ * android:layout_width="wrap_content"
+ * android:layout_height="wrap_content"
+ * android:text="@string/loading" /&gt;
+ * &lt;/LinearLayout&gt;</pre>
+ *
+ * <p>Other progress bar styles provided by the system include:</p>
+ * <ul>
+ * <li>{@link android.R.style#Widget_ProgressBar_Horizontal Widget.ProgressBar.Horizontal}</li>
+ * <li>{@link android.R.style#Widget_ProgressBar_Small Widget.ProgressBar.Small}</li>
+ * <li>{@link android.R.style#Widget_ProgressBar_Large Widget.ProgressBar.Large}</li>
+ * <li>{@link android.R.style#Widget_ProgressBar_Inverse Widget.ProgressBar.Inverse}</li>
+ * <li>{@link android.R.style#Widget_ProgressBar_Small_Inverse
+ * Widget.ProgressBar.Small.Inverse}</li>
+ * <li>{@link android.R.style#Widget_ProgressBar_Large_Inverse
+ * Widget.ProgressBar.Large.Inverse}</li>
+ * </ul>
+ * <p>The "inverse" styles provide an inverse color scheme for the spinner, which may be necessary
+ * if your application uses a light colored theme (a white background).</p>
*
* <p><strong>XML attributes</b></strong>
* <p>
@@ -115,13 +169,21 @@ import android.widget.RemoteViews.RemoteView;
* {@link android.R.styleable#View View Attributes}
* </p>
*
- * <p><strong>Styles</b></strong>
- * <p>
- * @attr ref android.R.styleable#Theme_progressBarStyle
- * @attr ref android.R.styleable#Theme_progressBarStyleSmall
- * @attr ref android.R.styleable#Theme_progressBarStyleLarge
- * @attr ref android.R.styleable#Theme_progressBarStyleHorizontal
- * </p>
+ * @attr ref android.R.styleable#ProgressBar_animationResolution
+ * @attr ref android.R.styleable#ProgressBar_indeterminate
+ * @attr ref android.R.styleable#ProgressBar_indeterminateBehavior
+ * @attr ref android.R.styleable#ProgressBar_indeterminateDrawable
+ * @attr ref android.R.styleable#ProgressBar_indeterminateDuration
+ * @attr ref android.R.styleable#ProgressBar_indeterminateOnly
+ * @attr ref android.R.styleable#ProgressBar_interpolator
+ * @attr ref android.R.styleable#ProgressBar_max
+ * @attr ref android.R.styleable#ProgressBar_maxHeight
+ * @attr ref android.R.styleable#ProgressBar_maxWidth
+ * @attr ref android.R.styleable#ProgressBar_minHeight
+ * @attr ref android.R.styleable#ProgressBar_minWidth
+ * @attr ref android.R.styleable#ProgressBar_progress
+ * @attr ref android.R.styleable#ProgressBar_progressDrawable
+ * @attr ref android.R.styleable#ProgressBar_secondaryProgress
*/
@RemoteView
public class ProgressBar extends View {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 4b4f5f2..ade3a0a 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -873,7 +873,7 @@ public class ScrollView extends FrameLayout {
int count = getChildCount();
if (count > 0) {
View view = getChildAt(count - 1);
- mTempRect.bottom = view.getBottom();
+ mTempRect.bottom = view.getBottom() + mPaddingBottom;
mTempRect.top = mTempRect.bottom - height;
}
}
@@ -949,9 +949,7 @@ public class ScrollView extends FrameLayout {
} else if (direction == View.FOCUS_DOWN) {
if (getChildCount() > 0) {
int daBottom = getChildAt(0).getBottom();
-
- int screenBottom = getScrollY() + getHeight();
-
+ int screenBottom = getScrollY() + getHeight() - mPaddingBottom;
if (daBottom - screenBottom < maxJump) {
scrollDelta = daBottom - screenBottom;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6c5d117..24b176d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -336,6 +336,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Set when this TextView gained focus with some text selected. Will start selection mode.
private boolean mCreatedWithASelection = false;
+ private WordIterator mWordIterator;
+
/*
* Kick-start the font cache for the zygote process (to pay the cost of
* initializing freetype for our default font only once).
@@ -7754,78 +7756,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
type == Character.DECIMAL_DIGIT_NUMBER);
}
- /**
- * Returns the offsets delimiting the 'word' located at position offset.
- *
- * @param offset An offset in the text.
- * @return The offsets for the start and end of the word located at <code>offset</code>.
- * The two ints offsets are packed in a long using {@link #packRangeInLong(int, int)}.
- * Returns -1 if no valid word was found.
- */
- private long getWordLimitsAt(int offset) {
- int klass = mInputType & InputType.TYPE_MASK_CLASS;
- int variation = mInputType & InputType.TYPE_MASK_VARIATION;
-
- // Text selection is not permitted in password fields
- if (hasPasswordTransformationMethod()) {
- return -1;
- }
-
- final int len = mText.length();
-
- // Specific text fields: always select the entire text
- if (klass == InputType.TYPE_CLASS_NUMBER ||
- klass == InputType.TYPE_CLASS_PHONE ||
- klass == InputType.TYPE_CLASS_DATETIME ||
- variation == InputType.TYPE_TEXT_VARIATION_URI ||
- variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS ||
- variation == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS ||
- variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
- return len > 0 ? packRangeInLong(0, len) : -1;
- }
-
- int end = Math.min(offset, len);
- if (end < 0) {
- return -1;
- }
-
- final int MAX_LENGTH = 48;
- int start = end;
-
- for (; start > 0; start--) {
- final char c = mTransformed.charAt(start - 1);
- final int type = Character.getType(c);
- if (start == end && type == Character.OTHER_PUNCTUATION) {
- // Cases where the text ends with a '.' and we select from the end of the line
- // (right after the dot), or when we select from the space character in "aaa, bbb".
- continue;
- }
- if (type == Character.SURROGATE) { // Two Character codepoint
- end = start - 1; // Recheck as a pair when scanning forward
- continue;
- }
- if (!isWordCharacter(c, type)) break;
- if ((end - start) > MAX_LENGTH) return -1;
- }
-
- for (; end < len; end++) {
- final int c = Character.codePointAt(mTransformed, end);
- final int type = Character.getType(c);
- if (!isWordCharacter(c, type)) break;
- if ((end - start) > MAX_LENGTH) return -1;
- if (c > 0xFFFF) { // Two Character codepoint
- end++;
- }
- }
-
- if (start == end) {
- return -1;
- }
-
- // Two ints packed in a long
- return packRangeInLong(start, end);
- }
-
private static long packRangeInLong(int start, int end) {
return (((long) start) << 32) | end;
}
@@ -7838,21 +7768,40 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return (int) (range & 0x00000000FFFFFFFFL);
}
- private void selectAll() {
- Selection.setSelection((Spannable) mText, 0, mText.length());
+ private boolean selectAll() {
+ final int length = mText.length();
+ Selection.setSelection((Spannable) mText, 0, length);
+ return length > 0;
}
- private void selectCurrentWord() {
+ /**
+ * Adjusts selection to the word under last touch offset.
+ * Return true if the operation was successfully performed.
+ */
+ private boolean selectCurrentWord() {
if (!canSelectText()) {
- return;
+ return false;
}
if (hasPasswordTransformationMethod()) {
// Always select all on a password field.
// Cut/copy menu entries are not available for passwords, but being able to select all
// is however useful to delete or paste to replace the entire content.
- selectAll();
- return;
+ return selectAll();
+ }
+
+ int klass = mInputType & InputType.TYPE_MASK_CLASS;
+ int variation = mInputType & InputType.TYPE_MASK_VARIATION;
+
+ // Specific text field types: select the entire text for these
+ if (klass == InputType.TYPE_CLASS_NUMBER ||
+ klass == InputType.TYPE_CLASS_PHONE ||
+ klass == InputType.TYPE_CLASS_DATETIME ||
+ variation == InputType.TYPE_TEXT_VARIATION_URI ||
+ variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS ||
+ variation == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS ||
+ variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
+ return selectAll();
}
long lastTouchOffsets = getLastTouchOffsets();
@@ -7868,22 +7817,21 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
selectionStart = ((Spanned) mText).getSpanStart(url);
selectionEnd = ((Spanned) mText).getSpanEnd(url);
} else {
- long wordLimits = getWordLimitsAt(minOffset);
- if (wordLimits >= 0) {
- selectionStart = extractRangeStartFromLong(wordLimits);
- } else {
- selectionStart = Math.max(minOffset - 5, 0);
+ if (mWordIterator == null) {
+ mWordIterator = new WordIterator();
}
+ // WordIerator handles text changes, this is a no-op if text in unchanged.
+ mWordIterator.setCharSequence(mText);
- wordLimits = getWordLimitsAt(maxOffset);
- if (wordLimits >= 0) {
- selectionEnd = extractRangeEndFromLong(wordLimits);
- } else {
- selectionEnd = Math.min(maxOffset + 5, mText.length());
- }
+ selectionStart = mWordIterator.getBeginning(minOffset);
+ if (selectionStart == BreakIterator.DONE) return false;
+
+ selectionEnd = mWordIterator.getEnd(maxOffset);
+ if (selectionEnd == BreakIterator.DONE) return false;
}
Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
+ return true;
}
private long getLastTouchOffsets() {
@@ -7903,6 +7851,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+
if (!isShown()) {
return;
}
@@ -8007,6 +7957,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* this will be {@link android.R.id#copyUrl}, {@link android.R.id#selectTextMode},
* {@link android.R.id#selectAll}, {@link android.R.id#paste}, {@link android.R.id#cut}
* or {@link android.R.id#copy}.
+ *
+ * @return true if the context menu item action was performed.
*/
public boolean onTextContextMenuItem(int id) {
int min = 0;
@@ -8051,7 +8003,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
case ID_SELECT_ALL:
// This does not enter text selection mode. Text is highlighted, so that it can be
- // bulk edited, like selectAllOnFocus does.
+ // bulk edited, like selectAllOnFocus does. Returns true even if text is empty.
selectAll();
return true;
@@ -8177,7 +8129,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mInsertionControllerEnabled) {
final int offset = getOffset(mLastDownPositionX, mLastDownPositionY);
stopSelectionActionMode();
- Selection.setSelection((Spannable)mText, offset);
+ Selection.setSelection((Spannable) mText, offset);
getInsertionController().showWithPaste();
handled = true;
}
@@ -8662,9 +8614,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return false;
}
- if (!hasSelection()) {
- // If selection mode is started after a device rotation, there is already a selection.
- selectCurrentWord();
+ boolean currentWordSelected = selectCurrentWord();
+ if (!currentWordSelected) {
+ // No word found under cursor or text selection not permitted.
+ return false;
}
ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
@@ -8695,16 +8648,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
(ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = clipboard.getPrimaryClip();
if (clip != null) {
- boolean didfirst = false;
+ boolean didFirst = false;
for (int i=0; i<clip.getItemCount(); i++) {
CharSequence paste = clip.getItemAt(i).coerceToText(getContext());
if (paste != null) {
- if (!didfirst) {
+ if (!didFirst) {
long minMax = prepareSpacesAroundPaste(min, max, paste);
min = extractRangeStartFromLong(minMax);
max = extractRangeEndFromLong(minMax);
Selection.setSelection((Spannable) mText, max);
((Editable) mText).replace(min, max, paste);
+ didFirst = true;
} else {
((Editable) mText).insert(getSelectionEnd(), "\n");
((Editable) mText).insert(getSelectionEnd(), paste);
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index dccfa6c..5c3563f 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -19,6 +19,7 @@ package com.android.internal.app;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuPopupHelper;
import com.android.internal.view.menu.SubMenuBuilder;
+import com.android.internal.widget.AbsActionBarView;
import com.android.internal.widget.ActionBarContainer;
import com.android.internal.widget.ActionBarContextView;
import com.android.internal.widget.ActionBarView;
@@ -46,7 +47,6 @@ import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.DecelerateInterpolator;
import android.widget.HorizontalScrollView;
-import android.widget.LinearLayout;
import android.widget.SpinnerAdapter;
import java.lang.ref.WeakReference;
@@ -61,8 +61,6 @@ import java.util.ArrayList;
*/
public class ActionBarImpl extends ActionBar {
private static final String TAG = "ActionBarImpl";
- private static final int NORMAL_VIEW = 0;
- private static final int CONTEXT_VIEW = 1;
private Context mContext;
private Activity mActivity;
@@ -70,8 +68,8 @@ public class ActionBarImpl extends ActionBar {
private ActionBarContainer mContainerView;
private ActionBarView mActionView;
- private ActionBarContextView mUpperContextView;
- private LinearLayout mLowerContextView;
+ private ActionBarContextView mContextView;
+ private ActionBarContainer mSplitView;
private View mContentView;
private ViewGroup mExternalTabView;
@@ -102,26 +100,6 @@ public class ActionBarImpl extends ActionBar {
private static final TimeInterpolator sFadeOutInterpolator = new DecelerateInterpolator();
- final AnimatorListener[] mAfterAnimation = new AnimatorListener[] {
- new AnimatorListenerAdapter() { // NORMAL_VIEW
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mLowerContextView != null) {
- mLowerContextView.removeAllViews();
- }
- mCurrentModeAnim = null;
- hideAllExcept(NORMAL_VIEW);
- }
- },
- new AnimatorListenerAdapter() { // CONTEXT_VIEW
- @Override
- public void onAnimationEnd(Animator animation) {
- mCurrentModeAnim = null;
- hideAllExcept(CONTEXT_VIEW);
- }
- }
- };
-
final AnimatorListener mHideListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -160,21 +138,21 @@ public class ActionBarImpl extends ActionBar {
private void init(View decor) {
mContext = decor.getContext();
mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
- mUpperContextView = (ActionBarContextView) decor.findViewById(
+ mContextView = (ActionBarContextView) decor.findViewById(
com.android.internal.R.id.action_context_bar);
- mLowerContextView = (LinearLayout) decor.findViewById(
- com.android.internal.R.id.lower_action_context_bar);
mContainerView = (ActionBarContainer) decor.findViewById(
com.android.internal.R.id.action_bar_container);
+ mSplitView = (ActionBarContainer) decor.findViewById(
+ com.android.internal.R.id.split_action_bar);
- if (mActionView == null || mUpperContextView == null || mContainerView == null) {
+ if (mActionView == null || mContextView == null || mContainerView == null) {
throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
"with a compatible window decor layout");
}
- mActionView.setContextView(mUpperContextView);
- mContextDisplayMode = mLowerContextView == null ?
- CONTEXT_DISPLAY_NORMAL : CONTEXT_DISPLAY_SPLIT;
+ mActionView.setContextView(mContextView);
+ mContextDisplayMode = mActionView.isSplitActionBar() ?
+ CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
if (!mActionView.hasEmbeddedTabs()) {
HorizontalScrollView tabScroller = new HorizontalScrollView(mContext);
@@ -341,16 +319,16 @@ public class ActionBarImpl extends ActionBar {
mActionMode.finish();
}
- mUpperContextView.killMode();
+ mContextView.killMode();
ActionMode mode = new ActionModeImpl(callback);
if (callback.onCreateActionMode(mode, mode.getMenu())) {
mWasHiddenBeforeMode = !isShowing();
mode.invalidate();
- mUpperContextView.initForMode(mode);
- animateTo(CONTEXT_VIEW);
- if (mLowerContextView != null) {
+ mContextView.initForMode(mode);
+ animateToMode(true);
+ if (mSplitView != null) {
// TODO animate this
- mLowerContextView.setVisibility(View.VISIBLE);
+ mSplitView.setVisibility(View.VISIBLE);
}
mActionMode = mode;
return mode;
@@ -495,6 +473,10 @@ public class ActionBarImpl extends ActionBar {
mContainerView.setTranslationY(-mContainerView.getHeight());
b.with(ObjectAnimator.ofFloat(mContainerView, "translationY", 0));
}
+ if (mSplitView != null) {
+ mSplitView.setAlpha(0);
+ b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 1));
+ }
anim.addListener(mShowListener);
mCurrentShowAnim = anim;
anim.start();
@@ -525,6 +507,10 @@ public class ActionBarImpl extends ActionBar {
b.with(ObjectAnimator.ofFloat(mContainerView, "translationY",
-mContainerView.getHeight()));
}
+ if (mSplitView != null) {
+ mSplitView.setAlpha(1);
+ b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 0));
+ }
anim.addListener(mHideListener);
mCurrentShowAnim = anim;
anim.start();
@@ -537,45 +523,14 @@ public class ActionBarImpl extends ActionBar {
return mContainerView.getVisibility() == View.VISIBLE;
}
- long animateTo(int viewIndex) {
+ void animateToMode(boolean toActionMode) {
show(false);
if (mCurrentModeAnim != null) {
mCurrentModeAnim.end();
}
- AnimatorSet set = new AnimatorSet();
-
- final View targetChild = mContainerView.getChildAt(viewIndex);
- targetChild.setVisibility(View.VISIBLE);
- targetChild.setAlpha(0);
- AnimatorSet.Builder b = set.play(ObjectAnimator.ofFloat(targetChild, "alpha", 1));
-
- final int count = mContainerView.getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = mContainerView.getChildAt(i);
- if (i == viewIndex || child == mContainerView.getTabContainer()) {
- continue;
- }
-
- if (child.getVisibility() != View.GONE) {
- Animator a = ObjectAnimator.ofFloat(child, "alpha", 0);
- a.setInterpolator(sFadeOutInterpolator);
- b.with(a);
- }
- }
-
- set.addListener(mAfterAnimation[viewIndex]);
-
- mCurrentModeAnim = set;
- set.start();
- return set.getDuration();
- }
-
- private void hideAllExcept(int viewIndex) {
- final int count = mContainerView.getChildCount();
- for (int i = 0; i < count; i++) {
- mContainerView.getChildAt(i).setVisibility(i == viewIndex ? View.VISIBLE : View.GONE);
- }
+ mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
+ mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE);
}
/**
@@ -612,14 +567,10 @@ public class ActionBarImpl extends ActionBar {
mCallback.onDestroyActionMode(this);
mCallback = null;
- animateTo(NORMAL_VIEW);
+ animateToMode(false);
// Clear out the context mode views after the animation finishes
- mUpperContextView.closeMode();
- if (mLowerContextView != null && mLowerContextView.getVisibility() != View.GONE) {
- // TODO Animate this
- mLowerContextView.setVisibility(View.GONE);
- }
+ mContextView.closeMode();
mActionMode = null;
if (mWasHiddenBeforeMode) {
@@ -636,18 +587,18 @@ public class ActionBarImpl extends ActionBar {
@Override
public void setCustomView(View view) {
- mUpperContextView.setCustomView(view);
+ mContextView.setCustomView(view);
mCustomView = new WeakReference<View>(view);
}
@Override
public void setSubtitle(CharSequence subtitle) {
- mUpperContextView.setSubtitle(subtitle);
+ mContextView.setSubtitle(subtitle);
}
@Override
public void setTitle(CharSequence title) {
- mUpperContextView.setTitle(title);
+ mContextView.setTitle(title);
}
@Override
@@ -662,12 +613,12 @@ public class ActionBarImpl extends ActionBar {
@Override
public CharSequence getTitle() {
- return mUpperContextView.getTitle();
+ return mContextView.getTitle();
}
@Override
public CharSequence getSubtitle() {
- return mUpperContextView.getSubtitle();
+ return mContextView.getSubtitle();
}
@Override
@@ -707,7 +658,7 @@ public class ActionBarImpl extends ActionBar {
return;
}
invalidate();
- mUpperContextView.showOverflowMenu();
+ mContextView.showOverflowMenu();
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 7cf33fc..12687a1 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -4904,7 +4904,7 @@ public final class BatteryStatsImpl extends BatteryStats {
void readOldHistory(Parcel in) {
mHistory = mHistoryEnd = mHistoryCache = null;
long time;
- while ((time=in.readLong()) >= 0) {
+ while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
HistoryItem rec = new HistoryItem(time, in);
addHistoryRecordLocked(rec);
}
diff --git a/core/java/com/android/internal/util/AsyncChannel.java b/core/java/com/android/internal/util/AsyncChannel.java
index 4d656c0..3973344 100644
--- a/core/java/com/android/internal/util/AsyncChannel.java
+++ b/core/java/com/android/internal/util/AsyncChannel.java
@@ -44,16 +44,16 @@ import java.util.Stack;
* In this usage model there is no need for the destination to
* use the connect methods. The typical sequence of operations is:</p>
*<ol>
- * <li>Client calls AsyncChannel#connect</li>
- * <li>Client receives CMD_CHANNEL_HALF_CONNECTED from AsyncChannel</li>
+ * <li>Client calls AsyncChannel#connectSync or Asynchronously:</li>
+ * <ol>For an asynchronous half connection client calls AsyncChannel#connect.</ol>
+ * <li>Client receives CMD_CHANNEL_HALF_CONNECTED from AsyncChannel</li>
+ * </ol>
* <li><code>comm-loop:</code></li>
- * <li>Client calls AsyncChannel#sendMessage(msgX)</li>
- * <li>Server receives and processes msgX</li>
- * <li>Server optionally calls AsyncChannel#replyToMessage(msgY)
- * and if sent Client receives and processes msgY</li>
+ * <li>Client calls AsyncChannel#sendMessage</li>
+ * <li>Server processes messages and optionally replies using AsyncChannel#replyToMessage
* <li>Loop to <code>comm-loop</code> until done</li>
- * <li>When done Client calls {@link AsyncChannel#disconnect(int)}</li>
- * <li>Client receives CMD_CHANNEL_DISCONNECTED from AsyncChannel</li>
+ * <li>When done Client calls {@link AsyncChannel#disconnect}</li>
+ * <li>Client/Server receives CMD_CHANNEL_DISCONNECTED from AsyncChannel</li>
*</ol>
*<br/>
* <p>A second usage model is where the server/destination needs to know
@@ -62,21 +62,26 @@ import java.util.Stack;
* different state for each client. In this model the server will also
* use the connect methods. The typical sequence of operation is:</p>
*<ol>
- * <li>Client calls AsyncChannel#connect</li>
- * <li>Client receives CMD_CHANNEL_HALF_CONNECTED from AsyncChannel</li>
- * <li>Client calls AsyncChannel#sendMessage(CMD_CHANNEL_FULL_CONNECTION)</li>
+ * <li>Client calls AsyncChannel#fullyConnectSync or Asynchronously:<li>
+ * <ol>For an asynchronous full connection it calls AsyncChannel#connect</li>
+ * <li>Client receives CMD_CHANNEL_HALF_CONNECTED from AsyncChannel</li>
+ * <li>Client calls AsyncChannel#sendMessage(CMD_CHANNEL_FULL_CONNECTION)</li>
+ * </ol>
* <li>Server receives CMD_CHANNEL_FULL_CONNECTION</li>
- * <li>Server calls AsyncChannel#connect</li>
- * <li>Server receives CMD_CHANNEL_HALF_CONNECTED from AsyncChannel</li>
+ * <li>Server calls AsyncChannel#connected</li>
* <li>Server sends AsyncChannel#sendMessage(CMD_CHANNEL_FULLY_CONNECTED)</li>
* <li>Client receives CMD_CHANNEL_FULLY_CONNECTED</li>
* <li><code>comm-loop:</code></li>
* <li>Client/Server uses AsyncChannel#sendMessage/replyToMessage
* to communicate and perform work</li>
* <li>Loop to <code>comm-loop</code> until done</li>
- * <li>When done Client/Server calls {@link AsyncChannel#disconnect(int)}</li>
+ * <li>When done Client/Server calls {@link AsyncChannel#disconnect}</li>
* <li>Client/Server receives CMD_CHANNEL_DISCONNECTED from AsyncChannel</li>
*</ol>
+ *
+ * TODO: Consider simplifying where we have connect and fullyConnect with only one response
+ * message RSP_CHANNEL_CONNECT instead of two, CMD_CHANNEL_HALF_CONNECTED and
+ * CMD_CHANNEL_FULLY_CONNECTED. We'd also change CMD_CHANNEL_FULL_CONNECTION to REQ_CHANNEL_CONNECT.
*/
public class AsyncChannel {
/** Log tag */
@@ -85,6 +90,8 @@ public class AsyncChannel {
/** Enable to turn on debugging */
private static final boolean DBG = false;
+ private static final int BASE = Protocol.BASE_SYSTEM_ASYNC_CHANNEL;
+
/**
* Command sent when the channel is half connected. Half connected
* means that the channel can be used to send commends to the destination
@@ -98,7 +105,7 @@ public class AsyncChannel {
* msg.obj == the AsyncChannel
* msg.replyTo == dstMessenger if successful
*/
- public static final int CMD_CHANNEL_HALF_CONNECTED = -1;
+ public static final int CMD_CHANNEL_HALF_CONNECTED = BASE + 0;
/**
* Command typically sent when after receiving the CMD_CHANNEL_HALF_CONNECTED.
@@ -107,7 +114,7 @@ public class AsyncChannel {
*
* msg.replyTo = srcMessenger.
*/
- public static final int CMD_CHANNEL_FULL_CONNECTION = -2;
+ public static final int CMD_CHANNEL_FULL_CONNECTION = BASE + 1;
/**
* Command typically sent after the destination receives a CMD_CHANNEL_FULL_CONNECTION.
@@ -115,20 +122,20 @@ public class AsyncChannel {
*
* msg.arg1 == 0 : Accept connection
* : All other values signify the destination rejected the connection
- * and {@link AsyncChannel#disconnect(int)} would typically be called.
+ * and {@link AsyncChannel#disconnect} would typically be called.
*/
- public static final int CMD_CHANNEL_FULLY_CONNECTED = -3;
+ public static final int CMD_CHANNEL_FULLY_CONNECTED = BASE + 2;
/**
* Command sent when one side or the other wishes to disconnect. The sender
* may or may not be able to receive a reply depending upon the protocol and
- * the state of the connection. The receiver should call {@link AsyncChannel#disconnect(int)}
+ * the state of the connection. The receiver should call {@link AsyncChannel#disconnect}
* to close its side of the channel and it will receive a CMD_CHANNEL_DISCONNECTED
* when the channel is closed.
*
* msg.replyTo = messenger that is disconnecting
*/
- public static final int CMD_CHANNEL_DISCONNECT = -4;
+ public static final int CMD_CHANNEL_DISCONNECT = BASE + 3;
/**
* Command sent when the channel becomes disconnected. This is sent when the
@@ -141,7 +148,7 @@ public class AsyncChannel {
* msg.obj == the AsyncChannel
* msg.replyTo = messenger disconnecting or null if it was never connected.
*/
- public static final int CMD_CHANNEL_DISCONNECTED = -5;
+ public static final int CMD_CHANNEL_DISCONNECTED = BASE + 4;
/** Successful status always 0, !0 is an unsuccessful status */
public static final int STATUS_SUCCESSFUL = 0;
@@ -152,6 +159,9 @@ public class AsyncChannel {
/** Error attempting to send a message */
public static final int STATUS_SEND_UNSUCCESSFUL = 2;
+ /** CMD_FULLY_CONNECTED refused because a connection already exists*/
+ public static final int STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED = 3;
+
/** Service connection */
private AsyncChannelConnection mConnection;
@@ -174,9 +184,7 @@ public class AsyncChannel {
}
/**
- * Connect handler to named package/class.
- *
- * Sends a CMD_CHANNEL_HALF_CONNECTED message to srcHandler when complete.
+ * Connect handler to named package/class synchronously.
*
* @param srcContext is the context of the source
* @param srcHandler is the hander to receive CONNECTED & DISCONNECTED
@@ -184,8 +192,10 @@ public class AsyncChannel {
* @param dstPackageName is the destination package name
* @param dstClassName is the fully qualified class name (i.e. contains
* package name)
+ *
+ * @return STATUS_SUCCESSFUL on success any other value is an error.
*/
- private void connectSrcHandlerToPackage(
+ public int connectSrcHandlerToPackageSync(
Context srcContext, Handler srcHandler, String dstPackageName, String dstClassName) {
if (DBG) log("connect srcHandler to dst Package & class E");
@@ -207,11 +217,61 @@ public class AsyncChannel {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(dstPackageName, dstClassName);
boolean result = srcContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
- if (!result) {
- replyHalfConnected(STATUS_BINDING_UNSUCCESSFUL);
- }
-
if (DBG) log("connect srcHandler to dst Package & class X result=" + result);
+ return result ? STATUS_SUCCESSFUL : STATUS_BINDING_UNSUCCESSFUL;
+ }
+
+ /**
+ * Connect a handler to Messenger synchronously.
+ *
+ * @param srcContext is the context of the source
+ * @param srcHandler is the hander to receive CONNECTED & DISCONNECTED
+ * messages
+ * @param dstMessenger is the hander to send messages to.
+ *
+ * @return STATUS_SUCCESSFUL on success any other value is an error.
+ */
+ public int connectSync(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
+ if (DBG) log("halfConnectSync srcHandler to the dstMessenger E");
+
+ // We are connected
+ connected(srcContext, srcHandler, dstMessenger);
+
+ if (DBG) log("halfConnectSync srcHandler to the dstMessenger X");
+ return STATUS_SUCCESSFUL;
+ }
+
+ /**
+ * connect two local Handlers synchronously.
+ *
+ * @param srcContext is the context of the source
+ * @param srcHandler is the hander to receive CONNECTED & DISCONNECTED
+ * messages
+ * @param dstHandler is the hander to send messages to.
+ *
+ * @return STATUS_SUCCESSFUL on success any other value is an error.
+ */
+ public int connectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {
+ return connectSync(srcContext, srcHandler, new Messenger(dstHandler));
+ }
+
+ /**
+ * Fully connect two local Handlers synchronously.
+ *
+ * @param srcContext is the context of the source
+ * @param srcHandler is the hander to receive CONNECTED & DISCONNECTED
+ * messages
+ * @param dstHandler is the hander to send messages to.
+ *
+ * @return STATUS_SUCCESSFUL on success any other value is an error.
+ */
+ public int fullyConnectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {
+ int status = connectSync(srcContext, srcHandler, dstHandler);
+ if (status == STATUS_SUCCESSFUL) {
+ Message response = sendMessageSynchronously(CMD_CHANNEL_FULL_CONNECTION);
+ status = response.arg1;
+ }
+ return status;
}
/**
@@ -246,8 +306,11 @@ public class AsyncChannel {
mDstClassName = dstClassName;
}
+ @Override
public void run() {
- connectSrcHandlerToPackage(mSrcCtx, mSrcHdlr, mDstPackageName, mDstClassName);
+ int result = connectSrcHandlerToPackageSync(mSrcCtx, mSrcHdlr, mDstPackageName,
+ mDstClassName);
+ replyHalfConnected(result);
}
}
@@ -286,6 +349,28 @@ public class AsyncChannel {
public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connect srcHandler to the dstMessenger E");
+ // We are connected
+ connected(srcContext, srcHandler, dstMessenger);
+
+ // Tell source we are half connected
+ replyHalfConnected(STATUS_SUCCESSFUL);
+
+ if (DBG) log("connect srcHandler to the dstMessenger X");
+ }
+
+ /**
+ * Connect handler to messenger. This method is typically called
+ * when a server receives a CMD_CHANNEL_FULL_CONNECTION request
+ * and initializes the internal instance variables to allow communication
+ * with the dstMessenger.
+ *
+ * @param srcContext
+ * @param srcHandler
+ * @param dstMessenger
+ */
+ public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
+ if (DBG) log("connected srcHandler to the dstMessenger E");
+
// Initialize source fields
mSrcContext = srcContext;
mSrcHandler = srcHandler;
@@ -294,21 +379,12 @@ public class AsyncChannel {
// Initialize destination fields
mDstMessenger = dstMessenger;
- if (DBG) log("tell source we are half connected");
-
- // Tell source we are half connected
- replyHalfConnected(STATUS_SUCCESSFUL);
-
- if (DBG) log("connect srcHandler to the dstMessenger X");
+ if (DBG) log("connected srcHandler to the dstMessenger X");
}
/**
* Connect two local Handlers.
*
- * Sends a CMD_CHANNEL_HALF_CONNECTED message to srcHandler when complete.
- * msg.arg1 = status
- * msg.obj = the AsyncChannel
- *
* @param srcContext is the context of the source
* @param srcHandler is the hander to receive CONNECTED & DISCONNECTED
* messages
@@ -336,6 +412,7 @@ public class AsyncChannel {
* To close the connection call when handler receives CMD_CHANNEL_DISCONNECTED
*/
public void disconnected() {
+ mSrcContext = null;
mSrcHandler = null;
mSrcMessenger = null;
mDstMessenger = null;
@@ -346,7 +423,7 @@ public class AsyncChannel {
* Disconnect
*/
public void disconnect() {
- if (mConnection != null) {
+ if ((mConnection != null) && (mSrcContext != null)) {
mSrcContext.unbindService(mConnection);
}
if (mSrcHandler != null) {
@@ -445,6 +522,7 @@ public class AsyncChannel {
*/
public void replyToMessage(Message srcMsg, Message dstMsg) {
try {
+ dstMsg.replyTo = mSrcMessenger;
srcMsg.replyTo.send(dstMsg);
} catch (RemoteException e) {
log("TODO: handle replyToMessage RemoteException" + e);
@@ -695,10 +773,14 @@ public class AsyncChannel {
private static Message sendMessageSynchronously(Messenger dstMessenger, Message msg) {
SyncMessenger sm = SyncMessenger.obtain();
try {
- msg.replyTo = sm.mMessenger;
- dstMessenger.send(msg);
- synchronized (sm.mHandler.mLockObject) {
- sm.mHandler.mLockObject.wait();
+ if (dstMessenger != null && msg != null) {
+ msg.replyTo = sm.mMessenger;
+ synchronized (sm.mHandler.mLockObject) {
+ dstMessenger.send(msg);
+ sm.mHandler.mLockObject.wait();
+ }
+ } else {
+ sm.mHandler.mResultMsg = null;
}
} catch (InterruptedException e) {
sm.mHandler.mResultMsg = null;
@@ -747,11 +829,13 @@ public class AsyncChannel {
AsyncChannelConnection() {
}
+ @Override
public void onServiceConnected(ComponentName className, IBinder service) {
mDstMessenger = new Messenger(service);
replyHalfConnected(STATUS_SUCCESSFUL);
}
+ @Override
public void onServiceDisconnected(ComponentName className) {
replyDisconnected(STATUS_SUCCESSFUL);
}
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 0000000..2e7ec58
--- /dev/null
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.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;
+
+ /** Base reserved for system */
+ public static final int BASE_SYSTEM_RESERVED = 0x00010000;
+ public static final int BASE_SYSTEM_ASYNC_CHANNEL = 0x00011000;
+
+ /** Non system protocols */
+ public static final int BASE_WIFI = 0x00020000;
+ public static final int BASE_DHCP = 0x00030000;
+ public static final int BASE_DATA_CONNECTION = 0x00040000;
+ public static final int BASE_DATA_CONNECTION_AC = 0x00041000;
+ public static final int BASE_DATA_CONNECTION_TRACKER = 0x00050000;
+
+ //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 a05fa53..0051ec3 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -21,7 +21,6 @@ import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.MenuItem;
import android.view.SoundEffectConstants;
@@ -36,11 +35,14 @@ import java.util.ArrayList;
* MenuPresenter for building action menus as seen in the action bar and action modes.
*/
public class ActionMenuPresenter extends BaseMenuPresenter {
+ private static final String TAG = "ActionMenuPresenter";
+
private View mOverflowButton;
private boolean mReserveOverflow;
private int mWidthLimit;
private int mActionItemWidthLimit;
private int mMaxItems;
+ private boolean mStrictWidthLimit;
// Group IDs that have been added as actions - used temporarily, allocated here for reuse.
private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray();
@@ -73,10 +75,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 +91,18 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
mScrapActionButtonView = null;
}
+ public void setWidthLimit(int width, boolean strict) {
+ if (mReserveOverflow) {
+ width -= mOverflowButton.getMeasuredWidth();
+ }
+ mActionItemWidthLimit = width;
+ mStrictWidthLimit = strict;
+ }
+
+ public void setItemLimit(int itemCount) {
+ mMaxItems = itemCount;
+ }
+
@Override
public MenuView getMenuView(ViewGroup root) {
MenuView result = super.getMenuView(root);
@@ -119,6 +134,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
if (mReserveOverflow && mMenu.getNonActionItems().size() > 0) {
if (mOverflowButton == null) {
mOverflowButton = new OverflowMenuButton(mContext);
+ mOverflowButton.setLayoutParams(
+ ((ActionMenuView) mMenuView).generateOverflowButtonLayoutParams());
}
ViewGroup parent = (ViewGroup) mOverflowButton.getParent();
if (parent != mMenuView) {
@@ -177,7 +194,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
public boolean showOverflowMenu() {
if (mReserveOverflow && !isOverflowMenuShowing() && mMenuView != null &&
mPostedOpenRunnable == null) {
- Log.d("ActionMenuPresenter", "showOverflowMenu");
OverflowPopup popup = new OverflowPopup(mContext, mMenu, mOverflowButton, true);
mPostedOpenRunnable = new OpenOverflowRunnable(popup);
// Post this for later; we might still need a layout for the anchor to be right.
@@ -326,9 +342,11 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
firstActionWidth = measuredWidth;
}
- // Did this push the entire first item past halfway?
- if (widthLimit + firstActionWidth <= 0) {
- isAction = false;
+ if (mStrictWidthLimit) {
+ isAction = widthLimit >= 0;
+ } else {
+ // Did this push the entire first item past the limit?
+ isAction = widthLimit + firstActionWidth > 0;
}
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 0ea9c89..290bf08 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -20,6 +20,7 @@ import android.content.res.Configuration;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
+import android.view.ViewDebug;
import android.view.ViewGroup;
import android.widget.LinearLayout;
@@ -33,6 +34,8 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
private boolean mReserveOverflow;
private ActionMenuPresenter mPresenter;
+ private boolean mUpdateContentsBeforeMeasure;
+ private boolean mFormatItems;
public ActionMenuView(Context context) {
this(context, null);
@@ -59,6 +62,95 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
}
@Override
+ public void requestLayout() {
+ // Layout can influence how many action items fit.
+ mUpdateContentsBeforeMeasure = true;
+ super.requestLayout();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (mUpdateContentsBeforeMeasure && mMenu != null) {
+ mMenu.onItemsChanged(true);
+ mUpdateContentsBeforeMeasure = false;
+ }
+ // If we've been given an exact size to match, apply special formatting during layout.
+ mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ if (!mFormatItems) {
+ super.onLayout(changed, left, top, right, bottom);
+ return;
+ }
+
+ final int childCount = getChildCount();
+ final int midVertical = (top + bottom) / 2;
+ final int dividerWidth = getDividerWidth();
+ boolean hasOverflow = false;
+ int overflowWidth = 0;
+ int nonOverflowWidth = 0;
+ int nonOverflowCount = 0;
+ int widthRemaining = right - left - getPaddingRight() - getPaddingLeft();
+ for (int i = 0; i < childCount; i++) {
+ final View v = getChildAt(i);
+ if (v.getVisibility() == GONE) {
+ continue;
+ }
+
+ LayoutParams p = (LayoutParams) v.getLayoutParams();
+ if (p.isOverflowButton) {
+ hasOverflow = true;
+ overflowWidth = v.getMeasuredWidth();
+ if (hasDividerBeforeChildAt(i)) {
+ overflowWidth += dividerWidth;
+ }
+
+ int height = v.getMeasuredHeight();
+ int r = getPaddingRight();
+ int l = r - overflowWidth;
+ int t = midVertical - (height / 2);
+ int b = t + height;
+ v.layout(l, t, r, b);
+
+ widthRemaining -= overflowWidth;
+ } else {
+ nonOverflowWidth += v.getMeasuredWidth() + p.leftMargin + p.rightMargin;
+ if (hasDividerBeforeChildAt(i)) {
+ nonOverflowWidth += dividerWidth;
+ }
+ nonOverflowCount++;
+ }
+ }
+
+ // Try to center non-overflow items with uniformly spaced padding, including on the edges.
+ // Overflow will always pin to the right edge. If there isn't enough room for that,
+ // center in the remaining space.
+ if (nonOverflowWidth <= widthRemaining - overflowWidth) {
+ widthRemaining -= overflowWidth;
+ }
+
+ final int spacing = (widthRemaining - nonOverflowWidth) / (nonOverflowCount + 1);
+ int startLeft = getPaddingLeft() + overflowWidth + spacing;
+ for (int i = 0; i < childCount; i++) {
+ final View v = getChildAt(i);
+ final LayoutParams lp = (LayoutParams) v.getLayoutParams();
+ if (v.getVisibility() == GONE || lp.isOverflowButton) {
+ continue;
+ }
+
+ startLeft += lp.leftMargin;
+ int width = v.getMeasuredWidth();
+ int height = v.getMeasuredHeight();
+ int t = midVertical - (height / 2);
+ v.layout(startLeft, t, startLeft + width, t + height);
+ startLeft += width + lp.rightMargin + spacing;
+ }
+ }
+
+ @Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
mPresenter.dismissPopupMenus();
@@ -97,6 +189,12 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
return p instanceof LayoutParams;
}
+ public LayoutParams generateOverflowButtonLayoutParams() {
+ LayoutParams result = generateDefaultLayoutParams();
+ result.isOverflowButton = true;
+ return result;
+ }
+
public boolean invokeItem(MenuItemImpl item) {
return mMenu.performItemAction(item, 0);
}
@@ -127,4 +225,28 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
public boolean needsDividerBefore();
public boolean needsDividerAfter();
}
+
+ public static class LayoutParams extends LinearLayout.LayoutParams {
+ @ViewDebug.ExportedProperty(category = "layout")
+ public boolean isOverflowButton;
+
+ public LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+ }
+
+ public LayoutParams(LayoutParams other) {
+ super((LinearLayout.LayoutParams) other);
+ isOverflowButton = other.isOverflowButton;
+ }
+
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ isOverflowButton = false;
+ }
+
+ public LayoutParams(int width, int height, boolean isOverflowButton) {
+ super(width, height);
+ this.isOverflowButton = isOverflowButton;
+ }
+ }
}
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index 7fba5ca..e9fcb23 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -226,6 +226,7 @@ public class MenuBuilder implements Menu {
private void dispatchPresenterUpdate(boolean cleared) {
if (mPresenters.isEmpty()) return;
+ stopDispatchingItemsChanged();
for (WeakReference<MenuPresenter> ref : mPresenters) {
final MenuPresenter presenter = ref.get();
if (presenter == null) {
@@ -234,6 +235,7 @@ public class MenuBuilder implements Menu {
presenter.updateMenuView(cleared);
}
}
+ startDispatchingItemsChanged();
}
private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu) {
diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java
new file mode 100644
index 0000000..3979eab
--- /dev/null
+++ b/core/java/com/android/internal/widget/AbsActionBarView.java
@@ -0,0 +1,211 @@
+/*
+ * 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.widget;
+
+import com.android.internal.view.menu.ActionMenuPresenter;
+import com.android.internal.view.menu.ActionMenuView;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
+
+public abstract class AbsActionBarView extends ViewGroup {
+ protected ActionMenuView mMenuView;
+ protected ActionMenuPresenter mMenuPresenter;
+ protected ActionBarContainer mSplitView;
+
+ protected Animator mVisibilityAnim;
+ protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
+
+ private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator();
+
+ private static final int FADE_DURATION = 200;
+
+ public AbsActionBarView(Context context) {
+ super(context);
+ }
+
+ public AbsActionBarView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AbsActionBarView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public void setSplitView(ActionBarContainer splitView) {
+ mSplitView = splitView;
+ }
+
+ public void animateToVisibility(int visibility) {
+ if (mVisibilityAnim != null) {
+ mVisibilityAnim.cancel();
+ }
+ if (visibility == VISIBLE) {
+ if (getVisibility() != VISIBLE) {
+ setAlpha(0);
+ if (mSplitView != null && mMenuView != null) {
+ mMenuView.setAlpha(0);
+ }
+ }
+ ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
+ anim.setDuration(FADE_DURATION);
+ anim.setInterpolator(sAlphaInterpolator);
+ if (mSplitView != null && mMenuView != null) {
+ AnimatorSet set = new AnimatorSet();
+ ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 1);
+ splitAnim.setDuration(FADE_DURATION);
+ set.addListener(mVisAnimListener.withFinalVisibility(visibility));
+ set.play(anim).with(splitAnim);
+ } else {
+ anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
+ anim.start();
+ }
+ } else {
+ ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
+ anim.setDuration(FADE_DURATION);
+ anim.setInterpolator(sAlphaInterpolator);
+ if (mSplitView != null && mMenuView != null) {
+ AnimatorSet set = new AnimatorSet();
+ ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0);
+ splitAnim.setDuration(FADE_DURATION);
+ set.addListener(mVisAnimListener.withFinalVisibility(visibility));
+ set.play(anim).with(splitAnim);
+ } else {
+ anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
+ anim.start();
+ }
+ }
+ }
+
+ @Override
+ public void setVisibility(int visibility) {
+ if (mVisibilityAnim != null) {
+ mVisibilityAnim.end();
+ }
+ super.setVisibility(visibility);
+ }
+
+ public boolean showOverflowMenu() {
+ if (mMenuPresenter != null) {
+ return mMenuPresenter.showOverflowMenu();
+ }
+ return false;
+ }
+
+ public void postShowOverflowMenu() {
+ post(new Runnable() {
+ public void run() {
+ showOverflowMenu();
+ }
+ });
+ }
+
+ public boolean hideOverflowMenu() {
+ if (mMenuPresenter != null) {
+ return mMenuPresenter.hideOverflowMenu();
+ }
+ return false;
+ }
+
+ public boolean isOverflowMenuShowing() {
+ if (mMenuPresenter != null) {
+ return mMenuPresenter.isOverflowMenuShowing();
+ }
+ return false;
+ }
+
+ public boolean isOverflowReserved() {
+ return mMenuPresenter != null && mMenuPresenter.isOverflowReserved();
+ }
+
+ public void dismissPopupMenus() {
+ if (mMenuPresenter != null) {
+ mMenuPresenter.dismissPopupMenus();
+ }
+ }
+
+ protected int measureChildView(View child, int availableWidth, int childSpecHeight,
+ int spacing) {
+ child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
+ childSpecHeight);
+
+ availableWidth -= child.getMeasuredWidth();
+ availableWidth -= spacing;
+
+ return availableWidth;
+ }
+
+ protected int positionChild(View child, int x, int y, int contentHeight) {
+ int childWidth = child.getMeasuredWidth();
+ int childHeight = child.getMeasuredHeight();
+ int childTop = y + (contentHeight - childHeight) / 2;
+
+ child.layout(x, childTop, x + childWidth, childTop + childHeight);
+
+ return childWidth;
+ }
+
+ protected int positionChildInverse(View child, int x, int y, int contentHeight) {
+ int childWidth = child.getMeasuredWidth();
+ int childHeight = child.getMeasuredHeight();
+ int childTop = y + (contentHeight - childHeight) / 2;
+
+ child.layout(x - childWidth, childTop, x, childTop + childHeight);
+
+ return childWidth;
+ }
+
+ protected class VisibilityAnimListener implements Animator.AnimatorListener {
+ private boolean mCanceled = false;
+ private int mFinalVisibility;
+
+ public VisibilityAnimListener withFinalVisibility(int visibility) {
+ mFinalVisibility = visibility;
+ return this;
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ setVisibility(VISIBLE);
+ mVisibilityAnim = animation;
+ mCanceled = false;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mCanceled) return;
+
+ mVisibilityAnim = null;
+ setVisibility(mFinalVisibility);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCanceled = true;
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index 3deb036..c18565d 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -19,6 +19,7 @@ package com.android.internal.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import android.view.ActionMode;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
@@ -85,6 +86,12 @@ public class ActionBarContainer extends FrameLayout {
}
@Override
+ public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
+ // No starting an action mode for an action bar child! (Where would it go?)
+ return null;
+ }
+
+ @Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 70fb3b2..f45a3bb 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -30,7 +30,7 @@ import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
import android.view.animation.DecelerateInterpolator;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -38,7 +38,7 @@ import android.widget.TextView;
/**
* @hide
*/
-public class ActionBarContextView extends ViewGroup implements AnimatorListener {
+public class ActionBarContextView extends AbsActionBarView implements AnimatorListener {
private static final String TAG = "ActionBarContextView";
private int mContentHeight;
@@ -53,8 +53,6 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener
private TextView mSubtitleView;
private int mTitleStyleRes;
private int mSubtitleStyleRes;
- private ActionMenuView mMenuView;
- private ActionMenuPresenter mPresenter;
private Animator mCurrentAnimation;
private boolean mAnimateInOnLayout;
@@ -87,12 +85,6 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener
com.android.internal.R.styleable.ActionMode_height, 0);
a.recycle();
}
-
- @Override
- public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
- // No starting an action mode for an existing action mode UI child! (Where would it go?)
- return null;
- }
public void setHeight(int height) {
mContentHeight = height;
@@ -178,10 +170,25 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener
});
final MenuBuilder menu = (MenuBuilder) mode.getMenu();
- mPresenter = new ActionMenuPresenter();
- menu.addMenuPresenter(mPresenter);
- mMenuView = (ActionMenuView) mPresenter.getMenuView(this);
- addView(mMenuView);
+ mMenuPresenter = new ActionMenuPresenter();
+ menu.addMenuPresenter(mMenuPresenter);
+ mMenuView = (ActionMenuView) mMenuPresenter.getMenuView(this);
+
+ final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT);
+ mMenuView.setLayoutParams(layoutParams);
+ if (mSplitView == null) {
+ addView(mMenuView);
+ } else {
+ // Allow full screen width in split mode.
+ mMenuPresenter.setWidthLimit(
+ getContext().getResources().getDisplayMetrics().widthPixels, true);
+ // No limit to the item count; use whatever will fit.
+ mMenuPresenter.setItemLimit(Integer.MAX_VALUE);
+ // Span the whole width
+ layoutParams.width = LayoutParams.MATCH_PARENT;
+ mSplitView.addView(mMenuView);
+ }
mAnimateInOnLayout = true;
}
@@ -213,28 +220,31 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener
public void killMode() {
finishAnimation();
removeAllViews();
+ if (mSplitView != null) {
+ mSplitView.removeView(mMenuView);
+ }
mCustomView = null;
mMenuView = null;
mAnimateInOnLayout = false;
}
public boolean showOverflowMenu() {
- if (mPresenter != null) {
- return mPresenter.showOverflowMenu();
+ if (mMenuPresenter != null) {
+ return mMenuPresenter.showOverflowMenu();
}
return false;
}
public boolean hideOverflowMenu() {
- if (mPresenter != null) {
- return mPresenter.hideOverflowMenu();
+ if (mMenuPresenter != null) {
+ return mMenuPresenter.hideOverflowMenu();
}
return false;
}
public boolean isOverflowMenuShowing() {
- if (mPresenter != null) {
- return mPresenter.isOverflowMenuShowing();
+ if (mMenuPresenter != null) {
+ return mMenuPresenter.isOverflowMenuShowing();
}
return false;
}
@@ -342,7 +352,7 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener
private Animator makeOutAnimation() {
ObjectAnimator buttonAnimator = ObjectAnimator.ofFloat(mClose, "translationX",
- 0, -mClose.getWidth());
+ -mClose.getWidth());
buttonAnimator.setDuration(200);
buttonAnimator.addListener(this);
buttonAnimator.setInterpolator(new DecelerateInterpolator());
@@ -356,7 +366,7 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener
for (int i = 0; i < 0; i++) {
View child = mMenuView.getChildAt(i);
child.setScaleY(0);
- ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 1, 0);
+ ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 0);
a.setDuration(100);
a.setStartDelay(i * 70);
b.with(a);
@@ -383,7 +393,7 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener
mAnimateInOnLayout = false;
}
}
-
+
if (mTitleLayout != null && mCustomView == null) {
x += positionChild(mTitleLayout, x, y, contentHeight);
}
@@ -399,36 +409,6 @@ public class ActionBarContextView extends ViewGroup implements AnimatorListener
}
}
- private int measureChildView(View child, int availableWidth, int childSpecHeight, int spacing) {
- child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
- childSpecHeight);
-
- availableWidth -= child.getMeasuredWidth();
- availableWidth -= spacing;
-
- return availableWidth;
- }
-
- private int positionChild(View child, int x, int y, int contentHeight) {
- int childWidth = child.getMeasuredWidth();
- int childHeight = child.getMeasuredHeight();
- int childTop = y + (contentHeight - childHeight) / 2;
-
- child.layout(x, childTop, x + childWidth, childTop + childHeight);
-
- return childWidth;
- }
-
- private int positionChildInverse(View child, int x, int y, int contentHeight) {
- int childWidth = child.getMeasuredWidth();
- int childHeight = child.getMeasuredHeight();
- int childTop = y + (contentHeight - childHeight) / 2;
-
- child.layout(x - childWidth, childTop, x, childTop + childHeight);
-
- return childWidth;
- }
-
@Override
public void onAnimationStart(Animator animation) {
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index a572e11..d4813ba 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -38,7 +38,6 @@ import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.view.ActionMode;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -59,7 +58,7 @@ import android.widget.TextView;
/**
* @hide
*/
-public class ActionBarView extends ViewGroup {
+public class ActionBarView extends AbsActionBarView {
private static final String TAG = "ActionBarView";
/**
@@ -110,13 +109,11 @@ public class ActionBarView extends ViewGroup {
private int mProgressStyle;
private int mIndeterminateProgressStyle;
- private boolean mShowMenu;
+ private boolean mSplitActionBar;
private boolean mUserTitle;
private boolean mIncludeTabs;
private MenuBuilder mOptionsMenu;
- private ActionMenuView mMenuView;
- private ActionMenuPresenter mActionMenuPresenter;
private ActionBarContextView mContextView;
@@ -245,6 +242,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;
}
@@ -253,12 +270,6 @@ public class ActionBarView extends ViewGroup {
mTabLayout = tabLayout;
}
- @Override
- public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
- // No starting an action mode for an action bar child! (Where would it go?)
- return null;
- }
-
public void setCallback(OnNavigationListener callback) {
mCallback = callback;
}
@@ -267,7 +278,7 @@ public class ActionBarView extends ViewGroup {
if (menu == mOptionsMenu) return;
if (mOptionsMenu != null) {
- mOptionsMenu.removeMenuPresenter(mActionMenuPresenter);
+ mOptionsMenu.removeMenuPresenter(mMenuPresenter);
}
MenuBuilder builder = (MenuBuilder) menu;
@@ -275,62 +286,30 @@ public class ActionBarView extends ViewGroup {
if (mMenuView != null) {
removeView(mMenuView);
}
- if (mActionMenuPresenter == null) {
- mActionMenuPresenter = new ActionMenuPresenter();
- mActionMenuPresenter.setCallback(cb);
- builder.addMenuPresenter(mActionMenuPresenter);
+ if (mMenuPresenter == null) {
+ mMenuPresenter = new ActionMenuPresenter();
+ mMenuPresenter.setCallback(cb);
+ builder.addMenuPresenter(mMenuPresenter);
}
- final ActionMenuView menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
+ final ActionMenuView menuView = (ActionMenuView) mMenuPresenter.getMenuView(this);
final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.MATCH_PARENT);
menuView.setLayoutParams(layoutParams);
- addView(menuView);
- mMenuView = menuView;
- }
-
- public boolean showOverflowMenu() {
- if (mActionMenuPresenter != null) {
- return mActionMenuPresenter.showOverflowMenu();
- }
- return false;
- }
-
- public void openOverflowMenu() {
- if (mActionMenuPresenter != null) {
- showOverflowMenu();
- }
- }
-
- public void postShowOverflowMenu() {
- post(new Runnable() {
- public void run() {
- showOverflowMenu();
- }
- });
- }
-
- public boolean hideOverflowMenu() {
- if (mActionMenuPresenter != null) {
- return mActionMenuPresenter.hideOverflowMenu();
- }
- return false;
- }
-
- public boolean isOverflowMenuShowing() {
- if (mActionMenuPresenter != null) {
- return mActionMenuPresenter.isOverflowMenuShowing();
- }
- return false;
- }
-
- public boolean isOverflowReserved() {
- return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
- }
-
- public void dismissPopupMenus() {
- if (mActionMenuPresenter != null) {
- mActionMenuPresenter.dismissPopupMenus();
+ if (!mSplitActionBar) {
+ addView(menuView);
+ } else {
+ // Allow full screen width in split mode.
+ mMenuPresenter.setWidthLimit(
+ getContext().getResources().getDisplayMetrics().widthPixels, true);
+ // No limit to the item count; use whatever will fit.
+ mMenuPresenter.setItemLimit(Integer.MAX_VALUE);
+ // Span the whole width
+ layoutParams.width = LayoutParams.MATCH_PARENT;
+ if (mSplitView != null) {
+ mSplitView.addView(menuView);
+ } // We'll add this later if we missed it this time.
}
+ mMenuView = menuView;
}
public void setCustomNavigationView(View view) {
@@ -718,7 +697,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();
@@ -836,16 +815,6 @@ public class ActionBarView extends ViewGroup {
}
}
- private int measureChildView(View child, int availableWidth, int childSpecHeight, int spacing) {
- child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
- childSpecHeight);
-
- availableWidth -= child.getMeasuredWidth();
- availableWidth -= spacing;
-
- return availableWidth;
- }
-
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int x = getPaddingLeft();
@@ -880,7 +849,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();
}
@@ -958,26 +927,6 @@ public class ActionBarView extends ViewGroup {
}
}
- private int positionChild(View child, int x, int y, int contentHeight) {
- int childWidth = child.getMeasuredWidth();
- int childHeight = child.getMeasuredHeight();
- int childTop = y + (contentHeight - childHeight) / 2;
-
- child.layout(x, childTop, x + childWidth, childTop + childHeight);
-
- return childWidth;
- }
-
- private int positionChildInverse(View child, int x, int y, int contentHeight) {
- int childWidth = child.getMeasuredWidth();
- int childHeight = child.getMeasuredHeight();
- int childTop = y + (contentHeight - childHeight) / 2;
-
- child.layout(x - childWidth, childTop, x, childTop + childHeight);
-
- return childWidth;
- }
-
private static class TabView extends LinearLayout {
private ActionBar.Tab mTab;
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 290f528..95224a4 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -47,6 +47,7 @@ LOCAL_SRC_FILES:= \
android_emoji_EmojiFactory.cpp \
android_view_Display.cpp \
android_view_Surface.cpp \
+ android_view_TextureView.cpp \
android_view_ViewRoot.cpp \
android_view_InputChannel.cpp \
android_view_InputQueue.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index a4a229a..c915753 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -118,6 +118,7 @@ extern int register_com_android_internal_graphics_NativeUtils(JNIEnv *env);
extern int register_android_view_Display(JNIEnv* env);
extern int register_android_view_GLES20Canvas(JNIEnv* env);
extern int register_android_view_Surface(JNIEnv* env);
+extern int register_android_view_TextureView(JNIEnv* env);
extern int register_android_view_ViewRoot(JNIEnv* env);
extern int register_android_database_CursorWindow(JNIEnv* env);
extern int register_android_database_SQLiteCompiledSql(JNIEnv* env);
@@ -1122,6 +1123,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_graphics_Graphics),
REG_JNI(register_android_view_GLES20Canvas),
REG_JNI(register_android_view_Surface),
+ REG_JNI(register_android_view_TextureView),
REG_JNI(register_android_view_ViewRoot),
REG_JNI(register_com_google_android_gles_jni_EGLImpl),
REG_JNI(register_com_google_android_gles_jni_GLImpl),
diff --git a/core/jni/android/graphics/Movie.cpp b/core/jni/android/graphics/Movie.cpp
index c112423..c1acaa3 100644
--- a/core/jni/android/graphics/Movie.cpp
+++ b/core/jni/android/graphics/Movie.cpp
@@ -112,6 +112,10 @@ static jobject movie_decodeByteArray(JNIEnv* env, jobject clazz,
return create_jmovie(env, moov);
}
+static void movie_destructor(JNIEnv* env, jobject, SkMovie* movie) {
+ delete movie;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////////
#include <android_runtime/AndroidRuntime.h>
@@ -126,6 +130,7 @@ static JNINativeMethod gMethods[] = {
(void*)movie_draw },
{ "decodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;",
(void*)movie_decodeStream },
+ { "nativeDestructor","(I)V", (void*)movie_destructor },
{ "decodeByteArray", "([BII)Landroid/graphics/Movie;",
(void*)movie_decodeByteArray },
};
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 4a0e68e..548376d 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -40,6 +40,16 @@ int dhcp_do_request(const char *ifname,
const char *dns2,
const char *server,
uint32_t *lease);
+
+int dhcp_do_request_renew(const char *ifname,
+ const char *ipaddr,
+ const char *gateway,
+ uint32_t *prefixLength,
+ const char *dns1,
+ const char *dns2,
+ const char *server,
+ uint32_t *lease);
+
int dhcp_stop(const char *ifname);
int dhcp_release_lease(const char *ifname);
char *dhcp_get_errmsg();
@@ -57,7 +67,6 @@ namespace android {
static struct fieldIds {
jmethodID constructorId;
jfieldID ipaddress;
- jfieldID gateway;
jfieldID prefixLength;
jfieldID dns1;
jfieldID dns2;
@@ -145,7 +154,8 @@ static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, jstri
return (jint)result;
}
-static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
+static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
+ jobject info, bool renew)
{
int result;
char ipaddr[PROPERTY_VALUE_MAX];
@@ -159,12 +169,41 @@ static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring if
const char *nameStr = env->GetStringUTFChars(ifname, NULL);
if (nameStr == NULL) return (jboolean)false;
- result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
- dns1, dns2, server, &lease);
+ if (renew) {
+ result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
+ dns1, dns2, server, &lease);
+ } else {
+ result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
+ dns1, dns2, server, &lease);
+ }
+
env->ReleaseStringUTFChars(ifname, nameStr);
if (result == 0) {
env->SetObjectField(info, dhcpInfoInternalFieldIds.ipaddress, env->NewStringUTF(ipaddr));
- env->SetObjectField(info, dhcpInfoInternalFieldIds.gateway, env->NewStringUTF(gateway));
+
+ // set the gateway
+ jclass cls = env->FindClass("java/net/InetAddress");
+ jmethodID method = env->GetStaticMethodID(cls, "getByName",
+ "(Ljava/lang/String;)Ljava/net/InetAddress;");
+ jvalue args[1];
+ args[0].l = env->NewStringUTF(gateway);
+ jobject inetAddressObject = env->CallStaticObjectMethodA(cls, method, args);
+
+ if (!env->ExceptionOccurred()) {
+ cls = env->FindClass("android/net/RouteInfo");
+ method = env->GetMethodID(cls, "<init>", "(Ljava/net/InetAddress;)V");
+ args[0].l = inetAddressObject;
+ jobject routeInfoObject = env->NewObjectA(cls, method, args);
+
+ cls = env->FindClass("android/net/DhcpInfoInternal");
+ method = env->GetMethodID(cls, "addRoute", "(Landroid/net/RouteInfo;)V");
+ args[0].l = routeInfoObject;
+ env->CallVoidMethodA(info, method, args);
+ } else {
+ // if we have an exception (host not found perhaps), just don't add the route
+ env->ExceptionClear();
+ }
+
env->SetIntField(info, dhcpInfoInternalFieldIds.prefixLength, prefixLength);
env->SetObjectField(info, dhcpInfoInternalFieldIds.dns1, env->NewStringUTF(dns1));
env->SetObjectField(info, dhcpInfoInternalFieldIds.dns2, env->NewStringUTF(dns2));
@@ -175,6 +214,17 @@ static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring if
return (jboolean)(result == 0);
}
+static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
+{
+ return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
+}
+
+static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
+{
+ return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true);
+}
+
+
static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname)
{
int result;
@@ -218,6 +268,7 @@ static JNINativeMethod gNetworkUtilMethods[] = {
{ "removeDefaultRoute", "(Ljava/lang/String;)I", (void *)android_net_utils_removeDefaultRoute },
{ "resetConnections", "(Ljava/lang/String;)I", (void *)android_net_utils_resetConnections },
{ "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z", (void *)android_net_utils_runDhcp },
+ { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z", (void *)android_net_utils_runDhcpRenew },
{ "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp },
{ "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease },
{ "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
@@ -229,7 +280,6 @@ int register_android_net_NetworkUtils(JNIEnv* env)
LOG_FATAL_IF(dhcpInfoInternalClass == NULL, "Unable to find class android/net/DhcpInfoInternal");
dhcpInfoInternalFieldIds.constructorId = env->GetMethodID(dhcpInfoInternalClass, "<init>", "()V");
dhcpInfoInternalFieldIds.ipaddress = env->GetFieldID(dhcpInfoInternalClass, "ipAddress", "Ljava/lang/String;");
- dhcpInfoInternalFieldIds.gateway = env->GetFieldID(dhcpInfoInternalClass, "gateway", "Ljava/lang/String;");
dhcpInfoInternalFieldIds.prefixLength = env->GetFieldID(dhcpInfoInternalClass, "prefixLength", "I");
dhcpInfoInternalFieldIds.dns1 = env->GetFieldID(dhcpInfoInternalClass, "dns1", "Ljava/lang/String;");
dhcpInfoInternalFieldIds.dns2 = env->GetFieldID(dhcpInfoInternalClass, "dns2", "Ljava/lang/String;");
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 314c2ee..f929a0e 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -24,6 +24,8 @@
#include <android_runtime/AndroidRuntime.h>
#include <utils/ResourceTypes.h>
+#include <gui/SurfaceTexture.h>
+
#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkMatrix.h>
@@ -539,6 +541,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 +578,16 @@ 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, SurfaceTexture* surface) {
+ float transform[16];
+ surface->updateTexImage();
+ surface->getTransformMatrix(transform);
+ GLenum renderTarget = surface->getCurrentTextureTarget();
+
+ LayerRenderer::updateTextureLayer(layer, width, height, renderTarget, transform);
+}
+
static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, Layer* layer) {
LayerRenderer::destroyLayer(layer);
}
@@ -696,6 +721,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", "(IIII)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/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
new file mode 100644
index 0000000..c5d86c8
--- /dev/null
+++ b/core/jni/android_view_TextureView.cpp
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#include "jni.h"
+#include <nativehelper/JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+
+#include <gui/SurfaceTexture.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+// Native layer
+// ----------------------------------------------------------------------------
+
+static void android_view_TextureView_setDefaultBufferSize(JNIEnv* env, jobject,
+ jint surfaceTexture, jint width, jint height) {
+
+ sp<SurfaceTexture> surface = reinterpret_cast<SurfaceTexture*>(surfaceTexture);
+ surface->setDefaultBufferSize(width, height);
+}
+
+// ----------------------------------------------------------------------------
+// JNI Glue
+// ----------------------------------------------------------------------------
+
+const char* const kClassPathName = "android/view/TextureView";
+
+static JNINativeMethod gMethods[] = {
+ { "nSetDefaultBufferSize", "(III)V", (void*) android_view_TextureView_setDefaultBufferSize }
+};
+
+int register_android_view_TextureView(JNIEnv* env) {
+ return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
+}
+
+};
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 5f2065a..f777527 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -27,6 +27,9 @@
#include <SkBitmap.h>
#include <SkPixelRef.h>
+#include <gui/SurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
+
namespace android {
static jclass gConfig_class;
@@ -319,6 +322,35 @@ not_valid_surface:
return (jint)sur;
}
+static jint jni_eglCreateWindowSurfaceTexture(JNIEnv *_env, jobject _this, jobject display,
+ jobject config, jint native_window, jintArray attrib_list) {
+ if (display == NULL || config == NULL
+ || !validAttribList(_env, attrib_list)) {
+ jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
+ return JNI_FALSE;
+ }
+ EGLDisplay dpy = getDisplay(_env, display);
+ EGLContext cnf = getConfig(_env, config);
+ sp<ANativeWindow> window;
+ if (native_window == 0) {
+not_valid_surface:
+ jniThrowException(_env, "java/lang/IllegalArgumentException",
+ "Make sure the SurfaceTexture is valid");
+ return 0;
+ }
+
+ sp<SurfaceTexture> surfaceTexture = reinterpret_cast<SurfaceTexture*>(native_window);
+
+ window = new SurfaceTextureClient(surfaceTexture);
+ if (window == NULL)
+ goto not_valid_surface;
+
+ jint* base = beginNativeAttribList(_env, attrib_list);
+ EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base);
+ endNativeAttributeList(_env, attrib_list, base);
+ return (jint)sur;
+}
+
static jboolean jni_eglGetConfigAttrib(JNIEnv *_env, jobject _this, jobject display,
jobject config, jint attribute, jintArray value) {
if (display == NULL || config == NULL
@@ -508,6 +540,7 @@ static JNINativeMethod methods[] = {
{"_eglCreatePbufferSurface","(" DISPLAY CONFIG "[I)I", (void*)jni_eglCreatePbufferSurface },
{"_eglCreatePixmapSurface", "(" SURFACE DISPLAY CONFIG OBJECT "[I)V", (void*)jni_eglCreatePixmapSurface },
{"_eglCreateWindowSurface", "(" DISPLAY CONFIG OBJECT "[I)I", (void*)jni_eglCreateWindowSurface },
+{"_eglCreateWindowSurfaceTexture", "(" DISPLAY CONFIG "I[I)I", (void*)jni_eglCreateWindowSurfaceTexture },
{"eglDestroyContext", "(" DISPLAY CONTEXT ")Z", (void*)jni_eglDestroyContext },
{"eglDestroySurface", "(" DISPLAY SURFACE ")Z", (void*)jni_eglDestroySurface },
{"eglMakeCurrent", "(" DISPLAY SURFACE SURFACE CONTEXT")Z", (void*)jni_eglMakeCurrent },
diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml
index 0cf4222..d8b729d 100644
--- a/core/res/res/layout/action_bar_title_item.xml
+++ b/core/res/res/layout/action_bar_title_item.xml
@@ -28,5 +28,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
- android:ellipsize="end" />
+ android:ellipsize="end"
+ android:visibility="gone" />
</LinearLayout>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index 70af265..9742b94 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -43,9 +43,10 @@ This is an optimized layout for a screen with the Action Bar enabled.
android:layout_weight="1"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
- <LinearLayout android:id="@+id/lower_action_context_bar"
+ <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
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 cfa335e..086acdd 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -46,10 +46,11 @@ the Action Bar enabled overlaying application content.
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/action_bar_container" />
- <LinearLayout android:id="@+id/lower_action_context_bar"
+ <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
android:layout_width="match_parent"
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-ca/strings.xml b/core/res/res/values-ca/strings.xml
index fbf4161..62e79f8 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -50,7 +50,7 @@
<string name="needPuk2" msgid="4526033371987193070">"Escriviu el PUK2 per desbloquejar la targeta SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Identificació de trucada entrant"</string>
<string name="ClirMmi" msgid="7784673673446833091">"Identificació de trucada de sortida"</string>
- <string name="CfMmi" msgid="5123218989141573515">"Desviament de trucades"</string>
+ <string name="CfMmi" msgid="5123218989141573515">"Desviació de trucades"</string>
<string name="CwMmi" msgid="9129678056795016867">"Trucada en espera"</string>
<string name="BaMmi" msgid="455193067926770581">"Restricció de trucades"</string>
<string name="PwdMmi" msgid="7043715687905254199">"Canvi de contrasenya"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 64da78f..acb9821 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -204,8 +204,8 @@
<string name="permdesc_getTasks" msgid="7048711358713443341">"Ermöglicht der Anwendung, Informationen zu aktuellen und kürzlich ausführten Aufgaben abzurufen. Schädliche Anwendungen können so eventuell geheime Informationen zu anderen Anwendungen entdecken."</string>
<string name="permlab_reorderTasks" msgid="5669588525059921549">"Laufende Anwendungen neu ordnen"</string>
<string name="permdesc_reorderTasks" msgid="126252774270522835">"Ermöglicht einer Anwendung, Aufgaben in den Vorder- und Hintergrund zu verschieben. Schädliche Anwendungen können so ohne Ihr Zutun eine Anzeige im Vordergrund erzwingen."</string>
- <string name="permlab_removeTasks" msgid="4802740047161700683">"Aktive Anwendungen beenden"</string>
- <string name="permdesc_removeTasks" msgid="2000332928514575461">"Ermöglicht einer Anwendung das Entfernen von Aufgaben und Beenden der entsprechenden Anwendungen. Schädliche Anwendungen können das Verhalten anderer Anwendungen stören."</string>
+ <string name="permlab_removeTasks" msgid="4802740047161700683">"Aktive Apps beenden"</string>
+ <string name="permdesc_removeTasks" msgid="2000332928514575461">"Ermöglicht einer App das Entfernen von Aufgaben und Beenden der entsprechenden Apps. Schädliche Apps können das Verhalten anderer Apps stören."</string>
<string name="permlab_setDebugApp" msgid="4339730312925176742">"Fehlerbeseitigung für Anwendung aktivieren"</string>
<string name="permdesc_setDebugApp" msgid="5584310661711990702">"Ermöglicht einer Anwendung, die Fehlerbeseitigung für eine andere Anwendung zu aktivieren. Schädliche Anwendungen können so andere Anwendungen löschen."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"UI-Einstellungen ändern"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 373f76c..2f1a1ad 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -466,7 +466,7 @@
<string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/eliminar contenido de la tarjeta SD"</string>
<string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Permite escribir en USB"</string>
<string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Permite que una aplicación escriba en la tarjeta SD."</string>
- <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"Cambiar/borrar almac interno"</string>
+ <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modificar o eliminar el contenido del almacenamiento de medios interno"</string>
<string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Permite que una aplicación modifique el contenido del almacenamiento interno de medios."</string>
<string name="permlab_cache_filesystem" msgid="5656487264819669824">"acceder al sistema de archivos almacenado en caché"</string>
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que una aplicación lea y escriba el sistema de archivos almacenado en caché."</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 1f0a94c..f112c33 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -204,7 +204,7 @@
<string name="permdesc_getTasks" msgid="7048711358713443341">"Mengizinkan aplikasi mengambil informasi tentang tugas yang sedang dan baru saja dijalankan. Aplikasi hasad dapat menemukan informasi bajakan tentang aplikasi lain."</string>
<string name="permlab_reorderTasks" msgid="5669588525059921549">"atur urutan aplikasi yang berjalan"</string>
<string name="permdesc_reorderTasks" msgid="126252774270522835">"Mengizinkan aplikasi memindah tugas ke latar depan dan latar belakang. Aplikasi hasad dapat memaksa dirinya ke latar depan tanpa sepengetahuan Anda."</string>
- <string name="permlab_removeTasks" msgid="4802740047161700683">"berhenti menjalankan aplikasi"</string>
+ <string name="permlab_removeTasks" msgid="4802740047161700683">"menghentikan aplikasi yang berjalan"</string>
<string name="permdesc_removeTasks" msgid="2000332928514575461">"Memungkinkan aplikasi menghapus tugas dan menghentikan aplikasinya. Aplikasi jahat dapat mengganggu perilaku aplikasi lain."</string>
<string name="permlab_setDebugApp" msgid="4339730312925176742">"aktifkan debugging aplikasi"</string>
<string name="permdesc_setDebugApp" msgid="5584310661711990702">"Mengizinkan aplikasi menghidupkan debug untuk aplikasi lain. Aplikasi hasad dapat menggunakan ini untuk menghentikan aplikasi penting lainnya."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 4d2b6c3..4d36eb3 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -204,8 +204,8 @@
<string name="permdesc_getTasks" msgid="7048711358713443341">"Permite aplicaţiei să regăsească informaţii despre activităţile rulate curent şi recent. Poate permite aplicaţiilor rău-intenţionate să descopere informaţii confidenţiale despre alte aplicaţii."</string>
<string name="permlab_reorderTasks" msgid="5669588525059921549">"reordonare aplicaţii aflate în derulare"</string>
<string name="permdesc_reorderTasks" msgid="126252774270522835">"Permite unei aplicaţii să mute activităţile în prim-plan şi în fundal. Aplicaţiile rău-intenţionate ar putea să apară forţat în prim-plan, fără ca dvs. să puteţi controla acest lucru."</string>
- <string name="permlab_removeTasks" msgid="4802740047161700683">"opriţi aplicaţiile care rulează"</string>
- <string name="permdesc_removeTasks" msgid="2000332928514575461">"Permite unei aplicaţii să elimine sarcinile şi să închidă aplicaţiile corespunzătoare acestora. Aplicaţiile rău intenţionate pot perturba comportamentul altor aplicaţii."</string>
+ <string name="permlab_removeTasks" msgid="4802740047161700683">"oprirea aplicaţiilor care rulează"</string>
+ <string name="permdesc_removeTasks" msgid="2000332928514575461">"Permite unei aplicaţii să elimine sarcini şi să închidă aplicaţiile corespunzătoare acestora. Aplicaţiile rău intenţionate pot perturba comportamentul altor aplicaţii."</string>
<string name="permlab_setDebugApp" msgid="4339730312925176742">"activare depanare aplicaţie"</string>
<string name="permdesc_setDebugApp" msgid="5584310661711990702">"Permite unei aplicaţii să activeze depanarea pentru o altă aplicaţie. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a închide alte aplicaţii."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"modificare setări UI"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 6155536..a81b2ee 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -205,7 +205,7 @@
<string name="permlab_reorderTasks" msgid="5669588525059921549">"zmena usporiadania spustených aplikácií"</string>
<string name="permdesc_reorderTasks" msgid="126252774270522835">"Umožňuje aplikácii presúvať úlohy do popredia alebo pozadia. Škodlivé aplikácie môžu vynútiť svoje presunutia do popredia bez vášho pričinenia."</string>
<string name="permlab_removeTasks" msgid="4802740047161700683">"zastavenie činnosti aplikácií"</string>
- <string name="permdesc_removeTasks" msgid="2000332928514575461">"Umožňuje aplikácii odstraňovať úlohy a ukončiť čínnosť súvisiacich aplikácií. Škodlivé aplikácie môžu narušovať správanie iných aplikácií."</string>
+ <string name="permdesc_removeTasks" msgid="2000332928514575461">"Umožňuje aplikácii odstraňovať úlohy a ukončiť činnosť súvisiacich aplikácií. Škodlivé aplikácie môžu narušovať správanie iných aplikácií."</string>
<string name="permlab_setDebugApp" msgid="4339730312925176742">"povoliť ladenie aplikácií"</string>
<string name="permdesc_setDebugApp" msgid="5584310661711990702">"Umožňuje aplikácii povoliť ladenie inej aplikácie. Škodlivé aplikácie môžu pomocou tohto nastavenia ukončiť iné aplikácie."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"zmeny vašich nastavení používateľského rozhrania"</string>
diff --git a/core/res/res/values-w480dp/bools.xml b/core/res/res/values-w480dp/bools.xml
index c202d90..8206e79 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-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 9c234a7..545be31 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -205,7 +205,7 @@
<string name="permlab_reorderTasks" msgid="5669588525059921549">"重新安排執行中的應用程式"</string>
<string name="permdesc_reorderTasks" msgid="126252774270522835">"允許應用程式將工作移至前端或背景作業。請注意:惡意程式可能使用此功能自行把自己拉到前端。"</string>
<string name="permlab_removeTasks" msgid="4802740047161700683">"停止執行中的應用程式"</string>
- <string name="permdesc_removeTasks" msgid="2000332928514575461">"允許應用程式移除工作並且關閉應用程式。惡意應用程式會干擾其他應用程式的行為。"</string>
+ <string name="permdesc_removeTasks" msgid="2000332928514575461">"允許應用程式移除工作並且關閉應用程式。惡意應用程式會干擾其他應用程式的運行。"</string>
<string name="permlab_setDebugApp" msgid="4339730312925176742">"啟用應用程式偵錯"</string>
<string name="permdesc_setDebugApp" msgid="5584310661711990702">"允許應用程式為其他程式開啟偵錯功能。請注意:惡意程式可利用此功能終止其他應用程式。"</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"變更介面設定"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3a44e4f..dac3bd2 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 6eb006f..8e27be4 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/config.xml b/core/res/res/values/config.xml
index b0c1962..3480604 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -549,10 +549,10 @@
<string name="gsm_alphabet_default_charset"></string>
<!-- Enables SIP on WIFI only -->
- <bool name="config_sip_wifi_only">true</bool>
+ <bool name="config_sip_wifi_only">false</bool>
<!-- Enables built-in SIP phone capability -->
- <bool name="config_built_in_sip_phone">false</bool>
+ <bool name="config_built_in_sip_phone">true</bool>
<!-- Boolean indicating if restoring network selection should be skipped -->
<!-- The restoring is handled by modem if it is true-->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 501d478..7ca5e98 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 be7b42f..cdfdd11 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/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index d22356d..27363e8 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -30,6 +30,7 @@ import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.ProxySettings;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.RouteInfo;
import android.util.Log;
import java.io.InputStream;
@@ -301,7 +302,7 @@ public class AccessPointParserHelper {
if (!InetAddress.isNumeric(gwAddr)) {
throw new SAXException();
}
- mLinkProperties.addGateway(InetAddress.getByName(gwAddr));
+ mLinkProperties.addRoute(new RouteInfo(InetAddress.getByName(gwAddr)));
} catch (UnknownHostException e) {
throw new SAXException();
}
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 010e3c3..fadf1ec 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -421,6 +421,13 @@
</intent-filter>
</activity>
+ <activity android:name="android.widget.scroll.arrowscroll.MultiPageTextWithPadding" android:label="arrowscrollMultiPageTextWithPadding">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<activity android:name="android.view.Include" android:label="IncludeTag">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index 50666b4..e3b6b5f 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -17,6 +17,7 @@
package android.net;
import android.net.LinkProperties;
+import android.net.RouteInfo;
import android.test.suitebuilder.annotation.SmallTest;
import junit.framework.TestCase;
@@ -55,8 +56,8 @@ public class LinkPropertiesTest extends TestCase {
source.addDns(NetworkUtils.numericToInetAddress(DNS1));
source.addDns(NetworkUtils.numericToInetAddress(DNS2));
// set 2 gateways
- source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
- source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+ source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
LinkProperties target = new LinkProperties();
@@ -68,8 +69,8 @@ public class LinkPropertiesTest extends TestCase {
NetworkUtils.numericToInetAddress(ADDRV6), 128));
target.addDns(NetworkUtils.numericToInetAddress(DNS1));
target.addDns(NetworkUtils.numericToInetAddress(DNS2));
- target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
- target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
assertTrue(source.equals(target));
assertTrue(source.hashCode() == target.hashCode());
@@ -83,8 +84,8 @@ public class LinkPropertiesTest extends TestCase {
NetworkUtils.numericToInetAddress(ADDRV6), 128));
target.addDns(NetworkUtils.numericToInetAddress(DNS1));
target.addDns(NetworkUtils.numericToInetAddress(DNS2));
- target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
- target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
assertFalse(source.equals(target));
target.clear();
@@ -96,8 +97,8 @@ public class LinkPropertiesTest extends TestCase {
NetworkUtils.numericToInetAddress(ADDRV6), 128));
target.addDns(NetworkUtils.numericToInetAddress(DNS1));
target.addDns(NetworkUtils.numericToInetAddress(DNS2));
- target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
- target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
assertFalse(source.equals(target));
target.clear();
@@ -109,8 +110,8 @@ public class LinkPropertiesTest extends TestCase {
// change dnses
target.addDns(NetworkUtils.numericToInetAddress("75.208.7.2"));
target.addDns(NetworkUtils.numericToInetAddress(DNS2));
- target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
- target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
assertFalse(source.equals(target));
target.clear();
@@ -122,8 +123,8 @@ public class LinkPropertiesTest extends TestCase {
target.addDns(NetworkUtils.numericToInetAddress(DNS1));
target.addDns(NetworkUtils.numericToInetAddress(DNS2));
// change gateway
- target.addGateway(NetworkUtils.numericToInetAddress("75.208.8.2"));
- target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
assertFalse(source.equals(target));
} catch (Exception e) {
@@ -146,8 +147,8 @@ public class LinkPropertiesTest extends TestCase {
source.addDns(NetworkUtils.numericToInetAddress(DNS1));
source.addDns(NetworkUtils.numericToInetAddress(DNS2));
// set 2 gateways
- source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
- source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+ source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+ source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
LinkProperties target = new LinkProperties();
// Exchange order
@@ -158,8 +159,8 @@ public class LinkPropertiesTest extends TestCase {
NetworkUtils.numericToInetAddress(ADDRV4), 32));
target.addDns(NetworkUtils.numericToInetAddress(DNS2));
target.addDns(NetworkUtils.numericToInetAddress(DNS1));
- target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
- target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+ target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
assertTrue(source.equals(target));
assertTrue(source.hashCode() == target.hashCode());
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index c82962d..d494c5d 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -19,6 +19,7 @@ package android.text;
import com.google.android.collect.Lists;
import android.test.MoreAsserts;
+import android.os.Parcel;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.style.StyleSpan;
@@ -344,6 +345,51 @@ public class TextUtilsTest extends TestCase {
assertFalse(TextUtils.delimitedStringContains("network,mock,gpsx", ',', "gps"));
}
+ @SmallTest
+ public void testCharSequenceCreator() {
+ Parcel p = Parcel.obtain();
+ TextUtils.writeToParcel(null, p, 0);
+ CharSequence text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
+ assertNull("null CharSequence should generate null from parcel", text);
+ p = Parcel.obtain();
+ TextUtils.writeToParcel("test", p, 0);
+ text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
+ assertEquals("conversion to/from parcel failed", "test", text);
+ }
+
+ @SmallTest
+ public void testCharSequenceCreatorNull() {
+ Parcel p;
+ CharSequence text;
+ p = Parcel.obtain();
+ TextUtils.writeToParcel(null, p, 0);
+ p.setDataPosition(0);
+ text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
+ assertNull("null CharSequence should generate null from parcel", text);
+ }
+
+ @SmallTest
+ public void testCharSequenceCreatorSpannable() {
+ Parcel p;
+ CharSequence text;
+ p = Parcel.obtain();
+ TextUtils.writeToParcel(new SpannableString("test"), p, 0);
+ p.setDataPosition(0);
+ text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
+ assertEquals("conversion to/from parcel failed", "test", text.toString());
+ }
+
+ @SmallTest
+ public void testCharSequenceCreatorString() {
+ Parcel p;
+ CharSequence text;
+ p = Parcel.obtain();
+ TextUtils.writeToParcel("test", p, 0);
+ p.setDataPosition(0);
+ text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p);
+ assertEquals("conversion to/from parcel failed", "test", text.toString());
+ }
+
/**
* CharSequence wrapper for testing the cases where text is copied into
* a char array instead of working from a String or a Spanned.
diff --git a/core/tests/coretests/src/android/util/ScrollViewScenario.java b/core/tests/coretests/src/android/util/ScrollViewScenario.java
index 83afe06..db3d9d0 100644
--- a/core/tests/coretests/src/android/util/ScrollViewScenario.java
+++ b/core/tests/coretests/src/android/util/ScrollViewScenario.java
@@ -61,6 +61,7 @@ public abstract class ScrollViewScenario extends Activity {
/**
* Partially implement ViewFactory given a height ratio.
+ * A negative height ratio means that WRAP_CONTENT will be used as height
*/
private static abstract class ViewFactoryBase implements ViewFactory {
@@ -87,6 +88,9 @@ public abstract class ScrollViewScenario extends Activity {
List<ViewFactory> mViewFactories = Lists.newArrayList();
+ int mTopPadding = 0;
+ int mBottomPadding = 0;
+
/**
* Add a text view.
* @param text The text of the text view.
@@ -186,6 +190,13 @@ public abstract class ScrollViewScenario extends Activity {
});
return this;
}
+
+ public Params addPaddingToScrollView(int topPadding, int bottomPadding) {
+ mTopPadding = topPadding;
+ mBottomPadding = bottomPadding;
+
+ return this;
+ }
}
/**
@@ -239,13 +250,17 @@ public abstract class ScrollViewScenario extends Activity {
// create views specified by params
for (ViewFactory viewFactory : params.mViewFactories) {
+ int height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ if (viewFactory.getHeightRatio() >= 0) {
+ height = (int) (viewFactory.getHeightRatio() * screenHeight);
+ }
final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- (int) (viewFactory.getHeightRatio() * screenHeight));
+ ViewGroup.LayoutParams.MATCH_PARENT, height);
mLinearLayout.addView(viewFactory.create(this), lp);
}
mScrollView = createScrollView();
+ mScrollView.setPadding(0, params.mTopPadding, 0, params.mBottomPadding);
mScrollView.addView(mLinearLayout, new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
diff --git a/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPadding.java b/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPadding.java
new file mode 100644
index 0000000..7d5a8d8
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPadding.java
@@ -0,0 +1,38 @@
+/*
+ * 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.widget.scroll.arrowscroll;
+
+import android.util.ScrollViewScenario;
+
+/**
+ * One TextView with a text covering several pages. Padding is added
+ * above and below the ScrollView.
+ */
+public class MultiPageTextWithPadding extends ScrollViewScenario {
+
+ @Override
+ protected void init(Params params) {
+
+ String text = "This is a long text.";
+ String longText = "First text.";
+ for (int i = 0; i < 300; i++) {
+ longText = longText + " " + text;
+ }
+ longText = longText + " Last text.";
+ params.addTextView(longText, -1.0f).addPaddingToScrollView(50, 50);
+ }
+}
diff --git a/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPaddingTest.java b/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPaddingTest.java
new file mode 100644
index 0000000..ddde48f
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPaddingTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 Sony Ericsson Mobile Communications AB.
+ *
+ * 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.widget.scroll.arrowscroll;
+
+import android.widget.scroll.arrowscroll.MultiPageTextWithPadding;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
+import android.widget.TextView;
+import android.widget.ScrollView;
+
+public class MultiPageTextWithPaddingTest extends
+ ActivityInstrumentationTestCase<MultiPageTextWithPadding> {
+
+ private ScrollView mScrollView;
+
+ private TextView mTextView;
+
+ public MultiPageTextWithPaddingTest() {
+ super("com.android.frameworks.coretests", MultiPageTextWithPadding.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mScrollView = getActivity().getScrollView();
+ mTextView = getActivity().getContentChildAt(0);
+ }
+
+ @MediumTest
+ public void testPreconditions() {
+ assertTrue("text should not fit on screen",
+ mTextView.getHeight() > mScrollView.getHeight());
+ }
+
+ @LargeTest
+ public void testScrollDownToBottom() throws Exception {
+ // Calculate the number of arrow scrolls needed to reach the bottom
+ int scrollsNeeded = (int)Math.ceil(Math.max(0.0f,
+ (mTextView.getHeight() - mScrollView.getHeight()))
+ / mScrollView.getMaxScrollAmount());
+ for (int i = 0; i < scrollsNeeded; i++) {
+ sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+ }
+
+ assertEquals(
+ "should be fully scrolled to bottom",
+ getActivity().getLinearLayout().getHeight()
+ - (mScrollView.getHeight() - mScrollView.getPaddingTop() - mScrollView
+ .getPaddingBottom()), mScrollView.getScrollY());
+ }
+}
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index 10d25bb..2a551e9 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -264,8 +264,8 @@ href="#Compatibility">Providing the Best Device Compatibility with Resources</a>
names.</p>
<table>
<tr>
- <th>Qualifier</th>
- <th>Values</th>
+ <th>Configuration</th>
+ <th>Qualifier Values</th>
<th>Description</th>
</tr>
<tr id="MccQualifier">
diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd
index 2da022c..4a574be 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/graphics/Movie.java b/graphics/java/android/graphics/Movie.java
index 95e9946..4a33453 100644
--- a/graphics/java/android/graphics/Movie.java
+++ b/graphics/java/android/graphics/Movie.java
@@ -46,6 +46,8 @@ public class Movie {
public static native Movie decodeByteArray(byte[] data, int offset,
int length);
+ private static native void nativeDestructor(int nativeMovie);
+
public static Movie decodeFile(String pathName) {
InputStream is;
try {
@@ -57,6 +59,15 @@ public class Movie {
return decodeTempStream(is);
}
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ nativeDestructor(mNativeMovie);
+ } finally {
+ super.finalize();
+ }
+ }
+
private static Movie decodeTempStream(InputStream is) {
Movie moov = null;
try {
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index cfae0c1..3c43a39 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -34,8 +34,9 @@ import android.os.Message;
* the stream to be skipped.
*
* <p>When sampling from the texture one should first transform the texture coordinates using the
- * matrix queried via {@link #getTransformMatrix}. The transform matrix may change each time {@link
- * #updateTexImage} is called, so it should be re-queried each time the texture image is updated.
+ * matrix queried via {@link #getTransformMatrix(float[])}. The transform matrix may change each
+ * time {@link #updateTexImage} is called, so it should be re-queried each time the texture image
+ * is updated.
* This matrix transforms traditional 2D OpenGL ES texture coordinate column vectors of the form (s,
* t, 0, 1) where s and t are on the inclusive interval [0, 1] to the proper sampling location in
* the streamed texture. This transform compensates for any properties of the image stream source
@@ -63,8 +64,13 @@ public class SurfaceTexture {
private EventHandler mEventHandler;
private OnFrameAvailableListener mOnFrameAvailableListener;
- @SuppressWarnings("unused")
- private int mSurfaceTexture;
+ /**
+ * This field is used by native code, do not access or modify.
+ *
+ * @hide
+ */
+ @SuppressWarnings({"UnusedDeclaration"})
+ public int mSurfaceTexture;
/**
* Callback interface for being notified that a new stream frame is available.
@@ -176,10 +182,13 @@ public class SurfaceTexture {
if (mOnFrameAvailableListener != null) {
mOnFrameAvailableListener.onFrameAvailable(SurfaceTexture.this);
}
- return;
}
}
+ /**
+ * This method is invoked from native code only.
+ */
+ @SuppressWarnings({"UnusedDeclaration"})
private static void postEventFromNative(Object selfRef) {
WeakReference weakSelf = (WeakReference)selfRef;
SurfaceTexture st = (SurfaceTexture)weakSelf.get();
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index a278466..c9c9fd7 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -546,10 +546,8 @@ public class BitmapDrawable extends Drawable {
mBitmapState = state;
if (res != null) {
mTargetDensity = res.getDisplayMetrics().densityDpi;
- } else if (state != null) {
- mTargetDensity = state.mTargetDensity;
} else {
- mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
+ mTargetDensity = state.mTargetDensity;
}
setBitmap(state != null ? state.mBitmap : null);
}
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 3f6f8c3..256435f 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -381,7 +381,7 @@ nTypeCreate(JNIEnv *_env, jobject _this, RsContext con, RsElement eid,
LOG_API("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i)",
con, eid, dimx, dimy, dimz, mips, faces);
- jint id = (jint)rsaTypeCreate(con, (RsElement)eid, dimx, dimy, dimz, mips, faces);
+ jint id = (jint)rsTypeCreate(con, (RsElement)eid, dimx, dimy, dimz, mips, faces);
return (jint)id;
}
@@ -409,7 +409,7 @@ static jint
nAllocationCreateTyped(JNIEnv *_env, jobject _this, RsContext con, jint type, jint mips, jint usage)
{
LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i)", con, (RsElement)type, mips, usage);
- return (jint) rsaAllocationCreateTyped(con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage);
+ return (jint) rsAllocationCreateTyped(con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage);
}
static void
@@ -435,7 +435,7 @@ nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint typ
bitmap.lockPixels();
const void* ptr = bitmap.getPixels();
- jint id = (jint)rsaAllocationCreateFromBitmap(con,
+ jint id = (jint)rsAllocationCreateFromBitmap(con,
(RsType)type, (RsAllocationMipmapControl)mip,
ptr, bitmap.getSize(), usage);
bitmap.unlockPixels();
@@ -451,7 +451,7 @@ nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint
bitmap.lockPixels();
const void* ptr = bitmap.getPixels();
- jint id = (jint)rsaAllocationCubeCreateFromBitmap(con,
+ jint id = (jint)rsAllocationCubeCreateFromBitmap(con,
(RsType)type, (RsAllocationMipmapControl)mip,
ptr, bitmap.getSize(), usage);
bitmap.unlockPixels();
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
index d2d1d7e..3330ebc 100644
--- a/include/drm/drm_framework_common.h
+++ b/include/drm/drm_framework_common.h
@@ -31,14 +31,17 @@ namespace android {
* Error code for DRM Frameowrk
*/
enum {
- DRM_ERROR_BASE = -2000,
-
- DRM_ERROR_UNKNOWN = DRM_ERROR_BASE,
- DRM_ERROR_LICENSE_EXPIRED = DRM_ERROR_BASE - 1,
- DRM_ERROR_SESSION_NOT_OPENED = DRM_ERROR_BASE - 2,
- DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED = DRM_ERROR_BASE - 3,
- DRM_ERROR_DECRYPT = DRM_ERROR_BASE - 4,
- DRM_ERROR_CANNOT_HANDLE = DRM_ERROR_BASE - 5,
+ // The following constant values should be in sync with
+ // media/stagefright/MediaErrors.h
+ ERROR_BASE = -2000,
+
+ DRM_ERROR_UNKNOWN = ERROR_BASE,
+ DRM_ERROR_NO_LICENSE = ERROR_BASE - 1,
+ DRM_ERROR_LICENSE_EXPIRED = ERROR_BASE - 2,
+ DRM_ERROR_SESSION_NOT_OPENED = ERROR_BASE - 3,
+ DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED = ERROR_BASE - 4,
+ DRM_ERROR_DECRYPT = ERROR_BASE - 5,
+ DRM_ERROR_CANNOT_HANDLE = ERROR_BASE - 6,
DRM_NO_ERROR = NO_ERROR
};
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index 9b1af6b..d552b2e 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -51,6 +51,8 @@ public:
virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
virtual status_t setAuxEffectSendLevel(float level) = 0;
virtual status_t attachAuxEffect(int effectId) = 0;
+ virtual status_t setParameter(int key, const Parcel& request) = 0;
+ virtual status_t getParameter(int key, Parcel* reply) = 0;
// Invoke a generic method on the player by using opaque parcels
// for the request and reply.
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index bebecc0..f0401cc 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -132,6 +132,8 @@ public:
virtual status_t reset() = 0;
virtual status_t setLooping(int loop) = 0;
virtual player_type playerType() = 0;
+ virtual status_t setParameter(int key, const Parcel &request) = 0;
+ virtual status_t getParameter(int key, Parcel *reply) = 0;
// Invoke a generic method on the player by using opaque parcels
// for the request and reply.
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 748e489..241626c 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -177,6 +177,9 @@ public:
int getAudioSessionId();
status_t setAuxEffectSendLevel(float level);
status_t attachAuxEffect(int effectId);
+ status_t setParameter(int key, const Parcel& request);
+ status_t getParameter(int key, Parcel* reply);
+
private:
void clear_l();
status_t seekTo_l(int msec);
diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h
index 1a6d548..7cc993c 100644
--- a/include/media/stagefright/MediaErrors.h
+++ b/include/media/stagefright/MediaErrors.h
@@ -41,7 +41,17 @@ enum {
INFO_FORMAT_CHANGED = MEDIA_ERROR_BASE - 12,
INFO_DISCONTINUITY = MEDIA_ERROR_BASE - 13,
- ERROR_NO_LICENSE = MEDIA_ERROR_BASE - 14,
+ // The following constant values should be in sync with
+ // drm/drm_framework_common.h
+ DRM_ERROR_BASE = -2000,
+
+ ERROR_DRM_UNKNOWN = DRM_ERROR_BASE,
+ ERROR_DRM_NO_LICENSE = DRM_ERROR_BASE - 1,
+ ERROR_DRM_LICENSE_EXPIRED = DRM_ERROR_BASE - 2,
+ ERROR_DRM_SESSION_NOT_OPENED = DRM_ERROR_BASE - 3,
+ ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED = DRM_ERROR_BASE - 4,
+ ERROR_DRM_DECRYPT = DRM_ERROR_BASE - 5,
+ ERROR_DRM_CANNOT_HANDLE = DRM_ERROR_BASE - 6,
// Heartbeat Error Codes
HEARTBEAT_ERROR_BASE = -3000,
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index c7db9a6..6b1fa77 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -26,14 +26,11 @@
#endif
#include <private/pixelflinger/ggl_context.h>
-#include <hardware/copybit.h>
#include <hardware/gralloc.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
-struct android_native_buffer_t;
-
namespace android {
@@ -604,14 +601,6 @@ struct prims_t {
void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*);
};
-struct copybits_context_t {
- // A handle to the blit engine, if it exists, else NULL.
- copybit_device_t* blitEngine;
- int32_t minScale;
- int32_t maxScale;
- android_native_buffer_t* drawSurfaceBuffer;
-};
-
struct ogles_context_t {
context_t rasterizer;
array_machine_t arrays __attribute__((aligned(32)));
@@ -636,13 +625,6 @@ struct ogles_context_t {
EGLSurfaceManager* surfaceManager;
EGLBufferObjectManager* bufferObjectManager;
- // copybits is only used if LIBAGL_USE_GRALLOC_COPYBITS is
- // defined, but it is always present because ogles_context_t is a public
- // struct that is used by clients of libagl. We want the size and offsets
- // to stay the same, whether or not LIBAGL_USE_GRALLOC_COPYBITS is defined.
-
- copybits_context_t copybits;
-
GLenum error;
static inline ogles_context_t* get() {
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 925fd06..6c9a620 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -24,8 +24,6 @@
#include <ui/Rect.h>
-#include <hardware/copybit.h>
-
namespace android {
// ---------------------------------------------------------------------------
@@ -183,27 +181,6 @@ Region& Region::operator -= (const Region& rhs) {
Region& Region::operator += (const Point& pt) {
return translateSelf(pt.x, pt.y);
}
-
-// ---------------------------------------------------------------------------
-
-struct region_iterator : public copybit_region_t {
- region_iterator(const Region& region)
- : b(region.begin()), e(region.end()) {
- this->next = iterate;
- }
-private:
- static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
- region_iterator const* me = static_cast<region_iterator const*>(self);
- if (me->b != me->e) {
- *reinterpret_cast<Rect*>(rect) = *me->b++;
- return 1;
- }
- return 0;
- }
- mutable Region::const_iterator b;
- Region::const_iterator const e;
-};
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 58bb0d3..b5737ff 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 ecd0995..8d3a9b5 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/Caches.h b/libs/hwui/Caches.h
index faecadd..596781e 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -62,8 +62,10 @@ static const TextureVertex gMeshVertices[] = {
static const GLsizei gMeshStride = sizeof(TextureVertex);
static const GLsizei gVertexStride = sizeof(Vertex);
static const GLsizei gAlphaVertexStride = sizeof(AlphaVertex);
+static const GLsizei gAAVertexStride = sizeof(AAVertex);
static const GLsizei gMeshTextureOffset = 2 * sizeof(float);
-static const GLsizei gVertexAlphaOffset = 2 * sizeof(float);
+static const GLsizei gVertexAAWidthOffset = 2 * sizeof(float);
+static const GLsizei gVertexAALengthOffset = 3 * sizeof(float);
static const GLsizei gMeshCount = 4;
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 6c4a2a9..0310bc3 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -45,6 +45,9 @@ struct Layer {
mesh = NULL;
meshIndices = NULL;
meshElementCount = 0;
+ isCacheable = true;
+ isTextureLayer = false;
+ renderTarget = GL_TEXTURE_2D;
}
~Layer() {
@@ -137,6 +140,27 @@ 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;
+
+ /**
+ * Indicates the render target.
+ */
+ GLenum renderTarget;
}; // struct Layer
}; // namespace uirenderer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index a9710ad..b2d795f 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 ca1e7ae..f316ba7 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,30 @@ 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);
+
+ 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 +269,27 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
return true;
}
+void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
+ GLenum renderTarget, 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);
+ layer->renderTarget = renderTarget;
+
+ glBindTexture(layer->renderTarget, layer->texture);
+
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+}
+
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 d2f565e..59cab96 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,
+ GLenum renderTarget, 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 ea42838..6f751e8 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -633,15 +633,52 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
}
}
+void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
+ float alpha = layer->alpha / 255.0f;
+
+ setupDraw();
+ if (layer->renderTarget == GL_TEXTURE_2D) {
+ setupDrawWithTexture();
+ } else {
+ setupDrawWithExternalTexture();
+ }
+ setupDrawTextureTransform();
+ setupDrawColor(alpha, alpha, alpha, alpha);
+ setupDrawColorFilter();
+ setupDrawBlending(layer->blend, layer->mode);
+ setupDrawProgram();
+ setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom);
+ setupDrawPureColorUniforms();
+ setupDrawColorFilterUniforms();
+ if (layer->renderTarget == GL_TEXTURE_2D) {
+ setupDrawTexture(layer->texture);
+ } else {
+ setupDrawExternalTexture(layer->texture);
+ }
+ setupDrawTextureTransformUniforms(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,8 +919,12 @@ void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
mDescription.hasAlpha8Texture = isAlpha8;
}
+void OpenGLRenderer::setupDrawWithExternalTexture() {
+ mDescription.hasExternalTexture = true;
+}
+
void OpenGLRenderer::setupDrawAALine() {
- mDescription.hasWidth = true;
+ mDescription.isAA = true;
}
void OpenGLRenderer::setupDrawPoint(float pointSize) {
@@ -1055,6 +1096,23 @@ 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() {
+ mDescription.hasTextureTransform = true;
+}
+
+void OpenGLRenderer::setupDrawTextureTransformUniforms(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);
@@ -1076,25 +1134,30 @@ void OpenGLRenderer::setupDrawVertices(GLvoid* vertices) {
/**
* Sets up the shader to draw an AA line. We draw AA lines with quads, where there is an
- * outer boundary that fades out to 0. The variables set in the shader define the width of the
- * core line primitive ("width") and the width of the fading boundary ("boundaryWidth"). The
- * "vtxDistance" attribute (one per vertex) is a value from zero to one that tells the fragment
- * shader where the fragment is in relation to the line width overall; this value is then used
- * to compute the proper color, based on whether the fragment lies in the fading AA region of
- * the line.
+ * outer boundary that fades out to 0. The variables set in the shader define the proportion of
+ * the width and length of the primitive occupied by the AA region. The vtxWidth and vtxLength
+ * attributes (one per vertex) are values from zero to one that tells the fragment
+ * shader where the fragment is in relation to the line width/length overall; these values are
+ * then used to compute the proper color, based on whether the fragment lies in the fading AA
+ * region of the line.
+ * Note that we only pass down the width values in this setup function. The length coordinates
+ * are set up for each individual segment.
*/
-void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, float strokeWidth) {
+void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* widthCoords,
+ GLvoid* lengthCoords, float strokeWidth) {
mCaches.unbindMeshBuffer();
glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
- gAlphaVertexStride, vertices);
- int distanceSlot = mCaches.currentProgram->getAttrib("vtxDistance");
- glEnableVertexAttribArray(distanceSlot);
- glVertexAttribPointer(distanceSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, distanceCoords);
- int widthSlot = mCaches.currentProgram->getUniform("width");
+ gAAVertexStride, vertices);
+ int widthSlot = mCaches.currentProgram->getAttrib("vtxWidth");
+ glEnableVertexAttribArray(widthSlot);
+ glVertexAttribPointer(widthSlot, 1, GL_FLOAT, GL_FALSE, gAAVertexStride, widthCoords);
+ int lengthSlot = mCaches.currentProgram->getAttrib("vtxLength");
+ glEnableVertexAttribArray(lengthSlot);
+ glVertexAttribPointer(lengthSlot, 1, GL_FLOAT, GL_FALSE, gAAVertexStride, lengthCoords);
int boundaryWidthSlot = mCaches.currentProgram->getUniform("boundaryWidth");
+ // Setting the inverse value saves computations per-fragment in the shader
int inverseBoundaryWidthSlot = mCaches.currentProgram->getUniform("inverseBoundaryWidth");
float boundaryWidth = (1 - strokeWidth) / 2;
- glUniform1f(widthSlot, strokeWidth);
glUniform1f(boundaryWidthSlot, boundaryWidth);
glUniform1f(inverseBoundaryWidthSlot, (1 / boundaryWidth));
}
@@ -1435,20 +1498,21 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
}
Vertex lines[verticesCount];
Vertex* vertices = &lines[0];
- AlphaVertex wLines[verticesCount];
- AlphaVertex* aaVertices = &wLines[0];
+ AAVertex wLines[verticesCount];
+ AAVertex* aaVertices = &wLines[0];
if (!isAA) {
setupDrawVertices(vertices);
} else {
- void* alphaCoords = ((GLbyte*) aaVertices) + gVertexAlphaOffset;
+ void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset;
+ void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset;
// innerProportion is the ratio of the inner (non-AA) port of the line to the total
// AA stroke width (the base stroke width expanded by a half pixel on either side).
// This value is used in the fragment shader to determine how to fill fragments.
float innerProportion = fmax(strokeWidth - 1.0f, 0) / (strokeWidth + .5f);
- setupDrawAALine((void*) aaVertices, alphaCoords, innerProportion);
+ setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords, innerProportion);
}
- AlphaVertex *prevAAVertex = NULL;
+ AAVertex *prevAAVertex = NULL;
Vertex *prevVertex = NULL;
float inverseScaleX = 1.0f;
float inverseScaleY = 1.0f;
@@ -1471,15 +1535,17 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
}
}
+ int boundaryLengthSlot = -1;
+ int inverseBoundaryLengthSlot = -1;
for (int i = 0; i < count; i += 4) {
// a = start point, b = end point
vec2 a(points[i], points[i + 1]);
vec2 b(points[i + 2], points[i + 3]);
+ float length = 0;
// Find the normal to the line
vec2 n = (b - a).copyNormalized() * strokeWidth;
if (isHairLine) {
- n *= inverseScaleX;
if (isAA) {
float wideningFactor;
if (fabs(n.x) >= fabs(n.y)) {
@@ -1489,27 +1555,35 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
}
n *= wideningFactor;
}
+ n.x *= inverseScaleX;
+ n.y *= inverseScaleY;
}
float x = n.x;
n.x = -n.y;
n.y = x;
+ // aa lines expand the endpoint vertices to encompass the AA boundary
+ if (isAA) {
+ vec2 abVector = (b - a);
+ length = abVector.length();
+ abVector.normalize();
+ a -= abVector;
+ b += abVector;
+ }
+
// Four corners of the rectangle defining a thick line
vec2 p1 = a - n;
vec2 p2 = a + n;
vec2 p3 = b + n;
vec2 p4 = b - n;
+
const float left = fmin(p1.x, fmin(p2.x, fmin(p3.x, p4.x)));
const float right = fmax(p1.x, fmax(p2.x, fmax(p3.x, p4.x)));
const float top = fmin(p1.y, fmin(p2.y, fmin(p3.y, p4.y)));
const float bottom = fmax(p1.y, fmax(p2.y, fmax(p3.y, p4.y)));
if (!quickReject(left, top, right, bottom)) {
- // Draw the line as 2 triangles, could be optimized
- // by using only 4 vertices and the correct indices
- // Also we should probably used non textured vertices
- // when line AA is disabled to save on bandwidth
if (!isAA) {
if (prevVertex != NULL) {
// Issue two repeat vertices to create degenerate triangles to bridge
@@ -1527,24 +1601,36 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
prevVertex = vertices - 1;
generatedVerticesCount += 4;
} else {
+ if (boundaryLengthSlot < 0) {
+ boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
+ inverseBoundaryLengthSlot =
+ mCaches.currentProgram->getUniform("inverseBoundaryLength");
+ }
+ float innerProportion = (length) / (length + 2);
+ float boundaryLength = (1 - innerProportion) / 2;
+ glUniform1f(boundaryLengthSlot, boundaryLength);
+ glUniform1f(inverseBoundaryLengthSlot, (1 / boundaryLength));
+
if (prevAAVertex != NULL) {
// Issue two repeat vertices to create degenerate triangles to bridge
// between the previous line and the new one. This is necessary because
// we are creating a single triangle_strip which will contain
// potentially discontinuous line segments.
- AlphaVertex::set(aaVertices++,prevAAVertex->position[0],
- prevAAVertex->position[1], prevAAVertex->alpha);
- AlphaVertex::set(aaVertices++, p4.x, p4.y, 1);
+ AAVertex::set(aaVertices++,prevAAVertex->position[0],
+ prevAAVertex->position[1], prevAAVertex->width, prevAAVertex->length);
+ AAVertex::set(aaVertices++, p4.x, p4.y, 1, 1);
generatedVerticesCount += 2;
}
- AlphaVertex::set(aaVertices++, p4.x, p4.y, 1);
- AlphaVertex::set(aaVertices++, p1.x, p1.y, 1);
- AlphaVertex::set(aaVertices++, p3.x, p3.y, 0);
- AlphaVertex::set(aaVertices++, p2.x, p2.y, 0);
+ AAVertex::set(aaVertices++, p4.x, p4.y, 1, 1);
+ AAVertex::set(aaVertices++, p1.x, p1.y, 1, 0);
+ AAVertex::set(aaVertices++, p3.x, p3.y, 0, 1);
+ AAVertex::set(aaVertices++, p2.x, p2.y, 0, 0);
prevAAVertex = aaVertices - 1;
generatedVerticesCount += 4;
}
- dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+ dirtyLayer(a.x == b.x ? left - 1 : left, a.y == b.y ? top - 1 : top,
+ a.x == b.x ? right: right, a.y == b.y ? bottom: bottom,
+ *mSnapshot->transform);
}
}
if (generatedVerticesCount > 0) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 918e1fb..b5c37c2 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,9 +464,13 @@ private:
void setupDrawColorFilterUniforms();
void setupDrawSimpleMesh();
void setupDrawTexture(GLuint texture);
+ void setupDrawExternalTexture(GLuint texture);
+ void setupDrawTextureTransform();
+ void setupDrawTextureTransformUniforms(mat4& transform);
void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0);
void setupDrawVertices(GLvoid* vertices);
- void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, float strokeWidth);
+ void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, GLvoid* lengthCoords,
+ float strokeWidth);
void finishDrawTexture();
void drawRegionRects(const Region& region);
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 80b1917..d419e3e 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -39,8 +39,11 @@ const char* gVS_Header_Attributes =
"attribute vec4 position;\n";
const char* gVS_Header_Attributes_TexCoords =
"attribute vec2 texCoords;\n";
-const char* gVS_Header_Attributes_Distance =
- "attribute float vtxDistance;\n";
+const char* gVS_Header_Attributes_AAParameters =
+ "attribute float vtxWidth;\n"
+ "attribute float vtxLength;\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 =
@@ -58,8 +61,9 @@ const char* gVS_Header_Uniforms_HasBitmap =
"uniform mediump vec2 textureDimension;\n";
const char* gVS_Header_Varyings_HasTexture =
"varying vec2 outTexCoords;\n";
-const char* gVS_Header_Varyings_HasWidth =
- "varying float distance;\n";
+const char* gVS_Header_Varyings_IsAA =
+ "varying float widthProportion;\n"
+ "varying float lengthProportion;\n";
const char* gVS_Header_Varyings_HasBitmap =
"varying vec2 outBitmapTexCoords;\n";
const char* gVS_Header_Varyings_PointHasBitmap =
@@ -76,6 +80,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",
@@ -92,8 +98,9 @@ const char* gVS_Main_Position =
" gl_Position = transform * position;\n";
const char* gVS_Main_PointSize =
" gl_PointSize = pointSize;\n";
-const char* gVS_Main_Width =
- " distance = vtxDistance;\n";
+const char* gVS_Main_AA =
+ " widthProportion = vtxWidth;\n"
+ " lengthProportion = vtxLength;\n";
const char* gVS_Footer =
"}\n\n";
@@ -103,19 +110,24 @@ 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 =
"uniform vec4 color;\n";
-const char* gFS_Uniforms_Width =
- "uniform float width;\n"
+const char* gFS_Uniforms_AA =
"uniform float boundaryWidth;\n"
- "uniform float inverseBoundaryWidth;\n";
+ "uniform float inverseBoundaryWidth;\n"
+ "uniform float boundaryLength;\n"
+ "uniform float inverseBoundaryLength;\n";
const char* gFS_Header_Uniforms_PointHasBitmap =
"uniform vec2 textureDimension;\n"
"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",
@@ -181,11 +193,16 @@ const char* gFS_Main_FetchColor =
" fragColor = color;\n";
const char* gFS_Main_ModulateColor =
" fragColor *= color.a;\n";
-const char* gFS_Main_AccountForWidth =
- " if (distance < boundaryWidth) {\n"
- " fragColor *= (distance * inverseBoundaryWidth);\n"
- " } else if (distance > (1.0 - boundaryWidth)) {\n"
- " fragColor *= ((1.0 - distance) * inverseBoundaryWidth);\n"
+const char* gFS_Main_AccountForAA =
+ " if (widthProportion < boundaryWidth) {\n"
+ " fragColor *= (widthProportion * inverseBoundaryWidth);\n"
+ " } else if (widthProportion > (1.0 - boundaryWidth)) {\n"
+ " fragColor *= ((1.0 - widthProportion) * inverseBoundaryWidth);\n"
+ " }\n"
+ " if (lengthProportion < boundaryLength) {\n"
+ " fragColor *= (lengthProportion * inverseBoundaryLength);\n"
+ " } else if (lengthProportion > (1.0 - boundaryLength)) {\n"
+ " fragColor *= ((1.0 - lengthProportion) * inverseBoundaryLength);\n"
" }\n";
const char* gFS_Main_FetchTexture[2] = {
// Don't modulate
@@ -369,14 +386,17 @@ 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) {
- shader.append(gVS_Header_Attributes_Distance);
+ if (description.isAA) {
+ shader.append(gVS_Header_Attributes_AAParameters);
}
// Uniforms
shader.append(gVS_Header_Uniforms);
+ if (description.hasTextureTransform) {
+ shader.append(gVS_Header_Uniforms_TextureTransform);
+ }
if (description.hasGradient) {
shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]);
}
@@ -387,11 +407,11 @@ 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) {
- shader.append(gVS_Header_Varyings_HasWidth);
+ if (description.isAA) {
+ shader.append(gVS_Header_Varyings_IsAA);
}
if (description.hasGradient) {
shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
@@ -404,11 +424,13 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
// Begin the shader
shader.append(gVS_Main); {
- if (description.hasTexture) {
+ if (description.hasTextureTransform) {
+ shader.append(gVS_Main_OutTransformedTexCoords);
+ } else if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Main_OutTexCoords);
}
- if (description.hasWidth) {
- shader.append(gVS_Main_Width);
+ if (description.isAA) {
+ shader.append(gVS_Main_AA);
}
if (description.hasGradient) {
shader.append(gVS_Main_OutGradient[description.gradientType]);
@@ -440,15 +462,18 @@ 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) {
- shader.append(gVS_Header_Varyings_HasWidth);
+ if (description.isAA) {
+ shader.append(gVS_Header_Varyings_IsAA);
}
if (description.hasGradient) {
shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
@@ -461,7 +486,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) {
@@ -470,9 +495,11 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
}
if (description.hasTexture) {
shader.append(gFS_Uniforms_TextureSampler);
+ } else if (description.hasExternalTexture) {
+ shader.append(gFS_Uniforms_ExternalTextureSampler);
}
- if (description.hasWidth) {
- shader.append(gFS_Uniforms_Width);
+ if (description.isAA) {
+ shader.append(gFS_Uniforms_AA);
}
if (description.hasGradient) {
shader.append(gFS_Uniforms_GradientSampler[description.gradientType]);
@@ -482,16 +509,16 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
}
// Optimization for common cases
- if (!description.hasWidth && !blendFramebuffer &&
+ if (!description.isAA && !blendFramebuffer &&
description.colorOp == ProgramDescription::kColorNone && !description.isPoint) {
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 +581,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]);
@@ -567,8 +594,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
shader.append(gFS_Main_FetchColor);
}
}
- if (description.hasWidth) {
- shader.append(gFS_Main_AccountForWidth);
+ if (description.isAA) {
+ shader.append(gFS_Main_AccountForAA);
}
if (description.hasGradient) {
shader.append(gFS_Main_FetchGradient[description.gradientType]);
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 18d98cb..5c7197b 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -75,7 +75,10 @@ namespace uirenderer {
#define PROGRAM_IS_POINT_SHIFT 36
-#define PROGRAM_HAS_WIDTH_SHIFT 37
+#define PROGRAM_HAS_AA_SHIFT 37
+
+#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
+#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
///////////////////////////////////////////////////////////////////////////////
// Types
@@ -113,6 +116,8 @@ struct ProgramDescription {
// Texturing
bool hasTexture;
bool hasAlpha8Texture;
+ bool hasExternalTexture;
+ bool hasTextureTransform;
// Modulate, this should only be set when setColor() return true
bool modulate;
@@ -121,7 +126,7 @@ struct ProgramDescription {
bool hasBitmap;
bool isBitmapNpot;
- bool hasWidth;
+ bool isAA;
bool hasGradient;
Gradient gradientType;
@@ -151,8 +156,10 @@ struct ProgramDescription {
void reset() {
hasTexture = false;
hasAlpha8Texture = false;
+ hasExternalTexture = false;
+ hasTextureTransform = false;
- hasWidth = false;
+ isAA = false;
modulate = false;
@@ -239,7 +246,9 @@ struct ProgramDescription {
if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
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 (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
+ if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
+ if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
return key;
}
diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h
index c120428..38455dc 100644
--- a/libs/hwui/Vertex.h
+++ b/libs/hwui/Vertex.h
@@ -68,6 +68,25 @@ struct AlphaVertex : Vertex {
}
}; // struct AlphaVertex
+/**
+ * Simple structure to describe a vertex with a position and an alpha value.
+ */
+struct AAVertex : Vertex {
+ float width;
+ float length;
+
+ static inline void set(AAVertex* vertex, float x, float y, float width, float length) {
+ Vertex::set(vertex, x, y);
+ vertex[0].width = width;
+ vertex[0].length = length;
+ }
+
+ static inline void setColor(AAVertex* vertex, float width, float length) {
+ vertex[0].width = width;
+ vertex[0].length = length;
+ }
+}; // struct AlphaVertex
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index a99a599..232ab36 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -110,20 +110,23 @@ LOCAL_SRC_FILES:= \
rsScriptC.cpp \
rsScriptC_Lib.cpp \
rsScriptC_LibGL.cpp \
- rsShaderCache.cpp \
rsSignal.cpp \
rsStream.cpp \
rsThreadIO.cpp \
rsType.cpp \
- rsVertexArray.cpp \
driver/rsdBcc.cpp \
driver/rsdCore.cpp \
driver/rsdGL.cpp \
+ driver/rsdMesh.cpp \
+ driver/rsdMeshObj.cpp \
+ driver/rsdProgram.cpp \
driver/rsdProgramRaster.cpp \
driver/rsdProgramStore.cpp \
driver/rsdRuntimeMath.cpp \
- driver/rsdRuntimeStubs.cpp
-
+ driver/rsdRuntimeStubs.cpp \
+ driver/rsdShader.cpp \
+ driver/rsdShaderCache.cpp \
+ driver/rsdVertexArray.cpp
LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc
diff --git a/libs/rs/driver/rsdCore.cpp b/libs/rs/driver/rsdCore.cpp
index 5b80439..d5d23c7 100644
--- a/libs/rs/driver/rsdCore.cpp
+++ b/libs/rs/driver/rsdCore.cpp
@@ -19,6 +19,9 @@
#include "rsdGL.h"
#include "rsdProgramStore.h"
#include "rsdProgramRaster.h"
+#include "rsdProgramVertex.h"
+#include "rsdProgramFragment.h"
+#include "rsdMesh.h"
#include <malloc.h>
#include "rsContext.h"
@@ -69,6 +72,24 @@ static RsdHalFunctions FunctionTable = {
rsdProgramRasterInit,
rsdProgramRasterSetActive,
rsdProgramRasterDestroy
+ },
+
+ {
+ rsdProgramVertexInit,
+ rsdProgramVertexSetActive,
+ rsdProgramVertexDestroy
+ },
+
+ {
+ rsdProgramFragmentInit,
+ rsdProgramFragmentSetActive,
+ rsdProgramFragmentDestroy
+ },
+
+ {
+ rsdMeshInit,
+ rsdMeshDraw,
+ rsdMeshDestroy
}
};
diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp
index 26e1bdf..48690d5 100644
--- a/libs/rs/driver/rsdGL.cpp
+++ b/libs/rs/driver/rsdGL.cpp
@@ -40,6 +40,8 @@
#include <malloc.h>
#include "rsContext.h"
+#include "rsdShaderCache.h"
+#include "rsdVertexArray.h"
using namespace android;
using namespace android::renderscript;
@@ -128,6 +130,11 @@ static void DumpDebug(RsdHal *dc) {
void rsdGLShutdown(const Context *rsc) {
RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ dc->gl.shaderCache->cleanupAll();
+ delete dc->gl.shaderCache;
+
+ delete dc->gl.vertexArrayState;
+
LOGV("%p, deinitEGL", rsc);
if (dc->gl.egl.context != EGL_NO_CONTEXT) {
@@ -287,6 +294,10 @@ bool rsdGLInit(const Context *rsc) {
DumpDebug(dc);
}
+ dc->gl.shaderCache = new RsdShaderCache();
+ dc->gl.vertexArrayState = new RsdVertexArrayState();
+ dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs);
+
LOGV("initGLThread end %p", rsc);
return true;
}
diff --git a/libs/rs/driver/rsdGL.h b/libs/rs/driver/rsdGL.h
index 246931f..351b2d5 100644
--- a/libs/rs/driver/rsdGL.h
+++ b/libs/rs/driver/rsdGL.h
@@ -19,7 +19,8 @@
#include <rs_hal.h>
-
+class RsdShaderCache;
+class RsdVertexArrayState;
typedef void (* InvokeFunc_t)(void);
typedef void (*WorkerCallback_t)(void *usr, uint32_t idx);
@@ -64,6 +65,8 @@ typedef struct RsdGLRec {
ANativeWindow *wndSurface;
uint32_t width;
uint32_t height;
+ RsdShaderCache *shaderCache;
+ RsdVertexArrayState *vertexArrayState;
} RsdGL;
diff --git a/libs/rs/driver/rsdMesh.cpp b/libs/rs/driver/rsdMesh.cpp
new file mode 100644
index 0000000..eb62ddb
--- /dev/null
+++ b/libs/rs/driver/rsdMesh.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+
+#include <rs_hal.h>
+#include <rsContext.h>
+#include <rsMesh.h>
+
+#include "rsdCore.h"
+#include "rsdMesh.h"
+#include "rsdMeshObj.h"
+#include "rsdShaderCache.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+bool rsdMeshInit(const Context *rsc, const Mesh *m) {
+ RsdMeshObj *drv = NULL;
+ if(m->mHal.drv) {
+ drv = (RsdMeshObj*)m->mHal.drv;
+ delete drv;
+ }
+ drv = new RsdMeshObj(rsc, m);
+ m->mHal.drv = drv;
+ return drv->init();
+}
+
+void rsdMeshDraw(const Context *rsc, const Mesh *m, uint32_t primIndex, uint32_t start, uint32_t len) {
+ if(m->mHal.drv) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ if (!dc->gl.shaderCache->setup(rsc)) {
+ return;
+ }
+
+ RsdMeshObj *drv = (RsdMeshObj*)m->mHal.drv;
+ drv->renderPrimitiveRange(rsc, primIndex, start, len);
+ }
+}
+
+void rsdMeshDestroy(const Context *rsc, const Mesh *m) {
+ if(m->mHal.drv) {
+ RsdMeshObj *drv = (RsdMeshObj*)m->mHal.drv;
+ delete drv;
+ }
+}
+
+
diff --git a/libs/rs/driver/rsdMesh.h b/libs/rs/driver/rsdMesh.h
new file mode 100644
index 0000000..d2714fd
--- /dev/null
+++ b/libs/rs/driver/rsdMesh.h
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#ifndef RSD_MESH_H
+#define RSD_MESH_H
+
+#include <rs_hal.h>
+
+
+bool rsdMeshInit(const android::renderscript::Context *rsc,
+ const android::renderscript::Mesh *m);
+void rsdMeshDraw(const android::renderscript::Context *rsc,
+ const android::renderscript::Mesh *m,
+ uint32_t primIndex, uint32_t start, uint32_t len);
+void rsdMeshDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::Mesh *m);
+
+
+#endif
diff --git a/libs/rs/driver/rsdMeshObj.cpp b/libs/rs/driver/rsdMeshObj.cpp
new file mode 100644
index 0000000..6bb33f7
--- /dev/null
+++ b/libs/rs/driver/rsdMeshObj.cpp
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+#include <GLES/glext.h>
+
+#include <rs_hal.h>
+#include <rsContext.h>
+#include <rsMesh.h>
+
+#include "rsdMeshObj.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+RsdMeshObj::RsdMeshObj(const Context *rsc, const Mesh *rsMesh) {
+ mRSMesh = rsMesh;
+
+ mAttribs = NULL;
+ mAttribAllocationIndex = NULL;
+ mGLPrimitives = NULL;
+
+ mAttribCount = 0;
+}
+
+RsdMeshObj::~RsdMeshObj() {
+ if (mAttribs) {
+ delete[] mAttribs;
+ delete[] mAttribAllocationIndex;
+ }
+ if (mGLPrimitives) {
+ delete[] mGLPrimitives;
+ }
+}
+
+bool RsdMeshObj::isValidGLComponent(const Element *elem, uint32_t fieldIdx) {
+ // Do not create attribs for padding
+ if (elem->getFieldName(fieldIdx)[0] == '#') {
+ return false;
+ }
+
+ // Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted.
+ // Filter rs types accordingly
+ RsDataType dt = elem->getField(fieldIdx)->getComponent().getType();
+ if (dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 &&
+ dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 &&
+ dt != RS_TYPE_SIGNED_16) {
+ return false;
+ }
+
+ // Now make sure they are not arrays
+ uint32_t arraySize = elem->getFieldArraySize(fieldIdx);
+ if (arraySize != 1) {
+ return false;
+ }
+
+ return true;
+}
+
+bool RsdMeshObj::init() {
+
+ updateGLPrimitives();
+
+ // Count the number of gl attrs to initialize
+ mAttribCount = 0;
+ for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
+ const Element *elem = mRSMesh->mHal.state.vertexBuffers[ct]->getType()->getElement();
+ for (uint32_t ct=0; ct < elem->getFieldCount(); ct++) {
+ if (isValidGLComponent(elem, ct)) {
+ mAttribCount ++;
+ }
+ }
+ }
+
+ if (mAttribs) {
+ delete [] mAttribs;
+ delete [] mAttribAllocationIndex;
+ mAttribs = NULL;
+ mAttribAllocationIndex = NULL;
+ }
+ if (!mAttribCount) {
+ return false;
+ }
+
+ mAttribs = new RsdVertexArray::Attrib[mAttribCount];
+ mAttribAllocationIndex = new uint32_t[mAttribCount];
+
+ uint32_t userNum = 0;
+ for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
+ const Element *elem = mRSMesh->mHal.state.vertexBuffers[ct]->getType()->getElement();
+ uint32_t stride = elem->getSizeBytes();
+ for (uint32_t fieldI=0; fieldI < elem->getFieldCount(); fieldI++) {
+ const Component &c = elem->getField(fieldI)->getComponent();
+
+ if (!isValidGLComponent(elem, fieldI)) {
+ continue;
+ }
+
+ mAttribs[userNum].size = c.getVectorSize();
+ mAttribs[userNum].offset = elem->getFieldOffsetBytes(fieldI);
+ mAttribs[userNum].type = c.getGLType();
+ mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized();
+ mAttribs[userNum].stride = stride;
+ String8 tmp(RS_SHADER_ATTR);
+ tmp.append(elem->getFieldName(fieldI));
+ mAttribs[userNum].name.setTo(tmp.string());
+
+ // Remember which allocation this attribute came from
+ mAttribAllocationIndex[userNum] = ct;
+ userNum ++;
+ }
+ }
+
+ return true;
+}
+
+void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const {
+ if (len < 1 || primIndex >= mRSMesh->mHal.state.primitivesCount || mAttribCount == 0) {
+ LOGE("Invalid mesh or parameters");
+ return;
+ }
+
+ rsc->checkError("Mesh::renderPrimitiveRange 1");
+ // update attributes with either buffer information or data ptr based on their current state
+ for (uint32_t ct=0; ct < mAttribCount; ct++) {
+ uint32_t allocIndex = mAttribAllocationIndex[ct];
+ Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[allocIndex].get();
+ if (alloc->getIsBufferObject() && alloc->getBufferObjectID()) {
+ mAttribs[ct].buffer = alloc->getBufferObjectID();
+ mAttribs[ct].ptr = NULL;
+ } else {
+ mAttribs[ct].buffer = 0;
+ mAttribs[ct].ptr = (const uint8_t*)alloc->getPtr();
+ }
+ }
+
+ RsdVertexArray va(mAttribs, mAttribCount);
+ va.setupGL2(rsc);
+
+ rsc->checkError("Mesh::renderPrimitiveRange 2");
+ Mesh::Primitive_t *prim = mRSMesh->mHal.state.primitives[primIndex];
+ if (prim->mIndexBuffer.get()) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prim->mIndexBuffer->getBufferObjectID());
+ glDrawElements(mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT, (uint16_t *)(start * 2));
+ } else {
+ glDrawArrays(mGLPrimitives[primIndex], start, len);
+ }
+
+ rsc->checkError("Mesh::renderPrimitiveRange");
+}
+
+void RsdMeshObj::updateGLPrimitives() {
+ mGLPrimitives = new uint32_t[mRSMesh->mHal.state.primitivesCount];
+ for (uint32_t i = 0; i < mRSMesh->mHal.state.primitivesCount; i ++) {
+ switch (mRSMesh->mHal.state.primitives[i]->mPrimitive) {
+ case RS_PRIMITIVE_POINT: mGLPrimitives[i] = GL_POINTS; break;
+ case RS_PRIMITIVE_LINE: mGLPrimitives[i] = GL_LINES; break;
+ case RS_PRIMITIVE_LINE_STRIP: mGLPrimitives[i] = GL_LINE_STRIP; break;
+ case RS_PRIMITIVE_TRIANGLE: mGLPrimitives[i] = GL_TRIANGLES; break;
+ case RS_PRIMITIVE_TRIANGLE_STRIP: mGLPrimitives[i] = GL_TRIANGLE_STRIP; break;
+ case RS_PRIMITIVE_TRIANGLE_FAN: mGLPrimitives[i] = GL_TRIANGLE_FAN; break;
+ }
+ }
+}
diff --git a/libs/rs/driver/rsdMeshObj.h b/libs/rs/driver/rsdMeshObj.h
new file mode 100644
index 0000000..8b1271b
--- /dev/null
+++ b/libs/rs/driver/rsdMeshObj.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_RSD_MESH_OBJ_H
+#define ANDROID_RSD_MESH_OBJ_H
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+ class Context;
+ class Mesh;
+ class Element;
+
+}
+}
+
+#include "driver/rsdVertexArray.h"
+
+// An element is a group of Components that occupies one cell in a structure.
+class RsdMeshObj {
+public:
+ RsdMeshObj(const android::renderscript::Context *,
+ const android::renderscript::Mesh *);
+ ~RsdMeshObj();
+
+ void renderPrimitiveRange(const android::renderscript::Context *, uint32_t primIndex, uint32_t start, uint32_t len) const;
+
+ bool init();
+
+protected:
+ const android::renderscript::Mesh *mRSMesh;
+
+ uint32_t *mGLPrimitives;
+ void updateGLPrimitives();
+
+ bool isValidGLComponent(const android::renderscript::Element *elem, uint32_t fieldIdx);
+ // Attribues that allow us to map to GL
+ RsdVertexArray::Attrib *mAttribs;
+ // This allows us to figure out which allocation the attribute
+ // belongs to. In the event the allocation is uploaded to GL
+ // buffer, it lets us properly map it
+ uint32_t *mAttribAllocationIndex;
+ uint32_t mAttribCount;
+};
+
+#endif //ANDROID_RSD_MESH_OBJ_H
+
+
+
diff --git a/libs/rs/driver/rsdProgram.cpp b/libs/rs/driver/rsdProgram.cpp
new file mode 100644
index 0000000..502c5ee
--- /dev/null
+++ b/libs/rs/driver/rsdProgram.cpp
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+
+#include "rsdCore.h"
+#include "rsdProgramVertex.h"
+#include "rsdShader.h"
+#include "rsdShaderCache.h"
+
+#include "rsContext.h"
+#include "rsProgramVertex.h"
+#include "rsProgramFragment.h"
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+bool rsdProgramVertexInit(const Context *rsc, const ProgramVertex *pv,
+ const char* shader, uint32_t shaderLen) {
+ RsdShader *drv = new RsdShader(pv, GL_VERTEX_SHADER, shader, shaderLen);
+ pv->mHal.drv = drv;
+
+ return drv->createShader();
+}
+
+void rsdProgramVertexSetActive(const Context *rsc, const ProgramVertex *pv) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ dc->gl.shaderCache->setActiveVertex((RsdShader*)pv->mHal.drv);
+}
+
+void rsdProgramVertexDestroy(const Context *rsc, const ProgramVertex *pv) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ RsdShader *drv = NULL;
+ if(pv->mHal.drv) {
+ drv = (RsdShader*)pv->mHal.drv;
+ if (rsc->props.mLogShaders) {
+ LOGV("Destroying vertex shader with ID %u", drv->getShaderID());
+ }
+ if (drv->getShaderID()) {
+ dc->gl.shaderCache->cleanupVertex(drv->getShaderID());
+ }
+ delete drv;
+ }
+}
+
+bool rsdProgramFragmentInit(const Context *rsc, const ProgramFragment *pf,
+ const char* shader, uint32_t shaderLen) {
+ RsdShader *drv = new RsdShader(pf, GL_FRAGMENT_SHADER, shader, shaderLen);
+ pf->mHal.drv = drv;
+
+ return drv->createShader();
+}
+
+void rsdProgramFragmentSetActive(const Context *rsc, const ProgramFragment *pf) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ dc->gl.shaderCache->setActiveFragment((RsdShader*)pf->mHal.drv);
+}
+
+void rsdProgramFragmentDestroy(const Context *rsc, const ProgramFragment *pf) {
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+ RsdShader *drv = NULL;
+ if(pf->mHal.drv) {
+ drv = (RsdShader*)pf->mHal.drv;
+ if (rsc->props.mLogShaders) {
+ LOGV("Destroying fragment shader with ID %u", drv->getShaderID());
+ }
+ if (drv->getShaderID()) {
+ dc->gl.shaderCache->cleanupFragment(drv->getShaderID());
+ }
+ delete drv;
+ }
+}
+
+
diff --git a/libs/rs/driver/rsdProgramFragment.h b/libs/rs/driver/rsdProgramFragment.h
new file mode 100644
index 0000000..366cb40
--- /dev/null
+++ b/libs/rs/driver/rsdProgramFragment.h
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#ifndef RSD_PROGRAM_FRAGMENT_H
+#define RSD_PROGRAM_FRAGMENT_H
+
+#include <rs_hal.h>
+
+
+bool rsdProgramFragmentInit(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramFragment *,
+ const char* shader, uint32_t shaderLen);
+void rsdProgramFragmentSetActive(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramFragment *);
+void rsdProgramFragmentDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramFragment *);
+
+
+#endif //RSD_PROGRAM_Fragment_H
diff --git a/libs/rs/driver/rsdProgramVertex.h b/libs/rs/driver/rsdProgramVertex.h
new file mode 100644
index 0000000..e998572
--- /dev/null
+++ b/libs/rs/driver/rsdProgramVertex.h
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#ifndef RSD_PROGRAM_VERTEX_H
+#define RSD_PROGRAM_VERTEX_H
+
+#include <rs_hal.h>
+
+bool rsdProgramVertexInit(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramVertex *,
+ const char* shader, uint32_t shaderLen);
+void rsdProgramVertexSetActive(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramVertex *);
+void rsdProgramVertexDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::ProgramVertex *);
+
+
+#endif //RSD_PROGRAM_VERTEX_H
diff --git a/libs/rs/driver/rsdRuntimeMath.cpp b/libs/rs/driver/rsdRuntimeMath.cpp
index 093e311..acb990d 100644
--- a/libs/rs/driver/rsdRuntimeMath.cpp
+++ b/libs/rs/driver/rsdRuntimeMath.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp
index b70a123..9cbff95 100644
--- a/libs/rs/driver/rsdRuntimeStubs.cpp
+++ b/libs/rs/driver/rsdRuntimeStubs.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
diff --git a/libs/rs/driver/rsdShader.cpp b/libs/rs/driver/rsdShader.cpp
new file mode 100644
index 0000000..fc623d6
--- /dev/null
+++ b/libs/rs/driver/rsdShader.cpp
@@ -0,0 +1,468 @@
+/*
+ * 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.
+ */
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <rs_hal.h>
+#include <rsContext.h>
+#include <rsProgram.h>
+
+#include "rsdShader.h"
+#include "rsdShaderCache.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+RsdShader::RsdShader(const Program *p, uint32_t type,
+ const char * shaderText, uint32_t shaderLength) {
+
+ mUserShader.setTo(shaderText, shaderLength);
+ mRSProgram = p;
+ mType = type;
+ initMemberVars();
+ initAttribAndUniformArray();
+ init();
+}
+
+RsdShader::~RsdShader() {
+ if (mShaderID) {
+ glDeleteShader(mShaderID);
+ }
+
+ delete[] mAttribNames;
+ delete[] mUniformNames;
+ delete[] mUniformArraySizes;
+}
+
+void RsdShader::initMemberVars() {
+ mDirty = true;
+ mShaderID = 0;
+ mAttribCount = 0;
+ mUniformCount = 0;
+
+ mAttribNames = NULL;
+ mUniformNames = NULL;
+ mUniformArraySizes = NULL;
+
+ mIsValid = false;
+}
+
+void RsdShader::init() {
+ uint32_t attribCount = 0;
+ uint32_t uniformCount = 0;
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
+ initAddUserElement(mRSProgram->mHal.state.inputElements[ct].get(), mAttribNames, NULL, &attribCount, RS_SHADER_ATTR);
+ }
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
+ initAddUserElement(mRSProgram->mHal.state.constantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI);
+ }
+
+ mTextureUniformIndexStart = uniformCount;
+ char buf[256];
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.texturesCount; ct++) {
+ snprintf(buf, sizeof(buf), "UNI_Tex%i", ct);
+ mUniformNames[uniformCount].setTo(buf);
+ mUniformArraySizes[uniformCount] = 1;
+ uniformCount++;
+ }
+}
+
+String8 RsdShader::getGLSLInputString() const {
+ String8 s;
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
+ const Element *e = mRSProgram->mHal.state.inputElements[ct].get();
+ for (uint32_t field=0; field < e->getFieldCount(); field++) {
+ const Element *f = e->getField(field);
+
+ // Cannot be complex
+ rsAssert(!f->getFieldCount());
+ switch (f->getComponent().getVectorSize()) {
+ case 1: s.append("attribute float ATTRIB_"); break;
+ case 2: s.append("attribute vec2 ATTRIB_"); break;
+ case 3: s.append("attribute vec3 ATTRIB_"); break;
+ case 4: s.append("attribute vec4 ATTRIB_"); break;
+ default:
+ rsAssert(0);
+ }
+
+ s.append(e->getFieldName(field));
+ s.append(";\n");
+ }
+ }
+ return s;
+}
+
+void RsdShader::appendAttributes() {
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
+ const Element *e = mRSProgram->mHal.state.inputElements[ct].get();
+ for (uint32_t field=0; field < e->getFieldCount(); field++) {
+ const Element *f = e->getField(field);
+ const char *fn = e->getFieldName(field);
+
+ if (fn[0] == '#') {
+ continue;
+ }
+
+ // Cannot be complex
+ rsAssert(!f->getFieldCount());
+ switch (f->getComponent().getVectorSize()) {
+ case 1: mShader.append("attribute float ATTRIB_"); break;
+ case 2: mShader.append("attribute vec2 ATTRIB_"); break;
+ case 3: mShader.append("attribute vec3 ATTRIB_"); break;
+ case 4: mShader.append("attribute vec4 ATTRIB_"); break;
+ default:
+ rsAssert(0);
+ }
+
+ mShader.append(fn);
+ mShader.append(";\n");
+ }
+ }
+}
+
+void RsdShader::appendTextures() {
+ char buf[256];
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.texturesCount; ct++) {
+ if (mRSProgram->mHal.state.textureTargets[ct] == RS_TEXTURE_2D) {
+ snprintf(buf, sizeof(buf), "uniform sampler2D UNI_Tex%i;\n", ct);
+ } else {
+ snprintf(buf, sizeof(buf), "uniform samplerCube UNI_Tex%i;\n", ct);
+ }
+ mShader.append(buf);
+ }
+}
+
+bool RsdShader::createShader() {
+
+ if (mType == GL_FRAGMENT_SHADER) {
+ mShader.append("precision mediump float;\n");
+ }
+ appendUserConstants();
+ appendAttributes();
+ appendTextures();
+
+ mShader.append(mUserShader);
+
+ return true;
+}
+
+bool RsdShader::loadShader(const Context *rsc) {
+ mShaderID = glCreateShader(mType);
+ rsAssert(mShaderID);
+
+ if (rsc->props.mLogShaders) {
+ LOGV("Loading shader type %x, ID %i", mType, mShaderID);
+ LOGV("%s", mShader.string());
+ }
+
+ if (mShaderID) {
+ const char * ss = mShader.string();
+ glShaderSource(mShaderID, 1, &ss, NULL);
+ glCompileShader(mShaderID);
+
+ GLint compiled = 0;
+ glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
+ if (!compiled) {
+ GLint infoLen = 0;
+ glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen) {
+ char* buf = (char*) malloc(infoLen);
+ if (buf) {
+ glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
+ LOGE("Could not compile shader \n%s\n", buf);
+ free(buf);
+ }
+ glDeleteShader(mShaderID);
+ mShaderID = 0;
+ rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
+ return false;
+ }
+ }
+ }
+
+ if (rsc->props.mLogShaders) {
+ LOGV("--Shader load result %x ", glGetError());
+ }
+ mIsValid = true;
+ return true;
+}
+
+void RsdShader::appendUserConstants() {
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
+ const Element *e = mRSProgram->mHal.state.constantTypes[ct]->getElement();
+ for (uint32_t field=0; field < e->getFieldCount(); field++) {
+ const Element *f = e->getField(field);
+ const char *fn = e->getFieldName(field);
+
+ if (fn[0] == '#') {
+ continue;
+ }
+
+ // Cannot be complex
+ rsAssert(!f->getFieldCount());
+ if (f->getType() == RS_TYPE_MATRIX_4X4) {
+ mShader.append("uniform mat4 UNI_");
+ } else if (f->getType() == RS_TYPE_MATRIX_3X3) {
+ mShader.append("uniform mat3 UNI_");
+ } else if (f->getType() == RS_TYPE_MATRIX_2X2) {
+ mShader.append("uniform mat2 UNI_");
+ } else {
+ switch (f->getComponent().getVectorSize()) {
+ case 1: mShader.append("uniform float UNI_"); break;
+ case 2: mShader.append("uniform vec2 UNI_"); break;
+ case 3: mShader.append("uniform vec3 UNI_"); break;
+ case 4: mShader.append("uniform vec4 UNI_"); break;
+ default:
+ rsAssert(0);
+ }
+ }
+
+ mShader.append(fn);
+ if (e->getFieldArraySize(field) > 1) {
+ mShader.appendFormat("[%d]", e->getFieldArraySize(field));
+ }
+ mShader.append(";\n");
+ }
+ }
+}
+
+void RsdShader::logUniform(const Element *field, const float *fd, uint32_t arraySize ) {
+ RsDataType dataType = field->getType();
+ uint32_t elementSize = field->getSizeBytes() / sizeof(float);
+ for (uint32_t i = 0; i < arraySize; i ++) {
+ if (arraySize > 1) {
+ LOGV("Array Element [%u]", i);
+ }
+ if (dataType == RS_TYPE_MATRIX_4X4) {
+ LOGV("Matrix4x4");
+ LOGV("{%f, %f, %f, %f", fd[0], fd[4], fd[8], fd[12]);
+ LOGV(" %f, %f, %f, %f", fd[1], fd[5], fd[9], fd[13]);
+ LOGV(" %f, %f, %f, %f", fd[2], fd[6], fd[10], fd[14]);
+ LOGV(" %f, %f, %f, %f}", fd[3], fd[7], fd[11], fd[15]);
+ } else if (dataType == RS_TYPE_MATRIX_3X3) {
+ LOGV("Matrix3x3");
+ LOGV("{%f, %f, %f", fd[0], fd[3], fd[6]);
+ LOGV(" %f, %f, %f", fd[1], fd[4], fd[7]);
+ LOGV(" %f, %f, %f}", fd[2], fd[5], fd[8]);
+ } else if (dataType == RS_TYPE_MATRIX_2X2) {
+ LOGV("Matrix2x2");
+ LOGV("{%f, %f", fd[0], fd[2]);
+ LOGV(" %f, %f}", fd[1], fd[3]);
+ } else {
+ switch (field->getComponent().getVectorSize()) {
+ case 1:
+ LOGV("Uniform 1 = %f", fd[0]);
+ break;
+ case 2:
+ LOGV("Uniform 2 = %f %f", fd[0], fd[1]);
+ break;
+ case 3:
+ LOGV("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
+ break;
+ case 4:
+ LOGV("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
+ break;
+ default:
+ rsAssert(0);
+ }
+ }
+ LOGE("Element size %u data=%p", elementSize, fd);
+ fd += elementSize;
+ LOGE("New data=%p", fd);
+ }
+}
+
+void RsdShader::setUniform(const Context *rsc, const Element *field, const float *fd,
+ int32_t slot, uint32_t arraySize ) {
+ RsDataType dataType = field->getType();
+ if (dataType == RS_TYPE_MATRIX_4X4) {
+ glUniformMatrix4fv(slot, arraySize, GL_FALSE, fd);
+ } else if (dataType == RS_TYPE_MATRIX_3X3) {
+ glUniformMatrix3fv(slot, arraySize, GL_FALSE, fd);
+ } else if (dataType == RS_TYPE_MATRIX_2X2) {
+ glUniformMatrix2fv(slot, arraySize, GL_FALSE, fd);
+ } else {
+ switch (field->getComponent().getVectorSize()) {
+ case 1:
+ glUniform1fv(slot, arraySize, fd);
+ break;
+ case 2:
+ glUniform2fv(slot, arraySize, fd);
+ break;
+ case 3:
+ glUniform3fv(slot, arraySize, fd);
+ break;
+ case 4:
+ glUniform4fv(slot, arraySize, fd);
+ break;
+ default:
+ rsAssert(0);
+ }
+ }
+}
+
+void RsdShader::setupTextures(const Context *rsc, RsdShaderCache *sc) {
+ if (mRSProgram->mHal.state.texturesCount == 0) {
+ return;
+ }
+
+ uint32_t numTexturesToBind = mRSProgram->mHal.state.texturesCount;
+ uint32_t numTexturesAvailable = rsc->getMaxFragmentTextures();
+ if (numTexturesToBind >= numTexturesAvailable) {
+ LOGE("Attempting to bind %u textures on shader id %u, but only %u are available",
+ mRSProgram->mHal.state.texturesCount, (uint32_t)this, numTexturesAvailable);
+ rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind more textuers than available");
+ numTexturesToBind = numTexturesAvailable;
+ }
+
+ for (uint32_t ct=0; ct < numTexturesToBind; ct++) {
+ glActiveTexture(GL_TEXTURE0 + ct);
+ if (!mRSProgram->mHal.state.textures[ct].get()) {
+ LOGE("No texture bound for shader id %u, texture unit %u", (uint)this, ct);
+ rsc->setError(RS_ERROR_BAD_SHADER, "No texture bound");
+ continue;
+ }
+
+ GLenum target = (GLenum)mRSProgram->mHal.state.textures[ct]->getGLTarget();
+ if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) {
+ LOGE("Attempting to bind unknown texture to shader id %u, texture unit %u", (uint)this, ct);
+ rsc->setError(RS_ERROR_BAD_SHADER, "Non-texture allocation bound to a shader");
+ }
+ glBindTexture(target, mRSProgram->mHal.state.textures[ct]->getTextureID());
+ rsc->checkError("ProgramFragment::setupGL2 tex bind");
+ if (mRSProgram->mHal.state.samplers[ct].get()) {
+ mRSProgram->mHal.state.samplers[ct]->setupGL(rsc, mRSProgram->mHal.state.textures[ct].get());
+ } else {
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ rsc->checkError("ProgramFragment::setupGL2 tex env");
+ }
+
+ glUniform1i(sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct);
+ rsc->checkError("ProgramFragment::setupGL2 uniforms");
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ mDirty = false;
+ rsc->checkError("ProgramFragment::setupGL2");
+}
+
+void RsdShader::setupUserConstants(const Context *rsc, RsdShaderCache *sc, bool isFragment) {
+ uint32_t uidx = 0;
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
+ Allocation *alloc = mRSProgram->mHal.state.constants[ct].get();
+ if (!alloc) {
+ LOGE("Attempting to set constants on shader id %u, but alloc at slot %u is not set", (uint32_t)this, ct);
+ rsc->setError(RS_ERROR_BAD_SHADER, "No constant allocation bound");
+ continue;
+ }
+
+ const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
+ const Element *e = mRSProgram->mHal.state.constantTypes[ct]->getElement();
+ for (uint32_t field=0; field < e->getFieldCount(); field++) {
+ const Element *f = e->getField(field);
+ const char *fieldName = e->getFieldName(field);
+ // If this field is padding, skip it
+ if (fieldName[0] == '#') {
+ continue;
+ }
+
+ uint32_t offset = e->getFieldOffsetBytes(field);
+ const float *fd = reinterpret_cast<const float *>(&data[offset]);
+
+ int32_t slot = -1;
+ uint32_t arraySize = 1;
+ if (!isFragment) {
+ slot = sc->vtxUniformSlot(uidx);
+ arraySize = sc->vtxUniformSize(uidx);
+ } else {
+ slot = sc->fragUniformSlot(uidx);
+ arraySize = sc->fragUniformSize(uidx);
+ }
+ if (rsc->props.mLogShadersUniforms) {
+ LOGV("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName);
+ }
+ uidx ++;
+ if (slot < 0) {
+ continue;
+ }
+
+ if (rsc->props.mLogShadersUniforms) {
+ logUniform(f, fd, arraySize);
+ }
+ setUniform(rsc, f, fd, slot, arraySize);
+ }
+ }
+}
+
+void RsdShader::setup(const android::renderscript::Context *rsc, RsdShaderCache *sc) {
+
+ setupUserConstants(rsc, sc, mType == GL_FRAGMENT_SHADER);
+ setupTextures(rsc, sc);
+}
+
+void RsdShader::initAttribAndUniformArray() {
+ mAttribCount = 0;
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
+ const Element *elem = mRSProgram->mHal.state.inputElements[ct].get();
+ for (uint32_t field=0; field < elem->getFieldCount(); field++) {
+ if (elem->getFieldName(field)[0] != '#') {
+ mAttribCount ++;
+ }
+ }
+ }
+
+ mUniformCount = 0;
+ for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
+ const Element *elem = mRSProgram->mHal.state.constantTypes[ct]->getElement();
+
+ for (uint32_t field=0; field < elem->getFieldCount(); field++) {
+ if (elem->getFieldName(field)[0] != '#') {
+ mUniformCount ++;
+ }
+ }
+ }
+ mUniformCount += mRSProgram->mHal.state.texturesCount;
+
+ if (mAttribCount) {
+ mAttribNames = new String8[mAttribCount];
+ }
+ if (mUniformCount) {
+ mUniformNames = new String8[mUniformCount];
+ mUniformArraySizes = new uint32_t[mUniformCount];
+ }
+}
+
+void RsdShader::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix) {
+ rsAssert(e->getFieldCount());
+ for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
+ const Element *ce = e->getField(ct);
+ if (ce->getFieldCount()) {
+ initAddUserElement(ce, names, arrayLengths, count, prefix);
+ } else if (e->getFieldName(ct)[0] != '#') {
+ String8 tmp(prefix);
+ tmp.append(e->getFieldName(ct));
+ names[*count].setTo(tmp.string());
+ if (arrayLengths) {
+ arrayLengths[*count] = e->getFieldArraySize(ct);
+ }
+ (*count)++;
+ }
+ }
+}
diff --git a/libs/rs/driver/rsdShader.h b/libs/rs/driver/rsdShader.h
new file mode 100644
index 0000000..37b1c3d
--- /dev/null
+++ b/libs/rs/driver/rsdShader.h
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_RSD_SHADER_H
+#define ANDROID_RSD_SHADER_H
+
+#include <utils/String8.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+class Element;
+class Context;
+class Program;
+
+}
+}
+
+class RsdShaderCache;
+
+#define RS_SHADER_ATTR "ATTRIB_"
+#define RS_SHADER_UNI "UNI_"
+
+class RsdShader {
+public:
+
+ RsdShader(const android::renderscript::Program *p, uint32_t type,
+ const char * shaderText, uint32_t shaderLength);
+ virtual ~RsdShader();
+
+ bool createShader();
+
+ uint32_t getShaderID() const {return mShaderID;}
+
+ uint32_t getAttribCount() const {return mAttribCount;}
+ uint32_t getUniformCount() const {return mUniformCount;}
+ const android::String8 & getAttribName(uint32_t i) const {return mAttribNames[i];}
+ const android::String8 & getUniformName(uint32_t i) const {return mUniformNames[i];}
+ uint32_t getUniformArraySize(uint32_t i) const {return mUniformArraySizes[i];}
+
+ android::String8 getGLSLInputString() const;
+
+ bool isValid() const {return mIsValid;}
+ void forceDirty() const {mDirty = true;}
+
+ bool loadShader(const android::renderscript::Context *);
+ void setup(const android::renderscript::Context *, RsdShaderCache *sc);
+
+protected:
+
+ const android::renderscript::Program *mRSProgram;
+ bool mIsValid;
+
+ // Applies to vertex and fragment shaders only
+ void appendUserConstants();
+ void setupUserConstants(const android::renderscript::Context *rsc, RsdShaderCache *sc, bool isFragment);
+ void initAddUserElement(const android::renderscript::Element *e, android::String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix);
+ void setupTextures(const android::renderscript::Context *rsc, RsdShaderCache *sc);
+
+ void appendAttributes();
+ void appendTextures();
+
+ void initAttribAndUniformArray();
+
+ mutable bool mDirty;
+ android::String8 mShader;
+ android::String8 mUserShader;
+ uint32_t mShaderID;
+ uint32_t mType;
+
+ uint32_t mTextureCount;
+ uint32_t mAttribCount;
+ uint32_t mUniformCount;
+ android::String8 *mAttribNames;
+ android::String8 *mUniformNames;
+ uint32_t *mUniformArraySizes;
+
+ int32_t mTextureUniformIndexStart;
+
+ void logUniform(const android::renderscript::Element *field, const float *fd, uint32_t arraySize );
+ void setUniform(const android::renderscript::Context *rsc, const android::renderscript::Element *field, const float *fd, int32_t slot, uint32_t arraySize );
+ void initMemberVars();
+ void init();
+};
+
+#endif //ANDROID_RSD_SHADER_H
+
+
+
+
diff --git a/libs/rs/rsShaderCache.cpp b/libs/rs/driver/rsdShaderCache.cpp
index e8d89c2..18a8225 100644
--- a/libs/rs/rsShaderCache.cpp
+++ b/libs/rs/driver/rsdShaderCache.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -14,25 +14,30 @@
* limitations under the License.
*/
-#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
+#include <rs_hal.h>
+#include <rsContext.h>
+
+#include "rsdShader.h"
+#include "rsdShaderCache.h"
+
#include <GLES/gl.h>
#include <GLES2/gl2.h>
-#endif //ANDROID_RS_SERIALIZE
using namespace android;
using namespace android::renderscript;
-ShaderCache::ShaderCache() {
+RsdShaderCache::RsdShaderCache() {
mEntries.setCapacity(16);
+ mVertexDirty = true;
+ mFragmentDirty = true;
}
-ShaderCache::~ShaderCache() {
+RsdShaderCache::~RsdShaderCache() {
cleanupAll();
}
-void ShaderCache::updateUniformArrayData(Context *rsc, Program *prog, uint32_t linkedID,
+void RsdShaderCache::updateUniformArrayData(const Context *rsc, RsdShader *prog, uint32_t linkedID,
UniformData *data, const char* logTag,
UniformQueryData **uniformList, uint32_t uniListSize) {
@@ -54,14 +59,14 @@ void ShaderCache::updateUniformArrayData(Context *rsc, Program *prog, uint32_t l
}
}
-void ShaderCache::populateUniformData(Program *prog, uint32_t linkedID, UniformData *data) {
+void RsdShaderCache::populateUniformData(RsdShader *prog, uint32_t linkedID, UniformData *data) {
for (uint32_t ct=0; ct < prog->getUniformCount(); ct++) {
data[ct].slot = glGetUniformLocation(linkedID, prog->getUniformName(ct));
data[ct].arraySize = prog->getUniformArraySize(ct);
}
}
-bool ShaderCache::hasArrayUniforms(ProgramVertex *vtx, ProgramFragment *frag) {
+bool RsdShaderCache::hasArrayUniforms(RsdShader *vtx, RsdShader *frag) {
UniformData *data = mCurrent->vtxUniforms;
for (uint32_t ct=0; ct < vtx->getUniformCount(); ct++) {
if (data[ct].slot >= 0 && data[ct].arraySize > 1) {
@@ -77,7 +82,31 @@ bool ShaderCache::hasArrayUniforms(ProgramVertex *vtx, ProgramFragment *frag) {
return false;
}
-bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag) {
+bool RsdShaderCache::setup(const Context *rsc) {
+ if (!mVertexDirty && !mFragmentDirty) {
+ return true;
+ }
+
+ if (!link(rsc)) {
+ return false;
+ }
+
+ if (mFragmentDirty) {
+ mFragment->setup(rsc, this);
+ mFragmentDirty = false;
+ }
+ if (mVertexDirty) {
+ mVertex->setup(rsc, this);
+ mVertexDirty = false;
+ }
+
+ return true;
+}
+
+bool RsdShaderCache::link(const Context *rsc) {
+
+ RsdShader *vtx = mVertex;
+ RsdShader *frag = mFragment;
if (!vtx->getShaderID()) {
vtx->loadShader(rsc);
}
@@ -89,7 +118,7 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag
if (!vtx->getShaderID() || !frag->getShaderID()) {
return false;
}
- //LOGV("ShaderCache lookup vtx %i, frag %i", vtx->getShaderID(), frag->getShaderID());
+ //LOGV("rsdShaderCache lookup vtx %i, frag %i", vtx->getShaderID(), frag->getShaderID());
uint32_t entryCount = mEntries.size();
for (uint32_t ct = 0; ct < entryCount; ct ++) {
if ((mEntries[ct]->vtx == vtx->getShaderID()) &&
@@ -98,13 +127,13 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag
//LOGV("SC using program %i", mEntries[ct]->program);
glUseProgram(mEntries[ct]->program);
mCurrent = mEntries[ct];
- //LOGV("ShaderCache hit, using %i", ct);
- rsc->checkError("ShaderCache::lookup (hit)");
+ //LOGV("RsdShaderCache hit, using %i", ct);
+ rsc->checkError("RsdShaderCache::link (hit)");
return true;
}
}
- //LOGV("ShaderCache miss");
+ //LOGV("RsdShaderCache miss");
//LOGE("e0 %x", glGetError());
ProgramEntry *e = new ProgramEntry(vtx->getAttribCount(),
vtx->getUniformCount(),
@@ -120,12 +149,10 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag
//LOGE("e1 %x", glGetError());
glAttachShader(pgm, frag->getShaderID());
- if (!vtx->isUserProgram()) {
- glBindAttribLocation(pgm, 0, "ATTRIB_position");
- glBindAttribLocation(pgm, 1, "ATTRIB_color");
- glBindAttribLocation(pgm, 2, "ATTRIB_normal");
- glBindAttribLocation(pgm, 3, "ATTRIB_texture0");
- }
+ glBindAttribLocation(pgm, 0, "ATTRIB_position");
+ glBindAttribLocation(pgm, 1, "ATTRIB_color");
+ glBindAttribLocation(pgm, 2, "ATTRIB_normal");
+ glBindAttribLocation(pgm, 3, "ATTRIB_texture0");
//LOGE("e2 %x", glGetError());
glLinkProgram(pgm);
@@ -203,11 +230,12 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag
//LOGV("SC made program %i", e->program);
glUseProgram(e->program);
- rsc->checkError("ShaderCache::lookup (miss)");
+ rsc->checkError("RsdShaderCache::link (miss)");
+
return true;
}
-int32_t ShaderCache::vtxAttribSlot(const String8 &attrName) const {
+int32_t RsdShaderCache::vtxAttribSlot(const String8 &attrName) const {
for (uint32_t ct=0; ct < mCurrent->vtxAttrCount; ct++) {
if (attrName == mCurrent->vtxAttrs[ct].name) {
return mCurrent->vtxAttrs[ct].slot;
@@ -216,7 +244,7 @@ int32_t ShaderCache::vtxAttribSlot(const String8 &attrName) const {
return -1;
}
-void ShaderCache::cleanupVertex(uint32_t id) {
+void RsdShaderCache::cleanupVertex(uint32_t id) {
int32_t numEntries = (int32_t)mEntries.size();
for (int32_t ct = 0; ct < numEntries; ct ++) {
if (mEntries[ct]->vtx == id) {
@@ -230,7 +258,7 @@ void ShaderCache::cleanupVertex(uint32_t id) {
}
}
-void ShaderCache::cleanupFragment(uint32_t id) {
+void RsdShaderCache::cleanupFragment(uint32_t id) {
int32_t numEntries = (int32_t)mEntries.size();
for (int32_t ct = 0; ct < numEntries; ct ++) {
if (mEntries[ct]->frag == id) {
@@ -244,7 +272,7 @@ void ShaderCache::cleanupFragment(uint32_t id) {
}
}
-void ShaderCache::cleanupAll() {
+void RsdShaderCache::cleanupAll() {
for (uint32_t ct=0; ct < mEntries.size(); ct++) {
glDeleteProgram(mEntries[ct]->program);
free(mEntries[ct]);
diff --git a/libs/rs/rsShaderCache.h b/libs/rs/driver/rsdShaderCache.h
index 3540366..17ee3e8 100644
--- a/libs/rs/rsShaderCache.h
+++ b/libs/rs/driver/rsdShaderCache.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -14,38 +14,59 @@
* limitations under the License.
*/
-#ifndef ANDROID_SHADER_CACHE_H
-#define ANDROID_SHADER_CACHE_H
+#ifndef ANDROID_RSD_SHADER_CACHE_H
+#define ANDROID_RSD_SHADER_CACHE_H
-
-#include "rsObjectBase.h"
-#include "rsVertexArray.h"
-
-// ---------------------------------------------------------------------------
namespace android {
namespace renderscript {
+class Context;
+
+}
+}
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+class RsdShader;
+
+// ---------------------------------------------------------------------------
// An element is a group of Components that occupies one cell in a structure.
-class ShaderCache {
+class RsdShaderCache {
public:
- ShaderCache();
- virtual ~ShaderCache();
+ RsdShaderCache();
+ virtual ~RsdShaderCache();
+
+ void setActiveVertex(RsdShader *pv) {
+ mVertexDirty = true;
+ mVertex = pv;
+ }
- bool lookup(Context *rsc, ProgramVertex *, ProgramFragment *);
+ void setActiveFragment(RsdShader *pf) {
+ mFragmentDirty = true;
+ mFragment = pf;
+ }
+
+ bool setup(const android::renderscript::Context *rsc);
void cleanupVertex(uint32_t id);
void cleanupFragment(uint32_t id);
void cleanupAll();
- int32_t vtxAttribSlot(const String8 &attrName) const;
+ int32_t vtxAttribSlot(const android::String8 &attrName) const;
int32_t vtxUniformSlot(uint32_t a) const {return mCurrent->vtxUniforms[a].slot;}
uint32_t vtxUniformSize(uint32_t a) const {return mCurrent->vtxUniforms[a].arraySize;}
int32_t fragUniformSlot(uint32_t a) const {return mCurrent->fragUniforms[a].slot;}
uint32_t fragUniformSize(uint32_t a) const {return mCurrent->fragUniforms[a].arraySize;}
protected:
+ bool link(const android::renderscript::Context *rsc);
+ bool mFragmentDirty;
+ bool mVertexDirty;
+ RsdShader *mVertex;
+ RsdShader *mFragment;
+
struct UniformQueryData {
char *name;
uint32_t nameLength;
@@ -111,21 +132,19 @@ protected:
UniformData *vtxUniforms;
UniformData *fragUniforms;
};
- Vector<ProgramEntry*> mEntries;
+ android::Vector<ProgramEntry*> mEntries;
ProgramEntry *mCurrent;
- bool hasArrayUniforms(ProgramVertex *vtx, ProgramFragment *frag);
- void populateUniformData(Program *prog, uint32_t linkedID, UniformData *data);
- void updateUniformArrayData(Context *rsc, Program *prog, uint32_t linkedID,
+ bool hasArrayUniforms(RsdShader *vtx, RsdShader *frag);
+ void populateUniformData(RsdShader *prog, uint32_t linkedID, UniformData *data);
+ void updateUniformArrayData(const android::renderscript::Context *rsc,
+ RsdShader *prog, uint32_t linkedID,
UniformData *data, const char* logTag,
UniformQueryData **uniformList, uint32_t uniListSize);
};
-
-}
-}
-#endif //ANDROID_SHADER_CACHE_H
+#endif //ANDROID_RSD_SHADER_CACHE_H
diff --git a/libs/rs/rsVertexArray.cpp b/libs/rs/driver/rsdVertexArray.cpp
index 354ee89..d0a5a54 100644
--- a/libs/rs/rsVertexArray.cpp
+++ b/libs/rs/driver/rsdVertexArray.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -14,28 +14,32 @@
* limitations under the License.
*/
-#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
+#include <rs_hal.h>
+#include <rsContext.h>
+
#include <GLES/gl.h>
#include <GLES2/gl2.h>
-#endif
+
+#include "rsdCore.h"
+#include "rsdVertexArray.h"
+#include "rsdShaderCache.h"
using namespace android;
using namespace android::renderscript;
-VertexArray::VertexArray(const Attrib *attribs, uint32_t numAttribs) {
+RsdVertexArray::RsdVertexArray(const Attrib *attribs, uint32_t numAttribs) {
mAttribs = attribs;
mCount = numAttribs;
}
-VertexArray::~VertexArray() {
+RsdVertexArray::~RsdVertexArray() {
}
-VertexArray::Attrib::Attrib() {
+RsdVertexArray::Attrib::Attrib() {
clear();
}
-void VertexArray::Attrib::clear() {
+void RsdVertexArray::Attrib::clear() {
buffer = 0;
offset = 0;
type = 0;
@@ -46,7 +50,7 @@ void VertexArray::Attrib::clear() {
name.setTo("");
}
-void VertexArray::Attrib::set(uint32_t type, uint32_t size, uint32_t stride,
+void RsdVertexArray::Attrib::set(uint32_t type, uint32_t size, uint32_t stride,
bool normalized, uint32_t offset,
const char *name) {
clear();
@@ -58,7 +62,7 @@ void VertexArray::Attrib::set(uint32_t type, uint32_t size, uint32_t stride,
this->name.setTo(name);
}
-void VertexArray::logAttrib(uint32_t idx, uint32_t slot) const {
+void RsdVertexArray::logAttrib(uint32_t idx, uint32_t slot) const {
if (idx == 0) {
LOGV("Starting vertex attribute binding");
}
@@ -74,11 +78,15 @@ void VertexArray::logAttrib(uint32_t idx, uint32_t slot) const {
mAttribs[idx].offset);
}
-void VertexArray::setupGL2(const Context *rsc,
- class VertexArrayState *state,
- ShaderCache *sc) const {
- rsc->checkError("VertexArray::setupGL2 start");
+void RsdVertexArray::setupGL2(const Context *rsc) const {
+
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ RsdVertexArrayState *state = dc->gl.vertexArrayState;
+ RsdShaderCache *sc = dc->gl.shaderCache;
+
+ rsc->checkError("RsdVertexArray::setupGL2 start");
uint32_t maxAttrs = state->mAttrsEnabledSize;
+
for (uint32_t ct=1; ct < maxAttrs; ct++) {
if(state->mAttrsEnabled[ct]) {
glDisableVertexAttribArray(ct);
@@ -86,7 +94,7 @@ void VertexArray::setupGL2(const Context *rsc,
}
}
- rsc->checkError("VertexArray::setupGL2 disabled");
+ rsc->checkError("RsdVertexArray::setupGL2 disabled");
for (uint32_t ct=0; ct < mCount; ct++) {
int32_t slot = sc->vtxAttribSlot(mAttribs[ct].name);
if (rsc->props.mLogShadersAttr) {
@@ -105,22 +113,22 @@ void VertexArray::setupGL2(const Context *rsc,
mAttribs[ct].stride,
mAttribs[ct].ptr + mAttribs[ct].offset);
}
- rsc->checkError("VertexArray::setupGL2 done");
+ rsc->checkError("RsdVertexArray::setupGL2 done");
}
////////////////////////////////////////////
-VertexArrayState::VertexArrayState() {
+RsdVertexArrayState::RsdVertexArrayState() {
mAttrsEnabled = NULL;
mAttrsEnabledSize = 0;
}
-VertexArrayState::~VertexArrayState() {
+RsdVertexArrayState::~RsdVertexArrayState() {
if (mAttrsEnabled) {
delete[] mAttrsEnabled;
mAttrsEnabled = NULL;
}
}
-void VertexArrayState::init(Context *rsc) {
- mAttrsEnabledSize = rsc->getMaxVertexAttributes();
+void RsdVertexArrayState::init(uint32_t maxAttrs) {
+ mAttrsEnabledSize = maxAttrs;
mAttrsEnabled = new bool[mAttrsEnabledSize];
for (uint32_t ct = 0; ct < mAttrsEnabledSize; ct++) {
mAttrsEnabled[ct] = false;
diff --git a/libs/rs/rsVertexArray.h b/libs/rs/driver/rsdVertexArray.h
index 45d9e82..925a6ae 100644
--- a/libs/rs/rsVertexArray.h
+++ b/libs/rs/driver/rsdVertexArray.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -14,20 +14,21 @@
* limitations under the License.
*/
-#ifndef ANDROID_VERTEX_ARRAY_H
-#define ANDROID_VERTEX_ARRAY_H
+#ifndef ANDROID_RSD_VERTEX_ARRAY_H
+#define ANDROID_RSD_VERTEX_ARRAY_H
-
-#include "rsObjectBase.h"
-
-// ---------------------------------------------------------------------------
namespace android {
namespace renderscript {
-class ShaderCache;
+class Context;
+
+}
+}
+
+#include <utils/String8.h>
// An element is a group of Components that occupies one cell in a structure.
-class VertexArray {
+class RsdVertexArray {
public:
class Attrib {
public:
@@ -38,17 +39,17 @@ public:
uint32_t size;
uint32_t stride;
bool normalized;
- String8 name;
+ android::String8 name;
Attrib();
void clear();
void set(uint32_t type, uint32_t size, uint32_t stride, bool normalized, uint32_t offset, const char *name);
};
- VertexArray(const Attrib *attribs, uint32_t numAttribs);
- virtual ~VertexArray();
+ RsdVertexArray(const Attrib *attribs, uint32_t numAttribs);
+ virtual ~RsdVertexArray();
- void setupGL2(const Context *rsc, class VertexArrayState *, ShaderCache *) const;
+ void setupGL2(const android::renderscript::Context *rsc) const;
void logAttrib(uint32_t idx, uint32_t slot) const;
protected:
@@ -61,20 +62,18 @@ protected:
};
-class VertexArrayState {
+class RsdVertexArrayState {
public:
- VertexArrayState();
- ~VertexArrayState();
- void init(Context *);
+ RsdVertexArrayState();
+ ~RsdVertexArrayState();
+ void init(uint32_t maxAttrs);
bool *mAttrsEnabled;
uint32_t mAttrsEnabledSize;
};
-}
-}
-#endif //ANDROID_VERTEX_ARRAY_H
+#endif //ANDROID_RSD_VERTEX_ARRAY_H
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 6310cf6..0c4e1ed 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -66,7 +66,7 @@ ContextDeinitToClient {
direct
}
-aTypeCreate {
+TypeCreate {
direct
param RsElement e
param uint32_t dimX
@@ -77,7 +77,7 @@ aTypeCreate {
ret RsType
}
-aAllocationCreateTyped {
+AllocationCreateTyped {
direct
param RsType vtype
param RsAllocationMipmapControl mips
@@ -85,7 +85,7 @@ aAllocationCreateTyped {
ret RsAllocation
}
-aAllocationCreateFromBitmap {
+AllocationCreateFromBitmap {
direct
param RsType vtype
param RsAllocationMipmapControl mips
@@ -94,7 +94,7 @@ aAllocationCreateFromBitmap {
ret RsAllocation
}
-aAllocationCubeCreateFromBitmap {
+AllocationCubeCreateFromBitmap {
direct
param RsType vtype
param RsAllocationMipmapControl mips
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 743b2c4..b5f6f56 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -649,11 +649,12 @@ void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY) {
//
#ifndef ANDROID_RS_SERIALIZE
-static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va);
namespace android {
namespace renderscript {
+static void AllocationGenerateScriptMips(RsContext con, RsAllocation va);
+
void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel) {
Allocation *alloc = static_cast<Allocation *>(va);
alloc->deferredUploadToTexture(rsc);
@@ -740,7 +741,7 @@ void rsi_AllocationSyncAll(Context *rsc, RsAllocation va, RsAllocationUsageType
void rsi_AllocationGenerateMipmaps(Context *rsc, RsAllocation va) {
Allocation *texAlloc = static_cast<Allocation *>(va);
- rsaAllocationGenerateScriptMips(rsc, texAlloc);
+ AllocationGenerateScriptMips(rsc, texAlloc);
}
void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) {
@@ -795,10 +796,7 @@ void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32
a->resize2D(rsc, dimX, dimY);
}
-}
-}
-
-static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va) {
+static void AllocationGenerateScriptMips(RsContext con, RsAllocation va) {
Context *rsc = static_cast<Context *>(con);
Allocation *texAlloc = static_cast<Allocation *>(va);
uint32_t numFaces = texAlloc->getType()->getDimFaces() ? 6 : 1;
@@ -815,29 +813,20 @@ static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va) {
}
}
-const void * rsaAllocationGetType(RsContext con, RsAllocation va) {
- Allocation *a = static_cast<Allocation *>(va);
- a->getType()->incUserRef();
-
- return a->getType();
-}
-
-RsAllocation rsaAllocationCreateTyped(RsContext con, RsType vtype,
- RsAllocationMipmapControl mips,
- uint32_t usages) {
- Context *rsc = static_cast<Context *>(con);
+RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype,
+ RsAllocationMipmapControl mips,
+ uint32_t usages) {
Allocation * alloc = new Allocation(rsc, static_cast<Type *>(vtype), usages, mips);
alloc->incUserRef();
return alloc;
}
-RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
- RsAllocationMipmapControl mips,
- const void *data, size_t data_length, uint32_t usages) {
- Context *rsc = static_cast<Context *>(con);
+RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, RsType vtype,
+ RsAllocationMipmapControl mips,
+ const void *data, size_t data_length, uint32_t usages) {
Type *t = static_cast<Type *>(vtype);
- RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, vtype, mips, usages);
+ RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages);
Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
if (texAlloc == NULL) {
LOGE("Memory allocation failure");
@@ -846,23 +835,22 @@ RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
memcpy(texAlloc->getPtr(), data, t->getDimX() * t->getDimY() * t->getElementSizeBytes());
if (mips == RS_ALLOCATION_MIPMAP_FULL) {
- rsaAllocationGenerateScriptMips(rsc, texAlloc);
+ AllocationGenerateScriptMips(rsc, texAlloc);
}
texAlloc->deferredUploadToTexture(rsc);
return texAlloc;
}
-RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype,
- RsAllocationMipmapControl mips,
- const void *data, size_t data_length, uint32_t usages) {
- Context *rsc = static_cast<Context *>(con);
+RsAllocation rsi_AllocationCubeCreateFromBitmap(Context *rsc, RsType vtype,
+ RsAllocationMipmapControl mips,
+ const void *data, size_t data_length, uint32_t usages) {
Type *t = static_cast<Type *>(vtype);
// Cubemap allocation's faces should be Width by Width each.
// Source data should have 6 * Width by Width pixels
// Error checking is done in the java layer
- RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, t, mips, usages);
+ RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages);
Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
if (texAlloc == NULL) {
LOGE("Memory allocation failure");
@@ -887,11 +875,21 @@ RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype,
}
if (mips == RS_ALLOCATION_MIPMAP_FULL) {
- rsaAllocationGenerateScriptMips(rsc, texAlloc);
+ AllocationGenerateScriptMips(rsc, texAlloc);
}
texAlloc->deferredUploadToTexture(rsc);
return texAlloc;
}
+}
+}
+
+const void * rsaAllocationGetType(RsContext con, RsAllocation va) {
+ Allocation *a = static_cast<Allocation *>(va);
+ a->getType()->incUserRef();
+
+ return a->getType();
+}
+
#endif //ANDROID_RS_SERIALIZE
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 50f5f55..6d63f67 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -215,15 +215,11 @@ void Context::timerPrint() {
}
bool Context::setupCheck() {
- if (!mShaderCache.lookup(this, mVertex.get(), mFragment.get())) {
- LOGE("Context::setupCheck() 1 fail");
- return false;
- }
mFragmentStore->setup(this, &mStateFragmentStore);
- mFragment->setupGL2(this, &mStateFragment, &mShaderCache);
+ mFragment->setupGL2(this, &mStateFragment);
mRaster->setup(this, &mStateRaster);
- mVertex->setupGL2(this, &mStateVertex, &mShaderCache);
+ mVertex->setupGL2(this, &mStateVertex);
mFBOCache.setupGL2(this);
return true;
}
@@ -295,7 +291,6 @@ void * Context::threadProc(void *vrsc) {
rsc->setProgramStore(NULL);
rsc->mStateFont.init(rsc);
rsc->setFont(NULL);
- rsc->mStateVertexArray.init(rsc);
}
rsc->mRunning = true;
@@ -356,7 +351,6 @@ void Context::destroyWorkerThreadResources() {
mStateFragment.deinit(this);
mStateFragmentStore.deinit(this);
mStateFont.deinit(this);
- mShaderCache.cleanupAll();
}
//LOGV("destroyWorkerThreadResources 2");
mExit = true;
@@ -598,7 +592,7 @@ RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen
*subID = d[0];
//LOGE("getMessageToClient %i %i", commandID, *subID);
- if (bufferLen >= bytesData) {
+ if (bufferLen >= (*receiveLen)) {
memcpy(data, d+1, *receiveLen);
mIO.mToClient.next();
return (RsMessageToClientType)commandID;
@@ -740,25 +734,21 @@ void rsi_ContextDestroyWorker(Context *rsc) {
rsc->destroyWorkerThreadResources();;
}
-}
-}
-
-void rsContextDestroy(RsContext vcon) {
- LOGV("rsContextDestroy %p", vcon);
- Context *rsc = static_cast<Context *>(vcon);
+void rsi_ContextDestroy(Context *rsc) {
+ LOGV("rsContextDestroy %p", rsc);
rsContextDestroyWorker(rsc);
delete rsc;
- LOGV("rsContextDestroy 2 %p", vcon);
+ LOGV("rsContextDestroy 2 %p", rsc);
}
-RsContext rsContextCreate(RsDevice vdev, uint32_t version) {
+RsContext rsi_ContextCreate(RsDevice vdev, uint32_t version) {
LOGV("rsContextCreate %p", vdev);
Device * dev = static_cast<Device *>(vdev);
Context *rsc = Context::createContext(dev, NULL);
return rsc;
}
-RsContext rsContextCreateGL(RsDevice vdev, uint32_t version,
+RsContext rsi_ContextCreateGL(RsDevice vdev, uint32_t version,
RsSurfaceConfig sc, uint32_t dpi) {
LOGV("rsContextCreateGL %p", vdev);
Device * dev = static_cast<Device *>(vdev);
@@ -768,32 +758,31 @@ RsContext rsContextCreateGL(RsDevice vdev, uint32_t version,
return rsc;
}
-RsMessageToClientType rsContextPeekMessage(RsContext vrsc,
+RsMessageToClientType rsi_ContextPeekMessage(Context *rsc,
size_t * receiveLen, size_t receiveLen_length,
uint32_t * subID, size_t subID_length, bool wait) {
- Context * rsc = static_cast<Context *>(vrsc);
return rsc->peekMessageToClient(receiveLen, subID, wait);
}
-RsMessageToClientType rsContextGetMessage(RsContext vrsc, void * data, size_t data_length,
+RsMessageToClientType rsi_ContextGetMessage(Context *rsc, void * data, size_t data_length,
size_t * receiveLen, size_t receiveLen_length,
uint32_t * subID, size_t subID_length, bool wait) {
- Context * rsc = static_cast<Context *>(vrsc);
rsAssert(subID_length == sizeof(uint32_t));
rsAssert(receiveLen_length == sizeof(size_t));
return rsc->getMessageToClient(data, receiveLen, subID, data_length, wait);
}
-void rsContextInitToClient(RsContext vrsc) {
- Context * rsc = static_cast<Context *>(vrsc);
+void rsi_ContextInitToClient(Context *rsc) {
rsc->initToClient();
}
-void rsContextDeinitToClient(RsContext vrsc) {
- Context * rsc = static_cast<Context *>(vrsc);
+void rsi_ContextDeinitToClient(Context *rsc) {
rsc->deinitToClient();
}
+}
+}
+
// Only to be called at a3d load time, before object is visible to user
// not thread safe
void rsaGetName(RsContext con, void * obj, const char **name) {
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index df85a6b..107f639 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -37,9 +37,7 @@
#include "rsProgramStore.h"
#include "rsProgramRaster.h"
#include "rsProgramVertex.h"
-#include "rsShaderCache.h"
#include "rsFBOCache.h"
-#include "rsVertexArray.h"
#include "rsgApiStructs.h"
#include "rsLocklessFifo.h"
@@ -111,11 +109,9 @@ public:
ProgramStoreState mStateFragmentStore;
ProgramRasterState mStateRaster;
ProgramVertexState mStateVertex;
- VertexArrayState mStateVertexArray;
FontState mStateFont;
ScriptCState mScriptC;
- ShaderCache mShaderCache;
FBOCache mFBOCache;
void swapBuffers();
diff --git a/libs/rs/rsDevice.cpp b/libs/rs/rsDevice.cpp
index d7d03f6..849fd98 100644
--- a/libs/rs/rsDevice.cpp
+++ b/libs/rs/rsDevice.cpp
@@ -40,17 +40,20 @@ void Device::removeContext(Context *rsc) {
}
}
-RsDevice rsDeviceCreate() {
+namespace android {
+namespace renderscript {
+
+RsDevice rsi_DeviceCreate() {
Device * d = new Device();
return d;
}
-void rsDeviceDestroy(RsDevice dev) {
+void rsi_DeviceDestroy(RsDevice dev) {
Device * d = static_cast<Device *>(dev);
delete d;
}
-void rsDeviceSetConfig(RsDevice dev, RsDeviceParam p, int32_t value) {
+void rsi_DeviceSetConfig(RsDevice dev, RsDeviceParam p, int32_t value) {
Device * d = static_cast<Device *>(dev);
if (p == RS_DEVICE_PARAM_FORCE_SOFTWARE_GL) {
d->mForceSW = value != 0;
@@ -59,3 +62,5 @@ void rsDeviceSetConfig(RsDevice dev, RsDeviceParam p, int32_t value) {
rsAssert(0);
}
+}
+}
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index b7b85b6..5e47ddb 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -25,11 +25,6 @@
#include FT_FREETYPE_H
#include FT_BITMAP_H
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
using namespace android;
using namespace android::renderscript;
@@ -457,7 +452,7 @@ bool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *r
// This will dirty the texture and the shader so next time
// we draw it will upload the data
- mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT);
+ mTextTexture->deferredUploadToTexture(mRSC);
mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get());
// Some debug code
@@ -568,7 +563,6 @@ void FontState::initVertexArrayBuffers() {
}
indexAlloc->deferredUploadToBufferObject(mRSC);
- mIndexBuffer.set(indexAlloc);
const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
@@ -585,7 +579,10 @@ void FontState::initVertexArrayBuffers() {
Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX);
mTextMeshPtr = (float*)vertexAlloc->getPtr();
- mVertexArray.set(vertexAlloc);
+ mMesh.set(new Mesh(mRSC, 1, 1));
+ mMesh->setVertexBuffer(vertexAlloc, 0);
+ mMesh->setPrimitive(indexAlloc, RS_PRIMITIVE_TRIANGLE, 0);
+ mMesh->init();
}
// We don't want to allocate anything unless we actually draw text
@@ -625,18 +622,7 @@ void FontState::issueDrawCommand() {
return;
}
- float *vtx = (float*)mVertexArray->getPtr();
- float *tex = vtx + 3;
-
- VertexArray::Attrib attribs[2];
- attribs[0].set(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position");
- attribs[1].set(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0");
- VertexArray va(attribs, 2);
- va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache);
-
- mIndexBuffer->uploadCheck(mRSC);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
- glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0));
+ mMesh->renderPrimitiveRange(mRSC, 0, 0, mCurrentQuadIndex * 6);
}
void FontState::appendMeshQuad(float x1, float y1, float z1,
@@ -787,8 +773,7 @@ void FontState::deinit(Context *rsc) {
mFontShaderFConstant.clear();
- mIndexBuffer.clear();
- mVertexArray.clear();
+ mMesh.clear();
mFontShaderF.clear();
mFontSampler.clear();
diff --git a/libs/rs/rsFont.h b/libs/rs/rsFont.h
index 91a5da9..d18c0d9 100644
--- a/libs/rs/rsFont.h
+++ b/libs/rs/rsFont.h
@@ -230,9 +230,7 @@ protected:
uint32_t mMaxNumberOfQuads;
void initVertexArrayBuffers();
- ObjectBaseRef<Allocation> mIndexBuffer;
- ObjectBaseRef<Allocation> mVertexArray;
-
+ ObjectBaseRef<Mesh> mMesh;
bool mInitialized;
diff --git a/libs/rs/rsMesh.cpp b/libs/rs/rsMesh.cpp
index e29c800..ed29063 100644
--- a/libs/rs/rsMesh.cpp
+++ b/libs/rs/rsMesh.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -15,46 +15,53 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#include <GLES2/gl2.h>
-#include <GLES/glext.h>
-#endif
using namespace android;
using namespace android::renderscript;
Mesh::Mesh(Context *rsc) : ObjectBase(rsc) {
- mPrimitives = NULL;
- mPrimitivesCount = 0;
- mVertexBuffers = NULL;
- mVertexBufferCount = 0;
-
-#ifndef ANDROID_RS_SERIALIZE
- mAttribs = NULL;
- mAttribAllocationIndex = NULL;
+ mHal.drv = NULL;
+ mHal.state.primitives = NULL;
+ mHal.state.primitivesCount = 0;
+ mHal.state.vertexBuffers = NULL;
+ mHal.state.vertexBuffersCount = 0;
+ mInitialized = false;
+}
- mAttribCount = 0;
-#endif
+Mesh::Mesh(Context *rsc,
+ uint32_t vertexBuffersCount,
+ uint32_t primitivesCount) : ObjectBase(rsc) {
+ mHal.drv = NULL;
+ mHal.state.primitivesCount = primitivesCount;
+ mHal.state.primitives = new Primitive_t *[mHal.state.primitivesCount];
+ for (uint32_t i = 0; i < mHal.state.primitivesCount; i ++) {
+ mHal.state.primitives[i] = new Primitive_t;
+ }
+ mHal.state.vertexBuffersCount = vertexBuffersCount;
+ mHal.state.vertexBuffers = new ObjectBaseRef<Allocation>[mHal.state.vertexBuffersCount];
}
Mesh::~Mesh() {
- if (mVertexBuffers) {
- delete[] mVertexBuffers;
+#ifndef ANDROID_RS_SERIALIZE
+ mRSC->mHal.funcs.mesh.destroy(mRSC, this);
+#endif
+
+ if (mHal.state.vertexBuffers) {
+ delete[] mHal.state.vertexBuffers;
}
- if (mPrimitives) {
- for (uint32_t i = 0; i < mPrimitivesCount; i ++) {
- delete mPrimitives[i];
+ if (mHal.state.primitives) {
+ for (uint32_t i = 0; i < mHal.state.primitivesCount; i ++) {
+ mHal.state.primitives[i]->mIndexBuffer.clear();
+ delete mHal.state.primitives[i];
}
- delete[] mPrimitives;
+ delete[] mHal.state.primitives;
}
+}
+void Mesh::init() {
#ifndef ANDROID_RS_SERIALIZE
- if (mAttribs) {
- delete[] mAttribs;
- delete[] mAttribAllocationIndex;
- }
+ mRSC->mHal.funcs.mesh.init(mRSC, this);
#endif
}
@@ -66,15 +73,15 @@ void Mesh::serialize(OStream *stream) const {
stream->addString(&name);
// Store number of vertex streams
- stream->addU32(mVertexBufferCount);
- for (uint32_t vCount = 0; vCount < mVertexBufferCount; vCount ++) {
- mVertexBuffers[vCount]->serialize(stream);
+ stream->addU32(mHal.state.vertexBuffersCount);
+ for (uint32_t vCount = 0; vCount < mHal.state.vertexBuffersCount; vCount ++) {
+ mHal.state.vertexBuffers[vCount]->serialize(stream);
}
- stream->addU32(mPrimitivesCount);
+ stream->addU32(mHal.state.primitivesCount);
// Store the primitives
- for (uint32_t pCount = 0; pCount < mPrimitivesCount; pCount ++) {
- Primitive_t * prim = mPrimitives[pCount];
+ for (uint32_t pCount = 0; pCount < mHal.state.primitivesCount; pCount ++) {
+ Primitive_t * prim = mHal.state.primitives[pCount];
stream->addU8((uint8_t)prim->mPrimitive);
@@ -95,213 +102,119 @@ Mesh *Mesh::createFromStream(Context *rsc, IStream *stream) {
return NULL;
}
- Mesh * mesh = new Mesh(rsc);
-
String8 name;
stream->loadString(&name);
- mesh->setName(name.string(), name.size());
- mesh->mVertexBufferCount = stream->loadU32();
- if (mesh->mVertexBufferCount) {
- mesh->mVertexBuffers = new ObjectBaseRef<Allocation>[mesh->mVertexBufferCount];
+ uint32_t vertexBuffersCount = stream->loadU32();
+ ObjectBaseRef<Allocation> *vertexBuffers = NULL;
+ if (vertexBuffersCount) {
+ vertexBuffers = new ObjectBaseRef<Allocation>[vertexBuffersCount];
- for (uint32_t vCount = 0; vCount < mesh->mVertexBufferCount; vCount ++) {
+ for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) {
Allocation *vertexAlloc = Allocation::createFromStream(rsc, stream);
- mesh->mVertexBuffers[vCount].set(vertexAlloc);
+ vertexBuffers[vCount].set(vertexAlloc);
}
}
- mesh->mPrimitivesCount = stream->loadU32();
- if (mesh->mPrimitivesCount) {
- mesh->mPrimitives = new Primitive_t *[mesh->mPrimitivesCount];
+ uint32_t primitivesCount = stream->loadU32();
+ ObjectBaseRef<Allocation> *indexBuffers = NULL;
+ RsPrimitive *primitives = NULL;
+ if (primitivesCount) {
+ indexBuffers = new ObjectBaseRef<Allocation>[primitivesCount];
+ primitives = new RsPrimitive[primitivesCount];
// load all primitives
- for (uint32_t pCount = 0; pCount < mesh->mPrimitivesCount; pCount ++) {
- Primitive_t * prim = new Primitive_t;
- mesh->mPrimitives[pCount] = prim;
-
- prim->mPrimitive = (RsPrimitive)stream->loadU8();
+ for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) {
+ primitives[pCount] = (RsPrimitive)stream->loadU8();
// Check to see if the index buffer was stored
uint32_t isIndexPresent = stream->loadU32();
if (isIndexPresent) {
Allocation *indexAlloc = Allocation::createFromStream(rsc, stream);
- prim->mIndexBuffer.set(indexAlloc);
+ indexBuffers[pCount].set(indexAlloc);
}
}
}
-#ifndef ANDROID_RS_SERIALIZE
- mesh->updateGLPrimitives();
- mesh->initVertexAttribs();
- mesh->uploadAll(rsc);
-#endif
- return mesh;
-}
-
-#ifndef ANDROID_RS_SERIALIZE
-
-bool Mesh::isValidGLComponent(const Element *elem, uint32_t fieldIdx) {
- // Do not create attribs for padding
- if (elem->getFieldName(fieldIdx)[0] == '#') {
- return false;
- }
-
- // Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted.
- // Filter rs types accordingly
- RsDataType dt = elem->getField(fieldIdx)->getComponent().getType();
- if (dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 &&
- dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 &&
- dt != RS_TYPE_SIGNED_16) {
- return false;
- }
-
- // Now make sure they are not arrays
- uint32_t arraySize = elem->getFieldArraySize(fieldIdx);
- if (arraySize != 1) {
- return false;
+ Mesh *mesh = new Mesh(rsc, vertexBuffersCount, primitivesCount);
+ mesh->setName(name.string(), name.size());
+ for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) {
+ mesh->setVertexBuffer(vertexBuffers[vCount].get(), vCount);
}
-
- return true;
-}
-
-void Mesh::initVertexAttribs() {
- // Count the number of gl attrs to initialize
- mAttribCount = 0;
- for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
- const Element *elem = mVertexBuffers[ct]->getType()->getElement();
- for (uint32_t ct=0; ct < elem->getFieldCount(); ct++) {
- if (isValidGLComponent(elem, ct)) {
- mAttribCount ++;
- }
- }
+ for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) {
+ mesh->setPrimitive(indexBuffers[pCount].get(), primitives[pCount], pCount);
}
- if (mAttribs) {
- delete [] mAttribs;
- delete [] mAttribAllocationIndex;
- mAttribs = NULL;
- mAttribAllocationIndex = NULL;
+ // Cleanup
+ if (vertexBuffersCount) {
+ delete[] vertexBuffers;
}
- if (!mAttribCount) {
- return;
+ if (primitivesCount) {
+ delete[] indexBuffers;
+ delete[] primitives;
}
- mAttribs = new VertexArray::Attrib[mAttribCount];
- mAttribAllocationIndex = new uint32_t[mAttribCount];
-
- uint32_t userNum = 0;
- for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
- const Element *elem = mVertexBuffers[ct]->getType()->getElement();
- uint32_t stride = elem->getSizeBytes();
- for (uint32_t fieldI=0; fieldI < elem->getFieldCount(); fieldI++) {
- const Component &c = elem->getField(fieldI)->getComponent();
-
- if (!isValidGLComponent(elem, fieldI)) {
- continue;
- }
-
- mAttribs[userNum].size = c.getVectorSize();
- mAttribs[userNum].offset = elem->getFieldOffsetBytes(fieldI);
- mAttribs[userNum].type = c.getGLType();
- mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized();
- mAttribs[userNum].stride = stride;
- String8 tmp(RS_SHADER_ATTR);
- tmp.append(elem->getFieldName(fieldI));
- mAttribs[userNum].name.setTo(tmp.string());
-
- // Remember which allocation this attribute came from
- mAttribAllocationIndex[userNum] = ct;
- userNum ++;
- }
- }
+#ifndef ANDROID_RS_SERIALIZE
+ mesh->init();
+ mesh->uploadAll(rsc);
+#endif
+ return mesh;
}
+#ifndef ANDROID_RS_SERIALIZE
+
void Mesh::render(Context *rsc) const {
- for (uint32_t ct = 0; ct < mPrimitivesCount; ct ++) {
+ for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
renderPrimitive(rsc, ct);
}
}
void Mesh::renderPrimitive(Context *rsc, uint32_t primIndex) const {
- if (primIndex >= mPrimitivesCount) {
+ if (primIndex >= mHal.state.primitivesCount) {
LOGE("Invalid primitive index");
return;
}
- Primitive_t *prim = mPrimitives[primIndex];
+ Primitive_t *prim = mHal.state.primitives[primIndex];
if (prim->mIndexBuffer.get()) {
renderPrimitiveRange(rsc, primIndex, 0, prim->mIndexBuffer->getType()->getDimX());
return;
}
- renderPrimitiveRange(rsc, primIndex, 0, mVertexBuffers[0]->getType()->getDimX());
+ renderPrimitiveRange(rsc, primIndex, 0, mHal.state.vertexBuffers[0]->getType()->getDimX());
}
void Mesh::renderPrimitiveRange(Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const {
- if (len < 1 || primIndex >= mPrimitivesCount || mAttribCount == 0) {
+ if (len < 1 || primIndex >= mHal.state.primitivesCount) {
LOGE("Invalid mesh or parameters");
return;
}
- rsc->checkError("Mesh::renderPrimitiveRange 1");
- for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
- mVertexBuffers[ct]->uploadCheck(rsc);
+ for (uint32_t ct=0; ct < mHal.state.vertexBuffersCount; ct++) {
+ mHal.state.vertexBuffers[ct]->uploadCheck(rsc);
}
- // update attributes with either buffer information or data ptr based on their current state
- for (uint32_t ct=0; ct < mAttribCount; ct++) {
- uint32_t allocIndex = mAttribAllocationIndex[ct];
- Allocation *alloc = mVertexBuffers[allocIndex].get();
- if (alloc->getIsBufferObject()) {
- mAttribs[ct].buffer = alloc->getBufferObjectID();
- mAttribs[ct].ptr = NULL;
- } else {
- mAttribs[ct].buffer = 0;
- mAttribs[ct].ptr = (const uint8_t*)alloc->getPtr();
- }
- }
-
- VertexArray va(mAttribs, mAttribCount);
- va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
- rsc->checkError("Mesh::renderPrimitiveRange 2");
- Primitive_t *prim = mPrimitives[primIndex];
+ Primitive_t *prim = mHal.state.primitives[primIndex];
if (prim->mIndexBuffer.get()) {
prim->mIndexBuffer->uploadCheck(rsc);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prim->mIndexBuffer->getBufferObjectID());
- glDrawElements(prim->mGLPrimitive, len, GL_UNSIGNED_SHORT, (uint16_t *)(start * 2));
- } else {
- glDrawArrays(prim->mGLPrimitive, start, len);
}
+ rsc->checkError("Mesh::renderPrimitiveRange upload check");
- rsc->checkError("Mesh::renderPrimitiveRange");
+ mRSC->mHal.funcs.mesh.draw(mRSC, this, primIndex, start, len);
+ rsc->checkError("Mesh::renderPrimitiveRange draw");
}
-
void Mesh::uploadAll(Context *rsc) {
- for (uint32_t ct = 0; ct < mVertexBufferCount; ct ++) {
- if (mVertexBuffers[ct].get()) {
- mVertexBuffers[ct]->deferredUploadToBufferObject(rsc);
+ for (uint32_t ct = 0; ct < mHal.state.vertexBuffersCount; ct ++) {
+ if (mHal.state.vertexBuffers[ct].get()) {
+ mHal.state.vertexBuffers[ct]->deferredUploadToBufferObject(rsc);
}
}
- for (uint32_t ct = 0; ct < mPrimitivesCount; ct ++) {
- if (mPrimitives[ct]->mIndexBuffer.get()) {
- mPrimitives[ct]->mIndexBuffer->deferredUploadToBufferObject(rsc);
- }
- }
-}
-
-void Mesh::updateGLPrimitives() {
- for (uint32_t i = 0; i < mPrimitivesCount; i ++) {
- switch (mPrimitives[i]->mPrimitive) {
- case RS_PRIMITIVE_POINT: mPrimitives[i]->mGLPrimitive = GL_POINTS; break;
- case RS_PRIMITIVE_LINE: mPrimitives[i]->mGLPrimitive = GL_LINES; break;
- case RS_PRIMITIVE_LINE_STRIP: mPrimitives[i]->mGLPrimitive = GL_LINE_STRIP; break;
- case RS_PRIMITIVE_TRIANGLE: mPrimitives[i]->mGLPrimitive = GL_TRIANGLES; break;
- case RS_PRIMITIVE_TRIANGLE_STRIP: mPrimitives[i]->mGLPrimitive = GL_TRIANGLE_STRIP; break;
- case RS_PRIMITIVE_TRIANGLE_FAN: mPrimitives[i]->mGLPrimitive = GL_TRIANGLE_FAN; break;
+ for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
+ if (mHal.state.primitives[ct]->mIndexBuffer.get()) {
+ mHal.state.primitives[ct]->mIndexBuffer->deferredUploadToBufferObject(rsc);
}
}
}
@@ -312,8 +225,8 @@ void Mesh::computeBBox() {
uint32_t stride = 0;
uint32_t numVerts = 0;
// First we need to find the position ptr and stride
- for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
- const Type *bufferType = mVertexBuffers[ct]->getType();
+ for (uint32_t ct=0; ct < mHal.state.vertexBuffersCount; ct++) {
+ const Type *bufferType = mHal.state.vertexBuffers[ct]->getType();
const Element *bufferElem = bufferType->getElement();
for (uint32_t ct=0; ct < bufferElem->getFieldCount(); ct++) {
@@ -321,7 +234,7 @@ void Mesh::computeBBox() {
vectorSize = bufferElem->getField(ct)->getComponent().getVectorSize();
stride = bufferElem->getSizeBytes() / sizeof(float);
uint32_t offset = bufferElem->getFieldOffsetBytes(ct);
- posPtr = (float*)((uint8_t*)mVertexBuffers[ct]->getPtr() + offset);
+ posPtr = (float*)((uint8_t*)mHal.state.vertexBuffers[ct]->getPtr() + offset);
numVerts = bufferType->getDimX();
break;
}
@@ -353,73 +266,62 @@ namespace android {
namespace renderscript {
RsMesh rsi_MeshCreate(Context *rsc, uint32_t vtxCount, uint32_t idxCount) {
- Mesh *sm = new Mesh(rsc);
+ Mesh *sm = new Mesh(rsc, vtxCount, idxCount);
sm->incUserRef();
- sm->mPrimitivesCount = idxCount;
- sm->mPrimitives = new Mesh::Primitive_t *[sm->mPrimitivesCount];
- for (uint32_t ct = 0; ct < idxCount; ct ++) {
- sm->mPrimitives[ct] = new Mesh::Primitive_t;
- }
-
- sm->mVertexBufferCount = vtxCount;
- sm->mVertexBuffers = new ObjectBaseRef<Allocation>[vtxCount];
-
return sm;
}
void rsi_MeshBindVertex(Context *rsc, RsMesh mv, RsAllocation va, uint32_t slot) {
Mesh *sm = static_cast<Mesh *>(mv);
- rsAssert(slot < sm->mVertexBufferCount);
+ rsAssert(slot < sm->mHal.state.vertexBuffersCount);
- sm->mVertexBuffers[slot].set((Allocation *)va);
+ sm->setVertexBuffer((Allocation *)va, slot);
}
void rsi_MeshBindIndex(Context *rsc, RsMesh mv, RsAllocation va, uint32_t primType, uint32_t slot) {
Mesh *sm = static_cast<Mesh *>(mv);
- rsAssert(slot < sm->mPrimitivesCount);
+ rsAssert(slot < sm->mHal.state.primitivesCount);
- sm->mPrimitives[slot]->mIndexBuffer.set((Allocation *)va);
- sm->mPrimitives[slot]->mPrimitive = (RsPrimitive)primType;
- sm->updateGLPrimitives();
+ sm->setPrimitive((Allocation *)va, (RsPrimitive)primType, slot);
}
void rsi_MeshInitVertexAttribs(Context *rsc, RsMesh mv) {
Mesh *sm = static_cast<Mesh *>(mv);
- sm->initVertexAttribs();
+ sm->init();
}
}}
void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx) {
Mesh *sm = static_cast<Mesh *>(mv);
- *numVtx = sm->mVertexBufferCount;
+ *numVtx = sm->mHal.state.vertexBuffersCount;
}
void rsaMeshGetIndexCount(RsContext con, RsMesh mv, int32_t *numIdx) {
Mesh *sm = static_cast<Mesh *>(mv);
- *numIdx = sm->mPrimitivesCount;
+ *numIdx = sm->mHal.state.primitivesCount;
}
void rsaMeshGetVertices(RsContext con, RsMesh mv, RsAllocation *vtxData, uint32_t vtxDataCount) {
Mesh *sm = static_cast<Mesh *>(mv);
- rsAssert(vtxDataCount == sm->mVertexBufferCount);
+ rsAssert(vtxDataCount == sm->mHal.state.vertexBuffersCount);
for (uint32_t ct = 0; ct < vtxDataCount; ct ++) {
- vtxData[ct] = sm->mVertexBuffers[ct].get();
- sm->mVertexBuffers[ct]->incUserRef();
+ vtxData[ct] = sm->mHal.state.vertexBuffers[ct].get();
+ sm->mHal.state.vertexBuffers[ct]->incUserRef();
}
}
void rsaMeshGetIndices(RsContext con, RsMesh mv, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount) {
Mesh *sm = static_cast<Mesh *>(mv);
- rsAssert(idxDataCount == sm->mPrimitivesCount);
+ rsAssert(idxDataCount == sm->mHal.state.primitivesCount);
for (uint32_t ct = 0; ct < idxDataCount; ct ++) {
- va[ct] = sm->mPrimitives[ct]->mIndexBuffer.get();
- primType[ct] = sm->mPrimitives[ct]->mPrimitive;
- if (sm->mPrimitives[ct]->mIndexBuffer.get()) {
- sm->mPrimitives[ct]->mIndexBuffer->incUserRef();
+ va[ct] = sm->mHal.state.primitives[ct]->mIndexBuffer.get();
+ primType[ct] = sm->mHal.state.primitives[ct]->mPrimitive;
+ if (sm->mHal.state.primitives[ct]->mIndexBuffer.get()) {
+ sm->mHal.state.primitives[ct]->mIndexBuffer->incUserRef();
}
}
}
diff --git a/libs/rs/rsMesh.h b/libs/rs/rsMesh.h
index 3e080e2..1e279f4 100644
--- a/libs/rs/rsMesh.h
+++ b/libs/rs/rsMesh.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -29,57 +29,65 @@ namespace renderscript {
class Mesh : public ObjectBase {
public:
Mesh(Context *);
+ Mesh(Context *, uint32_t vertexBuffersCount, uint32_t primitivesCount);
~Mesh();
- // Contains vertex data
- // Position, normal, texcoord, etc could either be strided in one allocation
- // of provided separetely in multiple ones
- ObjectBaseRef<Allocation> *mVertexBuffers;
- uint32_t mVertexBufferCount;
-
// Either mIndexBuffer, mPrimitiveBuffer or both could have a NULL reference
// If both are null, mPrimitive only would be used to render the mesh
- struct Primitive_t
- {
+ struct Primitive_t {
ObjectBaseRef<Allocation> mIndexBuffer;
-
RsPrimitive mPrimitive;
- uint32_t mGLPrimitive;
};
+ // compatibility to not break the build
+ ObjectBaseRef<Allocation> *mVertexBuffers;
+ uint32_t mVertexBufferCount;
Primitive_t ** mPrimitives;
uint32_t mPrimitivesCount;
+ // end compatibility
virtual void serialize(OStream *stream) const;
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_MESH; }
static Mesh *createFromStream(Context *rsc, IStream *stream);
+ void init();
+
+ struct Hal {
+ mutable void *drv;
+
+ struct State {
+ // Contains vertex data
+ // Position, normal, texcoord, etc could either be strided in one allocation
+ // of provided separetely in multiple ones
+ ObjectBaseRef<Allocation> *vertexBuffers;
+ uint32_t vertexBuffersCount;
+
+ Primitive_t ** primitives;
+ uint32_t primitivesCount;
+ };
+ State state;
+ };
+ Hal mHal;
+
+ void setVertexBuffer(Allocation *vb, uint32_t index) {
+ mHal.state.vertexBuffers[index].set(vb);
+ }
+
+ void setPrimitive(Allocation *idx, RsPrimitive prim, uint32_t index) {
+ mHal.state.primitives[index]->mIndexBuffer.set(idx);
+ mHal.state.primitives[index]->mPrimitive = prim;
+ }
-#ifndef ANDROID_RS_SERIALIZE
void render(Context *) const;
void renderPrimitive(Context *, uint32_t primIndex) const;
void renderPrimitiveRange(Context *, uint32_t primIndex, uint32_t start, uint32_t len) const;
void uploadAll(Context *);
- void updateGLPrimitives();
-
-
// Bounding volumes
float mBBoxMin[3];
float mBBoxMax[3];
void computeBBox();
-
- void initVertexAttribs();
-
protected:
- bool isValidGLComponent(const Element *elem, uint32_t fieldIdx);
- // Attribues that allow us to map to GL
- VertexArray::Attrib *mAttribs;
- // This allows us to figure out which allocation the attribute
- // belongs to. In the event the allocation is uploaded to GL
- // buffer, it lets us properly map it
- uint32_t *mAttribAllocationIndex;
- uint32_t mAttribCount;
-#endif
+ bool mInitialized;
};
class MeshContext {
@@ -92,7 +100,7 @@ public:
}
}
-#endif //ANDROID_RS_TRIANGLE_MESH_H
+#endif //ANDROID_RS_MESH_H
diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp
index 4ef05bf..28fa061 100644
--- a/libs/rs/rsProgram.cpp
+++ b/libs/rs/rsProgram.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -15,11 +15,6 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#endif //ANDROID_RS_SERIALIZE
-
#include "rsProgram.h"
using namespace android;
@@ -36,26 +31,22 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
initMemberVars();
for (uint32_t ct=0; ct < paramLength; ct+=2) {
if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
- mInputCount++;
- }
- if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
- mOutputCount++;
+ mHal.state.inputElementsCount++;
}
if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
- mConstantCount++;
+ mHal.state.constantsCount++;
}
if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) {
- mTextureCount++;
+ mHal.state.texturesCount++;
}
}
- mTextures = new ObjectBaseRef<Allocation>[mTextureCount];
- mSamplers = new ObjectBaseRef<Sampler>[mTextureCount];
- mTextureTargets = new RsTextureTarget[mTextureCount];
- mInputElements = new ObjectBaseRef<Element>[mInputCount];
- mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
- mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
- mConstants = new ObjectBaseRef<Allocation>[mConstantCount];
+ mHal.state.textures = new ObjectBaseRef<Allocation>[mHal.state.texturesCount];
+ mHal.state.samplers = new ObjectBaseRef<Sampler>[mHal.state.texturesCount];
+ mHal.state.textureTargets = new RsTextureTarget[mHal.state.texturesCount];
+ mHal.state.inputElements = new ObjectBaseRef<Element>[mHal.state.inputElementsCount];
+ mHal.state.constantTypes = new ObjectBaseRef<Type>[mHal.state.constantsCount];
+ mHal.state.constants = new ObjectBaseRef<Allocation>[mHal.state.constantsCount];
uint32_t input = 0;
uint32_t output = 0;
@@ -63,16 +54,13 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
uint32_t texture = 0;
for (uint32_t ct=0; ct < paramLength; ct+=2) {
if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
- mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
- }
- if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
- mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1]));
+ mHal.state.inputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
}
if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
- mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
+ mHal.state.constantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
}
if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) {
- mTextureTargets[texture++] = (RsTextureTarget)params[ct+1];
+ mHal.state.textureTargets[texture++] = (RsTextureTarget)params[ct+1];
}
}
mIsInternal = false;
@@ -84,88 +72,69 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
shaderLength -= internalTokenLen;
}
mUserShader.setTo(shaderText, shaderLength);
-
- initAttribAndUniformArray();
}
Program::~Program() {
- if (mRSC->props.mLogShaders) {
- LOGV("Program::~Program with shader id %u", mShaderID);
- }
- if (mShaderID) {
- glDeleteShader(mShaderID);
- }
-
- for (uint32_t ct=0; ct < mConstantCount; ct++) {
+ for (uint32_t ct=0; ct < mHal.state.constantsCount; ct++) {
bindAllocation(NULL, NULL, ct);
}
- for (uint32_t ct=0; ct < mTextureCount; ct++) {
+ for (uint32_t ct=0; ct < mHal.state.texturesCount; ct++) {
bindTexture(NULL, ct, NULL);
bindSampler(NULL, ct, NULL);
}
- delete[] mTextures;
- delete[] mSamplers;
- delete[] mTextureTargets;
- delete[] mInputElements;
- delete[] mOutputElements;
- delete[] mConstantTypes;
- delete[] mConstants;
- delete[] mAttribNames;
- delete[] mUniformNames;
- delete[] mUniformArraySizes;
- mInputCount = 0;
- mOutputCount = 0;
- mConstantCount = 0;
+ delete[] mHal.state.textures;
+ delete[] mHal.state.samplers;
+ delete[] mHal.state.textureTargets;
+ delete[] mHal.state.inputElements;
+ delete[] mHal.state.constantTypes;
+ delete[] mHal.state.constants;
+ mHal.state.inputElementsCount = 0;
+ mHal.state.constantsCount = 0;
+ mHal.state.texturesCount = 0;
}
void Program::initMemberVars() {
mDirty = true;
- mShaderID = 0;
- mAttribCount = 0;
- mUniformCount = 0;
- mTextureCount = 0;
- mTextures = NULL;
- mSamplers = NULL;
- mTextureTargets = NULL;
- mInputElements = NULL;
- mOutputElements = NULL;
- mConstantTypes = NULL;
- mConstants = NULL;
- mAttribNames = NULL;
- mUniformNames = NULL;
- mUniformArraySizes = NULL;
- mInputCount = 0;
- mOutputCount = 0;
- mConstantCount = 0;
- mIsValid = false;
+ mHal.drv = NULL;
+ mHal.state.textures = NULL;
+ mHal.state.samplers = NULL;
+ mHal.state.textureTargets = NULL;
+ mHal.state.inputElements = NULL;
+ mHal.state.constantTypes = NULL;
+ mHal.state.constants = NULL;
+
+ mHal.state.inputElementsCount = 0;
+ mHal.state.constantsCount = 0;
+ mHal.state.texturesCount = 0;
+
mIsInternal = false;
}
void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot) {
if (alloc != NULL) {
- if (slot >= mConstantCount) {
+ if (slot >= mHal.state.constantsCount) {
LOGE("Attempt to bind alloc at slot %u, on shader id %u, but const count is %u",
- slot, (uint32_t)this, mConstantCount);
+ slot, (uint32_t)this, mHal.state.constantsCount);
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
return;
}
- if (!alloc->getType()->isEqual(mConstantTypes[slot].get())) {
+ if (!alloc->getType()->isEqual(mHal.state.constantTypes[slot].get())) {
LOGE("Attempt to bind alloc at slot %u, on shader id %u, but types mismatch",
slot, (uint32_t)this);
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
return;
}
}
- if (mConstants[slot].get() == alloc) {
+ if (mHal.state.constants[slot].get() == alloc) {
return;
}
- if (mConstants[slot].get()) {
- mConstants[slot].get()->removeProgramToDirty(this);
+ if (mHal.state.constants[slot].get()) {
+ mHal.state.constants[slot].get()->removeProgramToDirty(this);
}
- mConstants[slot].set(alloc);
+ mHal.state.constants[slot].set(alloc);
if (alloc) {
alloc->addProgramToDirty(this);
}
@@ -173,327 +142,38 @@ void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot) {
}
void Program::bindTexture(Context *rsc, uint32_t slot, Allocation *a) {
- if (slot >= mTextureCount) {
- LOGE("Attempt to bind texture to slot %u but tex count is %u", slot, mTextureCount);
+ if (slot >= mHal.state.texturesCount) {
+ LOGE("Attempt to bind texture to slot %u but tex count is %u", slot, mHal.state.texturesCount);
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind texture");
return;
}
- if (a && a->getType()->getDimFaces() && mTextureTargets[slot] != RS_TEXTURE_CUBE) {
+ if (a && a->getType()->getDimFaces() && mHal.state.textureTargets[slot] != RS_TEXTURE_CUBE) {
LOGE("Attempt to bind cubemap to slot %u but 2d texture needed", slot);
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind cubemap to 2d texture slot");
return;
}
//LOGE("bindtex %i %p", slot, a);
- mTextures[slot].set(a);
+ mHal.state.textures[slot].set(a);
mDirty = true;
}
void Program::bindSampler(Context *rsc, uint32_t slot, Sampler *s) {
- if (slot >= mTextureCount) {
- LOGE("Attempt to bind sampler to slot %u but tex count is %u", slot, mTextureCount);
+ if (slot >= mHal.state.texturesCount) {
+ LOGE("Attempt to bind sampler to slot %u but tex count is %u", slot, mHal.state.texturesCount);
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind sampler");
return;
}
- mSamplers[slot].set(s);
+ mHal.state.samplers[slot].set(s);
mDirty = true;
}
-String8 Program::getGLSLInputString() const {
- String8 s;
- for (uint32_t ct=0; ct < mInputCount; ct++) {
- const Element *e = mInputElements[ct].get();
- for (uint32_t field=0; field < e->getFieldCount(); field++) {
- const Element *f = e->getField(field);
-
- // Cannot be complex
- rsAssert(!f->getFieldCount());
- switch (f->getComponent().getVectorSize()) {
- case 1: s.append("attribute float ATTRIB_"); break;
- case 2: s.append("attribute vec2 ATTRIB_"); break;
- case 3: s.append("attribute vec3 ATTRIB_"); break;
- case 4: s.append("attribute vec4 ATTRIB_"); break;
- default:
- rsAssert(0);
- }
-
- s.append(e->getFieldName(field));
- s.append(";\n");
- }
- }
- return s;
-}
-
-String8 Program::getGLSLOutputString() const {
- return String8();
-}
-
-String8 Program::getGLSLConstantString() const {
- return String8();
-}
-
-void Program::createShader() {
-}
-
-bool Program::loadShader(Context *rsc, uint32_t type) {
- mShaderID = glCreateShader(type);
- rsAssert(mShaderID);
-
- if (rsc->props.mLogShaders) {
- LOGV("Loading shader type %x, ID %i", type, mShaderID);
- LOGV("%s", mShader.string());
- }
-
- if (mShaderID) {
- const char * ss = mShader.string();
- glShaderSource(mShaderID, 1, &ss, NULL);
- glCompileShader(mShaderID);
-
- GLint compiled = 0;
- glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- GLint infoLen = 0;
- glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
- if (infoLen) {
- char* buf = (char*) malloc(infoLen);
- if (buf) {
- glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
- LOGE("Could not compile shader \n%s\n", buf);
- free(buf);
- }
- glDeleteShader(mShaderID);
- mShaderID = 0;
- rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
- return false;
- }
- }
- }
-
- if (rsc->props.mLogShaders) {
- LOGV("--Shader load result %x ", glGetError());
- }
- mIsValid = true;
- return true;
-}
-
void Program::setShader(const char *txt, uint32_t len) {
mUserShader.setTo(txt, len);
}
-void Program::appendUserConstants() {
- for (uint32_t ct=0; ct < mConstantCount; ct++) {
- const Element *e = mConstantTypes[ct]->getElement();
- for (uint32_t field=0; field < e->getFieldCount(); field++) {
- const Element *f = e->getField(field);
- const char *fn = e->getFieldName(field);
-
- if (fn[0] == '#') {
- continue;
- }
-
- // Cannot be complex
- rsAssert(!f->getFieldCount());
- if (f->getType() == RS_TYPE_MATRIX_4X4) {
- mShader.append("uniform mat4 UNI_");
- } else if (f->getType() == RS_TYPE_MATRIX_3X3) {
- mShader.append("uniform mat3 UNI_");
- } else if (f->getType() == RS_TYPE_MATRIX_2X2) {
- mShader.append("uniform mat2 UNI_");
- } else {
- switch (f->getComponent().getVectorSize()) {
- case 1: mShader.append("uniform float UNI_"); break;
- case 2: mShader.append("uniform vec2 UNI_"); break;
- case 3: mShader.append("uniform vec3 UNI_"); break;
- case 4: mShader.append("uniform vec4 UNI_"); break;
- default:
- rsAssert(0);
- }
- }
-
- mShader.append(fn);
- if (e->getFieldArraySize(field) > 1) {
- mShader.appendFormat("[%d]", e->getFieldArraySize(field));
- }
- mShader.append(";\n");
- }
- }
-}
-
-void Program::logUniform(const Element *field, const float *fd, uint32_t arraySize ) {
- RsDataType dataType = field->getType();
- uint32_t elementSize = field->getSizeBytes() / sizeof(float);
- for (uint32_t i = 0; i < arraySize; i ++) {
- if (arraySize > 1) {
- LOGV("Array Element [%u]", i);
- }
- if (dataType == RS_TYPE_MATRIX_4X4) {
- LOGV("Matrix4x4");
- LOGV("{%f, %f, %f, %f", fd[0], fd[4], fd[8], fd[12]);
- LOGV(" %f, %f, %f, %f", fd[1], fd[5], fd[9], fd[13]);
- LOGV(" %f, %f, %f, %f", fd[2], fd[6], fd[10], fd[14]);
- LOGV(" %f, %f, %f, %f}", fd[3], fd[7], fd[11], fd[15]);
- } else if (dataType == RS_TYPE_MATRIX_3X3) {
- LOGV("Matrix3x3");
- LOGV("{%f, %f, %f", fd[0], fd[3], fd[6]);
- LOGV(" %f, %f, %f", fd[1], fd[4], fd[7]);
- LOGV(" %f, %f, %f}", fd[2], fd[5], fd[8]);
- } else if (dataType == RS_TYPE_MATRIX_2X2) {
- LOGV("Matrix2x2");
- LOGV("{%f, %f", fd[0], fd[2]);
- LOGV(" %f, %f}", fd[1], fd[3]);
- } else {
- switch (field->getComponent().getVectorSize()) {
- case 1:
- LOGV("Uniform 1 = %f", fd[0]);
- break;
- case 2:
- LOGV("Uniform 2 = %f %f", fd[0], fd[1]);
- break;
- case 3:
- LOGV("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
- break;
- case 4:
- LOGV("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
- break;
- default:
- rsAssert(0);
- }
- }
- LOGE("Element size %u data=%p", elementSize, fd);
- fd += elementSize;
- LOGE("New data=%p", fd);
- }
-}
-
-void Program::setUniform(Context *rsc, const Element *field, const float *fd,
- int32_t slot, uint32_t arraySize ) {
- RsDataType dataType = field->getType();
- if (dataType == RS_TYPE_MATRIX_4X4) {
- glUniformMatrix4fv(slot, arraySize, GL_FALSE, fd);
- } else if (dataType == RS_TYPE_MATRIX_3X3) {
- glUniformMatrix3fv(slot, arraySize, GL_FALSE, fd);
- } else if (dataType == RS_TYPE_MATRIX_2X2) {
- glUniformMatrix2fv(slot, arraySize, GL_FALSE, fd);
- } else {
- switch (field->getComponent().getVectorSize()) {
- case 1:
- glUniform1fv(slot, arraySize, fd);
- break;
- case 2:
- glUniform2fv(slot, arraySize, fd);
- break;
- case 3:
- glUniform3fv(slot, arraySize, fd);
- break;
- case 4:
- glUniform4fv(slot, arraySize, fd);
- break;
- default:
- rsAssert(0);
- }
- }
-}
-
-void Program::setupUserConstants(Context *rsc, ShaderCache *sc, bool isFragment) {
- uint32_t uidx = 0;
- for (uint32_t ct=0; ct < mConstantCount; ct++) {
- Allocation *alloc = mConstants[ct].get();
- if (!alloc) {
- LOGE("Attempting to set constants on shader id %u, but alloc at slot %u is not set", (uint32_t)this, ct);
- rsc->setError(RS_ERROR_BAD_SHADER, "No constant allocation bound");
- continue;
- }
-
- const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
- const Element *e = mConstantTypes[ct]->getElement();
- for (uint32_t field=0; field < e->getFieldCount(); field++) {
- const Element *f = e->getField(field);
- const char *fieldName = e->getFieldName(field);
- // If this field is padding, skip it
- if (fieldName[0] == '#') {
- continue;
- }
-
- uint32_t offset = e->getFieldOffsetBytes(field);
- const float *fd = reinterpret_cast<const float *>(&data[offset]);
-
- int32_t slot = -1;
- uint32_t arraySize = 1;
- if (!isFragment) {
- slot = sc->vtxUniformSlot(uidx);
- arraySize = sc->vtxUniformSize(uidx);
- } else {
- slot = sc->fragUniformSlot(uidx);
- arraySize = sc->fragUniformSize(uidx);
- }
- if (rsc->props.mLogShadersUniforms) {
- LOGV("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName);
- }
- uidx ++;
- if (slot < 0) {
- continue;
- }
-
- if (rsc->props.mLogShadersUniforms) {
- logUniform(f, fd, arraySize);
- }
- setUniform(rsc, f, fd, slot, arraySize);
- }
- }
-}
-
-void Program::initAttribAndUniformArray() {
- mAttribCount = 0;
- for (uint32_t ct=0; ct < mInputCount; ct++) {
- const Element *elem = mInputElements[ct].get();
- for (uint32_t field=0; field < elem->getFieldCount(); field++) {
- if (elem->getFieldName(field)[0] != '#') {
- mAttribCount ++;
- }
- }
- }
-
- mUniformCount = 0;
- for (uint32_t ct=0; ct < mConstantCount; ct++) {
- const Element *elem = mConstantTypes[ct]->getElement();
-
- for (uint32_t field=0; field < elem->getFieldCount(); field++) {
- if (elem->getFieldName(field)[0] != '#') {
- mUniformCount ++;
- }
- }
- }
- mUniformCount += mTextureCount;
-
- if (mAttribCount) {
- mAttribNames = new String8[mAttribCount];
- }
- if (mUniformCount) {
- mUniformNames = new String8[mUniformCount];
- mUniformArraySizes = new uint32_t[mUniformCount];
- }
-}
-
-void Program::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix) {
- rsAssert(e->getFieldCount());
- for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
- const Element *ce = e->getField(ct);
- if (ce->getFieldCount()) {
- initAddUserElement(ce, names, arrayLengths, count, prefix);
- } else if (e->getFieldName(ct)[0] != '#') {
- String8 tmp(prefix);
- tmp.append(e->getFieldName(ct));
- names[*count].setTo(tmp.string());
- if (arrayLengths) {
- arrayLengths[*count] = e->getFieldArraySize(ct);
- }
- (*count)++;
- }
- }
-}
-
namespace android {
namespace renderscript {
diff --git a/libs/rs/rsProgram.h b/libs/rs/rsProgram.h
index c48464d..bcf5519 100644
--- a/libs/rs/rsProgram.h
+++ b/libs/rs/rsProgram.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -23,7 +23,6 @@
// ---------------------------------------------------------------------------
namespace android {
namespace renderscript {
-class ShaderCache;
#define RS_SHADER_INTERNAL "//rs_shader_internal\n"
#define RS_SHADER_ATTR "ATTRIB_"
@@ -38,75 +37,53 @@ public:
virtual ~Program();
void bindAllocation(Context *, Allocation *, uint32_t slot);
- virtual void createShader();
bool isUserProgram() const {return !mIsInternal;}
void bindTexture(Context *, uint32_t slot, Allocation *);
void bindSampler(Context *, uint32_t slot, Sampler *);
- uint32_t getShaderID() const {return mShaderID;}
void setShader(const char *, uint32_t len);
- uint32_t getAttribCount() const {return mAttribCount;}
- uint32_t getUniformCount() const {return mUniformCount;}
- const String8 & getAttribName(uint32_t i) const {return mAttribNames[i];}
- const String8 & getUniformName(uint32_t i) const {return mUniformNames[i];}
- uint32_t getUniformArraySize(uint32_t i) const {return mUniformArraySizes[i];}
-
- String8 getGLSLInputString() const;
- String8 getGLSLOutputString() const;
- String8 getGLSLConstantString() const;
-
- bool isValid() const {return mIsValid;}
void forceDirty() const {mDirty = true;}
+ struct Hal {
+ mutable void *drv;
+
+ struct State {
+ // The difference between Textures and Constants is how they are accessed
+ // Texture lookups go though a sampler which in effect converts normalized
+ // coordinates into type specific. Multiple samples may also be taken
+ // and filtered.
+ //
+ // Constants are strictly accessed by the shader code
+ ObjectBaseRef<Allocation> *textures;
+ RsTextureTarget *textureTargets;
+ uint32_t texturesCount;
+
+ ObjectBaseRef<Sampler> *samplers;
+ uint32_t samplersCount;
+
+ ObjectBaseRef<Allocation> *constants;
+ ObjectBaseRef<Type> *constantTypes;
+ uint32_t constantsCount;
+
+ ObjectBaseRef<Element> *inputElements;
+ uint32_t inputElementsCount;
+ };
+ State state;
+ };
+ Hal mHal;
+
protected:
- // Components not listed in "in" will be passed though
- // unless overwritten by components in out.
- ObjectBaseRef<Element> *mInputElements;
- ObjectBaseRef<Element> *mOutputElements;
- ObjectBaseRef<Type> *mConstantTypes;
- ObjectBaseRef<Allocation> *mConstants;
- uint32_t mInputCount;
- uint32_t mOutputCount;
- uint32_t mConstantCount;
- bool mIsValid;
bool mIsInternal;
- // Applies to vertex and fragment shaders only
- void appendUserConstants();
- void setupUserConstants(Context *rsc, ShaderCache *sc, bool isFragment);
- void initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix);
-
- void initAttribAndUniformArray();
-
mutable bool mDirty;
- String8 mShader;
String8 mUserShader;
- uint32_t mShaderID;
-
- uint32_t mTextureCount;
- uint32_t mAttribCount;
- uint32_t mUniformCount;
- String8 *mAttribNames;
- String8 *mUniformNames;
- uint32_t *mUniformArraySizes;
void logUniform(const Element *field, const float *fd, uint32_t arraySize );
void setUniform(Context *rsc, const Element *field, const float *fd, int32_t slot, uint32_t arraySize );
void initMemberVars();
-
- // The difference between Textures and Constants is how they are accessed
- // Texture lookups go though a sampler which in effect converts normalized
- // coordinates into type specific. Multiple samples may also be taken
- // and filtered.
- //
- // Constants are strictly accessed by programetic loads.
- ObjectBaseRef<Allocation> *mTextures;
- ObjectBaseRef<Sampler> *mSamplers;
- RsTextureTarget *mTextureTargets;
- bool loadShader(Context *, uint32_t type);
};
}
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index ff314b7..39887ca 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -15,13 +15,6 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#endif //ANDROID_RS_SERIALIZE
-
#include "rsProgramFragment.h"
using namespace android;
@@ -31,19 +24,16 @@ ProgramFragment::ProgramFragment(Context *rsc, const char * shaderText,
uint32_t shaderLength, const uint32_t * params,
uint32_t paramLength)
: Program(rsc, shaderText, shaderLength, params, paramLength) {
-
mConstantColor[0] = 1.f;
mConstantColor[1] = 1.f;
mConstantColor[2] = 1.f;
mConstantColor[3] = 1.f;
- init(rsc);
+ mRSC->mHal.funcs.fragment.init(mRSC, this, mUserShader.string(), mUserShader.length());
}
ProgramFragment::~ProgramFragment() {
- if (mShaderID) {
- mRSC->mShaderCache.cleanupFragment(mShaderID);
- }
+ mRSC->mHal.funcs.fragment.destroy(mRSC, this);
}
void ProgramFragment::setConstantColor(Context *rsc, float r, float g, float b, float a) {
@@ -52,7 +42,7 @@ void ProgramFragment::setConstantColor(Context *rsc, float r, float g, float b,
rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set fixed function emulation color on user program");
return;
}
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
LOGE("Unable to set fixed function emulation color because allocation is missing");
rsc->setError(RS_ERROR_BAD_SHADER, "Unable to set fixed function emulation color because allocation is missing");
return;
@@ -61,11 +51,11 @@ void ProgramFragment::setConstantColor(Context *rsc, float r, float g, float b,
mConstantColor[1] = g;
mConstantColor[2] = b;
mConstantColor[3] = a;
- memcpy(mConstants[0]->getPtr(), mConstantColor, 4*sizeof(float));
+ memcpy(mHal.state.constants[0]->getPtr(), mConstantColor, 4*sizeof(float));
mDirty = true;
}
-void ProgramFragment::setupGL2(Context *rsc, ProgramFragmentState *state, ShaderCache *sc) {
+void ProgramFragment::setupGL2(Context *rsc, ProgramFragmentState *state) {
//LOGE("sgl2 frag1 %x", glGetError());
if ((state->mLast.get() == this) && !mDirty) {
return;
@@ -74,94 +64,16 @@ void ProgramFragment::setupGL2(Context *rsc, ProgramFragmentState *state, Shader
rsc->checkError("ProgramFragment::setupGL2 start");
- rsc->checkError("ProgramFragment::setupGL2 begin uniforms");
- setupUserConstants(rsc, sc, true);
-
- uint32_t numTexturesToBind = mTextureCount;
- uint32_t numTexturesAvailable = rsc->getMaxFragmentTextures();
- if (numTexturesToBind >= numTexturesAvailable) {
- LOGE("Attempting to bind %u textures on shader id %u, but only %u are available",
- mTextureCount, (uint32_t)this, numTexturesAvailable);
- rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind more textuers than available");
- numTexturesToBind = numTexturesAvailable;
- }
-
- for (uint32_t ct=0; ct < numTexturesToBind; ct++) {
- glActiveTexture(GL_TEXTURE0 + ct);
- if (!mTextures[ct].get()) {
+ for (uint32_t ct=0; ct < mHal.state.texturesCount; ct++) {
+ if (!mHal.state.textures[ct].get()) {
LOGE("No texture bound for shader id %u, texture unit %u", (uint)this, ct);
rsc->setError(RS_ERROR_BAD_SHADER, "No texture bound");
continue;
}
-
- mTextures[ct]->uploadCheck(rsc);
- GLenum target = (GLenum)mTextures[ct]->getGLTarget();
- if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) {
- LOGE("Attempting to bind unknown texture to shader id %u, texture unit %u", (uint)this, ct);
- rsc->setError(RS_ERROR_BAD_SHADER, "Non-texture allocation bound to a shader");
- }
- glBindTexture(target, mTextures[ct]->getTextureID());
- rsc->checkError("ProgramFragment::setupGL2 tex bind");
- if (mSamplers[ct].get()) {
- mSamplers[ct]->setupGL(rsc, mTextures[ct].get());
- } else {
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- rsc->checkError("ProgramFragment::setupGL2 tex env");
- }
-
- glUniform1i(sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct);
- rsc->checkError("ProgramFragment::setupGL2 uniforms");
- }
-
- glActiveTexture(GL_TEXTURE0);
- mDirty = false;
- rsc->checkError("ProgramFragment::setupGL2");
-}
-
-void ProgramFragment::loadShader(Context *rsc) {
- Program::loadShader(rsc, GL_FRAGMENT_SHADER);
-}
-
-void ProgramFragment::createShader() {
- if (mUserShader.length() > 1) {
- mShader.append("precision mediump float;\n");
- appendUserConstants();
- char buf[256];
- for (uint32_t ct=0; ct < mTextureCount; ct++) {
- if (mTextureTargets[ct] == RS_TEXTURE_2D) {
- snprintf(buf, sizeof(buf), "uniform sampler2D UNI_Tex%i;\n", ct);
- } else {
- snprintf(buf, sizeof(buf), "uniform samplerCube UNI_Tex%i;\n", ct);
- }
- mShader.append(buf);
- }
- mShader.append(mUserShader);
- } else {
- LOGE("ProgramFragment::createShader cannot create program, shader code not defined");
- rsAssert(0);
- }
-}
-
-void ProgramFragment::init(Context *rsc) {
- uint32_t uniformIndex = 0;
- if (mUserShader.size() > 0) {
- for (uint32_t ct=0; ct < mConstantCount; ct++) {
- initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformIndex, RS_SHADER_UNI);
- }
- }
- mTextureUniformIndexStart = uniformIndex;
- char buf[256];
- for (uint32_t ct=0; ct < mTextureCount; ct++) {
- snprintf(buf, sizeof(buf), "UNI_Tex%i", ct);
- mUniformNames[uniformIndex].setTo(buf);
- mUniformArraySizes[uniformIndex] = 1;
- uniformIndex++;
+ mHal.state.textures[ct]->uploadCheck(rsc);
}
- createShader();
+ rsc->mHal.funcs.fragment.setActive(rsc, this);
}
void ProgramFragment::serialize(OStream *stream) const {
diff --git a/libs/rs/rsProgramFragment.h b/libs/rs/rsProgramFragment.h
index 3d28946..7520af0 100644
--- a/libs/rs/rsProgramFragment.h
+++ b/libs/rs/rsProgramFragment.h
@@ -32,11 +32,8 @@ public:
uint32_t paramLength);
virtual ~ProgramFragment();
- virtual void setupGL2(Context *, ProgramFragmentState *, ShaderCache *sc);
+ virtual void setupGL2(Context *, ProgramFragmentState *);
- virtual void createShader();
- virtual void loadShader(Context *rsc);
- virtual void init(Context *rsc);
virtual void serialize(OStream *stream) const;
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_FRAGMENT; }
static ProgramFragment *createFromStream(Context *rsc, IStream *stream);
diff --git a/libs/rs/rsProgramStore.h b/libs/rs/rsProgramStore.h
index bfe276d..88a06a8 100644
--- a/libs/rs/rsProgramStore.h
+++ b/libs/rs/rsProgramStore.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -62,8 +62,6 @@ public:
RsDepthFunc depthFunc;
};
State state;
-
-
};
Hal mHal;
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index e407d3a..dfd732f 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -15,13 +15,6 @@
*/
#include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#endif //ANDROID_RS_SERIALIZE
-
#include "rsProgramVertex.h"
using namespace android;
@@ -32,57 +25,14 @@ ProgramVertex::ProgramVertex(Context *rsc, const char * shaderText,
uint32_t shaderLength, const uint32_t * params,
uint32_t paramLength)
: Program(rsc, shaderText, shaderLength, params, paramLength) {
- init(rsc);
+ mRSC->mHal.funcs.vertex.init(mRSC, this, mUserShader.string(), mUserShader.length());
}
ProgramVertex::~ProgramVertex() {
- if (mShaderID) {
- mRSC->mShaderCache.cleanupVertex(mShaderID);
- }
-}
-
-void ProgramVertex::loadShader(Context *rsc) {
- Program::loadShader(rsc, GL_VERTEX_SHADER);
-}
-
-void ProgramVertex::createShader(Context *rsc) {
- if (mUserShader.length() > 1) {
-
- appendUserConstants();
-
- for (uint32_t ct=0; ct < mInputCount; ct++) {
- const Element *e = mInputElements[ct].get();
- for (uint32_t field=0; field < e->getFieldCount(); field++) {
- const Element *f = e->getField(field);
- const char *fn = e->getFieldName(field);
-
- if (fn[0] == '#') {
- continue;
- }
-
- // Cannot be complex
- rsAssert(!f->getFieldCount());
- switch (f->getComponent().getVectorSize()) {
- case 1: mShader.append("attribute float ATTRIB_"); break;
- case 2: mShader.append("attribute vec2 ATTRIB_"); break;
- case 3: mShader.append("attribute vec3 ATTRIB_"); break;
- case 4: mShader.append("attribute vec4 ATTRIB_"); break;
- default:
- rsAssert(0);
- }
-
- mShader.append(fn);
- mShader.append(";\n");
- }
- }
- mShader.append(mUserShader);
- } else {
- rsc->setError(RS_ERROR_FATAL_UNKNOWN,
- "ProgramFragment::createShader cannot create program, shader code not defined");
- }
+ mRSC->mHal.funcs.vertex.destroy(mRSC, this);
}
-void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state, ShaderCache *sc) {
+void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state) {
if ((state->mLast.get() == this) && !mDirty) {
return;
}
@@ -90,12 +40,12 @@ void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state, ShaderCach
rsc->checkError("ProgramVertex::setupGL2 start");
if (!isUserProgram()) {
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
rsc->setError(RS_ERROR_FATAL_UNKNOWN,
"Unable to set fixed function emulation matrices because allocation is missing");
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
Matrix4x4 mvp;
mvp.load(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
Matrix4x4 t;
@@ -106,10 +56,10 @@ void ProgramVertex::setupGL2(Context *rsc, ProgramVertexState *state, ShaderCach
}
}
- rsc->checkError("ProgramVertex::setupGL2 begin uniforms");
- setupUserConstants(rsc, sc, false);
-
state->mLast.set(this);
+
+ rsc->mHal.funcs.vertex.setActive(rsc, this);
+
rsc->checkError("ProgramVertex::setupGL2");
}
@@ -119,12 +69,12 @@ void ProgramVertex::setProjectionMatrix(Context *rsc, const rsc_Matrix *m) const
"Attempting to set fixed function emulation matrix projection on user program");
return;
}
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
rsc->setError(RS_ERROR_FATAL_UNKNOWN,
"Unable to set fixed function emulation matrix projection because allocation is missing");
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix));
mDirty = true;
}
@@ -135,12 +85,12 @@ void ProgramVertex::setModelviewMatrix(Context *rsc, const rsc_Matrix *m) const
"Attempting to set fixed function emulation matrix modelview on user program");
return;
}
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
rsc->setError(RS_ERROR_FATAL_UNKNOWN,
"Unable to set fixed function emulation matrix modelview because allocation is missing");
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix));
mDirty = true;
}
@@ -151,12 +101,12 @@ void ProgramVertex::setTextureMatrix(Context *rsc, const rsc_Matrix *m) const {
"Attempting to set fixed function emulation matrix texture on user program");
return;
}
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
rsc->setError(RS_ERROR_FATAL_UNKNOWN,
"Unable to set fixed function emulation matrix texture because allocation is missing");
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix));
mDirty = true;
}
@@ -167,12 +117,12 @@ void ProgramVertex::getProjectionMatrix(Context *rsc, rsc_Matrix *m) const {
"Attempting to get fixed function emulation matrix projection on user program");
return;
}
- if (mConstants[0].get() == NULL) {
+ if (mHal.state.constants[0].get() == NULL) {
rsc->setError(RS_ERROR_FATAL_UNKNOWN,
"Unable to get fixed function emulation matrix projection because allocation is missing");
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
memcpy(m, &f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], sizeof(rsc_Matrix));
}
@@ -180,27 +130,13 @@ void ProgramVertex::transformToScreen(Context *rsc, float *v4out, const float *v
if (isUserProgram()) {
return;
}
- float *f = static_cast<float *>(mConstants[0]->getPtr());
+ float *f = static_cast<float *>(mHal.state.constants[0]->getPtr());
Matrix4x4 mvp;
mvp.loadMultiply((Matrix4x4 *)&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET],
(Matrix4x4 *)&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
mvp.vectorMultiply(v4out, v3in);
}
-void ProgramVertex::init(Context *rsc) {
- uint32_t attribCount = 0;
- uint32_t uniformCount = 0;
- if (mUserShader.size() > 0) {
- for (uint32_t ct=0; ct < mInputCount; ct++) {
- initAddUserElement(mInputElements[ct].get(), mAttribNames, NULL, &attribCount, RS_SHADER_ATTR);
- }
- for (uint32_t ct=0; ct < mConstantCount; ct++) {
- initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI);
- }
- }
- createShader(rsc);
-}
-
void ProgramVertex::serialize(OStream *stream) const {
}
diff --git a/libs/rs/rsProgramVertex.h b/libs/rs/rsProgramVertex.h
index 2a5c863..04224a7 100644
--- a/libs/rs/rsProgramVertex.h
+++ b/libs/rs/rsProgramVertex.h
@@ -31,7 +31,7 @@ public:
const uint32_t * params, uint32_t paramLength);
virtual ~ProgramVertex();
- virtual void setupGL2(Context *rsc, ProgramVertexState *state, ShaderCache *sc);
+ virtual void setupGL2(Context *rsc, ProgramVertexState *state);
void setProjectionMatrix(Context *, const rsc_Matrix *) const;
void getProjectionMatrix(Context *, rsc_Matrix *) const;
@@ -40,10 +40,6 @@ public:
void transformToScreen(Context *, float *v4out, const float *v3in) const;
- virtual void createShader(Context *);
- virtual void loadShader(Context *);
- virtual void init(Context *);
-
virtual void serialize(OStream *stream) const;
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_VERTEX; }
static ProgramVertex *createFromStream(Context *rsc, IStream *stream);
diff --git a/libs/rs/rsScriptC_LibGL.cpp b/libs/rs/rsScriptC_LibGL.cpp
index 71f1312..ecda485 100644
--- a/libs/rs/rsScriptC_LibGL.cpp
+++ b/libs/rs/rsScriptC_LibGL.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -21,6 +21,9 @@
#include "rsMatrix2x2.h"
#include "utils/Timers.h"
+#include "driver/rsdVertexArray.h"
+#include "driver/rsdShaderCache.h"
+#include "driver/rsdCore.h"
#define GL_GLEXT_PROTOTYPES
@@ -134,6 +137,11 @@ void rsrDrawQuadTexCoords(Context *rsc, Script *sc,
return;
}
+ RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+ if (!dc->gl.shaderCache->setup(rsc)) {
+ return;
+ }
+
//LOGE("Quad");
//LOGE("%4.2f, %4.2f, %4.2f", x1, y1, z1);
//LOGE("%4.2f, %4.2f, %4.2f", x2, y2, z2);
@@ -143,12 +151,12 @@ void rsrDrawQuadTexCoords(Context *rsc, Script *sc,
float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4};
const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4};
- VertexArray::Attrib attribs[2];
+ RsdVertexArray::Attrib attribs[2];
attribs[0].set(GL_FLOAT, 3, 12, false, (uint32_t)vtx, "ATTRIB_position");
attribs[1].set(GL_FLOAT, 2, 8, false, (uint32_t)tex, "ATTRIB_texture0");
- VertexArray va(attribs, 2);
- va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
+ RsdVertexArray va(attribs, 2);
+ va.setupGL2(rsc);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index cd2be94..10e3182 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -274,17 +274,16 @@ Type * Type::cloneAndResize2D(Context *rsc,
namespace android {
namespace renderscript {
-}
-}
-
-RsType rsaTypeCreate(RsContext con, RsElement _e, uint32_t dimX,
+RsType rsi_TypeCreate(Context *rsc, RsElement _e, uint32_t dimX,
uint32_t dimY, uint32_t dimZ, bool mips, bool faces) {
- Context *rsc = static_cast<Context *>(con);
Element *e = static_cast<Element *>(_e);
return Type::getType(rsc, e, dimX, dimY, dimZ, mips, faces);
}
+}
+}
+
void rsaTypeGetNativeData(RsContext con, RsType type, uint32_t *typeData, uint32_t typeDataSize) {
rsAssert(typeDataSize == 6);
// Pack the data in the follofing way mDimX; mDimY; mDimZ;
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 90ae039..086db33 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -18,7 +18,6 @@
#define ANDROID_STRUCTURED_TYPE_H
#include "rsElement.h"
-#include "rsVertexArray.h"
// ---------------------------------------------------------------------------
namespace android {
diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h
index 4283d4a..d2f273b 100644
--- a/libs/rs/rs_hal.h
+++ b/libs/rs/rs_hal.h
@@ -32,6 +32,9 @@ class Script;
class ScriptC;
class ProgramStore;
class ProgramRaster;
+class ProgramVertex;
+class ProgramFragment;
+class Mesh;
typedef void *(*RsHalSymbolLookupFunc)(void *usrptr, char const *symbolName);
@@ -98,6 +101,25 @@ typedef struct {
void (*destroy)(const Context *rsc, const ProgramRaster *ps);
} raster;
+ struct {
+ bool (*init)(const Context *rsc, const ProgramVertex *pv,
+ const char* shader, uint32_t shaderLen);
+ void (*setActive)(const Context *rsc, const ProgramVertex *pv);
+ void (*destroy)(const Context *rsc, const ProgramVertex *pv);
+ } vertex;
+
+ struct {
+ bool (*init)(const Context *rsc, const ProgramFragment *pf,
+ const char* shader, uint32_t shaderLen);
+ void (*setActive)(const Context *rsc, const ProgramFragment *pf);
+ void (*destroy)(const Context *rsc, const ProgramFragment *pf);
+ } fragment;
+
+ struct {
+ bool (*init)(const Context *rsc, const Mesh *m);
+ void (*draw)(const Context *rsc, const Mesh *m, uint32_t primIndex, uint32_t start, uint32_t len);
+ void (*destroy)(const Context *rsc, const Mesh *m);
+ } mesh;
} RsdHalFunctions;
diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c
index 0059f19..0e914fc 100644
--- a/libs/rs/rsg_generator.c
+++ b/libs/rs/rsg_generator.c
@@ -97,9 +97,20 @@ void printStructures(FILE *f) {
}
}
-void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext) {
+void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext, int isFnPtr) {
printVarTypeAndName(f, &api->ret);
- fprintf(f, " %s%s (", prefix, api->name);
+ if (isFnPtr) {
+ char t[1024];
+ strcpy(t, api->name);
+ if (strlen(prefix) == 0) {
+ if (t[0] > 'A' && t[0] < 'Z') {
+ t[0] -= 'A' - 'a';
+ }
+ }
+ fprintf(f, " (* %s%s) (", prefix, api->name);
+ } else {
+ fprintf(f, " %s%s (", prefix, api->name);
+ }
if (!api->nocontext) {
if (addContext) {
fprintf(f, "Context *");
@@ -114,12 +125,24 @@ void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addCont
void printFuncDecls(FILE *f, const char *prefix, int addContext) {
int ct;
for (ct=0; ct < apiCount; ct++) {
- printFuncDecl(f, &apis[ct], prefix, addContext);
+ printFuncDecl(f, &apis[ct], prefix, addContext, 0);
fprintf(f, ";\n");
}
fprintf(f, "\n\n");
}
+void printFuncPointers(FILE *f, int addContext) {
+ fprintf(f, "\n");
+ fprintf(f, "typedef struct RsApiEntrypoints {\n");
+ int ct;
+ for (ct=0; ct < apiCount; ct++) {
+ fprintf(f, " ");
+ printFuncDecl(f, &apis[ct], "", addContext, 1);
+ fprintf(f, ";\n");
+ }
+ fprintf(f, "} RsApiEntrypoints_t;\n\n");
+}
+
void printPlaybackFuncs(FILE *f, const char *prefix) {
int ct;
for (ct=0; ct < apiCount; ct++) {
@@ -134,7 +157,8 @@ 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]) {
+ // Temporarly disable inbanding while we sort though the bugs.
+ if (1|| api->sync || api->ret.typeName[0]) {
return 0;
}
for (ct=0; ct < api->paramCount; ct++) {
@@ -172,21 +196,35 @@ void printApiCpp(FILE *f) {
fprintf(f, "#include \"rsHandcode.h\"\n");
fprintf(f, "\n");
+ printFuncPointers(f, 0);
+
+ // Generate RS funcs for local fifo
for (ct=0; ct < apiCount; ct++) {
int needFlush = 0;
const ApiEntry * api = &apis[ct];
- if (api->direct) {
- continue;
- }
-
- printFuncDecl(f, api, "rs", 0);
+ fprintf(f, "static ");
+ printFuncDecl(f, api, "LF_", 0, 0);
fprintf(f, "\n{\n");
- if (api->handcodeApi) {
- fprintf(f, " rsHCAPI_%s(rsc", api->name);
+ if (api->handcodeApi || api->direct) {
+ if (api->handcodeApi) {
+ fprintf(f, " rsHCAPI_%s(rsc", api->name);
+ } else {
+ fprintf(f, " ");
+ if (api->ret.typeName[0]) {
+ fprintf(f, "return ");
+ }
+ fprintf(f, "rsi_%s(", api->name);
+ if (!api->nocontext) {
+ fprintf(f, "(Context *)rsc");
+ }
+ }
for (ct2=0; ct2 < api->paramCount; ct2++) {
const VarType *vt = &api->params[ct2];
- fprintf(f, ", %s", vt->name);
+ if (ct2 > 0 || !api->nocontext) {
+ fprintf(f, ", ");
+ }
+ fprintf(f, "%s", vt->name);
}
fprintf(f, ");\n");
} else {
@@ -203,9 +241,11 @@ void printApiCpp(FILE *f) {
}
//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);
if (hasInlineDataPointers(api)) {
+ fprintf(f, " RS_CMD_%s *cmd = static_cast<RS_CMD_%s *>(io->mToCore.reserve(dataSize + sizeof(RS_CMD_%s)));\n", api->name, api->name, api->name);
fprintf(f, " uint8_t *payload = (uint8_t *)&cmd[1];\n");
+ } else {
+ 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);
}
for (ct2=0; ct2 < api->paramCount; ct2++) {
@@ -252,6 +292,43 @@ void printApiCpp(FILE *f) {
}
fprintf(f, "};\n\n");
}
+
+ fprintf(f, "\n");
+ fprintf(f, "static RsApiEntrypoints_t s_LocalTable = {\n");
+ for (ct=0; ct < apiCount; ct++) {
+ fprintf(f, " LF_%s,\n", apis[ct].name);
+ }
+ fprintf(f, "};\n");
+
+ fprintf(f, "static RsApiEntrypoints_t *s_CurrentTable = &s_LocalTable;\n\n");
+
+ for (ct=0; ct < apiCount; ct++) {
+ int needFlush = 0;
+ const ApiEntry * api = &apis[ct];
+
+ printFuncDecl(f, api, "rs", 0, 0);
+ fprintf(f, "\n{\n");
+ fprintf(f, " ");
+ if (api->ret.typeName[0]) {
+ fprintf(f, "return ");
+ }
+ fprintf(f, "s_CurrentTable->%s(", api->name);
+
+ if (!api->nocontext) {
+ fprintf(f, "(Context *)rsc");
+ }
+
+ for (ct2=0; ct2 < api->paramCount; ct2++) {
+ const VarType *vt = &api->params[ct2];
+ if (ct2 > 0 || !api->nocontext) {
+ fprintf(f, ", ");
+ }
+ fprintf(f, "%s", vt->name);
+ }
+ fprintf(f, ");\n");
+ fprintf(f, "}\n\n");
+ }
+
}
void printPlaybackCpp(FILE *f) {
@@ -373,6 +450,19 @@ int main(int argc, char **argv) {
printPlaybackCpp(f);
}
break;
+
+ case '4': // rsgApiStream.cpp
+ {
+ printFileHeader(f);
+ printPlaybackCpp(f);
+ }
+
+ case '5': // rsgApiStreamReplay.cpp
+ {
+ printFileHeader(f);
+ printPlaybackCpp(f);
+ }
+ break;
}
fclose(f);
return 0;
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index cc689bb..2817df8 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/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 5865b92..b914169 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1228,6 +1228,84 @@ public class MediaPlayer
public native void attachAuxEffect(int effectId);
/**
+ * Sets the parameter indicated by key.
+ * @param key key indicates the parameter to be set.
+ * @param value value of the parameter to be set.
+ * @return true if the parameter is set successfully, false otherwise
+ * {@hide}
+ */
+ public native boolean setParameter(int key, Parcel value);
+
+ /**
+ * Sets the parameter indicated by key.
+ * @param key key indicates the parameter to be set.
+ * @param value value of the parameter to be set.
+ * @return true if the parameter is set successfully, false otherwise
+ * {@hide}
+ */
+ public boolean setParameter(int key, String value) {
+ Parcel p = Parcel.obtain();
+ p.writeString(value);
+ return setParameter(key, p);
+ }
+
+ /**
+ * Sets the parameter indicated by key.
+ * @param key key indicates the parameter to be set.
+ * @param value value of the parameter to be set.
+ * @return true if the parameter is set successfully, false otherwise
+ * {@hide}
+ */
+ public boolean setParameter(int key, int value) {
+ Parcel p = Parcel.obtain();
+ p.writeInt(value);
+ return setParameter(key, p);
+ }
+
+ /**
+ * Gets the value of the parameter indicated by key.
+ * @param key key indicates the parameter to get.
+ * @param reply value of the parameter to get.
+ */
+ private native void getParameter(int key, Parcel reply);
+
+ /**
+ * Gets the value of the parameter indicated by key.
+ * @param key key indicates the parameter to get.
+ * @return value of the parameter.
+ * {@hide}
+ */
+ public Parcel getParcelParameter(int key) {
+ Parcel p = Parcel.obtain();
+ getParameter(key, p);
+ return p;
+ }
+
+ /**
+ * Gets the value of the parameter indicated by key.
+ * @param key key indicates the parameter to get.
+ * @return value of the parameter.
+ * {@hide}
+ */
+ public String getStringParameter(int key) {
+ Parcel p = Parcel.obtain();
+ getParameter(key, p);
+ return p.readString();
+ }
+
+ /**
+ * Gets the value of the parameter indicated by key.
+ * @param key key indicates the parameter to get.
+ * @return value of the parameter.
+ * {@hide}
+ */
+ public int getIntParameter(int key) {
+ Parcel p = Parcel.obtain();
+ getParameter(key, p);
+ return p.readInt();
+ }
+
+ /**
* Sets the send level of the player to the attached auxiliary effect
* {@see #attachAuxEffect(int)}. The level value range is 0 to 1.0.
* <p>By default the send level is 0, so even if an effect is attached to the player
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 80cc94e..790eaa3 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -431,34 +431,8 @@ public class MediaScanner
mFileSize = fileSize;
if (!isDirectory) {
- // special case certain file names
- // I use regionMatches() instead of substring() below
- // to avoid memory allocation
- int lastSlash = path.lastIndexOf('/');
- if (lastSlash >= 0 && lastSlash + 2 < path.length()) {
- if (!noMedia) {
- // ignore those ._* files created by MacOS
- if (path.regionMatches(lastSlash + 1, "._", 0, 2)) {
- noMedia = true;
- }
-
- // ignore album art files created by Windows Media Player:
- // Folder.jpg, AlbumArtSmall.jpg, AlbumArt_{...}_Large.jpg
- // and AlbumArt_{...}_Small.jpg
- if (path.regionMatches(true, path.length() - 4, ".jpg", 0, 4)) {
- if (path.regionMatches(true, lastSlash + 1, "AlbumArt_{", 0, 10) ||
- path.regionMatches(true, lastSlash + 1, "AlbumArt.", 0, 9)) {
- noMedia = true;
- }
- int length = path.length() - lastSlash - 1;
- if ((length == 17 && path.regionMatches(
- true, lastSlash + 1, "AlbumArtSmall", 0, 13)) ||
- (length == 10
- && path.regionMatches(true, lastSlash + 1, "Folder", 0, 6))) {
- noMedia = true;
- }
- }
- }
+ if (!noMedia && isNoMediaFile(path)) {
+ noMedia = true;
}
mNoMedia = noMedia;
@@ -1231,6 +1205,40 @@ public class MediaScanner
}
}
+ private static boolean isNoMediaFile(String path) {
+ File file = new File(path);
+ if (file.isDirectory()) return false;
+
+ // special case certain file names
+ // I use regionMatches() instead of substring() below
+ // to avoid memory allocation
+ int lastSlash = path.lastIndexOf('/');
+ if (lastSlash >= 0 && lastSlash + 2 < path.length()) {
+ // ignore those ._* files created by MacOS
+ if (path.regionMatches(lastSlash + 1, "._", 0, 2)) {
+ return true;
+ }
+
+ // ignore album art files created by Windows Media Player:
+ // Folder.jpg, AlbumArtSmall.jpg, AlbumArt_{...}_Large.jpg
+ // and AlbumArt_{...}_Small.jpg
+ if (path.regionMatches(true, path.length() - 4, ".jpg", 0, 4)) {
+ if (path.regionMatches(true, lastSlash + 1, "AlbumArt_{", 0, 10) ||
+ path.regionMatches(true, lastSlash + 1, "AlbumArt.", 0, 9)) {
+ return true;
+ }
+ int length = path.length() - lastSlash - 1;
+ if ((length == 17 && path.regionMatches(
+ true, lastSlash + 1, "AlbumArtSmall", 0, 13)) ||
+ (length == 10
+ && path.regionMatches(true, lastSlash + 1, "Folder", 0, 6))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public static boolean isNoMediaPath(String path) {
if (path == null) return false;
@@ -1252,7 +1260,7 @@ public class MediaScanner
}
offset = slashIndex;
}
- return false;
+ return isNoMediaFile(path);
}
public void scanMtpFile(String path, String volumeName, int objectHandle, int format) {
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 23a77d4..8763ebd 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -814,6 +814,39 @@ android_media_MediaPlayer_pullBatteryData(JNIEnv *env, jobject thiz, jobject jav
return service->pullBatteryData(reply);
}
+static jboolean
+android_media_MediaPlayer_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request)
+{
+ LOGV("setParameter: key %d", key);
+ sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+ if (mp == NULL ) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return false;
+ }
+
+ Parcel *request = parcelForJavaObject(env, java_request);
+ status_t err = mp->setParameter(key, *request);
+ if (err == OK) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static void
+android_media_MediaPlayer_getParameter(JNIEnv *env, jobject thiz, jint key, jobject java_reply)
+{
+ LOGV("getParameter: key %d", key);
+ sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+ if (mp == NULL ) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return;
+ }
+
+ Parcel *reply = parcelForJavaObject(env, java_reply);
+ process_media_player_call(env, thiz, mp->getParameter(key, reply), NULL, NULL );
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -850,6 +883,8 @@ static JNINativeMethod gMethods[] = {
{"setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel},
{"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect},
{"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData},
+ {"setParameter", "(ILandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_setParameter},
+ {"getParameter", "(ILandroid/os/Parcel;)V", (void *)android_media_MediaPlayer_getParameter},
};
static const char* const kClassPathName = "android/media/MediaPlayer";
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 8885bd5..76a8a91 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -48,6 +48,8 @@ enum {
SET_AUX_EFFECT_SEND_LEVEL,
ATTACH_AUX_EFFECT,
SET_VIDEO_SURFACETEXTURE,
+ SET_PARAMETER,
+ GET_PARAMETER,
};
class BpMediaPlayer: public BpInterface<IMediaPlayer>
@@ -236,6 +238,26 @@ public:
return reply.readInt32();
}
+ status_t setParameter(int key, const Parcel& request)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeInt32(key);
+ if (request.dataSize() > 0) {
+ data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize());
+ }
+ remote()->transact(SET_PARAMETER, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t getParameter(int key, Parcel *reply)
+ {
+ Parcel data;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeInt32(key);
+ return remote()->transact(GET_PARAMETER, data, reply);
+ }
+
};
IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -361,6 +383,23 @@ status_t BnMediaPlayer::onTransact(
reply->writeInt32(attachAuxEffect(data.readInt32()));
return NO_ERROR;
} break;
+ case SET_PARAMETER: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ int key = data.readInt32();
+
+ Parcel request;
+ if (data.dataAvail() > 0) {
+ request.appendFrom(
+ const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
+ }
+ request.setDataPosition(0);
+ reply->writeInt32(setParameter(key, request));
+ return NO_ERROR;
+ } break;
+ case GET_PARAMETER: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ return getParameter(data.readInt32(), reply);
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 4e22175..28c8642 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -135,20 +135,21 @@ status_t MediaScanner::doProcessDirectory(
}
if (type == DT_REG || type == DT_DIR) {
if (type == DT_DIR) {
+ bool childNoMedia = noMedia;
// set noMedia flag on directories with a name that starts with '.'
// for example, the Mac ".Trashes" directory
if (name[0] == '.')
- noMedia = true;
+ childNoMedia = true;
// report the directory to the client
if (stat(path, &statbuf) == 0) {
- client.scanFile(path, statbuf.st_mtime, 0, true, noMedia);
+ client.scanFile(path, statbuf.st_mtime, 0, true, childNoMedia);
}
// and now process its contents
strcat(fileSpot, "/");
int err = doProcessDirectory(path, pathRemaining - nameLength - 1, client,
- noMedia, exceptionCheck, exceptionEnv);
+ childNoMedia, exceptionCheck, exceptionEnv);
if (err) {
// pass exceptions up - ignore other errors
if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 9daa80f..28e07ff 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -553,6 +553,28 @@ status_t MediaPlayer::attachAuxEffect(int effectId)
return mPlayer->attachAuxEffect(effectId);
}
+status_t MediaPlayer::setParameter(int key, const Parcel& request)
+{
+ LOGV("MediaPlayer::setParameter(%d)", key);
+ Mutex::Autolock _l(mLock);
+ if (mPlayer != NULL) {
+ return mPlayer->setParameter(key, request);
+ }
+ LOGV("setParameter: no active player");
+ return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::getParameter(int key, Parcel *reply)
+{
+ LOGV("MediaPlayer::getParameter(%d)", key);
+ Mutex::Autolock _l(mLock);
+ if (mPlayer != NULL) {
+ return mPlayer->getParameter(key, reply);
+ }
+ LOGV("getParameter: no active player");
+ return INVALID_OPERATION;
+}
+
void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
{
LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 9dd353b..3b2cf10 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1024,6 +1024,20 @@ status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
return NO_ERROR;
}
+status_t MediaPlayerService::Client::setParameter(int key, const Parcel &request) {
+ LOGV("[%d] setParameter(%d)", mConnId, key);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->setParameter(key, request);
+}
+
+status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
+ LOGV("[%d] getParameter(%d)", mConnId, key);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->getParameter(key, reply);
+}
+
void MediaPlayerService::Client::notify(
void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
{
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 31b518e..6c4071f 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -279,6 +279,8 @@ private:
Parcel *reply);
virtual status_t setAuxEffectSendLevel(float level);
virtual status_t attachAuxEffect(int effectId);
+ virtual status_t setParameter(int key, const Parcel &request);
+ virtual status_t getParameter(int key, Parcel *reply);
sp<MediaPlayerBase> createPlayer(player_type playerType);
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index a98231c..b35696f 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -55,6 +55,13 @@ public:
virtual status_t invoke(const Parcel& request, Parcel *reply) {
return INVALID_OPERATION;
}
+ virtual status_t setParameter(int key, const Parcel &request) {
+ return INVALID_OPERATION;
+ }
+ virtual status_t getParameter(int key, Parcel *reply) {
+ return INVALID_OPERATION;
+ }
+
private:
status_t createOutputTrack();
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 6429395..02ec911 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -177,6 +177,16 @@ void StagefrightPlayer::setAudioSink(const sp<AudioSink> &audioSink) {
mPlayer->setAudioSink(audioSink);
}
+status_t StagefrightPlayer::setParameter(int key, const Parcel &request) {
+ LOGV("setParameter");
+ return mPlayer->setParameter(key, request);
+}
+
+status_t StagefrightPlayer::getParameter(int key, Parcel *reply) {
+ LOGV("getParameter");
+ return mPlayer->getParameter(key, reply);
+}
+
status_t StagefrightPlayer::getMetadata(
const media::Metadata::Filter& ids, Parcel *records) {
using media::Metadata;
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index e2796d2..ddd37e4 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -55,6 +55,8 @@ public:
virtual player_type playerType();
virtual status_t invoke(const Parcel &request, Parcel *reply);
virtual void setAudioSink(const sp<AudioSink> &audioSink);
+ virtual status_t setParameter(int key, const Parcel &request);
+ virtual status_t getParameter(int key, Parcel *reply);
virtual status_t getMetadata(
const media::Metadata::Filter& ids, Parcel *records);
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
index d9c3db3..802a11b 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -99,6 +99,12 @@ class TestPlayerStub : public MediaPlayerInterface {
virtual status_t invoke(const android::Parcel& in, android::Parcel *out) {
return mPlayer->invoke(in, out);
}
+ virtual status_t setParameter(int key, const Parcel &request) {
+ return mPlayer->setParameter(key, request);
+ }
+ virtual status_t getParameter(int key, Parcel *reply) {
+ return mPlayer->getParameter(key, reply);
+ }
// @return true if the current build is 'eng' or 'test' and the
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 0eca958..e1213f4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -246,6 +246,14 @@ void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
mPlayer->setAudioSink(audioSink);
}
+status_t NuPlayerDriver::setParameter(int key, const Parcel &request) {
+ return INVALID_OPERATION;
+}
+
+status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
+ return INVALID_OPERATION;
+}
+
status_t NuPlayerDriver::getMetadata(
const media::Metadata::Filter& ids, Parcel *records) {
return INVALID_OPERATION;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 67d0f3e..145fd80 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -52,6 +52,8 @@ struct NuPlayerDriver : public MediaPlayerInterface {
virtual player_type playerType();
virtual status_t invoke(const Parcel &request, Parcel *reply);
virtual void setAudioSink(const sp<AudioSink> &audioSink);
+ virtual status_t setParameter(int key, const Parcel &request);
+ virtual status_t getParameter(int key, Parcel *reply);
virtual status_t getMetadata(
const media::Metadata::Filter& ids, Parcel *records);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 1bfdd8e..974efa7 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -312,7 +312,7 @@ status_t AwesomePlayer::setDataSource_l(
if (mDecryptHandle != NULL) {
CHECK(mDrmManagerClient);
if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
- notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
}
}
@@ -1801,7 +1801,7 @@ status_t AwesomePlayer::finishSetDataSource_l() {
if (mDecryptHandle != NULL) {
CHECK(mDrmManagerClient);
if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
- notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
}
}
@@ -1905,4 +1905,11 @@ void AwesomePlayer::postAudioSeekComplete() {
postCheckAudioStatusEvent_l(0 /* delayUs */);
}
+status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
+ return OK;
+}
+
+status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
+ return OK;
+}
} // namespace android
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index c4ed516..1f3d581 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -146,18 +146,14 @@ status_t DRMSource::read(MediaBuffer **buffer, const ReadOptions *options) {
DrmBuffer *pDecryptedDrmBuffer = &decryptedDrmBuffer;
if ((err = mDrmManagerClient->decrypt(mDecryptHandle, mTrackId,
- &encryptedDrmBuffer, &pDecryptedDrmBuffer)) != DRM_NO_ERROR) {
+ &encryptedDrmBuffer, &pDecryptedDrmBuffer)) != NO_ERROR) {
if (decryptedDrmBuffer.data) {
delete [] decryptedDrmBuffer.data;
decryptedDrmBuffer.data = NULL;
}
- if (err == DRM_ERROR_LICENSE_EXPIRED) {
- return ERROR_NO_LICENSE;
- } else {
- return ERROR_IO;
- }
+ return err;
}
CHECK(pDecryptedDrmBuffer == &decryptedDrmBuffer);
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 8c61064..2c17d92 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -88,6 +88,9 @@ struct AwesomePlayer {
status_t getDuration(int64_t *durationUs);
status_t getPosition(int64_t *positionUs);
+ status_t setParameter(int key, const Parcel &request);
+ status_t getParameter(int key, Parcel *reply);
+
status_t seekTo(int64_t timeUs);
// This is a mask of MediaExtractor::Flags.
diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp
index d571106..ed3051b 100644
--- a/media/tests/players/invoke_mock_media_player.cpp
+++ b/media/tests/players/invoke_mock_media_player.cpp
@@ -84,6 +84,9 @@ class Player: public MediaPlayerBase
virtual status_t setLooping(int loop) {return OK;}
virtual player_type playerType() {return TEST_PLAYER;}
virtual status_t invoke(const Parcel& request, Parcel *reply);
+ virtual status_t setParameter(int key, const Parcel &request) {return OK;}
+ virtual status_t getParameter(int key, Parcel *reply) {return OK;}
+
private:
// Take a request, copy it to the reply.
diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java
index 8a7124d..f162d40 100644
--- a/opengl/java/com/google/android/gles_jni/EGLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java
@@ -18,10 +18,10 @@ package com.google.android.gles_jni;
import javax.microedition.khronos.egl.*;
+import android.graphics.SurfaceTexture;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
-import android.view.View;
public class EGLImpl implements EGL10 {
private EGLContextImpl mContext = new EGLContextImpl(-1);
@@ -71,19 +71,28 @@ public class EGLImpl implements EGL10 {
}
public EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list) {
- Surface sur;
+ Surface sur = null;
if (native_window instanceof SurfaceView) {
SurfaceView surfaceView = (SurfaceView)native_window;
sur = surfaceView.getHolder().getSurface();
} else if (native_window instanceof SurfaceHolder) {
SurfaceHolder holder = (SurfaceHolder)native_window;
sur = holder.getSurface();
+ }
+
+ int eglSurfaceId;
+ if (sur != null) {
+ eglSurfaceId = _eglCreateWindowSurface(display, config, sur, attrib_list);
+ } else if (native_window instanceof SurfaceTexture) {
+ eglSurfaceId = _eglCreateWindowSurfaceTexture(display, config,
+ ((SurfaceTexture) native_window).mSurfaceTexture, attrib_list);
} else {
throw new java.lang.UnsupportedOperationException(
"eglCreateWindowSurface() can only be called with an instance of " +
- "SurfaceView or SurfaceHolder at the moment, this will be fixed later.");
+ "SurfaceView, SurfaceHolder or SurfaceTexture at the moment, " +
+ "this will be fixed later.");
}
- int eglSurfaceId = _eglCreateWindowSurface(display, config, sur, attrib_list);
+
if (eglSurfaceId == 0) {
return EGL10.EGL_NO_SURFACE;
}
@@ -134,6 +143,7 @@ public class EGLImpl implements EGL10 {
private native int _eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list);
private native void _eglCreatePixmapSurface(EGLSurface sur, EGLDisplay display, EGLConfig config, Object native_pixmap, int[] attrib_list);
private native int _eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
+ private native int _eglCreateWindowSurfaceTexture(EGLDisplay display, EGLConfig config, int native_window, int[] attrib_list);
private native int _eglGetDisplay(Object native_display);
private native int _eglGetCurrentContext();
private native int _eglGetCurrentDisplay();
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index a1cb23a..97e913ba 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -41,8 +41,6 @@
#include <private/ui/android_natives_priv.h>
-#include <hardware/copybit.h>
-
#include "context.h"
#include "state.h"
#include "texture.h"
@@ -238,7 +236,6 @@ private:
android_native_buffer_t* buffer;
android_native_buffer_t* previousBuffer;
gralloc_module_t const* module;
- copybit_device_t* blitengine;
int width;
int height;
void* bits;
@@ -324,24 +321,6 @@ private:
ssize_t count;
};
- struct region_iterator : public copybit_region_t {
- region_iterator(const Region& region)
- : b(region.begin()), e(region.end()) {
- this->next = iterate;
- }
- private:
- static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
- region_iterator const* me = static_cast<region_iterator const*>(self);
- if (me->b != me->e) {
- *reinterpret_cast<Rect*>(rect) = *me->b++;
- return 1;
- }
- return 0;
- }
- mutable Region::const_iterator b;
- Region::const_iterator const e;
- };
-
void copyBlt(
android_native_buffer_t* dst, void* dst_vaddr,
android_native_buffer_t* src, void const* src_vaddr,
@@ -357,16 +336,8 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
ANativeWindow* window)
: egl_surface_t(dpy, config, depthFormat),
nativeWindow(window), buffer(0), previousBuffer(0), module(0),
- blitengine(0), bits(NULL)
+ bits(NULL)
{
- hw_module_t const* pModule;
- hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule);
- module = reinterpret_cast<gralloc_module_t const*>(pModule);
-
- if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &pModule) == 0) {
- copybit_open(pModule, &blitengine);
- }
-
pixelFormatTable = gglGetPixelFormatTable();
// keep a reference on the window
@@ -383,9 +354,6 @@ egl_window_surface_v2_t::~egl_window_surface_v2_t() {
previousBuffer->common.decRef(&previousBuffer->common);
}
nativeWindow->common.decRef(&nativeWindow->common);
- if (blitengine) {
- copybit_close(blitengine);
- }
}
EGLBoolean egl_window_surface_v2_t::connect()
@@ -472,63 +440,35 @@ void egl_window_surface_v2_t::copyBlt(
android_native_buffer_t* src, void const* src_vaddr,
const Region& clip)
{
- // FIXME: use copybit if possible
// NOTE: dst and src must be the same format
- status_t err = NO_ERROR;
- copybit_device_t* const copybit = blitengine;
- if (copybit) {
- copybit_image_t simg;
- simg.w = src->stride;
- simg.h = src->height;
- simg.format = src->format;
- simg.handle = const_cast<native_handle_t*>(src->handle);
-
- copybit_image_t dimg;
- dimg.w = dst->stride;
- dimg.h = dst->height;
- dimg.format = dst->format;
- dimg.handle = const_cast<native_handle_t*>(dst->handle);
-
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
- copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
- region_iterator it(clip);
- err = copybit->blit(copybit, &dimg, &simg, &it);
- if (err != NO_ERROR) {
- LOGE("copybit failed (%s)", strerror(err));
- }
- }
-
- if (!copybit || err) {
- Region::const_iterator cur = clip.begin();
- Region::const_iterator end = clip.end();
-
- const size_t bpp = pixelFormatTable[src->format].size;
- const size_t dbpr = dst->stride * bpp;
- const size_t sbpr = src->stride * bpp;
-
- uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
- uint8_t * const dst_bits = (uint8_t *)dst_vaddr;
-
- while (cur != end) {
- const Rect& r(*cur++);
- ssize_t w = r.right - r.left;
- ssize_t h = r.bottom - r.top;
- if (w <= 0 || h<=0) continue;
- size_t size = w * bpp;
- uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
- uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
- if (dbpr==sbpr && size==sbpr) {
- size *= h;
- h = 1;
- }
- do {
- memcpy(d, s, size);
- d += dbpr;
- s += sbpr;
- } while (--h > 0);
+ Region::const_iterator cur = clip.begin();
+ Region::const_iterator end = clip.end();
+
+ const size_t bpp = pixelFormatTable[src->format].size;
+ const size_t dbpr = dst->stride * bpp;
+ const size_t sbpr = src->stride * bpp;
+
+ uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
+ uint8_t * const dst_bits = (uint8_t *)dst_vaddr;
+
+ while (cur != end) {
+ const Rect& r(*cur++);
+ ssize_t w = r.right - r.left;
+ ssize_t h = r.bottom - r.top;
+ if (w <= 0 || h<=0) continue;
+ size_t size = w * bpp;
+ uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
+ uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
+ if (dbpr==sbpr && size==sbpr) {
+ size *= h;
+ h = 1;
}
+ do {
+ memcpy(d, s, size);
+ d += dbpr;
+ s += sbpr;
+ } while (--h > 0);
}
}
diff --git a/opengl/libagl2/src/egl.cpp b/opengl/libagl2/src/egl.cpp
index 6184644..ec5889d 100644
--- a/opengl/libagl2/src/egl.cpp
+++ b/opengl/libagl2/src/egl.cpp
@@ -1,19 +1,19 @@
/*
-**
-** Copyright 2007 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.
-*/
+ **
+ ** Copyright 2007 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.
+ */
#include <errno.h>
#include <stdlib.h>
@@ -30,8 +30,6 @@
#include <private/ui/android_natives_priv.h>
-#include <hardware/copybit.h>
-
#include "gles2context.h"
// ----------------------------------------------------------------------------
@@ -53,808 +51,750 @@ pthread_key_t gGLKey = -1;
template<typename T>
static T setError(GLint error, T returnValue)
{
- if (ggl_unlikely(gEGLErrorKey == -1)) {
- pthread_mutex_lock(&gErrorKeyMutex);
- if (gEGLErrorKey == -1)
- pthread_key_create(&gEGLErrorKey, NULL);
- pthread_mutex_unlock(&gErrorKeyMutex);
- }
- pthread_setspecific(gEGLErrorKey, (void*)error);
- return returnValue;
+ if (ggl_unlikely(gEGLErrorKey == -1)) {
+ pthread_mutex_lock(&gErrorKeyMutex);
+ if (gEGLErrorKey == -1)
+ pthread_key_create(&gEGLErrorKey, NULL);
+ pthread_mutex_unlock(&gErrorKeyMutex);
+ }
+ pthread_setspecific(gEGLErrorKey, (void*)error);
+ return returnValue;
}
static GLint getError()
{
- if (ggl_unlikely(gEGLErrorKey == -1))
- return EGL_SUCCESS;
- GLint error = (GLint)pthread_getspecific(gEGLErrorKey);
- if (error == 0) {
- // The TLS key has been created by another thread, but the value for
- // this thread has not been initialized.
- return EGL_SUCCESS;
- }
- pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS);
- return error;
+ if (ggl_unlikely(gEGLErrorKey == -1))
+ return EGL_SUCCESS;
+ GLint error = (GLint)pthread_getspecific(gEGLErrorKey);
+ if (error == 0) {
+ // The TLS key has been created by another thread, but the value for
+ // this thread has not been initialized.
+ return EGL_SUCCESS;
+ }
+ pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS);
+ return error;
}
// ----------------------------------------------------------------------------
struct egl_display_t {
- egl_display_t() : type(0), initialized(0) { }
+ egl_display_t() : type(0), initialized(0) { }
- static egl_display_t& get_display(EGLDisplay dpy);
+ static egl_display_t& get_display(EGLDisplay dpy);
- static EGLBoolean is_valid(EGLDisplay dpy) {
- return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE;
- }
+ static EGLBoolean is_valid(EGLDisplay dpy) {
+ return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE;
+ }
- NativeDisplayType type;
- volatile int32_t initialized;
+ NativeDisplayType type;
+ volatile int32_t initialized;
};
static egl_display_t gDisplays[NUM_DISPLAYS];
egl_display_t& egl_display_t::get_display(EGLDisplay dpy)
{
- return gDisplays[uintptr_t(dpy)-1U];
+ return gDisplays[uintptr_t(dpy)-1U];
}
// ----------------------------------------------------------------------------
struct egl_surface_t {
- enum {
- PAGE_FLIP = 0x00000001,
- MAGIC = 0x31415265
- };
-
- uint32_t magic;
- EGLDisplay dpy;
- EGLConfig config;
- EGLContext ctx;
-
- egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
- virtual ~egl_surface_t();
- bool isValid() const;
- virtual bool initCheck() const = 0;
-
- virtual EGLBoolean bindDrawSurface(GLES2Context* gl) = 0;
- virtual EGLBoolean bindReadSurface(GLES2Context* gl) = 0;
- virtual EGLBoolean connect() {
- return EGL_TRUE;
- }
- virtual void disconnect() {}
- virtual EGLint getWidth() const = 0;
- virtual EGLint getHeight() const = 0;
-
- virtual EGLint getHorizontalResolution() const;
- virtual EGLint getVerticalResolution() const;
- virtual EGLint getRefreshRate() const;
- virtual EGLint getSwapBehavior() const;
- virtual EGLBoolean swapBuffers();
- virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
+ enum {
+ PAGE_FLIP = 0x00000001,
+ MAGIC = 0x31415265
+ };
+
+ uint32_t magic;
+ EGLDisplay dpy;
+ EGLConfig config;
+ EGLContext ctx;
+
+ egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
+ virtual ~egl_surface_t();
+ bool isValid() const;
+ virtual bool initCheck() const = 0;
+
+ virtual EGLBoolean bindDrawSurface(GLES2Context* gl) = 0;
+ virtual EGLBoolean bindReadSurface(GLES2Context* gl) = 0;
+ virtual EGLBoolean connect() {
+ return EGL_TRUE;
+ }
+ virtual void disconnect() {}
+ virtual EGLint getWidth() const = 0;
+ virtual EGLint getHeight() const = 0;
+
+ virtual EGLint getHorizontalResolution() const;
+ virtual EGLint getVerticalResolution() const;
+ virtual EGLint getRefreshRate() const;
+ virtual EGLint getSwapBehavior() const;
+ virtual EGLBoolean swapBuffers();
+ virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
protected:
- GGLSurface depth;
+ GGLSurface depth;
};
egl_surface_t::egl_surface_t(EGLDisplay dpy,
- EGLConfig config,
- int32_t depthFormat)
- : magic(MAGIC), dpy(dpy), config(config), ctx(0)
+ EGLConfig config,
+ int32_t depthFormat)
+: magic(MAGIC), dpy(dpy), config(config), ctx(0)
{
- depth.version = sizeof(GGLSurface);
- depth.data = 0;
- depth.format = (GGLPixelFormat)depthFormat;
+ depth.version = sizeof(GGLSurface);
+ depth.data = 0;
+ depth.format = (GGLPixelFormat)depthFormat;
}
egl_surface_t::~egl_surface_t()
{
- magic = 0;
- free(depth.data);
+ magic = 0;
+ free(depth.data);
}
bool egl_surface_t::isValid() const
{
- LOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this);
- return magic == MAGIC;
+ LOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this);
+ return magic == MAGIC;
}
EGLBoolean egl_surface_t::swapBuffers()
{
- return EGL_FALSE;
+ return EGL_FALSE;
}
EGLint egl_surface_t::getHorizontalResolution() const
{
- return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+ return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
}
EGLint egl_surface_t::getVerticalResolution() const
{
- return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+ return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
}
EGLint egl_surface_t::getRefreshRate() const
{
- return (60 * EGL_DISPLAY_SCALING);
+ return (60 * EGL_DISPLAY_SCALING);
}
EGLint egl_surface_t::getSwapBehavior() const
{
- return EGL_BUFFER_PRESERVED;
+ return EGL_BUFFER_PRESERVED;
}
EGLBoolean egl_surface_t::setSwapRectangle(
- EGLint l, EGLint t, EGLint w, EGLint h)
+ EGLint l, EGLint t, EGLint w, EGLint h)
{
- return EGL_FALSE;
+ return EGL_FALSE;
}
// ----------------------------------------------------------------------------
struct egl_window_surface_v2_t : public egl_surface_t {
- egl_window_surface_v2_t(
- EGLDisplay dpy, EGLConfig config,
- int32_t depthFormat,
- ANativeWindow* window);
-
- ~egl_window_surface_v2_t();
-
- virtual bool initCheck() const {
- return true; // TODO: report failure if ctor fails
- }
- virtual EGLBoolean swapBuffers();
- virtual EGLBoolean bindDrawSurface(GLES2Context* gl);
- virtual EGLBoolean bindReadSurface(GLES2Context* gl);
- virtual EGLBoolean connect();
- virtual void disconnect();
- virtual EGLint getWidth() const {
- return width;
- }
- virtual EGLint getHeight() const {
- return height;
- }
- virtual EGLint getHorizontalResolution() const;
- virtual EGLint getVerticalResolution() const;
- virtual EGLint getRefreshRate() const;
- virtual EGLint getSwapBehavior() const;
- virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
+ egl_window_surface_v2_t(
+ EGLDisplay dpy, EGLConfig config,
+ int32_t depthFormat,
+ ANativeWindow* window);
+
+ ~egl_window_surface_v2_t();
+
+ virtual bool initCheck() const {
+ return true; // TODO: report failure if ctor fails
+ }
+ virtual EGLBoolean swapBuffers();
+ virtual EGLBoolean bindDrawSurface(GLES2Context* gl);
+ virtual EGLBoolean bindReadSurface(GLES2Context* gl);
+ virtual EGLBoolean connect();
+ virtual void disconnect();
+ virtual EGLint getWidth() const {
+ return width;
+ }
+ virtual EGLint getHeight() const {
+ return height;
+ }
+ virtual EGLint getHorizontalResolution() const;
+ virtual EGLint getVerticalResolution() const;
+ virtual EGLint getRefreshRate() const;
+ virtual EGLint getSwapBehavior() const;
+ virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h);
private:
- status_t lock(android_native_buffer_t* buf, int usage, void** vaddr);
- status_t unlock(android_native_buffer_t* buf);
- ANativeWindow* nativeWindow;
- android_native_buffer_t* buffer;
- android_native_buffer_t* previousBuffer;
- gralloc_module_t const* module;
- copybit_device_t* blitengine;
- int width;
- int height;
- void* bits;
- GGLFormat const* pixelFormatTable;
-
- struct Rect {
- inline Rect() { };
- inline Rect(int32_t w, int32_t h)
- : left(0), top(0), right(w), bottom(h) { }
- inline Rect(int32_t l, int32_t t, int32_t r, int32_t b)
- : left(l), top(t), right(r), bottom(b) { }
- Rect& andSelf(const Rect& r) {
- left = max(left, r.left);
- top = max(top, r.top);
- right = min(right, r.right);
- bottom = min(bottom, r.bottom);
- return *this;
- }
- bool isEmpty() const {
- return (left>=right || top>=bottom);
- }
- void dump(char const* what) {
- LOGD("%s { %5d, %5d, w=%5d, h=%5d }",
- what, left, top, right-left, bottom-top);
- }
-
- int32_t left;
- int32_t top;
- int32_t right;
- int32_t bottom;
- };
-
- struct Region {
- inline Region() : count(0) { }
- typedef Rect const* const_iterator;
- const_iterator begin() const {
- return storage;
- }
- const_iterator end() const {
- return storage+count;
- }
- static Region subtract(const Rect& lhs, const Rect& rhs) {
- Region reg;
- Rect* storage = reg.storage;
- if (!lhs.isEmpty()) {
- if (lhs.top < rhs.top) { // top rect
- storage->left = lhs.left;
- storage->top = lhs.top;
- storage->right = lhs.right;
- storage->bottom = rhs.top;
- storage++;
- }
- const int32_t top = max(lhs.top, rhs.top);
- const int32_t bot = min(lhs.bottom, rhs.bottom);
- if (top < bot) {
- if (lhs.left < rhs.left) { // left-side rect
- storage->left = lhs.left;
- storage->top = top;
- storage->right = rhs.left;
- storage->bottom = bot;
- storage++;
- }
- if (lhs.right > rhs.right) { // right-side rect
- storage->left = rhs.right;
- storage->top = top;
- storage->right = lhs.right;
- storage->bottom = bot;
- storage++;
- }
+ status_t lock(android_native_buffer_t* buf, int usage, void** vaddr);
+ status_t unlock(android_native_buffer_t* buf);
+ ANativeWindow* nativeWindow;
+ android_native_buffer_t* buffer;
+ android_native_buffer_t* previousBuffer;
+ gralloc_module_t const* module;
+ int width;
+ int height;
+ void* bits;
+ GGLFormat const* pixelFormatTable;
+
+ struct Rect {
+ inline Rect() { };
+ inline Rect(int32_t w, int32_t h)
+ : left(0), top(0), right(w), bottom(h) { }
+ inline Rect(int32_t l, int32_t t, int32_t r, int32_t b)
+ : left(l), top(t), right(r), bottom(b) { }
+ Rect& andSelf(const Rect& r) {
+ left = max(left, r.left);
+ top = max(top, r.top);
+ right = min(right, r.right);
+ bottom = min(bottom, r.bottom);
+ return *this;
+ }
+ bool isEmpty() const {
+ return (left>=right || top>=bottom);
+ }
+ void dump(char const* what) {
+ LOGD("%s { %5d, %5d, w=%5d, h=%5d }",
+ what, left, top, right-left, bottom-top);
+ }
+
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+ };
+
+ struct Region {
+ inline Region() : count(0) { }
+ typedef Rect const* const_iterator;
+ const_iterator begin() const {
+ return storage;
+ }
+ const_iterator end() const {
+ return storage+count;
+ }
+ static Region subtract(const Rect& lhs, const Rect& rhs) {
+ Region reg;
+ Rect* storage = reg.storage;
+ if (!lhs.isEmpty()) {
+ if (lhs.top < rhs.top) { // top rect
+ storage->left = lhs.left;
+ storage->top = lhs.top;
+ storage->right = lhs.right;
+ storage->bottom = rhs.top;
+ storage++;
+ }
+ const int32_t top = max(lhs.top, rhs.top);
+ const int32_t bot = min(lhs.bottom, rhs.bottom);
+ if (top < bot) {
+ if (lhs.left < rhs.left) { // left-side rect
+ storage->left = lhs.left;
+ storage->top = top;
+ storage->right = rhs.left;
+ storage->bottom = bot;
+ storage++;
+ }
+ if (lhs.right > rhs.right) { // right-side rect
+ storage->left = rhs.right;
+ storage->top = top;
+ storage->right = lhs.right;
+ storage->bottom = bot;
+ storage++;
+ }
+ }
+ if (lhs.bottom > rhs.bottom) { // bottom rect
+ storage->left = lhs.left;
+ storage->top = rhs.bottom;
+ storage->right = lhs.right;
+ storage->bottom = lhs.bottom;
+ storage++;
+ }
+ reg.count = storage - reg.storage;
}
- if (lhs.bottom > rhs.bottom) { // bottom rect
- storage->left = lhs.left;
- storage->top = rhs.bottom;
- storage->right = lhs.right;
- storage->bottom = lhs.bottom;
- storage++;
- }
- reg.count = storage - reg.storage;
- }
- return reg;
- }
- bool isEmpty() const {
- return count<=0;
- }
-private:
- Rect storage[4];
- ssize_t count;
- };
-
- struct region_iterator : public copybit_region_t {
- region_iterator(const Region& region)
- : b(region.begin()), e(region.end()) {
- this->next = iterate;
- }
-private:
- static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
- region_iterator const* me = static_cast<region_iterator const*>(self);
- if (me->b != me->e) {
- *reinterpret_cast<Rect*>(rect) = *me->b++;
- return 1;
- }
- return 0;
- }
- mutable Region::const_iterator b;
- Region::const_iterator const e;
- };
-
- void copyBlt(
- android_native_buffer_t* dst, void* dst_vaddr,
- android_native_buffer_t* src, void const* src_vaddr,
- const Region& clip);
-
- Rect dirtyRegion;
- Rect oldDirtyRegion;
+ return reg;
+ }
+ bool isEmpty() const {
+ return count<=0;
+ }
+ private:
+ Rect storage[4];
+ ssize_t count;
+ };
+
+ void copyBlt(
+ android_native_buffer_t* dst, void* dst_vaddr,
+ android_native_buffer_t* src, void const* src_vaddr,
+ const Region& clip);
+
+ Rect dirtyRegion;
+ Rect oldDirtyRegion;
};
egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
- EGLConfig config,
- int32_t depthFormat,
- ANativeWindow* window)
- : egl_surface_t(dpy, config, depthFormat),
- nativeWindow(window), buffer(0), previousBuffer(0), module(0),
- blitengine(0), bits(NULL)
+ EGLConfig config,
+ int32_t depthFormat,
+ ANativeWindow* window)
+: egl_surface_t(dpy, config, depthFormat),
+ nativeWindow(window), buffer(0), previousBuffer(0), module(0),
+ bits(NULL)
{
- hw_module_t const* pModule;
- hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule);
- module = reinterpret_cast<gralloc_module_t const*>(pModule);
-
- if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &pModule) == 0) {
- copybit_open(pModule, &blitengine);
- }
+ pixelFormatTable = gglGetPixelFormatTable();
- pixelFormatTable = gglGetPixelFormatTable();
-
- // keep a reference on the window
- nativeWindow->common.incRef(&nativeWindow->common);
- nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width);
- nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height);
- int format = 0;
- nativeWindow->query(nativeWindow, NATIVE_WINDOW_FORMAT, &format);
- LOGD("agl2: egl_window_surface_v2_t format=0x%.4X", format);
-// assert(0);
+ // keep a reference on the window
+ nativeWindow->common.incRef(&nativeWindow->common);
+ nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width);
+ nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height);
+ int format = 0;
+ nativeWindow->query(nativeWindow, NATIVE_WINDOW_FORMAT, &format);
+ LOGD("agl2: egl_window_surface_v2_t format=0x%.4X", format);
+ // assert(0);
}
egl_window_surface_v2_t::~egl_window_surface_v2_t()
{
- if (buffer) {
- buffer->common.decRef(&buffer->common);
- }
- if (previousBuffer) {
- previousBuffer->common.decRef(&previousBuffer->common);
- }
- nativeWindow->common.decRef(&nativeWindow->common);
- if (blitengine) {
- copybit_close(blitengine);
- }
+ if (buffer) {
+ buffer->common.decRef(&buffer->common);
+ }
+ if (previousBuffer) {
+ previousBuffer->common.decRef(&previousBuffer->common);
+ }
+ nativeWindow->common.decRef(&nativeWindow->common);
}
EGLBoolean egl_window_surface_v2_t::connect()
{
- // we're intending to do software rendering
- native_window_set_usage(nativeWindow,
- GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
-
- // dequeue a buffer
- if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
- return setError(EGL_BAD_ALLOC, EGL_FALSE);
- }
-
- // allocate a corresponding depth-buffer
- width = buffer->width;
- height = buffer->height;
- if (depth.format) {
- depth.width = width;
- depth.height = height;
- depth.stride = depth.width; // use the width here
- assert(GGL_PIXEL_FORMAT_Z_32 == depth.format);
- depth.data = (GGLubyte*)malloc(depth.stride*depth.height*4);
- if (depth.data == 0) {
- return setError(EGL_BAD_ALLOC, EGL_FALSE);
- }
- }
-
- // keep a reference on the buffer
- buffer->common.incRef(&buffer->common);
-
- // Lock the buffer
- nativeWindow->lockBuffer(nativeWindow, buffer);
- // pin the buffer down
- if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
+ // we're intending to do software rendering
+ native_window_set_usage(nativeWindow,
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
+ // dequeue a buffer
+ if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
+ return setError(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+
+ // allocate a corresponding depth-buffer
+ width = buffer->width;
+ height = buffer->height;
+ if (depth.format) {
+ depth.width = width;
+ depth.height = height;
+ depth.stride = depth.width; // use the width here
+ assert(GGL_PIXEL_FORMAT_Z_32 == depth.format);
+ depth.data = (GGLubyte*)malloc(depth.stride*depth.height*4);
+ if (depth.data == 0) {
+ return setError(EGL_BAD_ALLOC, EGL_FALSE);
+ }
+ }
+
+ // keep a reference on the buffer
+ buffer->common.incRef(&buffer->common);
+
+ // Lock the buffer
+ nativeWindow->lockBuffer(nativeWindow, buffer);
+ // pin the buffer down
+ if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
- LOGE("connect() failed to lock buffer %p (%ux%u)",
- buffer, buffer->width, buffer->height);
- return setError(EGL_BAD_ACCESS, EGL_FALSE);
- // FIXME: we should make sure we're not accessing the buffer anymore
- }
- return EGL_TRUE;
+ LOGE("connect() failed to lock buffer %p (%ux%u)",
+ buffer, buffer->width, buffer->height);
+ return setError(EGL_BAD_ACCESS, EGL_FALSE);
+ // FIXME: we should make sure we're not accessing the buffer anymore
+ }
+ return EGL_TRUE;
}
void egl_window_surface_v2_t::disconnect()
{
- if (buffer && bits) {
- bits = NULL;
- unlock(buffer);
- }
- // enqueue the last frame
- if (buffer)
- nativeWindow->queueBuffer(nativeWindow, buffer);
- if (buffer) {
- buffer->common.decRef(&buffer->common);
- buffer = 0;
- }
- if (previousBuffer) {
- previousBuffer->common.decRef(&previousBuffer->common);
- previousBuffer = 0;
- }
+ if (buffer && bits) {
+ bits = NULL;
+ unlock(buffer);
+ }
+ // enqueue the last frame
+ if (buffer)
+ nativeWindow->queueBuffer(nativeWindow, buffer);
+ if (buffer) {
+ buffer->common.decRef(&buffer->common);
+ buffer = 0;
+ }
+ if (previousBuffer) {
+ previousBuffer->common.decRef(&previousBuffer->common);
+ previousBuffer = 0;
+ }
}
status_t egl_window_surface_v2_t::lock(
- android_native_buffer_t* buf, int usage, void** vaddr)
+ android_native_buffer_t* buf, int usage, void** vaddr)
{
- int err;
+ int err;
- err = module->lock(module, buf->handle,
- usage, 0, 0, buf->width, buf->height, vaddr);
+ err = module->lock(module, buf->handle,
+ usage, 0, 0, buf->width, buf->height, vaddr);
- return err;
+ return err;
}
status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf)
{
- if (!buf) return BAD_VALUE;
- int err = NO_ERROR;
+ if (!buf) return BAD_VALUE;
+ int err = NO_ERROR;
- err = module->unlock(module, buf->handle);
+ err = module->unlock(module, buf->handle);
- return err;
+ return err;
}
void egl_window_surface_v2_t::copyBlt(
- android_native_buffer_t* dst, void* dst_vaddr,
- android_native_buffer_t* src, void const* src_vaddr,
- const Region& clip)
-{
- // FIXME: use copybit if possible
- // NOTE: dst and src must be the same format
-
- status_t err = NO_ERROR;
- copybit_device_t* const copybit = blitengine;
- if (copybit) {
- copybit_image_t simg;
- simg.w = src->stride;
- simg.h = src->height;
- simg.format = src->format;
- simg.handle = const_cast<native_handle_t*>(src->handle);
-
- copybit_image_t dimg;
- dimg.w = dst->stride;
- dimg.h = dst->height;
- dimg.format = dst->format;
- dimg.handle = const_cast<native_handle_t*>(dst->handle);
-
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
- copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
- region_iterator it(clip);
- err = copybit->blit(copybit, &dimg, &simg, &it);
- if (err != NO_ERROR) {
- LOGE("copybit failed (%s)", strerror(err));
- }
- }
-
- if (!copybit || err) {
- Region::const_iterator cur = clip.begin();
- Region::const_iterator end = clip.end();
-
- const size_t bpp = pixelFormatTable[src->format].size;
- const size_t dbpr = dst->stride * bpp;
- const size_t sbpr = src->stride * bpp;
-
- uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
- uint8_t * const dst_bits = (uint8_t *)dst_vaddr;
-
- while (cur != end) {
- const Rect& r(*cur++);
- ssize_t w = r.right - r.left;
- ssize_t h = r.bottom - r.top;
- if (w <= 0 || h<=0) continue;
- size_t size = w * bpp;
- uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
- uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
- if (dbpr==sbpr && size==sbpr) {
+ android_native_buffer_t* dst, void* dst_vaddr,
+ android_native_buffer_t* src, void const* src_vaddr,
+ const Region& clip)
+{
+ // NOTE: dst and src must be the same format
+
+ Region::const_iterator cur = clip.begin();
+ Region::const_iterator end = clip.end();
+
+ const size_t bpp = pixelFormatTable[src->format].size;
+ const size_t dbpr = dst->stride * bpp;
+ const size_t sbpr = src->stride * bpp;
+
+ uint8_t const * const src_bits = (uint8_t const *)src_vaddr;
+ uint8_t * const dst_bits = (uint8_t *)dst_vaddr;
+
+ while (cur != end) {
+ const Rect& r(*cur++);
+ ssize_t w = r.right - r.left;
+ ssize_t h = r.bottom - r.top;
+ if (w <= 0 || h<=0) continue;
+ size_t size = w * bpp;
+ uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp;
+ uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp;
+ if (dbpr==sbpr && size==sbpr) {
size *= h;
h = 1;
- }
- do {
+ }
+ do {
memcpy(d, s, size);
d += dbpr;
s += sbpr;
- } while (--h > 0);
- }
- }
+ } while (--h > 0);
+ }
}
EGLBoolean egl_window_surface_v2_t::swapBuffers()
{
- if (!buffer) {
- return setError(EGL_BAD_ACCESS, EGL_FALSE);
- }
-
- /*
- * Handle eglSetSwapRectangleANDROID()
- * We copyback from the front buffer
- */
- if (!dirtyRegion.isEmpty()) {
- dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
- if (previousBuffer) {
- // This was const Region copyBack, but that causes an
- // internal compile error on simulator builds
- /*const*/
- Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
- if (!copyBack.isEmpty()) {
- void* prevBits;
- if (lock(previousBuffer,
- GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) {
- // copy from previousBuffer to buffer
- copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);
- unlock(previousBuffer);
+ if (!buffer) {
+ return setError(EGL_BAD_ACCESS, EGL_FALSE);
+ }
+
+ /*
+ * Handle eglSetSwapRectangleANDROID()
+ * We copyback from the front buffer
+ */
+ if (!dirtyRegion.isEmpty()) {
+ dirtyRegion.andSelf(Rect(buffer->width, buffer->height));
+ if (previousBuffer) {
+ // This was const Region copyBack, but that causes an
+ // internal compile error on simulator builds
+ /*const*/
+ Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
+ if (!copyBack.isEmpty()) {
+ void* prevBits;
+ if (lock(previousBuffer,
+ GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) {
+ // copy from previousBuffer to buffer
+ copyBlt(buffer, bits, previousBuffer, prevBits, copyBack);
+ unlock(previousBuffer);
+ }
}
- }
- }
- oldDirtyRegion = dirtyRegion;
- }
-
- if (previousBuffer) {
- previousBuffer->common.decRef(&previousBuffer->common);
- previousBuffer = 0;
- }
-
- unlock(buffer);
- previousBuffer = buffer;
- nativeWindow->queueBuffer(nativeWindow, buffer);
- buffer = 0;
-
- // dequeue a new buffer
- if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) == NO_ERROR) {
-
- // TODO: lockBuffer should rather be executed when the very first
- // direct rendering occurs.
- nativeWindow->lockBuffer(nativeWindow, buffer);
-
- // reallocate the depth-buffer if needed
- if ((width != buffer->width) || (height != buffer->height)) {
- // TODO: we probably should reset the swap rect here
- // if the window size has changed
- width = buffer->width;
- height = buffer->height;
- if (depth.data) {
- free(depth.data);
- depth.width = width;
- depth.height = height;
- depth.stride = buffer->stride;
- depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
- if (depth.data == 0) {
- setError(EGL_BAD_ALLOC, EGL_FALSE);
- return EGL_FALSE;
+ }
+ oldDirtyRegion = dirtyRegion;
+ }
+
+ if (previousBuffer) {
+ previousBuffer->common.decRef(&previousBuffer->common);
+ previousBuffer = 0;
+ }
+
+ unlock(buffer);
+ previousBuffer = buffer;
+ nativeWindow->queueBuffer(nativeWindow, buffer);
+ buffer = 0;
+
+ // dequeue a new buffer
+ if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) == NO_ERROR) {
+
+ // TODO: lockBuffer should rather be executed when the very first
+ // direct rendering occurs.
+ nativeWindow->lockBuffer(nativeWindow, buffer);
+
+ // reallocate the depth-buffer if needed
+ if ((width != buffer->width) || (height != buffer->height)) {
+ // TODO: we probably should reset the swap rect here
+ // if the window size has changed
+ width = buffer->width;
+ height = buffer->height;
+ if (depth.data) {
+ free(depth.data);
+ depth.width = width;
+ depth.height = height;
+ depth.stride = buffer->stride;
+ depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
+ if (depth.data == 0) {
+ setError(EGL_BAD_ALLOC, EGL_FALSE);
+ return EGL_FALSE;
+ }
}
- }
- }
+ }
- // keep a reference on the buffer
- buffer->common.incRef(&buffer->common);
+ // keep a reference on the buffer
+ buffer->common.incRef(&buffer->common);
- // finally pin the buffer down
- if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
- GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
- LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
- buffer, buffer->width, buffer->height);
- return setError(EGL_BAD_ACCESS, EGL_FALSE);
- // FIXME: we should make sure we're not accessing the buffer anymore
- }
- } else {
- return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
- }
+ // finally pin the buffer down
+ if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) {
+ LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)",
+ buffer, buffer->width, buffer->height);
+ return setError(EGL_BAD_ACCESS, EGL_FALSE);
+ // FIXME: we should make sure we're not accessing the buffer anymore
+ }
+ } else {
+ return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
+ }
- return EGL_TRUE;
+ return EGL_TRUE;
}
EGLBoolean egl_window_surface_v2_t::setSwapRectangle(
- EGLint l, EGLint t, EGLint w, EGLint h)
+ EGLint l, EGLint t, EGLint w, EGLint h)
{
- dirtyRegion = Rect(l, t, l+w, t+h);
- return EGL_TRUE;
+ dirtyRegion = Rect(l, t, l+w, t+h);
+ return EGL_TRUE;
}
EGLBoolean egl_window_surface_v2_t::bindDrawSurface(GLES2Context* gl)
{
- GGLSurface buffer;
- buffer.version = sizeof(GGLSurface);
- buffer.width = this->buffer->width;
- buffer.height = this->buffer->height;
- buffer.stride = this->buffer->stride;
- buffer.data = (GGLubyte*)bits;
- buffer.format = (GGLPixelFormat)this->buffer->format;
- gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
- if (depth.data != gl->rasterizer.depthSurface.data)
- gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
+ GGLSurface buffer;
+ buffer.version = sizeof(GGLSurface);
+ buffer.width = this->buffer->width;
+ buffer.height = this->buffer->height;
+ buffer.stride = this->buffer->stride;
+ buffer.data = (GGLubyte*)bits;
+ buffer.format = (GGLPixelFormat)this->buffer->format;
+ gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
+ if (depth.data != gl->rasterizer.depthSurface.data)
+ gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
- return EGL_TRUE;
+ return EGL_TRUE;
}
EGLBoolean egl_window_surface_v2_t::bindReadSurface(GLES2Context* gl)
{
- GGLSurface buffer;
- buffer.version = sizeof(GGLSurface);
- buffer.width = this->buffer->width;
- buffer.height = this->buffer->height;
- buffer.stride = this->buffer->stride;
- buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
- buffer.format = (GGLPixelFormat)this->buffer->format;
- puts("agl2: readBuffer not implemented");
- //gl->rasterizer.interface.readBuffer(gl, &buffer);
- return EGL_TRUE;
+ GGLSurface buffer;
+ buffer.version = sizeof(GGLSurface);
+ buffer.width = this->buffer->width;
+ buffer.height = this->buffer->height;
+ buffer.stride = this->buffer->stride;
+ buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!!
+ buffer.format = (GGLPixelFormat)this->buffer->format;
+ puts("agl2: readBuffer not implemented");
+ //gl->rasterizer.interface.readBuffer(gl, &buffer);
+ return EGL_TRUE;
}
EGLint egl_window_surface_v2_t::getHorizontalResolution() const
{
- return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+ return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
}
EGLint egl_window_surface_v2_t::getVerticalResolution() const
{
- return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
+ return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f);
}
EGLint egl_window_surface_v2_t::getRefreshRate() const
{
- return (60 * EGL_DISPLAY_SCALING); // FIXME
+ return (60 * EGL_DISPLAY_SCALING); // FIXME
}
EGLint egl_window_surface_v2_t::getSwapBehavior() const
{
- /*
- * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
- * the content of the swapped buffer.
- *
- * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
- *
- * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
- * only applies to the area specified by eglSetSwapRectangleANDROID(), that
- * is, everything outside of this area is preserved.
- *
- * This implementation of EGL assumes the later case.
- *
- */
+ /*
+ * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves
+ * the content of the swapped buffer.
+ *
+ * EGL_BUFFER_DESTROYED means that the content of the buffer is lost.
+ *
+ * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED
+ * only applies to the area specified by eglSetSwapRectangleANDROID(), that
+ * is, everything outside of this area is preserved.
+ *
+ * This implementation of EGL assumes the later case.
+ *
+ */
- return EGL_BUFFER_DESTROYED;
+ return EGL_BUFFER_DESTROYED;
}
// ----------------------------------------------------------------------------
struct egl_pixmap_surface_t : public egl_surface_t {
- egl_pixmap_surface_t(
- EGLDisplay dpy, EGLConfig config,
- int32_t depthFormat,
- egl_native_pixmap_t const * pixmap);
-
- virtual ~egl_pixmap_surface_t() { }
-
- virtual bool initCheck() const {
- return !depth.format || depth.data!=0;
- }
- virtual EGLBoolean bindDrawSurface(GLES2Context* gl);
- virtual EGLBoolean bindReadSurface(GLES2Context* gl);
- virtual EGLint getWidth() const {
- return nativePixmap.width;
- }
- virtual EGLint getHeight() const {
- return nativePixmap.height;
- }
+ egl_pixmap_surface_t(
+ EGLDisplay dpy, EGLConfig config,
+ int32_t depthFormat,
+ egl_native_pixmap_t const * pixmap);
+
+ virtual ~egl_pixmap_surface_t() { }
+
+ virtual bool initCheck() const {
+ return !depth.format || depth.data!=0;
+ }
+ virtual EGLBoolean bindDrawSurface(GLES2Context* gl);
+ virtual EGLBoolean bindReadSurface(GLES2Context* gl);
+ virtual EGLint getWidth() const {
+ return nativePixmap.width;
+ }
+ virtual EGLint getHeight() const {
+ return nativePixmap.height;
+ }
private:
- egl_native_pixmap_t nativePixmap;
+ egl_native_pixmap_t nativePixmap;
};
egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy,
- EGLConfig config,
- int32_t depthFormat,
- egl_native_pixmap_t const * pixmap)
- : egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap)
-{
- if (depthFormat) {
- depth.width = pixmap->width;
- depth.height = pixmap->height;
- depth.stride = depth.width; // use the width here
- depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
- if (depth.data == 0) {
- setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
- }
- }
+ EGLConfig config,
+ int32_t depthFormat,
+ egl_native_pixmap_t const * pixmap)
+: egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap)
+{
+ if (depthFormat) {
+ depth.width = pixmap->width;
+ depth.height = pixmap->height;
+ depth.stride = depth.width; // use the width here
+ depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
+ if (depth.data == 0) {
+ setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ }
+ }
}
EGLBoolean egl_pixmap_surface_t::bindDrawSurface(GLES2Context* gl)
{
- GGLSurface buffer;
- buffer.version = sizeof(GGLSurface);
- buffer.width = nativePixmap.width;
- buffer.height = nativePixmap.height;
- buffer.stride = nativePixmap.stride;
- buffer.data = nativePixmap.data;
- buffer.format = (GGLPixelFormat)nativePixmap.format;
+ GGLSurface buffer;
+ buffer.version = sizeof(GGLSurface);
+ buffer.width = nativePixmap.width;
+ buffer.height = nativePixmap.height;
+ buffer.stride = nativePixmap.stride;
+ buffer.data = nativePixmap.data;
+ buffer.format = (GGLPixelFormat)nativePixmap.format;
- gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
- if (depth.data != gl->rasterizer.depthSurface.data)
- gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
- return EGL_TRUE;
+ gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer);
+ if (depth.data != gl->rasterizer.depthSurface.data)
+ gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
+ return EGL_TRUE;
}
EGLBoolean egl_pixmap_surface_t::bindReadSurface(GLES2Context* gl)
{
- GGLSurface buffer;
- buffer.version = sizeof(GGLSurface);
- buffer.width = nativePixmap.width;
- buffer.height = nativePixmap.height;
- buffer.stride = nativePixmap.stride;
- buffer.data = nativePixmap.data;
- buffer.format = (GGLPixelFormat)nativePixmap.format;
- puts("agl2: readBuffer not implemented");
- //gl->rasterizer.interface.readBuffer(gl, &buffer);
- return EGL_TRUE;
+ GGLSurface buffer;
+ buffer.version = sizeof(GGLSurface);
+ buffer.width = nativePixmap.width;
+ buffer.height = nativePixmap.height;
+ buffer.stride = nativePixmap.stride;
+ buffer.data = nativePixmap.data;
+ buffer.format = (GGLPixelFormat)nativePixmap.format;
+ puts("agl2: readBuffer not implemented");
+ //gl->rasterizer.interface.readBuffer(gl, &buffer);
+ return EGL_TRUE;
}
// ----------------------------------------------------------------------------
struct egl_pbuffer_surface_t : public egl_surface_t {
- egl_pbuffer_surface_t(
- EGLDisplay dpy, EGLConfig config, int32_t depthFormat,
- int32_t w, int32_t h, int32_t f);
-
- virtual ~egl_pbuffer_surface_t();
-
- virtual bool initCheck() const {
- return pbuffer.data != 0;
- }
- virtual EGLBoolean bindDrawSurface(GLES2Context* gl);
- virtual EGLBoolean bindReadSurface(GLES2Context* gl);
- virtual EGLint getWidth() const {
- return pbuffer.width;
- }
- virtual EGLint getHeight() const {
- return pbuffer.height;
- }
+ egl_pbuffer_surface_t(
+ EGLDisplay dpy, EGLConfig config, int32_t depthFormat,
+ int32_t w, int32_t h, int32_t f);
+
+ virtual ~egl_pbuffer_surface_t();
+
+ virtual bool initCheck() const {
+ return pbuffer.data != 0;
+ }
+ virtual EGLBoolean bindDrawSurface(GLES2Context* gl);
+ virtual EGLBoolean bindReadSurface(GLES2Context* gl);
+ virtual EGLint getWidth() const {
+ return pbuffer.width;
+ }
+ virtual EGLint getHeight() const {
+ return pbuffer.height;
+ }
private:
- GGLSurface pbuffer;
+ GGLSurface pbuffer;
};
egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy,
- EGLConfig config, int32_t depthFormat,
- int32_t w, int32_t h, int32_t f)
- : egl_surface_t(dpy, config, depthFormat)
-{
- size_t size = w*h;
- switch (f) {
- case GGL_PIXEL_FORMAT_A_8:
- size *= 1;
- break;
- case GGL_PIXEL_FORMAT_RGB_565:
- size *= 2;
- break;
- case GGL_PIXEL_FORMAT_RGBA_8888:
- size *= 4;
- break;
- case GGL_PIXEL_FORMAT_RGBX_8888:
- size *= 4;
- break;
- default:
- LOGE("incompatible pixel format for pbuffer (format=%d)", f);
- pbuffer.data = 0;
- break;
- }
- pbuffer.version = sizeof(GGLSurface);
- pbuffer.width = w;
- pbuffer.height = h;
- pbuffer.stride = w;
- pbuffer.data = (GGLubyte*)malloc(size);
- pbuffer.format = (GGLPixelFormat)f;
-
- if (depthFormat) {
- depth.width = pbuffer.width;
- depth.height = pbuffer.height;
- depth.stride = depth.width; // use the width here
- depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
- if (depth.data == 0) {
- setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
- return;
- }
- }
+ EGLConfig config, int32_t depthFormat,
+ int32_t w, int32_t h, int32_t f)
+: egl_surface_t(dpy, config, depthFormat)
+{
+ size_t size = w*h;
+ switch (f) {
+ case GGL_PIXEL_FORMAT_A_8:
+ size *= 1;
+ break;
+ case GGL_PIXEL_FORMAT_RGB_565:
+ size *= 2;
+ break;
+ case GGL_PIXEL_FORMAT_RGBA_8888:
+ size *= 4;
+ break;
+ case GGL_PIXEL_FORMAT_RGBX_8888:
+ size *= 4;
+ break;
+ default:
+ LOGE("incompatible pixel format for pbuffer (format=%d)", f);
+ pbuffer.data = 0;
+ break;
+ }
+ pbuffer.version = sizeof(GGLSurface);
+ pbuffer.width = w;
+ pbuffer.height = h;
+ pbuffer.stride = w;
+ pbuffer.data = (GGLubyte*)malloc(size);
+ pbuffer.format = (GGLPixelFormat)f;
+
+ if (depthFormat) {
+ depth.width = pbuffer.width;
+ depth.height = pbuffer.height;
+ depth.stride = depth.width; // use the width here
+ depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
+ if (depth.data == 0) {
+ setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ return;
+ }
+ }
}
egl_pbuffer_surface_t::~egl_pbuffer_surface_t()
{
- free(pbuffer.data);
+ free(pbuffer.data);
}
EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(GLES2Context* gl)
{
- gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &pbuffer);
- if (depth.data != gl->rasterizer.depthSurface.data)
- gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
- return EGL_TRUE;
+ gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &pbuffer);
+ if (depth.data != gl->rasterizer.depthSurface.data)
+ gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth);
+ return EGL_TRUE;
}
EGLBoolean egl_pbuffer_surface_t::bindReadSurface(GLES2Context* gl)
{
- puts("agl2: readBuffer not implemented");
- //gl->rasterizer.interface.readBuffer(gl, &pbuffer);
- return EGL_TRUE;
+ puts("agl2: readBuffer not implemented");
+ //gl->rasterizer.interface.readBuffer(gl, &pbuffer);
+ return EGL_TRUE;
}
// ----------------------------------------------------------------------------
struct config_pair_t {
- GLint key;
- GLint value;
+ GLint key;
+ GLint value;
};
struct configs_t {
- const config_pair_t* array;
- int size;
+ const config_pair_t* array;
+ int size;
};
struct config_management_t {
- GLint key;
- bool (*match)(GLint reqValue, GLint confValue);
- static bool atLeast(GLint reqValue, GLint confValue) {
- return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue);
- }
- static bool exact(GLint reqValue, GLint confValue) {
- return (reqValue == EGL_DONT_CARE) || (confValue == reqValue);
- }
- static bool mask(GLint reqValue, GLint confValue) {
- return (confValue & reqValue) == reqValue;
- }
- static bool ignore(GLint reqValue, GLint confValue) {
- return true;
- }
+ GLint key;
+ bool (*match)(GLint reqValue, GLint confValue);
+ static bool atLeast(GLint reqValue, GLint confValue) {
+ return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue);
+ }
+ static bool exact(GLint reqValue, GLint confValue) {
+ return (reqValue == EGL_DONT_CARE) || (confValue == reqValue);
+ }
+ static bool mask(GLint reqValue, GLint confValue) {
+ return (confValue & reqValue) == reqValue;
+ }
+ static bool ignore(GLint reqValue, GLint confValue) {
+ return true;
+ }
};
// ----------------------------------------------------------------------------
@@ -865,62 +805,62 @@ static char const * const gVendorString = "Google Inc.";
static char const * const gVersionString = "0.0 Android Driver 0.0.0";
static char const * const gClientApiString = "OpenGL ES2";
static char const * const gExtensionsString =
- //"EGL_KHR_image_base "
- // "KHR_image_pixmap "
- //"EGL_ANDROID_image_native_buffer "
- //"EGL_ANDROID_swap_rectangle "
- "";
+ //"EGL_KHR_image_base "
+ // "KHR_image_pixmap "
+ //"EGL_ANDROID_image_native_buffer "
+ //"EGL_ANDROID_swap_rectangle "
+ "";
// ----------------------------------------------------------------------------
struct extention_map_t {
- const char * const name;
- __eglMustCastToProperFunctionPointerType address;
+ const char * const name;
+ __eglMustCastToProperFunctionPointerType address;
};
static const extention_map_t gExtentionMap[] = {
-// { "glDrawTexsOES",
-// (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
-// { "glDrawTexiOES",
-// (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
-// { "glDrawTexfOES",
-// (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
-// { "glDrawTexxOES",
-// (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
-// { "glDrawTexsvOES",
-// (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
-// { "glDrawTexivOES",
-// (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
-// { "glDrawTexfvOES",
-// (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
-// { "glDrawTexxvOES",
-// (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
-// { "glQueryMatrixxOES",
-// (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
-// { "glEGLImageTargetTexture2DOES",
-// (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
-// { "glEGLImageTargetRenderbufferStorageOES",
-// (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
-// { "glClipPlanef",
-// (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
-// { "glClipPlanex",
-// (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
-// { "glBindBuffer",
-// (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
-// { "glBufferData",
-// (__eglMustCastToProperFunctionPointerType)&glBufferData },
-// { "glBufferSubData",
-// (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
-// { "glDeleteBuffers",
-// (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
-// { "glGenBuffers",
-// (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
-// { "eglCreateImageKHR",
-// (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
-// { "eglDestroyImageKHR",
-// (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
-// { "eglSetSwapRectangleANDROID",
-// (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
+ // { "glDrawTexsOES",
+ // (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
+ // { "glDrawTexiOES",
+ // (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
+ // { "glDrawTexfOES",
+ // (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
+ // { "glDrawTexxOES",
+ // (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
+ // { "glDrawTexsvOES",
+ // (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
+ // { "glDrawTexivOES",
+ // (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
+ // { "glDrawTexfvOES",
+ // (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
+ // { "glDrawTexxvOES",
+ // (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
+ // { "glQueryMatrixxOES",
+ // (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
+ // { "glEGLImageTargetTexture2DOES",
+ // (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES },
+ // { "glEGLImageTargetRenderbufferStorageOES",
+ // (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES },
+ // { "glClipPlanef",
+ // (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
+ // { "glClipPlanex",
+ // (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
+ // { "glBindBuffer",
+ // (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
+ // { "glBufferData",
+ // (__eglMustCastToProperFunctionPointerType)&glBufferData },
+ // { "glBufferSubData",
+ // (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
+ // { "glDeleteBuffers",
+ // (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
+ // { "glGenBuffers",
+ // (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
+ // { "eglCreateImageKHR",
+ // (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
+ // { "eglDestroyImageKHR",
+ // (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
+ // { "eglSetSwapRectangleANDROID",
+ // (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
};
/*
@@ -930,31 +870,31 @@ static const extention_map_t gExtentionMap[] = {
*/
static config_pair_t const config_base_attribute_list[] = {
- { EGL_STENCIL_SIZE, 0 },
- { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG },
- { EGL_LEVEL, 0 },
- { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS },
- { EGL_MAX_PBUFFER_PIXELS,
- GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS },
- { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS },
- { EGL_NATIVE_RENDERABLE, EGL_TRUE },
- { EGL_NATIVE_VISUAL_ID, 0 },
- { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGBA_8888 },
- { EGL_SAMPLES, 0 },
- { EGL_SAMPLE_BUFFERS, 0 },
- { EGL_TRANSPARENT_TYPE, EGL_NONE },
- { EGL_TRANSPARENT_BLUE_VALUE, 0 },
- { EGL_TRANSPARENT_GREEN_VALUE, 0 },
- { EGL_TRANSPARENT_RED_VALUE, 0 },
- { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE },
- { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE },
- { EGL_MIN_SWAP_INTERVAL, 1 },
- { EGL_MAX_SWAP_INTERVAL, 1 },
- { EGL_LUMINANCE_SIZE, 0 },
- { EGL_ALPHA_MASK_SIZE, 0 },
- { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER },
- { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT },
- { EGL_CONFORMANT, 0 }
+ { EGL_STENCIL_SIZE, 0 },
+ { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG },
+ { EGL_LEVEL, 0 },
+ { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS },
+ { EGL_MAX_PBUFFER_PIXELS,
+ GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS },
+ { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS },
+ { EGL_NATIVE_RENDERABLE, EGL_TRUE },
+ { EGL_NATIVE_VISUAL_ID, 0 },
+ { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGBA_8888 },
+ { EGL_SAMPLES, 0 },
+ { EGL_SAMPLE_BUFFERS, 0 },
+ { EGL_TRANSPARENT_TYPE, EGL_NONE },
+ { EGL_TRANSPARENT_BLUE_VALUE, 0 },
+ { EGL_TRANSPARENT_GREEN_VALUE, 0 },
+ { EGL_TRANSPARENT_RED_VALUE, 0 },
+ { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE },
+ { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE },
+ { EGL_MIN_SWAP_INTERVAL, 1 },
+ { EGL_MAX_SWAP_INTERVAL, 1 },
+ { EGL_LUMINANCE_SIZE, 0 },
+ { EGL_ALPHA_MASK_SIZE, 0 },
+ { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER },
+ { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT },
+ { EGL_CONFORMANT, 0 }
};
// These configs can override the base attribute list
@@ -962,199 +902,199 @@ static config_pair_t const config_base_attribute_list[] = {
// 565 configs
static config_pair_t const config_0_attribute_list[] = {
- { EGL_BUFFER_SIZE, 16 },
- { EGL_ALPHA_SIZE, 0 },
- { EGL_BLUE_SIZE, 5 },
- { EGL_GREEN_SIZE, 6 },
- { EGL_RED_SIZE, 5 },
- { EGL_DEPTH_SIZE, 0 },
- { EGL_CONFIG_ID, 0 },
- { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
- { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+ { EGL_BUFFER_SIZE, 16 },
+ { EGL_ALPHA_SIZE, 0 },
+ { EGL_BLUE_SIZE, 5 },
+ { EGL_GREEN_SIZE, 6 },
+ { EGL_RED_SIZE, 5 },
+ { EGL_DEPTH_SIZE, 0 },
+ { EGL_CONFIG_ID, 0 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
+ { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
static config_pair_t const config_1_attribute_list[] = {
- { EGL_BUFFER_SIZE, 16 },
- { EGL_ALPHA_SIZE, 0 },
- { EGL_BLUE_SIZE, 5 },
- { EGL_GREEN_SIZE, 6 },
- { EGL_RED_SIZE, 5 },
- { EGL_DEPTH_SIZE, 16 },
- { EGL_CONFIG_ID, 1 },
- { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
- { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+ { EGL_BUFFER_SIZE, 16 },
+ { EGL_ALPHA_SIZE, 0 },
+ { EGL_BLUE_SIZE, 5 },
+ { EGL_GREEN_SIZE, 6 },
+ { EGL_RED_SIZE, 5 },
+ { EGL_DEPTH_SIZE, 16 },
+ { EGL_CONFIG_ID, 1 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 },
+ { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
// RGB 888 configs
static config_pair_t const config_2_attribute_list[] = {
- { EGL_BUFFER_SIZE, 32 },
- { EGL_ALPHA_SIZE, 0 },
- { EGL_BLUE_SIZE, 8 },
- { EGL_GREEN_SIZE, 8 },
- { EGL_RED_SIZE, 8 },
- { EGL_DEPTH_SIZE, 0 },
- { EGL_CONFIG_ID, 6 },
- { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
- { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+ { EGL_BUFFER_SIZE, 32 },
+ { EGL_ALPHA_SIZE, 0 },
+ { EGL_BLUE_SIZE, 8 },
+ { EGL_GREEN_SIZE, 8 },
+ { EGL_RED_SIZE, 8 },
+ { EGL_DEPTH_SIZE, 0 },
+ { EGL_CONFIG_ID, 6 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
+ { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
static config_pair_t const config_3_attribute_list[] = {
- { EGL_BUFFER_SIZE, 32 },
- { EGL_ALPHA_SIZE, 0 },
- { EGL_BLUE_SIZE, 8 },
- { EGL_GREEN_SIZE, 8 },
- { EGL_RED_SIZE, 8 },
- { EGL_DEPTH_SIZE, 16 },
- { EGL_CONFIG_ID, 7 },
- { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
- { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+ { EGL_BUFFER_SIZE, 32 },
+ { EGL_ALPHA_SIZE, 0 },
+ { EGL_BLUE_SIZE, 8 },
+ { EGL_GREEN_SIZE, 8 },
+ { EGL_RED_SIZE, 8 },
+ { EGL_DEPTH_SIZE, 16 },
+ { EGL_CONFIG_ID, 7 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 },
+ { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
// 8888 configs
static config_pair_t const config_4_attribute_list[] = {
- { EGL_BUFFER_SIZE, 32 },
- { EGL_ALPHA_SIZE, 8 },
- { EGL_BLUE_SIZE, 8 },
- { EGL_GREEN_SIZE, 8 },
- { EGL_RED_SIZE, 8 },
- { EGL_DEPTH_SIZE, 0 },
- { EGL_CONFIG_ID, 2 },
- { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
- { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+ { EGL_BUFFER_SIZE, 32 },
+ { EGL_ALPHA_SIZE, 8 },
+ { EGL_BLUE_SIZE, 8 },
+ { EGL_GREEN_SIZE, 8 },
+ { EGL_RED_SIZE, 8 },
+ { EGL_DEPTH_SIZE, 0 },
+ { EGL_CONFIG_ID, 2 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
+ { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
static config_pair_t const config_5_attribute_list[] = {
- { EGL_BUFFER_SIZE, 32 },
- { EGL_ALPHA_SIZE, 8 },
- { EGL_BLUE_SIZE, 8 },
- { EGL_GREEN_SIZE, 8 },
- { EGL_RED_SIZE, 8 },
- { EGL_DEPTH_SIZE, 16 },
- { EGL_CONFIG_ID, 3 },
- { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
- { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+ { EGL_BUFFER_SIZE, 32 },
+ { EGL_ALPHA_SIZE, 8 },
+ { EGL_BLUE_SIZE, 8 },
+ { EGL_GREEN_SIZE, 8 },
+ { EGL_RED_SIZE, 8 },
+ { EGL_DEPTH_SIZE, 16 },
+ { EGL_CONFIG_ID, 3 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 },
+ { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
// A8 configs
static config_pair_t const config_6_attribute_list[] = {
- { EGL_BUFFER_SIZE, 8 },
- { EGL_ALPHA_SIZE, 8 },
- { EGL_BLUE_SIZE, 0 },
- { EGL_GREEN_SIZE, 0 },
- { EGL_RED_SIZE, 0 },
- { EGL_DEPTH_SIZE, 0 },
- { EGL_CONFIG_ID, 4 },
- { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
- { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+ { EGL_BUFFER_SIZE, 8 },
+ { EGL_ALPHA_SIZE, 8 },
+ { EGL_BLUE_SIZE, 0 },
+ { EGL_GREEN_SIZE, 0 },
+ { EGL_RED_SIZE, 0 },
+ { EGL_DEPTH_SIZE, 0 },
+ { EGL_CONFIG_ID, 4 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
+ { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
static config_pair_t const config_7_attribute_list[] = {
- { EGL_BUFFER_SIZE, 8 },
- { EGL_ALPHA_SIZE, 8 },
- { EGL_BLUE_SIZE, 0 },
- { EGL_GREEN_SIZE, 0 },
- { EGL_RED_SIZE, 0 },
- { EGL_DEPTH_SIZE, 16 },
- { EGL_CONFIG_ID, 5 },
- { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
- { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+ { EGL_BUFFER_SIZE, 8 },
+ { EGL_ALPHA_SIZE, 8 },
+ { EGL_BLUE_SIZE, 0 },
+ { EGL_GREEN_SIZE, 0 },
+ { EGL_RED_SIZE, 0 },
+ { EGL_DEPTH_SIZE, 16 },
+ { EGL_CONFIG_ID, 5 },
+ { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 },
+ { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
};
static configs_t const gConfigs[] = {
- { config_0_attribute_list, NELEM(config_0_attribute_list) },
- { config_1_attribute_list, NELEM(config_1_attribute_list) },
- { config_2_attribute_list, NELEM(config_2_attribute_list) },
- { config_3_attribute_list, NELEM(config_3_attribute_list) },
- { config_4_attribute_list, NELEM(config_4_attribute_list) },
- { config_5_attribute_list, NELEM(config_5_attribute_list) },
-// { config_6_attribute_list, NELEM(config_6_attribute_list) },
-// { config_7_attribute_list, NELEM(config_7_attribute_list) },
+ { config_0_attribute_list, NELEM(config_0_attribute_list) },
+ { config_1_attribute_list, NELEM(config_1_attribute_list) },
+ { config_2_attribute_list, NELEM(config_2_attribute_list) },
+ { config_3_attribute_list, NELEM(config_3_attribute_list) },
+ { config_4_attribute_list, NELEM(config_4_attribute_list) },
+ { config_5_attribute_list, NELEM(config_5_attribute_list) },
+ // { config_6_attribute_list, NELEM(config_6_attribute_list) },
+ // { config_7_attribute_list, NELEM(config_7_attribute_list) },
};
static config_management_t const gConfigManagement[] = {
- { EGL_BUFFER_SIZE, config_management_t::atLeast },
- { EGL_ALPHA_SIZE, config_management_t::atLeast },
- { EGL_BLUE_SIZE, config_management_t::atLeast },
- { EGL_GREEN_SIZE, config_management_t::atLeast },
- { EGL_RED_SIZE, config_management_t::atLeast },
- { EGL_DEPTH_SIZE, config_management_t::atLeast },
- { EGL_STENCIL_SIZE, config_management_t::atLeast },
- { EGL_CONFIG_CAVEAT, config_management_t::exact },
- { EGL_CONFIG_ID, config_management_t::exact },
- { EGL_LEVEL, config_management_t::exact },
- { EGL_MAX_PBUFFER_HEIGHT, config_management_t::ignore },
- { EGL_MAX_PBUFFER_PIXELS, config_management_t::ignore },
- { EGL_MAX_PBUFFER_WIDTH, config_management_t::ignore },
- { EGL_NATIVE_RENDERABLE, config_management_t::exact },
- { EGL_NATIVE_VISUAL_ID, config_management_t::ignore },
- { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact },
- { EGL_SAMPLES, config_management_t::exact },
- { EGL_SAMPLE_BUFFERS, config_management_t::exact },
- { EGL_SURFACE_TYPE, config_management_t::mask },
- { EGL_TRANSPARENT_TYPE, config_management_t::exact },
- { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact },
- { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact },
- { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact },
- { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact },
- { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact },
- { EGL_MIN_SWAP_INTERVAL, config_management_t::exact },
- { EGL_MAX_SWAP_INTERVAL, config_management_t::exact },
- { EGL_LUMINANCE_SIZE, config_management_t::atLeast },
- { EGL_ALPHA_MASK_SIZE, config_management_t::atLeast },
- { EGL_COLOR_BUFFER_TYPE, config_management_t::exact },
- { EGL_RENDERABLE_TYPE, config_management_t::mask },
- { EGL_CONFORMANT, config_management_t::mask }
+ { EGL_BUFFER_SIZE, config_management_t::atLeast },
+ { EGL_ALPHA_SIZE, config_management_t::atLeast },
+ { EGL_BLUE_SIZE, config_management_t::atLeast },
+ { EGL_GREEN_SIZE, config_management_t::atLeast },
+ { EGL_RED_SIZE, config_management_t::atLeast },
+ { EGL_DEPTH_SIZE, config_management_t::atLeast },
+ { EGL_STENCIL_SIZE, config_management_t::atLeast },
+ { EGL_CONFIG_CAVEAT, config_management_t::exact },
+ { EGL_CONFIG_ID, config_management_t::exact },
+ { EGL_LEVEL, config_management_t::exact },
+ { EGL_MAX_PBUFFER_HEIGHT, config_management_t::ignore },
+ { EGL_MAX_PBUFFER_PIXELS, config_management_t::ignore },
+ { EGL_MAX_PBUFFER_WIDTH, config_management_t::ignore },
+ { EGL_NATIVE_RENDERABLE, config_management_t::exact },
+ { EGL_NATIVE_VISUAL_ID, config_management_t::ignore },
+ { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact },
+ { EGL_SAMPLES, config_management_t::exact },
+ { EGL_SAMPLE_BUFFERS, config_management_t::exact },
+ { EGL_SURFACE_TYPE, config_management_t::mask },
+ { EGL_TRANSPARENT_TYPE, config_management_t::exact },
+ { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact },
+ { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact },
+ { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact },
+ { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact },
+ { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact },
+ { EGL_MIN_SWAP_INTERVAL, config_management_t::exact },
+ { EGL_MAX_SWAP_INTERVAL, config_management_t::exact },
+ { EGL_LUMINANCE_SIZE, config_management_t::atLeast },
+ { EGL_ALPHA_MASK_SIZE, config_management_t::atLeast },
+ { EGL_COLOR_BUFFER_TYPE, config_management_t::exact },
+ { EGL_RENDERABLE_TYPE, config_management_t::mask },
+ { EGL_CONFORMANT, config_management_t::mask }
};
static config_pair_t const config_defaults[] = {
- // attributes that are not specified are simply ignored, if a particular
- // one needs not be ignored, it must be specified here, eg:
- // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
+ // attributes that are not specified are simply ignored, if a particular
+ // one needs not be ignored, it must be specified here, eg:
+ // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT },
};
// ----------------------------------------------------------------------------
static status_t getConfigFormatInfo(EGLint configID,
- int32_t& pixelFormat, int32_t& depthFormat)
-{
- switch (configID) {
- case 0:
- pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
- depthFormat = 0;
- break;
- case 1:
- pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
- depthFormat = GGL_PIXEL_FORMAT_Z_32;
- break;
- case 2:
- pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
- depthFormat = 0;
- break;
- case 3:
- pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
- depthFormat = GGL_PIXEL_FORMAT_Z_32;
- break;
- case 4:
- pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
- depthFormat = 0;
- break;
- case 5:
- pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
- depthFormat = GGL_PIXEL_FORMAT_Z_32;
- break;
- case 6:
- pixelFormat = GGL_PIXEL_FORMAT_A_8;
- depthFormat = 0;
- break;
- case 7:
- pixelFormat = GGL_PIXEL_FORMAT_A_8;
- depthFormat = GGL_PIXEL_FORMAT_Z_32;
- break;
- default:
- return NAME_NOT_FOUND;
- }
- return NO_ERROR;
+ int32_t& pixelFormat, int32_t& depthFormat)
+{
+ switch (configID) {
+ case 0:
+ pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+ depthFormat = 0;
+ break;
+ case 1:
+ pixelFormat = GGL_PIXEL_FORMAT_RGB_565;
+ depthFormat = GGL_PIXEL_FORMAT_Z_32;
+ break;
+ case 2:
+ pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+ depthFormat = 0;
+ break;
+ case 3:
+ pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+ depthFormat = GGL_PIXEL_FORMAT_Z_32;
+ break;
+ case 4:
+ pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+ depthFormat = 0;
+ break;
+ case 5:
+ pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888;
+ depthFormat = GGL_PIXEL_FORMAT_Z_32;
+ break;
+ case 6:
+ pixelFormat = GGL_PIXEL_FORMAT_A_8;
+ depthFormat = 0;
+ break;
+ case 7:
+ pixelFormat = GGL_PIXEL_FORMAT_A_8;
+ depthFormat = GGL_PIXEL_FORMAT_Z_32;
+ break;
+ default:
+ return NAME_NOT_FOUND;
+ }
+ return NO_ERROR;
}
// ----------------------------------------------------------------------------
@@ -1162,256 +1102,256 @@ static status_t getConfigFormatInfo(EGLint configID,
template<typename T>
static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
{
- while (first <= last) {
- int mid = (first + last) / 2;
- if (key > sortedArray[mid].key) {
- first = mid + 1;
- } else if (key < sortedArray[mid].key) {
- last = mid - 1;
- } else {
- return mid;
- }
- }
- return -1;
+ while (first <= last) {
+ int mid = (first + last) / 2;
+ if (key > sortedArray[mid].key) {
+ first = mid + 1;
+ } else if (key < sortedArray[mid].key) {
+ last = mid - 1;
+ } else {
+ return mid;
+ }
+ }
+ return -1;
}
static int isAttributeMatching(int i, EGLint attr, EGLint val)
{
- // look for the attribute in all of our configs
- config_pair_t const* configFound = gConfigs[i].array;
- int index = binarySearch<config_pair_t>(
- gConfigs[i].array,
- 0, gConfigs[i].size-1,
- attr);
- if (index < 0) {
- configFound = config_base_attribute_list;
- index = binarySearch<config_pair_t>(
- config_base_attribute_list,
- 0, NELEM(config_base_attribute_list)-1,
- attr);
- }
- if (index >= 0) {
- // attribute found, check if this config could match
- int cfgMgtIndex = binarySearch<config_management_t>(
- gConfigManagement,
- 0, NELEM(gConfigManagement)-1,
- attr);
- if (cfgMgtIndex >= 0) {
- bool match = gConfigManagement[cfgMgtIndex].match(
- val, configFound[index].value);
- if (match) {
- // this config matches
- return 1;
- }
- } else {
- // attribute not found. this should NEVER happen.
- }
- } else {
- // error, this attribute doesn't exist
- }
- return 0;
+ // look for the attribute in all of our configs
+ config_pair_t const* configFound = gConfigs[i].array;
+ int index = binarySearch<config_pair_t>(
+ gConfigs[i].array,
+ 0, gConfigs[i].size-1,
+ attr);
+ if (index < 0) {
+ configFound = config_base_attribute_list;
+ index = binarySearch<config_pair_t>(
+ config_base_attribute_list,
+ 0, NELEM(config_base_attribute_list)-1,
+ attr);
+ }
+ if (index >= 0) {
+ // attribute found, check if this config could match
+ int cfgMgtIndex = binarySearch<config_management_t>(
+ gConfigManagement,
+ 0, NELEM(gConfigManagement)-1,
+ attr);
+ if (cfgMgtIndex >= 0) {
+ bool match = gConfigManagement[cfgMgtIndex].match(
+ val, configFound[index].value);
+ if (match) {
+ // this config matches
+ return 1;
+ }
+ } else {
+ // attribute not found. this should NEVER happen.
+ }
+ } else {
+ // error, this attribute doesn't exist
+ }
+ return 0;
}
static int makeCurrent(GLES2Context* gl)
{
- GLES2Context* current = (GLES2Context*)getGlThreadSpecific();
- if (gl) {
- egl_context_t* c = egl_context_t::context(gl);
- if (c->flags & egl_context_t::IS_CURRENT) {
- if (current != gl) {
- // it is an error to set a context current, if it's already
- // current to another thread
- return -1;
- }
- } else {
- if (current) {
+ GLES2Context* current = (GLES2Context*)getGlThreadSpecific();
+ if (gl) {
+ egl_context_t* c = egl_context_t::context(gl);
+ if (c->flags & egl_context_t::IS_CURRENT) {
+ if (current != gl) {
+ // it is an error to set a context current, if it's already
+ // current to another thread
+ return -1;
+ }
+ } else {
+ if (current) {
+ // mark the current context as not current, and flush
+ glFlush();
+ egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
+ }
+ }
+ if (!(c->flags & egl_context_t::IS_CURRENT)) {
+ // The context is not current, make it current!
+ setGlThreadSpecific(gl);
+ c->flags |= egl_context_t::IS_CURRENT;
+ }
+ } else {
+ if (current) {
// mark the current context as not current, and flush
glFlush();
egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
- }
- }
- if (!(c->flags & egl_context_t::IS_CURRENT)) {
- // The context is not current, make it current!
- setGlThreadSpecific(gl);
- c->flags |= egl_context_t::IS_CURRENT;
- }
- } else {
- if (current) {
- // mark the current context as not current, and flush
- glFlush();
- egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT;
- }
- // this thread has no context attached to it
- setGlThreadSpecific(0);
- }
- return 0;
+ }
+ // this thread has no context attached to it
+ setGlThreadSpecific(0);
+ }
+ return 0;
}
static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config,
- EGLint attribute, EGLint *value)
-{
- size_t numConfigs = NELEM(gConfigs);
- int index = (int)config;
- if (uint32_t(index) >= numConfigs)
- return setError(EGL_BAD_CONFIG, EGL_FALSE);
-
- int attrIndex;
- attrIndex = binarySearch<config_pair_t>(
- gConfigs[index].array,
- 0, gConfigs[index].size-1,
- attribute);
- if (attrIndex>=0) {
- *value = gConfigs[index].array[attrIndex].value;
- return EGL_TRUE;
- }
-
- attrIndex = binarySearch<config_pair_t>(
- config_base_attribute_list,
- 0, NELEM(config_base_attribute_list)-1,
- attribute);
- if (attrIndex>=0) {
- *value = config_base_attribute_list[attrIndex].value;
- return EGL_TRUE;
- }
- return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ EGLint attribute, EGLint *value)
+{
+ size_t numConfigs = NELEM(gConfigs);
+ int index = (int)config;
+ if (uint32_t(index) >= numConfigs)
+ return setError(EGL_BAD_CONFIG, EGL_FALSE);
+
+ int attrIndex;
+ attrIndex = binarySearch<config_pair_t>(
+ gConfigs[index].array,
+ 0, gConfigs[index].size-1,
+ attribute);
+ if (attrIndex>=0) {
+ *value = gConfigs[index].array[attrIndex].value;
+ return EGL_TRUE;
+ }
+
+ attrIndex = binarySearch<config_pair_t>(
+ config_base_attribute_list,
+ 0, NELEM(config_base_attribute_list)-1,
+ attribute);
+ if (attrIndex>=0) {
+ *value = config_base_attribute_list[attrIndex].value;
+ return EGL_TRUE;
+ }
+ return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
}
static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config,
- NativeWindowType window, const EGLint *attrib_list)
-{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
- if (window == 0)
- return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
-
- EGLint surfaceType;
- if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
- return EGL_FALSE;
-
- if (!(surfaceType & EGL_WINDOW_BIT))
- return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
-
- if (reinterpret_cast<ANativeWindow*>(window)->common.magic !=
- ANDROID_NATIVE_WINDOW_MAGIC) {
- return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
- }
-
- EGLint configID;
- if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
- return EGL_FALSE;
-
- int32_t depthFormat;
- int32_t pixelFormat;
- if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
- return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
- }
-
- // FIXME: we don't have access to the pixelFormat here just yet.
- // (it's possible that the surface is not fully initialized)
- // maybe this should be done after the page-flip
- //if (EGLint(info.format) != pixelFormat)
- // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
-
- egl_surface_t* surface;
- surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
- reinterpret_cast<ANativeWindow*>(window));
-
- if (!surface->initCheck()) {
- // there was a problem in the ctor, the error
- // flag has been set.
- delete surface;
- surface = 0;
- }
- return surface;
+ NativeWindowType window, const EGLint *attrib_list)
+{
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+ if (window == 0)
+ return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+ EGLint surfaceType;
+ if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
+ return EGL_FALSE;
+
+ if (!(surfaceType & EGL_WINDOW_BIT))
+ return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+ if (reinterpret_cast<ANativeWindow*>(window)->common.magic !=
+ ANDROID_NATIVE_WINDOW_MAGIC) {
+ return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+ }
+
+ EGLint configID;
+ if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
+ return EGL_FALSE;
+
+ int32_t depthFormat;
+ int32_t pixelFormat;
+ if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
+ return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ }
+
+ // FIXME: we don't have access to the pixelFormat here just yet.
+ // (it's possible that the surface is not fully initialized)
+ // maybe this should be done after the page-flip
+ //if (EGLint(info.format) != pixelFormat)
+ // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+
+ egl_surface_t* surface;
+ surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
+ reinterpret_cast<ANativeWindow*>(window));
+
+ if (!surface->initCheck()) {
+ // there was a problem in the ctor, the error
+ // flag has been set.
+ delete surface;
+ surface = 0;
+ }
+ return surface;
}
static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config,
- NativePixmapType pixmap, const EGLint *attrib_list)
+ NativePixmapType pixmap, const EGLint *attrib_list)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
- if (pixmap == 0)
- return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+ if (pixmap == 0)
+ return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
- EGLint surfaceType;
- if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
- return EGL_FALSE;
+ EGLint surfaceType;
+ if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
+ return EGL_FALSE;
- if (!(surfaceType & EGL_PIXMAP_BIT))
- return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ if (!(surfaceType & EGL_PIXMAP_BIT))
+ return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
- if (reinterpret_cast<egl_native_pixmap_t*>(pixmap)->version !=
- sizeof(egl_native_pixmap_t)) {
- return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
- }
+ if (reinterpret_cast<egl_native_pixmap_t*>(pixmap)->version !=
+ sizeof(egl_native_pixmap_t)) {
+ return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
+ }
- EGLint configID;
- if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
- return EGL_FALSE;
+ EGLint configID;
+ if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
+ return EGL_FALSE;
- int32_t depthFormat;
- int32_t pixelFormat;
- if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
- return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
- }
+ int32_t depthFormat;
+ int32_t pixelFormat;
+ if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
+ return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ }
- if (reinterpret_cast<egl_native_pixmap_t *>(pixmap)->format != pixelFormat)
- return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ if (reinterpret_cast<egl_native_pixmap_t *>(pixmap)->format != pixelFormat)
+ return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
- egl_surface_t* surface =
- new egl_pixmap_surface_t(dpy, config, depthFormat,
- reinterpret_cast<egl_native_pixmap_t*>(pixmap));
+ egl_surface_t* surface =
+ new egl_pixmap_surface_t(dpy, config, depthFormat,
+ reinterpret_cast<egl_native_pixmap_t*>(pixmap));
- if (!surface->initCheck()) {
- // there was a problem in the ctor, the error
- // flag has been set.
- delete surface;
- surface = 0;
- }
- return surface;
+ if (!surface->initCheck()) {
+ // there was a problem in the ctor, the error
+ // flag has been set.
+ delete surface;
+ surface = 0;
+ }
+ return surface;
}
static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config,
- const EGLint *attrib_list)
+ const EGLint *attrib_list)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
- EGLint surfaceType;
- if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
- return EGL_FALSE;
+ EGLint surfaceType;
+ if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE)
+ return EGL_FALSE;
- if (!(surfaceType & EGL_PBUFFER_BIT))
- return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ if (!(surfaceType & EGL_PBUFFER_BIT))
+ return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
- EGLint configID;
- if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
- return EGL_FALSE;
+ EGLint configID;
+ if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
+ return EGL_FALSE;
- int32_t depthFormat;
- int32_t pixelFormat;
- if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
- return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
- }
+ int32_t depthFormat;
+ int32_t pixelFormat;
+ if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) {
+ return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ }
- int32_t w = 0;
- int32_t h = 0;
- while (attrib_list[0]) {
- if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1];
- if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
- attrib_list+=2;
- }
+ int32_t w = 0;
+ int32_t h = 0;
+ while (attrib_list[0]) {
+ if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1];
+ if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
+ attrib_list+=2;
+ }
- egl_surface_t* surface =
- new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
+ egl_surface_t* surface =
+ new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
- if (!surface->initCheck()) {
- // there was a problem in the ctor, the error
- // flag has been set.
- delete surface;
- surface = 0;
- }
- return surface;
+ if (!surface->initCheck()) {
+ // there was a problem in the ctor, the error
+ // flag has been set.
+ delete surface;
+ surface = 0;
+ }
+ return surface;
}
// ----------------------------------------------------------------------------
@@ -1426,61 +1366,61 @@ using namespace android;
EGLDisplay eglGetDisplay(NativeDisplayType display)
{
- puts("agl2:eglGetDisplay");
+ puts("agl2:eglGetDisplay");
#ifndef HAVE_ANDROID_OS
- // this just needs to be done once
- if (gGLKey == -1) {
- pthread_mutex_lock(&gInitMutex);
- if (gGLKey == -1)
- pthread_key_create(&gGLKey, NULL);
- pthread_mutex_unlock(&gInitMutex);
- }
+ // this just needs to be done once
+ if (gGLKey == -1) {
+ pthread_mutex_lock(&gInitMutex);
+ if (gGLKey == -1)
+ pthread_key_create(&gGLKey, NULL);
+ pthread_mutex_unlock(&gInitMutex);
+ }
#endif
- if (display == EGL_DEFAULT_DISPLAY) {
- EGLDisplay dpy = (EGLDisplay)1;
- egl_display_t& d = egl_display_t::get_display(dpy);
- d.type = display;
- return dpy;
- }
- return EGL_NO_DISPLAY;
+ if (display == EGL_DEFAULT_DISPLAY) {
+ EGLDisplay dpy = (EGLDisplay)1;
+ egl_display_t& d = egl_display_t::get_display(dpy);
+ d.type = display;
+ return dpy;
+ }
+ return EGL_NO_DISPLAY;
}
EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
- puts("agl2:eglInitialize");
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ puts("agl2:eglInitialize");
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- EGLBoolean res = EGL_TRUE;
- egl_display_t& d = egl_display_t::get_display(dpy);
+ EGLBoolean res = EGL_TRUE;
+ egl_display_t& d = egl_display_t::get_display(dpy);
- if (android_atomic_inc(&d.initialized) == 0) {
- // initialize stuff here if needed
- //pthread_mutex_lock(&gInitMutex);
- //pthread_mutex_unlock(&gInitMutex);
- }
+ if (android_atomic_inc(&d.initialized) == 0) {
+ // initialize stuff here if needed
+ //pthread_mutex_lock(&gInitMutex);
+ //pthread_mutex_unlock(&gInitMutex);
+ }
- if (res == EGL_TRUE) {
- if (major != NULL) *major = VERSION_MAJOR;
- if (minor != NULL) *minor = VERSION_MINOR;
- }
- return res;
+ if (res == EGL_TRUE) {
+ if (major != NULL) *major = VERSION_MAJOR;
+ if (minor != NULL) *minor = VERSION_MINOR;
+ }
+ return res;
}
EGLBoolean eglTerminate(EGLDisplay dpy)
{
- puts("agl2:eglTerminate");
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ puts("agl2:eglTerminate");
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- EGLBoolean res = EGL_TRUE;
- egl_display_t& d = egl_display_t::get_display(dpy);
- if (android_atomic_dec(&d.initialized) == 1) {
- // TODO: destroy all resources (surfaces, contexts, etc...)
- //pthread_mutex_lock(&gInitMutex);
- //pthread_mutex_unlock(&gInitMutex);
- }
- return res;
+ EGLBoolean res = EGL_TRUE;
+ egl_display_t& d = egl_display_t::get_display(dpy);
+ if (android_atomic_dec(&d.initialized) == 1) {
+ // TODO: destroy all resources (surfaces, contexts, etc...)
+ //pthread_mutex_lock(&gInitMutex);
+ //pthread_mutex_unlock(&gInitMutex);
+ }
+ return res;
}
// ----------------------------------------------------------------------------
@@ -1488,166 +1428,166 @@ EGLBoolean eglTerminate(EGLDisplay dpy)
// ----------------------------------------------------------------------------
EGLBoolean eglGetConfigs( EGLDisplay dpy,
- EGLConfig *configs,
- EGLint config_size, EGLint *num_config)
-{
- puts("agl2:eglGetConfigs");
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
- GLint numConfigs = NELEM(gConfigs);
- if (!configs) {
- *num_config = numConfigs;
- return EGL_TRUE;
- }
- GLint i;
- for (i=0 ; i<numConfigs && i<config_size ; i++) {
- *configs++ = (EGLConfig)i;
- }
- *num_config = i;
- return EGL_TRUE;
+ EGLConfig *configs,
+ EGLint config_size, EGLint *num_config)
+{
+ puts("agl2:eglGetConfigs");
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+ GLint numConfigs = NELEM(gConfigs);
+ if (!configs) {
+ *num_config = numConfigs;
+ return EGL_TRUE;
+ }
+ GLint i;
+ for (i=0 ; i<numConfigs && i<config_size ; i++) {
+ *configs++ = (EGLConfig)i;
+ }
+ *num_config = i;
+ return EGL_TRUE;
}
static const char * ATTRIBUTE_NAMES [] = {
- "EGL_BUFFER_SIZE",
- "EGL_ALPHA_SIZE",
- "EGL_BLUE_SIZE",
- "EGL_GREEN_SIZE",
- "EGL_RED_SIZE",
- "EGL_DEPTH_SIZE",
- "EGL_STENCIL_SIZE",
- "EGL_CONFIG_CAVEAT",
- "EGL_CONFIG_ID",
- "EGL_LEVEL",
- "EGL_MAX_PBUFFER_HEIGHT",
- "EGL_MAX_PBUFFER_PIXELS",
- "EGL_MAX_PBUFFER_WIDTH",
- "EGL_NATIVE_RENDERABLE",
- "EGL_NATIVE_VISUAL_ID",
- "EGL_NATIVE_VISUAL_TYPE",
- "EGL_PRESERVED_RESOURCES",
- "EGL_SAMPLES",
- "EGL_SAMPLE_BUFFERS",
- "EGL_SURFACE_TYPE",
- "EGL_TRANSPARENT_TYPE",
- "EGL_TRANSPARENT_BLUE_VALUE",
- "EGL_TRANSPARENT_GREEN_VALUE",
- "EGL_TRANSPARENT_RED_VALUE",
- "EGL_NONE", /* Attrib list terminator */
- "EGL_BIND_TO_TEXTURE_RGB",
- "EGL_BIND_TO_TEXTURE_RGBA",
- "EGL_MIN_SWAP_INTERVAL",
- "EGL_MAX_SWAP_INTERVAL",
- "EGL_LUMINANCE_SIZE",
- "EGL_ALPHA_MASK_SIZE",
- "EGL_COLOR_BUFFER_TYPE",
- "EGL_RENDERABLE_TYPE",
- "EGL_MATCH_NATIVE_PIXMAP", /* Pseudo-attribute (not queryable) */
- "EGL_CONFORMANT",
+ "EGL_BUFFER_SIZE",
+ "EGL_ALPHA_SIZE",
+ "EGL_BLUE_SIZE",
+ "EGL_GREEN_SIZE",
+ "EGL_RED_SIZE",
+ "EGL_DEPTH_SIZE",
+ "EGL_STENCIL_SIZE",
+ "EGL_CONFIG_CAVEAT",
+ "EGL_CONFIG_ID",
+ "EGL_LEVEL",
+ "EGL_MAX_PBUFFER_HEIGHT",
+ "EGL_MAX_PBUFFER_PIXELS",
+ "EGL_MAX_PBUFFER_WIDTH",
+ "EGL_NATIVE_RENDERABLE",
+ "EGL_NATIVE_VISUAL_ID",
+ "EGL_NATIVE_VISUAL_TYPE",
+ "EGL_PRESERVED_RESOURCES",
+ "EGL_SAMPLES",
+ "EGL_SAMPLE_BUFFERS",
+ "EGL_SURFACE_TYPE",
+ "EGL_TRANSPARENT_TYPE",
+ "EGL_TRANSPARENT_BLUE_VALUE",
+ "EGL_TRANSPARENT_GREEN_VALUE",
+ "EGL_TRANSPARENT_RED_VALUE",
+ "EGL_NONE", /* Attrib list terminator */
+ "EGL_BIND_TO_TEXTURE_RGB",
+ "EGL_BIND_TO_TEXTURE_RGBA",
+ "EGL_MIN_SWAP_INTERVAL",
+ "EGL_MAX_SWAP_INTERVAL",
+ "EGL_LUMINANCE_SIZE",
+ "EGL_ALPHA_MASK_SIZE",
+ "EGL_COLOR_BUFFER_TYPE",
+ "EGL_RENDERABLE_TYPE",
+ "EGL_MATCH_NATIVE_PIXMAP", /* Pseudo-attribute (not queryable) */
+ "EGL_CONFORMANT",
};
EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
- EGLConfig *configs, EGLint config_size,
- EGLint *num_config)
-{
- puts("agl2:eglChooseConfig");
- LOGD("\n***\n***\n agl2:LOGD eglChooseConfig \n***\n***\n");
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
- if (ggl_unlikely(num_config==0)) {
- LOGD("\n***\n***\n num_config==0 \n***\n***\n");
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
- }
-
- if (ggl_unlikely(attrib_list==0)) {
- /*
- * A NULL attrib_list should be treated as though it was an empty
- * one (terminated with EGL_NONE) as defined in
- * section 3.4.1 "Querying Configurations" in the EGL specification.
- */
- LOGD("\n***\n***\n attrib_list==0 \n***\n***\n");
- static const EGLint dummy = EGL_NONE;
- attrib_list = &dummy;
- }
-
- for (const EGLint * attrib = attrib_list; *attrib != EGL_NONE; attrib += 2) {
- LOGD("eglChooseConfig %s(%.4X): %d \n", ATTRIBUTE_NAMES[attrib[0] - EGL_BUFFER_SIZE], attrib[0], attrib[1]);
- if (EGL_BUFFER_SIZE > attrib[0] || EGL_CONFORMANT < attrib[0])
- LOGD("eglChooseConfig invalid config attrib: 0x%.4X=%d \n", attrib[0], attrib[1]);
- }
-
- int numAttributes = 0;
- int numConfigs = NELEM(gConfigs);
- uint32_t possibleMatch = (1<<numConfigs)-1;
- while (possibleMatch && *attrib_list != EGL_NONE) {
- numAttributes++;
- EGLint attr = *attrib_list++;
- EGLint val = *attrib_list++;
- for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
- if (!(possibleMatch & (1<<i)))
- continue;
- if (isAttributeMatching(i, attr, val) == 0) {
- LOGD("!isAttributeMatching config(%d) %s=%d \n", i, ATTRIBUTE_NAMES[attr - EGL_BUFFER_SIZE], val);
- possibleMatch &= ~(1<<i);
- }
- }
- }
-
- LOGD("eglChooseConfig possibleMatch=%.4X \n", possibleMatch);
-
- // now, handle the attributes which have a useful default value
- for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
- // see if this attribute was specified, if not, apply its
- // default value
- if (binarySearch<config_pair_t>(
- (config_pair_t const*)attrib_list,
- 0, numAttributes-1,
- config_defaults[j].key) < 0) {
- for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
+ EGLConfig *configs, EGLint config_size,
+ EGLint *num_config)
+{
+ puts("agl2:eglChooseConfig");
+ LOGD("\n***\n***\n agl2:LOGD eglChooseConfig \n***\n***\n");
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+ if (ggl_unlikely(num_config==0)) {
+ LOGD("\n***\n***\n num_config==0 \n***\n***\n");
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
+ if (ggl_unlikely(attrib_list==0)) {
+ /*
+ * A NULL attrib_list should be treated as though it was an empty
+ * one (terminated with EGL_NONE) as defined in
+ * section 3.4.1 "Querying Configurations" in the EGL specification.
+ */
+ LOGD("\n***\n***\n attrib_list==0 \n***\n***\n");
+ static const EGLint dummy = EGL_NONE;
+ attrib_list = &dummy;
+ }
+
+ for (const EGLint * attrib = attrib_list; *attrib != EGL_NONE; attrib += 2) {
+ LOGD("eglChooseConfig %s(%.4X): %d \n", ATTRIBUTE_NAMES[attrib[0] - EGL_BUFFER_SIZE], attrib[0], attrib[1]);
+ if (EGL_BUFFER_SIZE > attrib[0] || EGL_CONFORMANT < attrib[0])
+ LOGD("eglChooseConfig invalid config attrib: 0x%.4X=%d \n", attrib[0], attrib[1]);
+ }
+
+ int numAttributes = 0;
+ int numConfigs = NELEM(gConfigs);
+ uint32_t possibleMatch = (1<<numConfigs)-1;
+ while (possibleMatch && *attrib_list != EGL_NONE) {
+ numAttributes++;
+ EGLint attr = *attrib_list++;
+ EGLint val = *attrib_list++;
+ for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
if (!(possibleMatch & (1<<i)))
- continue;
- if (isAttributeMatching(i,
- config_defaults[j].key,
- config_defaults[j].value) == 0) {
- possibleMatch &= ~(1<<i);
+ continue;
+ if (isAttributeMatching(i, attr, val) == 0) {
+ LOGD("!isAttributeMatching config(%d) %s=%d \n", i, ATTRIBUTE_NAMES[attr - EGL_BUFFER_SIZE], val);
+ possibleMatch &= ~(1<<i);
+ }
+ }
+ }
+
+ LOGD("eglChooseConfig possibleMatch=%.4X \n", possibleMatch);
+
+ // now, handle the attributes which have a useful default value
+ for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) {
+ // see if this attribute was specified, if not, apply its
+ // default value
+ if (binarySearch<config_pair_t>(
+ (config_pair_t const*)attrib_list,
+ 0, numAttributes-1,
+ config_defaults[j].key) < 0) {
+ for (int i=0 ; possibleMatch && i<numConfigs ; i++) {
+ if (!(possibleMatch & (1<<i)))
+ continue;
+ if (isAttributeMatching(i,
+ config_defaults[j].key,
+ config_defaults[j].value) == 0) {
+ possibleMatch &= ~(1<<i);
+ }
}
- }
- }
- }
-
- // return the configurations found
- int n=0;
- if (possibleMatch) {
- if (configs) {
- for (int i=0 ; config_size && i<numConfigs ; i++) {
- if (possibleMatch & (1<<i)) {
- *configs++ = (EGLConfig)i;
- config_size--;
- n++;
+ }
+ }
+
+ // return the configurations found
+ int n=0;
+ if (possibleMatch) {
+ if (configs) {
+ for (int i=0 ; config_size && i<numConfigs ; i++) {
+ if (possibleMatch & (1<<i)) {
+ *configs++ = (EGLConfig)i;
+ config_size--;
+ n++;
+ }
}
- }
- } else {
- for (int i=0 ; i<numConfigs ; i++) {
- if (possibleMatch & (1<<i)) {
- n++;
+ } else {
+ for (int i=0 ; i<numConfigs ; i++) {
+ if (possibleMatch & (1<<i)) {
+ n++;
+ }
}
- }
- }
- }
- *num_config = n;
- LOGD("\n***\n***\n num_config==%d \n***\n***\n", *num_config);
- return EGL_TRUE;
+ }
+ }
+ *num_config = n;
+ LOGD("\n***\n***\n num_config==%d \n***\n***\n", *num_config);
+ return EGL_TRUE;
}
EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
- EGLint attribute, EGLint *value)
+ EGLint attribute, EGLint *value)
{
- puts("agl2:eglGetConfigAttrib");
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ puts("agl2:eglGetConfigAttrib");
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- return getConfigAttrib(dpy, config, attribute, value);
+ return getConfigAttrib(dpy, config, attribute, value);
}
// ----------------------------------------------------------------------------
@@ -1655,396 +1595,396 @@ EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
// ----------------------------------------------------------------------------
EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
- NativeWindowType window,
- const EGLint *attrib_list)
+ NativeWindowType window,
+ const EGLint *attrib_list)
{
- puts("agl2:eglCreateWindowSurface");
- return createWindowSurface(dpy, config, window, attrib_list);
+ puts("agl2:eglCreateWindowSurface");
+ return createWindowSurface(dpy, config, window, attrib_list);
}
EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
- NativePixmapType pixmap,
- const EGLint *attrib_list)
+ NativePixmapType pixmap,
+ const EGLint *attrib_list)
{
- puts("agl2:eglCreatePixmapSurface");
- return createPixmapSurface(dpy, config, pixmap, attrib_list);
+ puts("agl2:eglCreatePixmapSurface");
+ return createPixmapSurface(dpy, config, pixmap, attrib_list);
}
EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
- const EGLint *attrib_list)
+ const EGLint *attrib_list)
{
- puts("agl2:eglCreatePbufferSurface");
- return createPbufferSurface(dpy, config, attrib_list);
+ puts("agl2:eglCreatePbufferSurface");
+ return createPbufferSurface(dpy, config, attrib_list);
}
EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
{
- puts("agl2:eglDestroySurface");
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- if (eglSurface != EGL_NO_SURFACE) {
- egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
- if (!surface->isValid())
- return setError(EGL_BAD_SURFACE, EGL_FALSE);
- if (surface->dpy != dpy)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- if (surface->ctx) {
- // FIXME: this surface is current check what the spec says
- surface->disconnect();
- surface->ctx = 0;
- }
- delete surface;
- }
- return EGL_TRUE;
+ puts("agl2:eglDestroySurface");
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ if (eglSurface != EGL_NO_SURFACE) {
+ egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
+ if (!surface->isValid())
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ if (surface->dpy != dpy)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ if (surface->ctx) {
+ // FIXME: this surface is current check what the spec says
+ surface->disconnect();
+ surface->ctx = 0;
+ }
+ delete surface;
+ }
+ return EGL_TRUE;
}
EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface,
- EGLint attribute, EGLint *value)
-{
- puts("agl2:eglQuerySurface");
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
- if (!surface->isValid())
- return setError(EGL_BAD_SURFACE, EGL_FALSE);
- if (surface->dpy != dpy)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
- EGLBoolean ret = EGL_TRUE;
- switch (attribute) {
- case EGL_CONFIG_ID:
- ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
- break;
- case EGL_WIDTH:
- *value = surface->getWidth();
- break;
- case EGL_HEIGHT:
- *value = surface->getHeight();
- break;
- case EGL_LARGEST_PBUFFER:
- // not modified for a window or pixmap surface
- break;
- case EGL_TEXTURE_FORMAT:
- *value = EGL_NO_TEXTURE;
- break;
- case EGL_TEXTURE_TARGET:
- *value = EGL_NO_TEXTURE;
- break;
- case EGL_MIPMAP_TEXTURE:
- *value = EGL_FALSE;
- break;
- case EGL_MIPMAP_LEVEL:
- *value = 0;
- break;
- case EGL_RENDER_BUFFER:
- // TODO: return the real RENDER_BUFFER here
- *value = EGL_BACK_BUFFER;
- break;
- case EGL_HORIZONTAL_RESOLUTION:
- // pixel/mm * EGL_DISPLAY_SCALING
- *value = surface->getHorizontalResolution();
- break;
- case EGL_VERTICAL_RESOLUTION:
- // pixel/mm * EGL_DISPLAY_SCALING
- *value = surface->getVerticalResolution();
- break;
- case EGL_PIXEL_ASPECT_RATIO: {
- // w/h * EGL_DISPLAY_SCALING
- int wr = surface->getHorizontalResolution();
- int hr = surface->getVerticalResolution();
- *value = (wr * EGL_DISPLAY_SCALING) / hr;
- }
- break;
- case EGL_SWAP_BEHAVIOR:
- *value = surface->getSwapBehavior();
- break;
- default:
- ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
- }
- return ret;
+ EGLint attribute, EGLint *value)
+{
+ puts("agl2:eglQuerySurface");
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
+ if (!surface->isValid())
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ if (surface->dpy != dpy)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+ EGLBoolean ret = EGL_TRUE;
+ switch (attribute) {
+ case EGL_CONFIG_ID:
+ ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value);
+ break;
+ case EGL_WIDTH:
+ *value = surface->getWidth();
+ break;
+ case EGL_HEIGHT:
+ *value = surface->getHeight();
+ break;
+ case EGL_LARGEST_PBUFFER:
+ // not modified for a window or pixmap surface
+ break;
+ case EGL_TEXTURE_FORMAT:
+ *value = EGL_NO_TEXTURE;
+ break;
+ case EGL_TEXTURE_TARGET:
+ *value = EGL_NO_TEXTURE;
+ break;
+ case EGL_MIPMAP_TEXTURE:
+ *value = EGL_FALSE;
+ break;
+ case EGL_MIPMAP_LEVEL:
+ *value = 0;
+ break;
+ case EGL_RENDER_BUFFER:
+ // TODO: return the real RENDER_BUFFER here
+ *value = EGL_BACK_BUFFER;
+ break;
+ case EGL_HORIZONTAL_RESOLUTION:
+ // pixel/mm * EGL_DISPLAY_SCALING
+ *value = surface->getHorizontalResolution();
+ break;
+ case EGL_VERTICAL_RESOLUTION:
+ // pixel/mm * EGL_DISPLAY_SCALING
+ *value = surface->getVerticalResolution();
+ break;
+ case EGL_PIXEL_ASPECT_RATIO: {
+ // w/h * EGL_DISPLAY_SCALING
+ int wr = surface->getHorizontalResolution();
+ int hr = surface->getVerticalResolution();
+ *value = (wr * EGL_DISPLAY_SCALING) / hr;
+ }
+ break;
+ case EGL_SWAP_BEHAVIOR:
+ *value = surface->getSwapBehavior();
+ break;
+ default:
+ ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ }
+ return ret;
}
EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
- EGLContext share_list, const EGLint *attrib_list)
+ EGLContext share_list, const EGLint *attrib_list)
{
- puts("agl2:eglCreateContext");
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+ puts("agl2:eglCreateContext");
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
- GLES2Context* gl = new GLES2Context();//ogles_init(sizeof(egl_context_t));
- if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
+ GLES2Context* gl = new GLES2Context();//ogles_init(sizeof(egl_context_t));
+ if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
- //egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
- egl_context_t * c = &gl->egl;
- c->flags = egl_context_t::NEVER_CURRENT;
- c->dpy = dpy;
- c->config = config;
- c->read = 0;
- c->draw = 0;
-
- c->frame = 0;
- c->lastSwapTime = clock();
- c->accumulateSeconds = 0;
- return (EGLContext)gl;
+ //egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base);
+ egl_context_t * c = &gl->egl;
+ c->flags = egl_context_t::NEVER_CURRENT;
+ c->dpy = dpy;
+ c->config = config;
+ c->read = 0;
+ c->draw = 0;
+
+ c->frame = 0;
+ c->lastSwapTime = clock();
+ c->accumulateSeconds = 0;
+ return (EGLContext)gl;
}
EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
{
- puts("agl2:eglDestroyContext");
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- egl_context_t* c = egl_context_t::context(ctx);
- if (c->flags & egl_context_t::IS_CURRENT)
- setGlThreadSpecific(0);
- //ogles_uninit((GLES2Context*)ctx);
- delete (GLES2Context*)ctx;
- return EGL_TRUE;
+ puts("agl2:eglDestroyContext");
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ egl_context_t* c = egl_context_t::context(ctx);
+ if (c->flags & egl_context_t::IS_CURRENT)
+ setGlThreadSpecific(0);
+ //ogles_uninit((GLES2Context*)ctx);
+ delete (GLES2Context*)ctx;
+ return EGL_TRUE;
}
EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
- EGLSurface read, EGLContext ctx)
-{
- puts("agl2:eglMakeCurrent");
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- if (draw) {
- egl_surface_t* s = (egl_surface_t*)draw;
- if (!s->isValid())
- return setError(EGL_BAD_SURFACE, EGL_FALSE);
- if (s->dpy != dpy)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- // TODO: check that draw is compatible with the context
- }
- if (read && read!=draw) {
- egl_surface_t* s = (egl_surface_t*)read;
- if (!s->isValid())
- return setError(EGL_BAD_SURFACE, EGL_FALSE);
- if (s->dpy != dpy)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- // TODO: check that read is compatible with the context
- }
-
- EGLContext current_ctx = EGL_NO_CONTEXT;
-
- if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
- return setError(EGL_BAD_MATCH, EGL_FALSE);
-
- if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
- return setError(EGL_BAD_MATCH, EGL_FALSE);
-
- if (ctx == EGL_NO_CONTEXT) {
- // if we're detaching, we need the current context
- current_ctx = (EGLContext)getGlThreadSpecific();
- } else {
- egl_context_t* c = egl_context_t::context(ctx);
- egl_surface_t* d = (egl_surface_t*)draw;
- egl_surface_t* r = (egl_surface_t*)read;
- if ((d && d->ctx && d->ctx != ctx) ||
- (r && r->ctx && r->ctx != ctx)) {
- // one of the surface is bound to a context in another thread
- return setError(EGL_BAD_ACCESS, EGL_FALSE);
- }
- }
-
- GLES2Context* gl = (GLES2Context*)ctx;
- if (makeCurrent(gl) == 0) {
- if (ctx) {
- egl_context_t* c = egl_context_t::context(ctx);
- egl_surface_t* d = (egl_surface_t*)draw;
- egl_surface_t* r = (egl_surface_t*)read;
-
- if (c->draw) {
- egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
- s->disconnect();
- }
- if (c->read) {
- // FIXME: unlock/disconnect the read surface too
- }
-
- c->draw = draw;
- c->read = read;
-
- if (c->flags & egl_context_t::NEVER_CURRENT) {
- c->flags &= ~egl_context_t::NEVER_CURRENT;
- GLint w = 0;
- GLint h = 0;
- if (draw) {
- w = d->getWidth();
- h = d->getHeight();
+ EGLSurface read, EGLContext ctx)
+{
+ puts("agl2:eglMakeCurrent");
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ if (draw) {
+ egl_surface_t* s = (egl_surface_t*)draw;
+ if (!s->isValid())
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ if (s->dpy != dpy)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ // TODO: check that draw is compatible with the context
+ }
+ if (read && read!=draw) {
+ egl_surface_t* s = (egl_surface_t*)read;
+ if (!s->isValid())
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ if (s->dpy != dpy)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ // TODO: check that read is compatible with the context
+ }
+
+ EGLContext current_ctx = EGL_NO_CONTEXT;
+
+ if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
+ return setError(EGL_BAD_MATCH, EGL_FALSE);
+
+ if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
+ return setError(EGL_BAD_MATCH, EGL_FALSE);
+
+ if (ctx == EGL_NO_CONTEXT) {
+ // if we're detaching, we need the current context
+ current_ctx = (EGLContext)getGlThreadSpecific();
+ } else {
+ egl_context_t* c = egl_context_t::context(ctx);
+ egl_surface_t* d = (egl_surface_t*)draw;
+ egl_surface_t* r = (egl_surface_t*)read;
+ if ((d && d->ctx && d->ctx != ctx) ||
+ (r && r->ctx && r->ctx != ctx)) {
+ // one of the surface is bound to a context in another thread
+ return setError(EGL_BAD_ACCESS, EGL_FALSE);
+ }
+ }
+
+ GLES2Context* gl = (GLES2Context*)ctx;
+ if (makeCurrent(gl) == 0) {
+ if (ctx) {
+ egl_context_t* c = egl_context_t::context(ctx);
+ egl_surface_t* d = (egl_surface_t*)draw;
+ egl_surface_t* r = (egl_surface_t*)read;
+
+ if (c->draw) {
+ egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
+ s->disconnect();
}
- gl->rasterizer.interface.Viewport(&gl->rasterizer.interface, 0, 0, w, h);
- //ogles_surfaceport(gl, 0, 0);
- //ogles_viewport(gl, 0, 0, w, h);
- //ogles_scissor(gl, 0, 0, w, h);
- }
- if (d) {
- if (d->connect() == EGL_FALSE) {
- return EGL_FALSE;
+ if (c->read) {
+ // FIXME: unlock/disconnect the read surface too
+ }
+
+ c->draw = draw;
+ c->read = read;
+
+ if (c->flags & egl_context_t::NEVER_CURRENT) {
+ c->flags &= ~egl_context_t::NEVER_CURRENT;
+ GLint w = 0;
+ GLint h = 0;
+ if (draw) {
+ w = d->getWidth();
+ h = d->getHeight();
+ }
+ gl->rasterizer.interface.Viewport(&gl->rasterizer.interface, 0, 0, w, h);
+ //ogles_surfaceport(gl, 0, 0);
+ //ogles_viewport(gl, 0, 0, w, h);
+ //ogles_scissor(gl, 0, 0, w, h);
}
- d->ctx = ctx;
- d->bindDrawSurface(gl);
- }
- if (r) {
- // FIXME: lock/connect the read surface too
- r->ctx = ctx;
- r->bindReadSurface(gl);
- }
- } else {
- // if surfaces were bound to the context bound to this thread
- // mark then as unbound.
- if (current_ctx) {
- egl_context_t* c = egl_context_t::context(current_ctx);
- egl_surface_t* d = (egl_surface_t*)c->draw;
- egl_surface_t* r = (egl_surface_t*)c->read;
if (d) {
- c->draw = 0;
- d->ctx = EGL_NO_CONTEXT;
- d->disconnect();
+ if (d->connect() == EGL_FALSE) {
+ return EGL_FALSE;
+ }
+ d->ctx = ctx;
+ d->bindDrawSurface(gl);
}
if (r) {
- c->read = 0;
- r->ctx = EGL_NO_CONTEXT;
- // FIXME: unlock/disconnect the read surface too
+ // FIXME: lock/connect the read surface too
+ r->ctx = ctx;
+ r->bindReadSurface(gl);
+ }
+ } else {
+ // if surfaces were bound to the context bound to this thread
+ // mark then as unbound.
+ if (current_ctx) {
+ egl_context_t* c = egl_context_t::context(current_ctx);
+ egl_surface_t* d = (egl_surface_t*)c->draw;
+ egl_surface_t* r = (egl_surface_t*)c->read;
+ if (d) {
+ c->draw = 0;
+ d->ctx = EGL_NO_CONTEXT;
+ d->disconnect();
+ }
+ if (r) {
+ c->read = 0;
+ r->ctx = EGL_NO_CONTEXT;
+ // FIXME: unlock/disconnect the read surface too
+ }
}
- }
- }
- return EGL_TRUE;
- }
- return setError(EGL_BAD_ACCESS, EGL_FALSE);
+ }
+ return EGL_TRUE;
+ }
+ return setError(EGL_BAD_ACCESS, EGL_FALSE);
}
EGLContext eglGetCurrentContext(void)
{
- // eglGetCurrentContext returns the current EGL rendering context,
- // as specified by eglMakeCurrent. If no context is current,
- // EGL_NO_CONTEXT is returned.
- return (EGLContext)getGlThreadSpecific();
+ // eglGetCurrentContext returns the current EGL rendering context,
+ // as specified by eglMakeCurrent. If no context is current,
+ // EGL_NO_CONTEXT is returned.
+ return (EGLContext)getGlThreadSpecific();
}
EGLSurface eglGetCurrentSurface(EGLint readdraw)
{
- // eglGetCurrentSurface returns the read or draw surface attached
- // to the current EGL rendering context, as specified by eglMakeCurrent.
- // If no context is current, EGL_NO_SURFACE is returned.
- EGLContext ctx = (EGLContext)getGlThreadSpecific();
- if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
- egl_context_t* c = egl_context_t::context(ctx);
- if (readdraw == EGL_READ) {
- return c->read;
- } else if (readdraw == EGL_DRAW) {
- return c->draw;
- }
- return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ // eglGetCurrentSurface returns the read or draw surface attached
+ // to the current EGL rendering context, as specified by eglMakeCurrent.
+ // If no context is current, EGL_NO_SURFACE is returned.
+ EGLContext ctx = (EGLContext)getGlThreadSpecific();
+ if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE;
+ egl_context_t* c = egl_context_t::context(ctx);
+ if (readdraw == EGL_READ) {
+ return c->read;
+ } else if (readdraw == EGL_DRAW) {
+ return c->draw;
+ }
+ return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
EGLDisplay eglGetCurrentDisplay(void)
{
- // eglGetCurrentDisplay returns the current EGL display connection
- // for the current EGL rendering context, as specified by eglMakeCurrent.
- // If no context is current, EGL_NO_DISPLAY is returned.
- EGLContext ctx = (EGLContext)getGlThreadSpecific();
- if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
- egl_context_t* c = egl_context_t::context(ctx);
- return c->dpy;
+ // eglGetCurrentDisplay returns the current EGL display connection
+ // for the current EGL rendering context, as specified by eglMakeCurrent.
+ // If no context is current, EGL_NO_DISPLAY is returned.
+ EGLContext ctx = (EGLContext)getGlThreadSpecific();
+ if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY;
+ egl_context_t* c = egl_context_t::context(ctx);
+ return c->dpy;
}
EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
- EGLint attribute, EGLint *value)
+ EGLint attribute, EGLint *value)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- egl_context_t* c = egl_context_t::context(ctx);
- switch (attribute) {
- case EGL_CONFIG_ID:
- // Returns the ID of the EGL frame buffer configuration with
- // respect to which the context was created
- return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
- }
- return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ egl_context_t* c = egl_context_t::context(ctx);
+ switch (attribute) {
+ case EGL_CONFIG_ID:
+ // Returns the ID of the EGL frame buffer configuration with
+ // respect to which the context was created
+ return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value);
+ }
+ return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
}
EGLBoolean eglWaitGL(void)
{
- return EGL_TRUE;
+ return EGL_TRUE;
}
EGLBoolean eglWaitNative(EGLint engine)
{
- return EGL_TRUE;
+ return EGL_TRUE;
}
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
- egl_surface_t* d = static_cast<egl_surface_t*>(draw);
- if (!d->isValid())
- return setError(EGL_BAD_SURFACE, EGL_FALSE);
- if (d->dpy != dpy)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-
- // post the surface
- d->swapBuffers();
-
- // if it's bound to a context, update the buffer
- if (d->ctx != EGL_NO_CONTEXT) {
- d->bindDrawSurface((GLES2Context*)d->ctx);
- // if this surface is also the read surface of the context
- // it is bound to, make sure to update the read buffer as well.
- // The EGL spec is a little unclear about this.
- egl_context_t* c = egl_context_t::context(d->ctx);
- if (c->read == draw) {
- d->bindReadSurface((GLES2Context*)d->ctx);
- }
- clock_t time = clock();
- float elapsed = (float)(time - c->lastSwapTime) / CLOCKS_PER_SEC;
- c->accumulateSeconds += elapsed;
- c->frame++;
-// LOGD("agl2: eglSwapBuffers elapsed=%.2fms \n*", elapsed * 1000);
- if (20 == c->frame) {
- float avg = c->accumulateSeconds / c->frame;
- LOGD("\n*\n* agl2: eglSwapBuffers %u frame avg fps=%.1f elapsed=%.2fms \n*",
- c->frame, 1 / avg, avg * 1000);
- c->frame = 0;
- c->accumulateSeconds = 0;
- }
- c->lastSwapTime = time;
- }
-
- return EGL_TRUE;
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+ egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+ if (!d->isValid())
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ if (d->dpy != dpy)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+
+ // post the surface
+ d->swapBuffers();
+
+ // if it's bound to a context, update the buffer
+ if (d->ctx != EGL_NO_CONTEXT) {
+ d->bindDrawSurface((GLES2Context*)d->ctx);
+ // if this surface is also the read surface of the context
+ // it is bound to, make sure to update the read buffer as well.
+ // The EGL spec is a little unclear about this.
+ egl_context_t* c = egl_context_t::context(d->ctx);
+ if (c->read == draw) {
+ d->bindReadSurface((GLES2Context*)d->ctx);
+ }
+ clock_t time = clock();
+ float elapsed = (float)(time - c->lastSwapTime) / CLOCKS_PER_SEC;
+ c->accumulateSeconds += elapsed;
+ c->frame++;
+ // LOGD("agl2: eglSwapBuffers elapsed=%.2fms \n*", elapsed * 1000);
+ if (20 == c->frame) {
+ float avg = c->accumulateSeconds / c->frame;
+ LOGD("\n*\n* agl2: eglSwapBuffers %u frame avg fps=%.1f elapsed=%.2fms \n*",
+ c->frame, 1 / avg, avg * 1000);
+ c->frame = 0;
+ c->accumulateSeconds = 0;
+ }
+ c->lastSwapTime = time;
+ }
+
+ return EGL_TRUE;
}
EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
- NativePixmapType target)
+ NativePixmapType target)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- // TODO: eglCopyBuffers()
- return EGL_FALSE;
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ // TODO: eglCopyBuffers()
+ return EGL_FALSE;
}
EGLint eglGetError(void)
{
- return getError();
+ return getError();
}
const char* eglQueryString(EGLDisplay dpy, EGLint name)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, (const char*)0);
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, (const char*)0);
- switch (name) {
- case EGL_VENDOR:
- return gVendorString;
- case EGL_VERSION:
- return gVersionString;
- case EGL_EXTENSIONS:
- return gExtensionsString;
- case EGL_CLIENT_APIS:
- return gClientApiString;
- }
- return setError(EGL_BAD_PARAMETER, (const char *)0);
+ switch (name) {
+ case EGL_VENDOR:
+ return gVendorString;
+ case EGL_VERSION:
+ return gVersionString;
+ case EGL_EXTENSIONS:
+ return gExtensionsString;
+ case EGL_CLIENT_APIS:
+ return gClientApiString;
+ }
+ return setError(EGL_BAD_PARAMETER, (const char *)0);
}
// ----------------------------------------------------------------------------
@@ -2052,38 +1992,38 @@ const char* eglQueryString(EGLDisplay dpy, EGLint name)
// ----------------------------------------------------------------------------
EGLBoolean eglSurfaceAttrib(
- EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+ EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- // TODO: eglSurfaceAttrib()
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ // TODO: eglSurfaceAttrib()
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
}
EGLBoolean eglBindTexImage(
- EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+ EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- // TODO: eglBindTexImage()
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ // TODO: eglBindTexImage()
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
}
EGLBoolean eglReleaseTexImage(
- EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+ EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- // TODO: eglReleaseTexImage()
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ // TODO: eglReleaseTexImage()
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
}
EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- // TODO: eglSwapInterval()
- return EGL_TRUE;
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ // TODO: eglSwapInterval()
+ return EGL_TRUE;
}
// ----------------------------------------------------------------------------
@@ -2092,36 +2032,36 @@ EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
EGLBoolean eglBindAPI(EGLenum api)
{
- if (api != EGL_OPENGL_ES_API)
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
- return EGL_TRUE;
+ if (api != EGL_OPENGL_ES_API)
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ return EGL_TRUE;
}
EGLenum eglQueryAPI(void)
{
- return EGL_OPENGL_ES_API;
+ return EGL_OPENGL_ES_API;
}
EGLBoolean eglWaitClient(void)
{
- glFinish();
- return EGL_TRUE;
+ glFinish();
+ return EGL_TRUE;
}
EGLBoolean eglReleaseThread(void)
{
- // TODO: eglReleaseThread()
- return EGL_TRUE;
+ // TODO: eglReleaseThread()
+ return EGL_TRUE;
}
EGLSurface eglCreatePbufferFromClientBuffer(
- EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
- EGLConfig config, const EGLint *attrib_list)
+ EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
+ EGLConfig config, const EGLint *attrib_list)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
- // TODO: eglCreatePbufferFromClientBuffer()
- return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
+ // TODO: eglCreatePbufferFromClientBuffer()
+ return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
}
// ----------------------------------------------------------------------------
@@ -2129,84 +2069,84 @@ EGLSurface eglCreatePbufferFromClientBuffer(
// ----------------------------------------------------------------------------
void (*eglGetProcAddress (const char *procname))()
-{
- extention_map_t const * const map = gExtentionMap;
- for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
- if (!strcmp(procname, map[i].name)) {
- return map[i].address;
- }
- }
- return NULL;
-}
+ {
+ extention_map_t const * const map = gExtentionMap;
+ for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) {
+ if (!strcmp(procname, map[i].name)) {
+ return map[i].address;
+ }
+ }
+ return NULL;
+ }
EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
- const EGLint *attrib_list)
+ const EGLint *attrib_list)
{
- EGLBoolean result = EGL_FALSE;
- return result;
+ EGLBoolean result = EGL_FALSE;
+ return result;
}
EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
{
- EGLBoolean result = EGL_FALSE;
- return result;
+ EGLBoolean result = EGL_FALSE;
+ return result;
}
EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
- EGLClientBuffer buffer, const EGLint *attrib_list)
-{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
- return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
- }
- if (ctx != EGL_NO_CONTEXT) {
- return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
- }
- if (target != EGL_NATIVE_BUFFER_ANDROID) {
- return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
- }
-
- android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
-
- if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
- return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
-
- if (native_buffer->common.version != sizeof(android_native_buffer_t))
- return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
-
- switch (native_buffer->format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGBX_8888:
- case HAL_PIXEL_FORMAT_RGB_888:
- case HAL_PIXEL_FORMAT_RGB_565:
- case HAL_PIXEL_FORMAT_BGRA_8888:
- case HAL_PIXEL_FORMAT_RGBA_5551:
- case HAL_PIXEL_FORMAT_RGBA_4444:
- break;
- default:
- return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
- }
-
- native_buffer->common.incRef(&native_buffer->common);
- return (EGLImageKHR)native_buffer;
+ EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
+ return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
+ }
+ if (ctx != EGL_NO_CONTEXT) {
+ return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+ }
+ if (target != EGL_NATIVE_BUFFER_ANDROID) {
+ return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+ }
+
+ android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer;
+
+ if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+ return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+
+ if (native_buffer->common.version != sizeof(android_native_buffer_t))
+ return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+
+ switch (native_buffer->format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ break;
+ default:
+ return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
+ }
+
+ native_buffer->common.incRef(&native_buffer->common);
+ return (EGLImageKHR)native_buffer;
}
EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- }
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE) {
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ }
- android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
+ android_native_buffer_t* native_buffer = (android_native_buffer_t*)img;
- if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
- if (native_buffer->common.version != sizeof(android_native_buffer_t))
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ if (native_buffer->common.version != sizeof(android_native_buffer_t))
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
- native_buffer->common.decRef(&native_buffer->common);
+ native_buffer->common.decRef(&native_buffer->common);
- return EGL_TRUE;
+ return EGL_TRUE;
}
// ----------------------------------------------------------------------------
@@ -2214,19 +2154,19 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
// ----------------------------------------------------------------------------
EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw,
- EGLint left, EGLint top, EGLint width, EGLint height)
+ EGLint left, EGLint top, EGLint width, EGLint height)
{
- if (egl_display_t::is_valid(dpy) == EGL_FALSE)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ if (egl_display_t::is_valid(dpy) == EGL_FALSE)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- egl_surface_t* d = static_cast<egl_surface_t*>(draw);
- if (!d->isValid())
- return setError(EGL_BAD_SURFACE, EGL_FALSE);
- if (d->dpy != dpy)
- return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+ if (!d->isValid())
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ if (d->dpy != dpy)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- // post the surface
- d->setSwapRectangle(left, top, width, height);
+ // post the surface
+ d->setSwapRectangle(left, top, width, height);
- return EGL_TRUE;
+ return EGL_TRUE;
}
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 1f06dcc..c47383a 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -316,9 +316,10 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
filteredPos++;
}
- throw new IllegalArgumentException("position " + position + " out of "
- + "range of showable actions, filtered count = "
- + "= " + getCount() + ", keyguardshowing=" + mKeyguardShowing
+ throw new IllegalArgumentException("position " + position
+ + " out of range of showable actions"
+ + ", filtered count=" + getCount()
+ + ", keyguardshowing=" + mKeyguardShowing
+ ", provisioned=" + mDeviceProvisioned);
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 73003c8..d22d760 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -28,17 +28,15 @@ import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
import com.android.internal.view.RootViewSurfaceTaker;
import com.android.internal.view.StandaloneActionMode;
-import com.android.internal.view.menu.ActionMenuView;
import com.android.internal.view.menu.ContextMenuBuilder;
-import com.android.internal.view.menu.ListMenuPresenter;
import com.android.internal.view.menu.IconMenuPresenter;
+import com.android.internal.view.menu.ListMenuPresenter;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuDialogHelper;
-import com.android.internal.view.menu.MenuItemImpl;
-import com.android.internal.view.menu.MenuPopupHelper;
-import com.android.internal.view.menu.MenuView;
import com.android.internal.view.menu.MenuPresenter;
+import com.android.internal.view.menu.MenuView;
import com.android.internal.view.menu.SubMenuBuilder;
+import com.android.internal.widget.ActionBarContainer;
import com.android.internal.widget.ActionBarContextView;
import com.android.internal.widget.ActionBarView;
@@ -625,7 +623,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
- private void checkCloseActionMenu(Menu menu) {
+ void checkCloseActionMenu(Menu menu) {
if (mClosingActionMenu) {
return;
}
@@ -882,7 +880,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
if (cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) {
cb.onMenuOpened(FEATURE_ACTION_BAR, st.menu);
- mActionBar.openOverflowMenu();
+ mActionBar.showOverflowMenu();
}
}
} else {
@@ -2587,6 +2585,25 @@ 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 ActionBarContainer splitView = (ActionBarContainer) findViewById(
+ com.android.internal.R.id.split_action_bar);
+ if (splitView != null) {
+ mActionBar.setSplitActionBar(splitActionBar);
+ mActionBar.setSplitView(splitView);
+
+ final ActionBarContextView cab = (ActionBarContextView) findViewById(
+ com.android.internal.R.id.action_context_bar);
+ cab.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 9c43067..f04fb02 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/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 6c3b3d3..c225e89 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -34,6 +34,7 @@ import android.net.NetworkStateTracker;
import android.net.NetworkUtils;
import android.net.Proxy;
import android.net.ProxyProperties;
+import android.net.RouteInfo;
import android.net.vpn.VpnManager;
import android.net.wifi.WifiStateTracker;
import android.os.Binder;
@@ -1417,14 +1418,19 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (p == null) return;
String interfaceName = p.getInterfaceName();
if (TextUtils.isEmpty(interfaceName)) return;
- for (InetAddress gateway : p.getGateways()) {
+ for (RouteInfo route : p.getRoutes()) {
- if (NetworkUtils.addHostRoute(interfaceName, gateway, null) &&
- NetworkUtils.addDefaultRoute(interfaceName, gateway)) {
- if (DBG) {
- NetworkInfo networkInfo = nt.getNetworkInfo();
- log("addDefaultRoute for " + networkInfo.getTypeName() +
- " (" + interfaceName + "), GatewayAddr=" + gateway.getHostAddress());
+ //TODO - handle non-default routes
+ if (route.isDefaultRoute()) {
+ InetAddress gateway = route.getGateway();
+ if (NetworkUtils.addHostRoute(interfaceName, gateway, null) &&
+ NetworkUtils.addDefaultRoute(interfaceName, gateway)) {
+ if (DBG) {
+ NetworkInfo networkInfo = nt.getNetworkInfo();
+ log("addDefaultRoute for " + networkInfo.getTypeName() +
+ " (" + interfaceName + "), GatewayAddr=" +
+ gateway.getHostAddress());
+ }
}
}
}
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index d841cb3..02332b7 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/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 31b7f86..da34644 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7091,18 +7091,25 @@ public final class ActivityManagerService extends ActivityManagerNative
* to append various headers to the dropbox log text.
*/
private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
+ // Watchdog thread ends up invoking this function (with
+ // a null ProcessRecord) to add the stack file to dropbox.
+ // Do not acquire a lock on this (am) in such cases, as it
+ // could cause a potential deadlock, if and when watchdog
+ // is invoked due to unavailability of lock on am and it
+ // would prevent watchdog from killing system_server.
+ if (process == null) {
+ sb.append("Process: system_server\n");
+ return;
+ }
// Note: ProcessRecord 'process' is guarded by the service
// instance. (notably process.pkgList, which could otherwise change
// concurrently during execution of this method)
synchronized (this) {
- if (process == null || process.pid == MY_PID) {
+ if (process.pid == MY_PID) {
sb.append("Process: system_server\n");
} else {
sb.append("Process: ").append(process.processName).append("\n");
}
- if (process == null) {
- return;
- }
int flags = process.info.flags;
IPackageManager pm = AppGlobals.getPackageManager();
sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
diff --git a/services/java/com/android/server/location/ComprehensiveCountryDetector.java b/services/java/com/android/server/location/ComprehensiveCountryDetector.java
index e9ce3ce..bb9e60f 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 139f05d..d4fb8ee 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/surfaceflinger/TextureManager.cpp b/services/surfaceflinger/TextureManager.cpp
index c9a15f5..9e24f90 100644
--- a/services/surfaceflinger/TextureManager.cpp
+++ b/services/surfaceflinger/TextureManager.cpp
@@ -186,7 +186,7 @@ status_t TextureManager::loadTexture(Texture* texture,
if (texture->name == -1UL) {
status_t err = initTexture(texture);
LOGE_IF(err, "loadTexture failed in initTexture (%s)", strerror(err));
- return err;
+ if (err != NO_ERROR) return err;
}
if (texture->target != Texture::TEXTURE_2D)
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 186b349..295f324 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 2fcce78..f8d1426 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 0000000..6f55f46
--- /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 71e8e2a..60677df 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/android/telephony/JapanesePhoneNumberFormatter.java b/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java
index 6390d8e..f5e53ef 100644
--- a/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java
+++ b/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java
@@ -24,6 +24,7 @@ import android.text.Editable;
*
* 022-229-1234 0223-23-1234 022-301-9876 015-482-7849 0154-91-3478
* 01547-5-4534 090-1234-1234 080-0123-6789
+ * 050-0000-0000 060-0000-0000
* 0800-000-9999 0570-000-000 0276-00-0000
*
* As you can see, there is no straight-forward rule here.
@@ -31,7 +32,7 @@ import android.text.Editable;
*/
/* package */ class JapanesePhoneNumberFormatter {
private static short FORMAT_MAP[] = {
- -100, 10, 220, -15, 410, 530, -15, 670, 780, 1060,
+ -100, 10, 220, -15, 410, 530, 1200, 670, 780, 1060,
-100, -25, 20, 40, 70, 100, 150, 190, 200, 210,
-36, -100, -100, -35, -35, -35, 30, -100, -100, -100,
-35, -35, -35, -35, -35, -35, -35, -45, -35, -35,
@@ -84,7 +85,7 @@ import android.text.Editable;
-35, -25, -25, -25, -25, -25, -25, -25, -25, -25,
-25, -25, -25, -35, -35, -35, -25, -25, -25, 520,
-100, -100, -45, -100, -45, -100, -45, -100, -45, -100,
- -25, -100, -25, 540, 580, 590, 600, 610, 630, 640,
+ -26, -100, -25, 540, 580, 590, 600, 610, 630, 640,
-25, -35, -35, -35, -25, -25, -35, -35, -35, 550,
-35, -35, -25, -25, -25, -25, 560, 570, -25, -35,
-35, -35, -35, -35, -25, -25, -25, -25, -25, -25,
@@ -150,7 +151,8 @@ import android.text.Editable;
-35, 1170, -25, -35, 1180, -35, 1190, -35, -25, -25,
-100, -100, -45, -45, -100, -100, -100, -100, -100, -100,
-25, -35, -35, -35, -35, -35, -35, -25, -25, -35,
- -35, -35, -35, -35, -35, -35, -35, -35, -35, -45};
+ -35, -35, -35, -35, -35, -35, -35, -35, -35, -45,
+ -26, -15, -15, -15, -15, -15, -15, -15, -15, -15};
public static void format(Editable text) {
// Here, "root" means the position of "'":
diff --git a/telephony/java/com/android/internal/telephony/ApnContext.java b/telephony/java/com/android/internal/telephony/ApnContext.java
index 3f1ca9e..010d61d 100644
--- a/telephony/java/com/android/internal/telephony/ApnContext.java
+++ b/telephony/java/com/android/internal/telephony/ApnContext.java
@@ -51,6 +51,8 @@ public class ApnContext {
DataConnection mDataConnection;
+ DataConnectionAc mDataConnectionAc;
+
String mReason;
PendingIntent mReconnectIntent;
@@ -96,6 +98,17 @@ public class ApnContext {
mDataConnection = dataConnection;
}
+
+ public synchronized DataConnectionAc getDataConnectionAc() {
+ log("getDataConnectionAc dcac=" + mDataConnectionAc);
+ return mDataConnectionAc;
+ }
+
+ public synchronized void setDataConnectionAc(DataConnectionAc dcac) {
+ log("setDataConnectionAc dcac=" + dcac);
+ mDataConnectionAc = dcac;
+ }
+
public synchronized ApnSetting getApnSetting() {
return mApnSetting;
}
@@ -206,6 +219,11 @@ public class ApnContext {
return mDependencyMet.get();
}
+ @Override
+ public String toString() {
+ return "state=" + getState() + " apnType=" + mApnType;
+ }
+
protected void log(String s) {
Log.d(LOG_TAG, "[ApnContext] " + s);
}
diff --git a/telephony/java/com/android/internal/telephony/DataCallState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
index a883e8e..1d67d45 100644
--- a/telephony/java/com/android/internal/telephony/DataCallState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -20,6 +20,7 @@ package com.android.internal.telephony;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkUtils;
+import android.net.RouteInfo;
import android.os.SystemProperties;
import android.util.Log;
@@ -196,7 +197,7 @@ public class DataCallState {
} catch (IllegalArgumentException e) {
throw new UnknownHostException("Non-numeric gateway addr=" + addr);
}
- linkProperties.addGateway(ia);
+ linkProperties.addRoute(new RouteInfo(ia));
}
result = SetupResult.SUCCESS;
@@ -223,5 +224,3 @@ public class DataCallState {
return result;
}
}
-
-
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 791fbfd..6a5b82c 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -17,22 +17,24 @@
package com.android.internal.telephony;
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
-import android.net.LinkAddress;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
-import android.net.NetworkUtils;
+import android.net.ProxyProperties;
import android.os.AsyncResult;
+import android.os.Bundle;
import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.SystemProperties;
import android.text.TextUtils;
-import java.net.InetAddress;
-import java.net.Inet4Address;
-import java.net.UnknownHostException;
import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* {@hide}
@@ -60,6 +62,8 @@ public abstract class DataConnection extends StateMachine {
protected static Object mCountLock = new Object();
protected static int mCount;
+ protected AsyncChannel mAc;
+
/**
* Used internally for saving connecting parameters.
@@ -76,13 +80,6 @@ public abstract class DataConnection extends StateMachine {
}
/**
- * An instance used for notification of blockingReset.
- * TODO: Remove when blockingReset is removed.
- */
- class ResetSynchronouslyLock {
- }
-
- /**
* Used internally for saving disconnecting parameters.
*/
protected static class DisconnectParams {
@@ -90,15 +87,9 @@ public abstract class DataConnection extends StateMachine {
this.reason = reason;
this.onCompletedMsg = onCompletedMsg;
}
- public DisconnectParams(ResetSynchronouslyLock lockObj) {
- this.reason = null;
- this.lockObj = lockObj;
- }
-
public int tag;
public String reason;
public Message onCompletedMsg;
- public ResetSynchronouslyLock lockObj;
}
/**
@@ -188,13 +179,13 @@ public abstract class DataConnection extends StateMachine {
}
// ***** Event codes for driving the state machine
- protected static final int EVENT_RESET = 1;
- protected static final int EVENT_CONNECT = 2;
- protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 3;
- protected static final int EVENT_GET_LAST_FAIL_DONE = 4;
- protected static final int EVENT_DEACTIVATE_DONE = 5;
- protected static final int EVENT_DISCONNECT = 6;
- protected static final int EVENT_RIL_CONNECTED = 7;
+ protected static final int BASE = Protocol.BASE_DATA_CONNECTION;
+ protected static final int EVENT_CONNECT = BASE + 0;
+ protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = BASE + 1;
+ protected static final int EVENT_GET_LAST_FAIL_DONE = BASE + 2;
+ protected static final int EVENT_DEACTIVATE_DONE = BASE + 3;
+ protected static final int EVENT_DISCONNECT = BASE + 4;
+ protected static final int EVENT_RIL_CONNECTED = BASE + 5;
//***** Tag IDs for EventLog
protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
@@ -313,13 +304,8 @@ public abstract class DataConnection extends StateMachine {
AsyncResult.forMessage(msg);
msg.sendToTarget();
}
- if (dp.lockObj != null) {
- synchronized(dp.lockObj) {
- dp.lockObj.notify();
- }
- }
-
clearSettings();
+ if (DBG) log("NotifyDisconnectCompleted DisconnectParams=" + dp);
}
protected int getRadioTechnology(int defaultRadioTechnology) {
@@ -408,6 +394,49 @@ public abstract class DataConnection extends StateMachine {
return mRetryMgr.isRetryForever();
}
+ private AtomicInteger mRefCount = new AtomicInteger(0);
+
+ /**
+ * Set refCount.
+ *
+ * @param val is new refCount
+ */
+ public void setRefCount(int val) {
+ mRefCount.set(val);
+ }
+
+ /**
+ * Get refCount
+ *
+ * @return refCount
+ */
+ public int getRefCount() {
+ return mRefCount.get();
+ }
+
+ /**
+ * @return decrement and return refCount
+ *
+ * TODO: Consider using the refCount for defining the
+ * life time of a connection. When this goes zero the
+ * DataConnection could tear itself down.
+ */
+ public int decAndGetRefCount() {
+ int v = mRefCount.decrementAndGet();
+ if (v < 0) {
+ log("BUG: decAndGetRefCount caused refCount to be < 0");
+ mRefCount.set(0);
+ }
+ return v;
+ }
+
+ /**
+ * @return increment and return refCount
+ */
+ public int incAndGetRefCount() {
+ return mRefCount.incrementAndGet();
+ }
+
/*
* **************************************************************************
* End members owned by DataConnectionTracker
@@ -498,12 +527,74 @@ public abstract class DataConnection extends StateMachine {
AsyncResult ar;
switch (msg.what) {
- case EVENT_RESET:
- if (DBG) log("DcDefaultState: msg.what=EVENT_RESET");
- clearSettings();
- if (msg.obj != null) {
- notifyDisconnectCompleted((DisconnectParams) msg.obj);
+ case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
+ if (mAc != null) {
+ log("Disconnecting to previous connection mAc=" + mAc);
+ mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+ AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED);
+ } else {
+ mAc = new AsyncChannel();
+ mAc.connected(null, getHandler(), msg.replyTo);
+ log("DcDefaultState: FULL_CONNECTION reply connected");
+ mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+ AsyncChannel.STATUS_SUCCESSFUL, mId, "hi");
}
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
+ log("CMD_CHANNEL_DISCONNECT");
+ mAc.disconnect();
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ log("CMD_CHANNEL_DISCONNECTED");
+ mAc = null;
+ break;
+ }
+ case DataConnectionAc.REQ_IS_INACTIVE: {
+ boolean val = getCurrentState() == mInactiveState;
+ log("REQ_IS_INACTIVE isInactive=" + val);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_IS_INACTIVE, val ? 1 : 0);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_CID: {
+ log("REQ_GET_CID cid=" + cid);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_CID, cid);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_APNSETTING: {
+ log("REQ_GET_APNSETTING apnSetting=" + mApn);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_APNSETTING, mApn);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_LINK_PROPERTIES: {
+ LinkProperties lp = new LinkProperties(mLinkProperties);
+ log("REQ_GET_LINK_PROPERTIES linkProperties" + lp);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_LINK_PROPERTIES, lp);
+ break;
+ }
+ case DataConnectionAc.REQ_SET_LINK_PROPERTIES_HTTP_PROXY: {
+ ProxyProperties proxy = (ProxyProperties) msg.obj;
+ log("REQ_SET_LINK_PROPERTIES_HTTP_PROXY proxy=" + proxy);
+ mLinkProperties.setHttpProxy(proxy);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_SET_LINK_PROPERTIES_HTTP_PROXY);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_LINK_CAPABILITIES: {
+ LinkCapabilities lc = new LinkCapabilities(mCapabilities);
+ log("REQ_GET_LINK_CAPABILITIES linkCapabilities" + lc);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_LINK_CAPABILITIES, lc);
+ break;
+ }
+ case DataConnectionAc.REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE: {
+ Bundle data = msg.getData();
+ mLinkProperties = (LinkProperties) data.get("linkProperties");
+ break;
+ }
+ case DataConnectionAc.REQ_RESET:
+ if (DBG) log("DcDefaultState: msg.what=REQ_RESET");
+ clearSettings();
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
transitionTo(mInactiveState);
break;
@@ -539,7 +630,7 @@ public abstract class DataConnection extends StateMachine {
break;
}
- return true;
+ return HANDLED;
}
}
private DcDefaultState mDefaultState = new DcDefaultState();
@@ -597,14 +688,12 @@ public abstract class DataConnection extends StateMachine {
boolean retVal;
switch (msg.what) {
- case EVENT_RESET:
+ case DataConnectionAc.REQ_RESET:
if (DBG) {
- log("DcInactiveState: msg.what=EVENT_RESET, ignore we're already reset");
+ log("DcInactiveState: msg.what=RSP_RESET, ignore we're already reset");
}
- if (msg.obj != null) {
- notifyDisconnectCompleted((DisconnectParams) msg.obj);
- }
- retVal = true;
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
+ retVal = HANDLED;
break;
case EVENT_CONNECT:
@@ -613,12 +702,12 @@ public abstract class DataConnection extends StateMachine {
cp.tag = mTag;
onConnect(cp);
transitionTo(mActivatingState);
- retVal = true;
+ retVal = HANDLED;
break;
default:
if (DBG) log("DcInactiveState nothandled msg.what=" + msg.what);
- retVal = false;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -640,7 +729,7 @@ public abstract class DataConnection extends StateMachine {
case EVENT_DISCONNECT:
if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT");
deferMessage(msg);
- retVal = true;
+ retVal = HANDLED;
break;
case EVENT_SETUP_DATA_CONNECTION_DONE:
@@ -685,7 +774,7 @@ public abstract class DataConnection extends StateMachine {
default:
throw new RuntimeException("Unknown SetupResult, should not happen");
}
- retVal = true;
+ retVal = HANDLED;
break;
case EVENT_GET_LAST_FAIL_DONE:
@@ -710,12 +799,12 @@ public abstract class DataConnection extends StateMachine {
}
}
- retVal = true;
+ retVal = HANDLED;
break;
default:
if (DBG) log("DcActivatingState not handled msg.what=" + msg.what);
- retVal = false;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -768,12 +857,12 @@ public abstract class DataConnection extends StateMachine {
dp.tag = mTag;
tearDownData(dp);
transitionTo(mDisconnectingState);
- retVal = true;
+ retVal = HANDLED;
break;
default:
if (DBG) log("DcActiveState nothandled msg.what=" + msg.what);
- retVal = false;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -803,12 +892,12 @@ public abstract class DataConnection extends StateMachine {
if (DBG) log("DcDisconnectState EVENT_DEACTIVATE_DONE stale dp.tag="
+ dp.tag + " mTag=" + mTag);
}
- retVal = true;
+ retVal = HANDLED;
break;
default:
if (DBG) log("DcDisconnectingState not handled msg.what=" + msg.what);
- retVal = false;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -845,7 +934,7 @@ public abstract class DataConnection extends StateMachine {
" stale dp.tag=" + cp.tag + ", mTag=" + mTag);
}
}
- retVal = true;
+ retVal = HANDLED;
break;
default:
@@ -853,7 +942,7 @@ public abstract class DataConnection extends StateMachine {
log("DcDisconnectionErrorCreatingConnection not handled msg.what="
+ msg.what);
}
- retVal = false;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -865,147 +954,26 @@ public abstract class DataConnection extends StateMachine {
// ******* public interface
/**
- * Disconnect from the network.
- *
- * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
- * With AsyncResult.userObj set to the original msg.obj.
- */
- public void reset(Message onCompletedMsg) {
- sendMessage(obtainMessage(EVENT_RESET, new DisconnectParams(null, onCompletedMsg)));
- }
-
- /**
- * Reset the connection and wait for it to complete.
- * TODO: Remove when all callers only need the asynchronous
- * reset defined above.
- */
- public void resetSynchronously() {
- ResetSynchronouslyLock lockObj = new ResetSynchronouslyLock();
- synchronized(lockObj) {
- sendMessage(obtainMessage(EVENT_RESET, new DisconnectParams(lockObj)));
- try {
- lockObj.wait();
- } catch (InterruptedException e) {
- log("blockingReset: unexpected interrupted of wait()");
- }
- }
- }
-
- /**
- * Connect to the apn and return an AsyncResult in onCompletedMsg.
+ * Bring up a connection to the apn and return an AsyncResult in onCompletedMsg.
* Used for cellular networks that use Acesss Point Names (APN) such
* as GSM networks.
*
* @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
* With AsyncResult.userObj set to the original msg.obj,
* AsyncResult.result = FailCause and AsyncResult.exception = Exception().
- * @param apn is the Access Point Name to connect to
+ * @param apn is the Access Point Name to bring up a connection to
*/
- public void connect(Message onCompletedMsg, ApnSetting apn) {
+ public void bringUp(Message onCompletedMsg, ApnSetting apn) {
sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg)));
}
/**
- * Connect to the apn and return an AsyncResult in onCompletedMsg.
- *
- * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
- * With AsyncResult.userObj set to the original msg.obj,
- * AsyncResult.result = FailCause and AsyncResult.exception = Exception().
- */
- public void connect(Message onCompletedMsg) {
- sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(null, onCompletedMsg)));
- }
-
- /**
- * Disconnect from the network.
+ * Tear down the connection through the apn on the network.
*
* @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
* With AsyncResult.userObj set to the original msg.obj.
*/
- public void disconnect(String reason, Message onCompletedMsg) {
+ public void tearDown(String reason, Message onCompletedMsg) {
sendMessage(obtainMessage(EVENT_DISCONNECT, new DisconnectParams(reason, onCompletedMsg)));
}
-
- // ****** The following are used for debugging.
-
- /**
- * TODO: This should be an asynchronous call and we wouldn't
- * have to use handle the notification in the DcInactiveState.enter.
- *
- * @return true if the state machine is in the inactive state.
- */
- public boolean isInactive() {
- boolean retVal = getCurrentState() == mInactiveState;
- return retVal;
- }
-
- /**
- * TODO: This should be an asynchronous call and we wouldn't
- * have to use handle the notification in the DcActiveState.enter.
- *
- * @return true if the state machine is in the active state.
- */
- public boolean isActive() {
- boolean retVal = getCurrentState() == mActiveState;
- return retVal;
- }
-
- /**
- * Return the LinkProperties for the connection.
- *
- * @return a copy of the LinkProperties, is never null.
- */
- public LinkProperties getLinkProperties() {
- return new LinkProperties(mLinkProperties);
- }
-
- /**
- * A capability is an Integer/String pair, the capabilities
- * are defined in the class LinkSocket#Key.
- *
- * @return a copy of this connections capabilities, may be empty but never null.
- */
- public LinkCapabilities getLinkCapabilities() {
- return new LinkCapabilities(mCapabilities);
- }
-
- /**
- * @return the current state as a string.
- */
- public String getStateAsString() {
- String retVal = getCurrentState().getName();
- return retVal;
- }
-
- /**
- * @return the time of when this connection was created.
- */
- public long getConnectionTime() {
- return createTime;
- }
-
- /**
- * @return the time of the last failure.
- */
- public long getLastFailTime() {
- return lastFailTime;
- }
-
- /**
- * @return the last cause of failure.
- */
- public FailCause getLastFailCause() {
- return lastFailCause;
- }
-
- /**
- * @return the current ApnSetting
- */
- public ApnSetting getApn() {
- return mApn;
- }
-
- public int getCid() {
- return cid;
- }
}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionAc.java b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
new file mode 100644
index 0000000..a9796dd
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
@@ -0,0 +1,288 @@
+/*
+ * 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.telephony;
+
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
+import android.net.ProxyProperties;
+import android.os.Message;
+
+/**
+ * AsyncChannel to a DataConnection
+ */
+public class DataConnectionAc extends AsyncChannel {
+ private static final boolean DBG = true;
+ private String mLogTag;
+
+ public DataConnection dataConnection;
+
+ public static final int BASE = Protocol.BASE_DATA_CONNECTION_AC;
+
+ public static final int REQ_IS_INACTIVE = BASE + 0;
+ public static final int RSP_IS_INACTIVE = BASE + 1;
+
+ public static final int REQ_GET_CID = BASE + 2;
+ public static final int RSP_GET_CID = BASE + 3;
+
+ public static final int REQ_GET_APNSETTING = BASE + 4;
+ public static final int RSP_GET_APNSETTING = BASE + 5;
+
+ public static final int REQ_GET_LINK_PROPERTIES = BASE + 6;
+ public static final int RSP_GET_LINK_PROPERTIES = BASE + 7;
+
+ public static final int REQ_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 8;
+ public static final int RSP_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 9;
+
+ public static final int REQ_GET_LINK_CAPABILITIES = BASE + 10;
+ public static final int RSP_GET_LINK_CAPABILITIES = BASE + 11;
+
+ public static final int REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE = BASE + 12;
+ public static final int RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE = BASE + 13;
+
+ public static final int REQ_RESET = BASE + 14;
+ public static final int RSP_RESET = BASE + 15;
+
+ public DataConnectionAc(DataConnection dc, String logTag) {
+ dataConnection = dc;
+ mLogTag = logTag;
+ }
+
+ /**
+ * Request if the state machine is in the inactive state.
+ * Response {@link #rspIsInactive}
+ */
+ public void reqIsInactive() {
+ sendMessage(REQ_IS_INACTIVE);
+ if (DBG) log("reqIsInactive");
+ }
+
+ /**
+ * Evaluate RSP_IS_INACTIVE.
+ *
+ * @return true if the state machine is in the inactive state.
+ */
+ public boolean rspIsInactive(Message response) {
+ boolean retVal = response.arg1 == 1;
+ if (DBG) log("rspIsInactive=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * @return true if the state machine is in the inactive state.
+ */
+ public boolean isInactiveSync() {
+ Message response = sendMessageSynchronously(REQ_IS_INACTIVE);
+ if ((response != null) && (response.what == RSP_IS_INACTIVE)) {
+ return rspIsInactive(response);
+ } else {
+ log("rspIsInactive error response=" + response);
+ return false;
+ }
+ }
+
+ /**
+ * Request the Connection ID.
+ * Response {@link #rspCid}
+ */
+ public void reqCid() {
+ sendMessage(REQ_GET_CID);
+ if (DBG) log("reqCid");
+ }
+
+ /**
+ * Evaluate a RSP_GET_CID message and return the cid.
+ *
+ * @param response Message
+ * @return connection id or -1 if an error
+ */
+ public int rspCid(Message response) {
+ int retVal = response.arg1;
+ if (DBG) log("rspCid=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * @return connection id or -1 if an error
+ */
+ public int getCidSync() {
+ Message response = sendMessageSynchronously(REQ_GET_CID);
+ if ((response != null) && (response.what == RSP_GET_CID)) {
+ return rspCid(response);
+ } else {
+ log("rspCid error response=" + response);
+ return -1;
+ }
+ }
+
+ /**
+ * Request the connections ApnSetting.
+ * Response {@link #rspApnSetting}
+ */
+ public void reqApnSetting() {
+ sendMessage(REQ_GET_APNSETTING);
+ if (DBG) log("reqApnSetting");
+ }
+
+ /**
+ * Evaluate a RSP_APN_SETTING message and return the ApnSetting.
+ *
+ * @param response Message
+ * @return ApnSetting, maybe null
+ */
+ public ApnSetting rspApnSetting(Message response) {
+ ApnSetting retVal = (ApnSetting) response.obj;
+ if (DBG) log("rspApnSetting=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * Get the connections ApnSetting.
+ *
+ * @return ApnSetting or null if an error
+ */
+ public ApnSetting getApnSettingSync() {
+ Message response = sendMessageSynchronously(REQ_GET_APNSETTING);
+ if ((response != null) && (response.what == RSP_GET_APNSETTING)) {
+ return rspApnSetting(response);
+ } else {
+ log("getApnSetting error response=" + response);
+ return null;
+ }
+ }
+
+ /**
+ * Request the connections LinkProperties.
+ * Response {@link #rspLinkProperties}
+ */
+ public void reqLinkProperties() {
+ sendMessage(REQ_GET_LINK_PROPERTIES);
+ if (DBG) log("reqLinkProperties");
+ }
+
+ /**
+ * Evaluate RSP_GET_LINK_PROPERTIES
+ *
+ * @param response
+ * @return LinkProperties, maybe null.
+ */
+ public LinkProperties rspLinkProperties(Message response) {
+ LinkProperties retVal = (LinkProperties) response.obj;
+ if (DBG) log("rspLinkProperties=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * Get the connections LinkProperties.
+ *
+ * @return LinkProperties or null if an error
+ */
+ public LinkProperties getLinkPropertiesSync() {
+ Message response = sendMessageSynchronously(REQ_GET_LINK_PROPERTIES);
+ if ((response != null) && (response.what == RSP_GET_LINK_PROPERTIES)) {
+ return rspLinkProperties(response);
+ } else {
+ log("getLinkProperties error response=" + response);
+ return null;
+ }
+ }
+
+ /**
+ * Request setting the connections LinkProperties.HttpProxy.
+ * Response RSP_SET_LINK_PROPERTIES when complete.
+ */
+ public void reqSetLinkPropertiesHttpProxy(ProxyProperties proxy) {
+ sendMessage(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy);
+ if (DBG) log("reqSetLinkPropertiesHttpProxy proxy=" + proxy);
+ }
+
+ /**
+ * Set the connections LinkProperties.HttpProxy
+ */
+ public void setLinkPropertiesHttpProxySync(ProxyProperties proxy) {
+ Message response =
+ sendMessageSynchronously(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy);
+ if ((response != null) && (response.what == RSP_SET_LINK_PROPERTIES_HTTP_PROXY)) {
+ if (DBG) log("setLinkPropertiesHttpPoxy ok");
+ } else {
+ log("setLinkPropertiesHttpPoxy error response=" + response);
+ }
+ }
+
+ /**
+ * Request the connections LinkCapabilities.
+ * Response {@link #rspLinkCapabilities}
+ */
+ public void reqLinkCapabilities() {
+ sendMessage(REQ_GET_LINK_CAPABILITIES);
+ if (DBG) log("reqLinkCapabilities");
+ }
+
+ /**
+ * Evaluate RSP_GET_LINK_CAPABILITIES
+ *
+ * @param response
+ * @return LinkCapabilites, maybe null.
+ */
+ public LinkCapabilities rspLinkCapabilities(Message response) {
+ LinkCapabilities retVal = (LinkCapabilities) response.obj;
+ if (DBG) log("rspLinkCapabilities=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * Get the connections LinkCapabilities.
+ *
+ * @return LinkCapabilities or null if an error
+ */
+ public LinkCapabilities getLinkCapabilitiesSync() {
+ Message response = sendMessageSynchronously(REQ_GET_LINK_CAPABILITIES);
+ if ((response != null) && (response.what == RSP_GET_LINK_CAPABILITIES)) {
+ return rspLinkCapabilities(response);
+ } else {
+ log("getLinkCapabilities error response=" + response);
+ return null;
+ }
+ }
+
+ /**
+ * Request the connections LinkCapabilities.
+ * Response RSP_RESET when complete
+ */
+ public void reqReset() {
+ sendMessage(REQ_RESET);
+ if (DBG) log("reqReset");
+ }
+
+ /**
+ * Reset the connection and wait for it to complete.
+ */
+ public void resetSync() {
+ Message response = sendMessageSynchronously(REQ_RESET);
+ if ((response != null) && (response.what == RSP_RESET)) {
+ if (DBG) log("restSync ok");
+ } else {
+ if (DBG) log("restSync error response=" + response);
+ }
+ }
+
+ private void log(String s) {
+ android.util.Log.d(mLogTag, "DataConnectionAc " + s);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 01ac95f..ad4e796 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -22,7 +22,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
-import android.net.IConnectivityManager;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkInfo;
@@ -32,7 +31,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
-import android.os.ServiceManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@@ -40,6 +38,8 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.internal.R;
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
import java.util.ArrayList;
import java.util.HashMap;
@@ -91,38 +91,39 @@ public abstract class DataConnectionTracker extends Handler {
public static String EXTRA_MESSENGER = "EXTRA_MESSENGER";
/***** Event Codes *****/
- protected static final int EVENT_DATA_SETUP_COMPLETE = 1;
- protected static final int EVENT_RADIO_AVAILABLE = 3;
- protected static final int EVENT_RECORDS_LOADED = 4;
- protected static final int EVENT_TRY_SETUP_DATA = 5;
- protected static final int EVENT_DATA_STATE_CHANGED = 6;
- protected static final int EVENT_POLL_PDP = 7;
- protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
- protected static final int EVENT_VOICE_CALL_STARTED = 14;
- protected static final int EVENT_VOICE_CALL_ENDED = 15;
- protected static final int EVENT_DATA_CONNECTION_DETACHED = 19;
- protected static final int EVENT_LINK_STATE_CHANGED = 20;
- protected static final int EVENT_ROAMING_ON = 21;
- protected static final int EVENT_ROAMING_OFF = 22;
- protected static final int EVENT_ENABLE_NEW_APN = 23;
- protected static final int EVENT_RESTORE_DEFAULT_APN = 24;
- protected static final int EVENT_DISCONNECT_DONE = 25;
- protected static final int EVENT_DATA_CONNECTION_ATTACHED = 26;
- protected static final int EVENT_START_NETSTAT_POLL = 27;
- protected static final int EVENT_START_RECOVERY = 28;
- protected static final int EVENT_APN_CHANGED = 29;
- protected static final int EVENT_CDMA_DATA_DETACHED = 30;
- protected static final int EVENT_NV_READY = 31;
- protected static final int EVENT_PS_RESTRICT_ENABLED = 32;
- protected static final int EVENT_PS_RESTRICT_DISABLED = 33;
- public static final int EVENT_CLEAN_UP_CONNECTION = 34;
- protected static final int EVENT_CDMA_OTA_PROVISION = 35;
- protected static final int EVENT_RESTART_RADIO = 36;
- protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = 37;
- protected static final int EVENT_RESET_DONE = 38;
- public static final int CMD_SET_DATA_ENABLE = 39;
- public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = 40;
- public static final int CMD_SET_DEPENDENCY_MET = 41;
+ protected static final int BASE = Protocol.BASE_DATA_CONNECTION_TRACKER;
+ protected static final int EVENT_DATA_SETUP_COMPLETE = BASE + 0;
+ protected static final int EVENT_RADIO_AVAILABLE = BASE + 1;
+ protected static final int EVENT_RECORDS_LOADED = BASE + 2;
+ protected static final int EVENT_TRY_SETUP_DATA = BASE + 3;
+ protected static final int EVENT_DATA_STATE_CHANGED = BASE + 4;
+ protected static final int EVENT_POLL_PDP = BASE + 5;
+ protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = BASE + 6;
+ protected static final int EVENT_VOICE_CALL_STARTED = BASE + 7;
+ protected static final int EVENT_VOICE_CALL_ENDED = BASE + 8;
+ protected static final int EVENT_DATA_CONNECTION_DETACHED = BASE + 9;
+ protected static final int EVENT_LINK_STATE_CHANGED = BASE + 10;
+ protected static final int EVENT_ROAMING_ON = BASE + 11;
+ protected static final int EVENT_ROAMING_OFF = BASE + 12;
+ protected static final int EVENT_ENABLE_NEW_APN = BASE + 13;
+ protected static final int EVENT_RESTORE_DEFAULT_APN = BASE + 14;
+ protected static final int EVENT_DISCONNECT_DONE = BASE + 15;
+ protected static final int EVENT_DATA_CONNECTION_ATTACHED = BASE + 16;
+ protected static final int EVENT_START_NETSTAT_POLL = BASE + 17;
+ protected static final int EVENT_START_RECOVERY = BASE + 18;
+ protected static final int EVENT_APN_CHANGED = BASE + 19;
+ protected static final int EVENT_CDMA_DATA_DETACHED = BASE + 20;
+ protected static final int EVENT_NV_READY = BASE + 21;
+ protected static final int EVENT_PS_RESTRICT_ENABLED = BASE + 22;
+ protected static final int EVENT_PS_RESTRICT_DISABLED = BASE + 23;
+ public static final int EVENT_CLEAN_UP_CONNECTION = BASE + 24;
+ protected static final int EVENT_CDMA_OTA_PROVISION = BASE + 25;
+ protected static final int EVENT_RESTART_RADIO = BASE + 26;
+ protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = BASE + 27;
+ protected static final int EVENT_RESET_DONE = BASE + 28;
+ public static final int CMD_SET_DATA_ENABLE = BASE + 29;
+ public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 30;
+ public static final int CMD_SET_DEPENDENCY_MET = BASE + 31;
/***** Constants *****/
@@ -227,7 +228,7 @@ public abstract class DataConnectionTracker extends Handler {
/** indication of our availability (preconditions to trysetupData are met) **/
protected boolean mAvailability = false;
- // When false we will not auto attach and manully attaching is required.
+ // When false we will not auto attach and manually attaching is required.
protected boolean mAutoAttachOnCreation = false;
// State of screen
@@ -235,12 +236,6 @@ public abstract class DataConnectionTracker extends Handler {
// really a lower power mode")
protected boolean mIsScreenOn = true;
- /** The link properties (dns, gateway, ip, etc) */
- protected LinkProperties mLinkProperties = new LinkProperties();
-
- /** The link capabilities */
- protected LinkCapabilities mLinkCapabilities = new LinkCapabilities();
-
/** Allows the generation of unique Id's for DataConnection objects */
protected AtomicInteger mUniqueIdGenerator = new AtomicInteger(0);
@@ -248,6 +243,10 @@ public abstract class DataConnectionTracker extends Handler {
protected HashMap<Integer, DataConnection> mDataConnections =
new HashMap<Integer, DataConnection>();
+ /** The data connection async channels */
+ protected HashMap<Integer, DataConnectionAc> mDataConnectionAsyncChannels =
+ new HashMap<Integer, DataConnectionAc>();
+
/** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
protected HashMap<String, Integer> mApnToDataConnectionId =
new HashMap<String, Integer>();
@@ -267,7 +266,6 @@ public abstract class DataConnectionTracker extends Handler {
/** Is packet service restricted by network */
protected boolean mIsPsRestricted = false;
-
/* Once disposed dont handle any messages */
protected boolean mIsDisposed = false;
@@ -351,6 +349,10 @@ public abstract class DataConnectionTracker extends Handler {
}
public void dispose() {
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ dcac.disconnect();
+ }
+ mDataConnectionAsyncChannels.clear();
mIsDisposed = true;
mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
}
@@ -463,7 +465,13 @@ public abstract class DataConnectionTracker extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
-
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ log("DISCONNECTED_CONNECTED: msg=" + msg);
+ DataConnectionAc dcac = (DataConnectionAc) msg.obj;
+ mDataConnectionAsyncChannels.remove(dcac.dataConnection.getDataConnectionId());
+ dcac.disconnected();
+ break;
+ }
case EVENT_ENABLE_NEW_APN:
onEnableApn(msg.arg1, msg.arg2);
break;
@@ -528,19 +536,20 @@ public abstract class DataConnectionTracker extends Handler {
break;
}
case EVENT_RESET_DONE: {
+ if (DBG) log("EVENT_RESET_DONE");
onResetDone((AsyncResult) msg.obj);
break;
}
case CMD_SET_DATA_ENABLE: {
- log("CMD_SET_DATA_ENABLE msg=" + msg);
boolean enabled = (msg.arg1 == ENABLED) ? true : false;
+ if (DBG) log("CMD_SET_DATA_ENABLE enabled=" + enabled);
onSetDataEnabled(enabled);
break;
}
case CMD_SET_DEPENDENCY_MET: {
- log("CMD_SET_DEPENDENCY_MET msg=" + msg);
boolean met = (msg.arg1 == ENABLED) ? true : false;
+ if (DBG) log("CMD_SET_DEPENDENCY_MET met=" + met);
Bundle bundle = msg.getData();
if (bundle != null) {
String apnType = (String)bundle.get(APN_TYPE_KEY);
@@ -552,7 +561,7 @@ public abstract class DataConnectionTracker extends Handler {
}
default:
- Log.e("DATA", "Unidentified event = " + msg.what);
+ Log.e("DATA", "Unidentified event msg=" + msg);
break;
}
}
@@ -618,7 +627,8 @@ public abstract class DataConnectionTracker extends Handler {
protected LinkProperties getLinkProperties(String apnType) {
int id = apnTypeToId(apnType);
if (isApnIdEnabled(id)) {
- return new LinkProperties(mLinkProperties);
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(id);
+ return dcac.getLinkPropertiesSync();
} else {
return new LinkProperties();
}
@@ -627,33 +637,13 @@ public abstract class DataConnectionTracker extends Handler {
protected LinkCapabilities getLinkCapabilities(String apnType) {
int id = apnTypeToId(apnType);
if (isApnIdEnabled(id)) {
- return new LinkCapabilities(mLinkCapabilities);
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(id);
+ return dcac.getLinkCapabilitiesSync();
} else {
return new LinkCapabilities();
}
}
- /**
- * Return the LinkProperties for the connection.
- *
- * @param connection
- * @return a copy of the LinkProperties, is never null.
- */
- protected LinkProperties getLinkProperties(DataConnection connection) {
- return connection.getLinkProperties();
- }
-
- /**
- * A capability is an Integer/String pair, the capabilities
- * are defined in the class LinkSocket#Key.
- *
- * @param connection
- * @return a copy of this connections capabilities, may be empty but never null.
- */
- protected LinkCapabilities getLinkCapabilities(DataConnection connection) {
- return connection.getLinkCapabilities();
- }
-
// tell all active apns of the current condition
protected void notifyDataConnection(String reason) {
for (int id = 0; id < APN_NUM_TYPES; id++) {
diff --git a/telephony/java/com/android/internal/telephony/IccUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java
index df579b0..c3b0ffc 100644
--- a/telephony/java/com/android/internal/telephony/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/IccUtils.java
@@ -416,7 +416,6 @@ public class IccUtils {
int colorNumber = data[valueIndex++] & 0xFF;
int clutOffset = ((data[valueIndex++] & 0xFF) << 8)
| (data[valueIndex++] & 0xFF);
- length = length - 6;
int[] colorIndexArray = getCLUT(data, clutOffset, colorNumber);
if (true == transparency) {
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index c052e51..490051d 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -3024,7 +3024,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
dataCall.active = p.readInt();
dataCall.type = p.readString();
String addresses = p.readString();
- if (TextUtils.isEmpty(addresses)) {
+ if (!TextUtils.isEmpty(addresses)) {
dataCall.addresses = addresses.split(" ");
}
} else {
@@ -3033,7 +3033,8 @@ public final class RIL extends BaseCommands implements CommandsInterface {
dataCall.active = p.readInt();
dataCall.type = p.readString();
dataCall.ifname = p.readString();
- if (TextUtils.isEmpty(dataCall.ifname)) {
+ if ((dataCall.status == DataConnection.FailCause.NONE.getErrorCode()) &&
+ TextUtils.isEmpty(dataCall.ifname)) {
throw new RuntimeException("getDataCallState, no ifname");
}
String addresses = p.readString();
diff --git a/telephony/java/com/android/internal/telephony/cat/CatService.java b/telephony/java/com/android/internal/telephony/cat/CatService.java
index 5217ecd..33cc97e 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 cd585cf..d55f346 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -20,7 +20,6 @@ import android.os.Message;
import android.util.Log;
import com.android.internal.telephony.DataConnection;
-import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.RetryManager;
@@ -99,9 +98,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/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index dc85017..4b185a0 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -37,10 +37,12 @@ import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnectionAc;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.Phone;
+import com.android.internal.util.AsyncChannel;
import java.util.ArrayList;
@@ -297,14 +299,18 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
boolean notificationDeferred = false;
for (DataConnection conn : mDataConnections.values()) {
if(conn != null) {
+ DataConnectionAc dcac =
+ mDataConnectionAsyncChannels.get(conn.getDataConnectionId());
if (tearDown) {
if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
- conn.disconnect(reason, obtainMessage(EVENT_DISCONNECT_DONE,
+ conn.tearDown(reason, obtainMessage(EVENT_DISCONNECT_DONE,
conn.getDataConnectionId(), 0, reason));
notificationDeferred = true;
} else {
if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
- conn.resetSynchronously();
+ if (dcac != null) {
+ dcac.resetSync();
+ }
notificationDeferred = false;
}
}
@@ -319,11 +325,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
private CdmaDataConnection findFreeDataConnection() {
- for (DataConnection dc : mDataConnections.values()) {
- if (dc.isInactive()) {
- return (CdmaDataConnection) dc;
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ if (dcac.isInactiveSync()) {
+ log("found free GsmDataConnection");
+ return (CdmaDataConnection) dcac.dataConnection;
}
}
+ log("NO free CdmaDataConnection");
return null;
}
@@ -349,12 +357,12 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
mActiveApn = new ApnSetting(apnId, "", "", "", "", "", "", "", "", "",
"", 0, types, "IP", "IP");
- if (DBG) log("setupData: mActiveApn=" + mActiveApn);
+ if (DBG) log("call conn.bringUp mActiveApn=" + mActiveApn);
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = reason;
- conn.connect(msg, mActiveApn);
+ conn.bringUp(msg, mActiveApn);
setState(State.INITING);
notifyDataConnection(reason);
@@ -653,11 +661,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
if (ar.exception == null) {
- // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
- mLinkProperties = getLinkProperties(mPendingDataConnection);
- mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
-
- // everything is setup
+ // Everything is setup
notifyDefaultData(reason);
} else {
FailCause cause = (FailCause) (ar.result);
@@ -767,6 +771,16 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
int id = mUniqueIdGenerator.getAndIncrement();
dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone, id, rm);
mDataConnections.put(id, dataConn);
+ DataConnectionAc dcac = new DataConnectionAc(dataConn, LOG_TAG);
+ int status = dcac.fullyConnectSync(mPhone.getContext(), this, dataConn.getHandler());
+ if (status == AsyncChannel.STATUS_SUCCESSFUL) {
+ log("Fully connected");
+ mDataConnectionAsyncChannels.put(dcac.dataConnection.getDataConnectionId(), dcac);
+ } else {
+ log("Could not connect to dcac.dataConnection=" + dcac.dataConnection +
+ " status=" + status);
+ }
+
}
}
@@ -897,6 +911,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
@Override
public void handleMessage (Message msg) {
+ if (DBG) log("CdmaDCT handleMessage msg=" + msg);
if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
log("Ignore CDMA msgs since CDMA phone is inactive");
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index 109daf0..32c5d75 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -44,22 +44,14 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
CDMALTEPhone mCdmaLtePhone;
- private int gprsState = ServiceState.STATE_OUT_OF_SERVICE;
-
- private int newGPRSState = ServiceState.STATE_OUT_OF_SERVICE;
+ private ServiceState mLteSS; // The last LTE state from Voice Registration
public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
super(phone);
mCdmaLtePhone = phone;
- if (DBG) log("CdmaLteServiceStateTracker Constructors");
- }
- /**
- * @return The current GPRS state. IN_SERVICE is the same as "attached" and
- * OUT_OF_SERVICE is the same as detached.
- */
- public int getCurrentDataConnectionState() {
- return gprsState;
+ mLteSS = new ServiceState();
+ if (DBG) log("CdmaLteServiceStateTracker Constructors");
}
@Override
@@ -77,11 +69,13 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
}
/**
- * The LTE data connection state, only return true here
+ * Set the cdmaSS for EVENT_POLL_STATE_REGISTRATION_CDMA
*/
@Override
- protected boolean checkAdditionalDataAvaiable() {
- return newGPRSState != ServiceState.STATE_IN_SERVICE;
+ protected void setCdmaTechnology(int radioTechnology) {
+ // Called on voice registration state response.
+ // Just record new CDMA radio technology
+ newSS.setRadioTechnology(radioTechnology);
}
/**
@@ -109,14 +103,10 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
}
}
- newGPRSState = regCodeToServiceState(regState);
// Not sure if this is needed in CDMALTE phone.
// mDataRoaming = regCodeIsRoaming(regState);
- if (newGPRSState == ServiceState.STATE_IN_SERVICE) {
- this.newCdmaDataConnectionState = newGPRSState;
- newNetworkType = type;
- newSS.setRadioTechnology(type);
- }
+ mLteSS.setRadioTechnology(type);
+ mLteSS.setState(regCodeToServiceState(regState));
} else {
super.handlePollStateResultMessage(what, ar);
}
@@ -216,6 +206,21 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
@Override
protected void pollStateDone() {
+ // determine data NetworkType from both LET and CDMA SS
+ if (mLteSS.getState() == ServiceState.STATE_IN_SERVICE) {
+ //in LTE service
+ newNetworkType = mLteSS.getRadioTechnology();
+ mNewDataConnectionState = mLteSS.getState();
+ newSS.setRadioTechnology(newNetworkType);
+ log("pollStateDone LTE/eHRPD STATE_IN_SERVICE newNetworkType = " + newNetworkType);
+ } else {
+ // LTE out of service, get CDMA Service State
+ newNetworkType = newSS.getRadioTechnology();
+ mNewDataConnectionState = radioTechnologyToDataServiceState(newNetworkType);
+ log("pollStateDone CDMA STATE_IN_SERVICE newNetworkType = " + newNetworkType +
+ " mNewDataConnectionState = " + mNewDataConnectionState);
+ }
+
if (DBG) log("pollStateDone: oldSS=[" + ss + "] newSS=[" + newSS + "]");
boolean hasRegistered = ss.getState() != ServiceState.STATE_IN_SERVICE
@@ -225,15 +230,15 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
&& newSS.getState() != ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionAttached =
- this.cdmaDataConnectionState != ServiceState.STATE_IN_SERVICE
- && this.newCdmaDataConnectionState == ServiceState.STATE_IN_SERVICE;
+ mDataConnectionState != ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState == ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionDetached =
- this.cdmaDataConnectionState == ServiceState.STATE_IN_SERVICE
- && this.newCdmaDataConnectionState != ServiceState.STATE_IN_SERVICE;
+ mDataConnectionState == ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState != ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionChanged =
- cdmaDataConnectionState != newCdmaDataConnectionState;
+ mDataConnectionState != mNewDataConnectionState;
boolean hasNetworkTypeChanged = networkType != newNetworkType;
@@ -272,9 +277,9 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
}
// Add an event log when connection state changes
if (ss.getState() != newSS.getState()
- || cdmaDataConnectionState != newCdmaDataConnectionState) {
+ || mDataConnectionState != mNewDataConnectionState) {
EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE, ss.getState(),
- cdmaDataConnectionState, newSS.getState(), newCdmaDataConnectionState);
+ mDataConnectionState, newSS.getState(), mNewDataConnectionState);
}
ServiceState tss;
@@ -283,6 +288,7 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
newSS = tss;
// clean slate for next time
newSS.setStateOutOfService();
+ mLteSS.setStateOutOfService();
// TODO: 4G Tech Handoff
// if (has4gHandoff) {
@@ -309,11 +315,9 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
cellLoc = newCellLoc;
newCellLoc = tcl;
- cdmaDataConnectionState = newCdmaDataConnectionState;
+ mDataConnectionState = mNewDataConnectionState;
networkType = newNetworkType;
- gprsState = newCdmaDataConnectionState;
-
newSS.setStateOutOfService(); // clean slate for next time
if (hasNetworkTypeChanged) {
@@ -424,8 +428,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/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index ac8352d..afebebe 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -97,8 +97,8 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
/**
* Initially assume no data connection.
*/
- protected int cdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
- protected int newCdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
+ protected int mDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
+ protected int mNewDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
protected int mRegistrationState = -1;
protected RegistrantList cdmaForSubscriptionInfoReadyRegistrants = new RegistrantList();
@@ -217,8 +217,8 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
phone.mRuimRecords.unregisterForRecordsLoaded(this);
cm.unSetOnSignalStrengthUpdate(this);
cm.unSetOnNITZTime(this);
- cr.unregisterContentObserver(this.mAutoTimeObserver);
- cr.unregisterContentObserver(this.mAutoTimeZoneObserver);
+ cr.unregisterContentObserver(mAutoTimeObserver);
+ cr.unregisterContentObserver(mAutoTimeZoneObserver);
}
@Override
@@ -548,10 +548,12 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
}
/**
- * The LTE data connection state, only return true here
+ * Determine data network type based on radio technology.
*/
- protected boolean checkAdditionalDataAvaiable(){
- return true;
+ protected void setCdmaTechnology(int radioTechnology){
+ mNewDataConnectionState = radioTechnologyToDataServiceState(radioTechnology);
+ newSS.setRadioTechnology(radioTechnology);
+ newNetworkType = radioTechnology;
}
/**
@@ -639,12 +641,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
regCodeIsRoaming(registrationState) && !isRoamIndForHomeSystem(states[10]);
newSS.setState (regCodeToServiceState(registrationState));
- if(checkAdditionalDataAvaiable()) {
- this.newCdmaDataConnectionState =
- radioTechnologyToDataServiceState(radioTechnology);
- newSS.setRadioTechnology(radioTechnology);
- newNetworkType = radioTechnology;
- }
+ setCdmaTechnology(radioTechnology);
newSS.setCssIndicator(cssIndicator);
newSS.setSystemAndNetworkId(systemId, networkId);
@@ -953,15 +950,15 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
&& newSS.getState() != ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionAttached =
- this.cdmaDataConnectionState != ServiceState.STATE_IN_SERVICE
- && this.newCdmaDataConnectionState == ServiceState.STATE_IN_SERVICE;
+ mDataConnectionState != ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState == ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionDetached =
- this.cdmaDataConnectionState == ServiceState.STATE_IN_SERVICE
- && this.newCdmaDataConnectionState != ServiceState.STATE_IN_SERVICE;
+ mDataConnectionState == ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState != ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionChanged =
- cdmaDataConnectionState != newCdmaDataConnectionState;
+ mDataConnectionState != mNewDataConnectionState;
boolean hasNetworkTypeChanged = networkType != newNetworkType;
@@ -975,10 +972,10 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
// Add an event log when connection state changes
if (ss.getState() != newSS.getState() ||
- cdmaDataConnectionState != newCdmaDataConnectionState) {
+ mDataConnectionState != mNewDataConnectionState) {
EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE,
- ss.getState(), cdmaDataConnectionState,
- newSS.getState(), newCdmaDataConnectionState);
+ ss.getState(), mDataConnectionState,
+ newSS.getState(), mNewDataConnectionState);
}
ServiceState tss;
@@ -992,7 +989,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
cellLoc = newCellLoc;
newCellLoc = tcl;
- cdmaDataConnectionState = newCdmaDataConnectionState;
+ mDataConnectionState = mNewDataConnectionState;
networkType = newNetworkType;
// this new state has been applied - forget it until we get a new new state
newNetworkType = 0;
@@ -1175,7 +1172,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
}
- private int radioTechnologyToDataServiceState(int code) {
+ protected int radioTechnologyToDataServiceState(int code) {
int retVal = ServiceState.STATE_OUT_OF_SERVICE;
switch(code) {
case 0:
@@ -1226,14 +1223,14 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
* ServiceState.RADIO_TECHNOLOGY_UNKNOWN is the same as detached.
*/
/*package*/ int getCurrentCdmaDataConnectionState() {
- return cdmaDataConnectionState;
+ return mDataConnectionState;
}
/**
* TODO: In the future, we need remove getCurrentCdmaDataConnectionState
*/
public int getCurrentDataConnectionState() {
- return cdmaDataConnectionState;
+ return mDataConnectionState;
}
/**
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index 8a11ae3..9695344 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -21,7 +21,6 @@ import android.util.Log;
import android.util.Patterns;
import android.text.TextUtils;
-import com.android.internal.telephony.ApnSetting;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneBase;
@@ -130,7 +129,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 223c8ad..a1b4376 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -53,6 +53,7 @@ import com.android.internal.telephony.ApnContext;
import com.android.internal.telephony.ApnSetting;
import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnectionAc;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneBase;
@@ -60,6 +61,7 @@ import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.RILConstants;
+import com.android.internal.util.AsyncChannel;
import java.io.IOException;
import java.net.InetAddress;
@@ -115,10 +117,11 @@ 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) {
- log("GPRS reconnect alarm. Previous state was " + mState);
+ if (DBG) log("GPRS reconnect alarm. Previous state was " + mState);
String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
String type = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
@@ -223,7 +226,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
boolean possible = (isDataAllowed()
&& !(getAnyDataEnabled() && (getOverallState() == State.FAILED)));
if (!possible && DBG && isDataAllowed()) {
- log("Data not possible. No coverage: dataState = " + getOverallState());
+ if (DBG) log("Data not possible. No coverage: dataState = " + getOverallState());
}
return possible;
}
@@ -318,10 +321,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected LinkProperties getLinkProperties(String apnType) {
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext != null) {
- DataConnection dataConnection = apnContext.getDataConnection();
- if (dataConnection != null) {
- if (DBG) log("get active pdp is not null, return link properites for " + apnType);
- return dataConnection.getLinkProperties();
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac != null) {
+ if (DBG) log("return link properites for " + apnType);
+ return dcac.getLinkPropertiesSync();
}
}
if (DBG) log("return new LinkProperties");
@@ -332,10 +335,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected LinkCapabilities getLinkCapabilities(String apnType) {
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext!=null) {
- DataConnection dataConnection = apnContext.getDataConnection();
- if (dataConnection != null) {
+ DataConnectionAc dataConnectionAc = apnContext.getDataConnectionAc();
+ if (dataConnectionAc != null) {
if (DBG) log("get active pdp is not null, return link Capabilities for " + apnType);
- return dataConnection.getLinkCapabilities();
+ return dataConnectionAc.getLinkCapabilitiesSync();
}
}
if (DBG) log("return new LinkCapabilities");
@@ -423,6 +426,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
if (!isAnyEnabled) { // Nothing enabled. return IDLE.
+ if (DBG) log( "overall state is IDLE");
return State.IDLE;
}
@@ -449,34 +453,34 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
*/
@Override
public synchronized int enableApnType(String apnType) {
- if (DBG) log("calling enableApnType with type:" + apnType);
-
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext == null || !isApnTypeAvailable(apnType)) {
- if (DBG) log("type not available");
+ if (DBG) log("enableApnType: " + apnType + " is type not available");
return Phone.APN_TYPE_NOT_AVAILABLE;
}
// If already active, return
- log("enableApnType(" + apnType + ")" + ", mState(" + apnContext.getState() + ")");
+ if (DBG) log("enableApnType: " + apnType + " mState(" + apnContext.getState() + ")");
if (apnContext.getState() == State.INITING) {
- if (DBG) log("return APN_REQUEST_STARTED");
+ if (DBG) log("enableApnType: return APN_REQUEST_STARTED");
return Phone.APN_REQUEST_STARTED;
}
else if (apnContext.getState() == State.CONNECTED) {
- if (DBG) log("return APN_ALREADY_ACTIVE");
+ if (DBG) log("enableApnType: return APN_ALREADY_ACTIVE");
return Phone.APN_ALREADY_ACTIVE;
}
else if (apnContext.getState() == State.DISCONNECTING) {
- if (DBG) log("requested APN while disconnecting");
+ if (DBG) log("enableApnType: while disconnecting, return APN_REQUEST_STARTED");
apnContext.setPendingAction(ApnContext.PENDING_ACTION_RECONNECT);
return Phone.APN_REQUEST_STARTED;
}
- if (DBG) log("new apn request for type " + apnType + " is to be handled");
setEnabled(apnTypeToId(apnType), true);
- if (DBG) log("return APN_REQUEST_STARTED");
+ if (DBG) {
+ log("enableApnType: new apn request for type " + apnType +
+ " return APN_REQUEST_STARTED");
+ }
return Phone.APN_REQUEST_STARTED;
}
@@ -501,7 +505,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
public synchronized int disableApnType(String type) {
- if (DBG) log("calling disableApnType with type:" + type);
+ if (DBG) log("disableApnType:" + type);
ApnContext apnContext = mApnContexts.get(type);
if (apnContext != null) {
@@ -514,17 +518,19 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.setReason(Phone.REASON_DATA_DISABLED);
msg.obj = apnContext;
sendMessage(msg);
- if (DBG) log("return APN_REQUEST_STARTED");
+ if (DBG) log("diableApnType: return APN_REQUEST_STARTED");
return Phone.APN_REQUEST_STARTED;
} else {
- if (DBG) log("return APN_ALREADY_INACTIVE");
+ if (DBG) log("disableApnType: return APN_ALREADY_INACTIVE");
apnContext.setEnabled(false);
+ apnContext.setDataConnection(null);
return Phone.APN_ALREADY_INACTIVE;
}
} else {
- if (DBG)
- log("no apn context was found, return APN_REQUEST_FAILED");
+ if (DBG) {
+ log("disableApnType: no apn context was found, return APN_REQUEST_FAILED");
+ }
return Phone.APN_REQUEST_FAILED;
}
}
@@ -581,12 +587,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* We presently believe it is unnecessary to tear down the PDP context
* when GPRS detaches, but we should stop the network polling.
*/
+ if (DBG) log ("onDataConnectionDetached: stop polling and notify detached");
stopNetStatPoll();
notifyDataConnection(Phone.REASON_DATA_DETACHED);
}
private void onDataConnectionAttached() {
+ if (DBG) log("onDataConnectionAttached");
if (getOverallState() == State.CONNECTED) {
+ if (DBG) log("onDataConnectionAttached: start polling notify attached");
startNetStatPoll();
notifyDataConnection(Phone.REASON_DATA_ATTACHED);
}
@@ -622,11 +631,40 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
if (mIsPsRestricted) reason += " - mIsPsRestricted= true";
if (!desiredPowerState) reason += " - desiredPowerState= false";
- log("Data not allowed due to" + reason);
+ if (DBG) log("isDataAllowed: not allowed due to" + reason);
}
return allowed;
}
+ /**
+ * Release the apnContext
+ *
+ * @param apnContext
+ * @param tearDown
+ * @return refCount
+ */
+ private int releaseApnContext(ApnContext apnContext, boolean tearDown) {
+ if (apnContext == null) {
+ if (DBG) loge("releaseApnContext: apnContext null should not happen, ignore");
+ return -1;
+ }
+ DataConnection dc = apnContext.getDataConnection();
+ if (dc == null) {
+ if (DBG) loge("releaseApnContext: apnContext dc == null should not happen, ignore");
+ return -1;
+ }
+ int refCount = dc.decAndGetRefCount();
+ if (DBG) log("releaseApnContext: dec refCount=" + refCount + " tearDown=" + tearDown);
+ if (tearDown && (refCount == 0)) {
+ if (DBG) log("releaseApnContext: tearing down");
+ Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
+ apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
+ }
+ apnContext.setDataConnection(null);
+ apnContext.setDataConnectionAc(null);
+ return refCount;
+ }
+
private void setupDataOnReadyApns(String reason) {
// Only check for default APN state
for (ApnContext apnContext : mApnContexts.values()) {
@@ -649,9 +687,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private boolean trySetupData(String reason, String type) {
if (DBG) {
- log("***trySetupData for type:" + type +
- " due to " + (reason == null ? "(unspecified)" : reason) +
- " isPsRestricted=" + mIsPsRestricted);
+ log("trySetupData: " + type + " due to " + (reason == null ? "(unspecified)" : reason)
+ + " isPsRestricted=" + mIsPsRestricted);
}
if (type == null) {
@@ -661,18 +698,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
ApnContext apnContext = mApnContexts.get(type);
if (apnContext == null ){
- if (DBG) log("new apn context for type:" + type);
+ if (DBG) log("trySetupData new apn context for type:" + type);
apnContext = new ApnContext(type, LOG_TAG);
mApnContexts.put(type, apnContext);
}
apnContext.setReason(reason);
return trySetupData(apnContext);
-
}
private boolean trySetupData(ApnContext apnContext) {
-
if (DBG) {
log("trySetupData for type:" + apnContext.getApnType() +
" due to " + apnContext.getReason());
@@ -685,7 +720,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.setState(State.CONNECTED);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
- log("(fix?) We're on the simulator; assuming data is connected");
+ log("trySetupData: (fix?) We're on the simulator; assuming data is connected");
return true;
}
@@ -697,13 +732,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (apnContext.getState() == State.IDLE) {
ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType());
if (waitingApns.isEmpty()) {
- if (DBG) log("No APN found");
+ if (DBG) log("trySetupData: No APN found");
notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext);
notifyOffApnsOfAvailability(apnContext.getReason(), false);
return false;
} else {
apnContext.setWaitingApns(waitingApns);
- log ("Create from mAllApns : " + apnListToString(mAllApns));
+ if (DBG) {
+ log ("trySetupData: Create from mAllApns : " + apnListToString(mAllApns));
+ }
}
}
@@ -733,7 +770,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
for (ApnContext apnContext : mApnContexts.values()) {
if (!apnContext.isReady()) {
- if (DBG) log("notify disconnected for type:" + apnContext.getApnType());
+ if (DBG) log("notifyOffApnOfAvailability type:" + apnContext.getApnType());
mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
apnContext.getApnType(),
Phone.DataState.DISCONNECTED);
@@ -751,7 +788,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* @param reason reason for the clean up.
*/
protected void cleanUpAllConnections(boolean tearDown, String reason) {
- if (DBG) log("Clean up all connections due to " + reason);
+ if (DBG) log("cleanUpAllConnections: tearDown=" + tearDown + " reason=" + reason);
for (ApnContext apnContext : mApnContexts.values()) {
apnContext.setReason(reason);
@@ -782,11 +819,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void cleanUpConnection(boolean tearDown, ApnContext apnContext) {
if (apnContext == null) {
- if (DBG) log("apn context is null");
+ if (DBG) log("cleanUpConnection: apn context is null");
return;
}
- if (DBG) log("Clean up connection due to " + apnContext.getReason());
+ if (DBG) {
+ log("cleanUpConnection: tearDown=" + tearDown + " reason=" + apnContext.getReason());
+ }
// Clear the reconnect alarm, if set.
if (apnContext.getReconnectIntent() != null) {
@@ -797,24 +836,26 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
if (apnContext.getState() == State.IDLE || apnContext.getState() == State.DISCONNECTING) {
- if (DBG) log("state is in " + apnContext.getState());
+ if (DBG) log("cleanUpConnection: state= " + apnContext.getState());
return;
}
if (apnContext.getState() == State.FAILED) {
- if (DBG) log("state is in FAILED");
+ if (DBG) log("cleanUpConnection: state is in FAILED");
apnContext.setState(State.IDLE);
return;
}
DataConnection conn = apnContext.getDataConnection();
if (conn != null) {
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(conn.getDataConnectionId());
apnContext.setState(State.DISCONNECTING);
if (tearDown) {
- Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
- conn.disconnect(apnContext.getReason(), msg);
+ releaseApnContext(apnContext, tearDown);
} else {
- conn.resetSynchronously();
+ if (dcac != null) {
+ dcac.resetSync();
+ }
apnContext.setState(State.IDLE);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
}
@@ -869,27 +910,31 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
private GsmDataConnection findFreeDataConnection() {
- for (DataConnection dc : mDataConnections.values()) {
- if (dc.isInactive()) {
- log("found free GsmDataConnection");
- return (GsmDataConnection) dc;
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ if (dcac.isInactiveSync()) {
+ log("findFreeDataConnection: found free GsmDataConnection");
+ return (GsmDataConnection) dcac.dataConnection;
}
}
- log("NO free GsmDataConnection");
+ log("findFreeDataConnection: NO free GsmDataConnection");
return null;
}
protected GsmDataConnection findReadyDataConnection(ApnSetting apn) {
if (DBG)
- log("findReadyDataConnection for apn string <" +
+ log("findReadyDataConnection: apn string <" +
(apn!=null?(apn.toString()):"null") +">");
- for (DataConnection conn : mDataConnections.values()) {
- GsmDataConnection dc = (GsmDataConnection) conn;
- if (DBG) log("dc apn string <" +
- (dc.getApn() != null ? (dc.getApn().toString()) : "null") + ">");
- if (dc.getApn() != null && apn != null
- && dc.getApn().toString().equals(apn.toString())) {
- return dc;
+ if (apn == null) {
+ return null;
+ }
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ ApnSetting apnSetting = dcac.getApnSettingSync();
+ if (DBG) {
+ log("findReadyDataConnection: dc apn string <" +
+ (apnSetting != null ? (apnSetting.toString()) : "null") + ">");
+ }
+ if ((apnSetting != null) && TextUtils.equals(apnSetting.toString(), apn.toString())) {
+ return (GsmDataConnection) dcac.dataConnection;
}
}
return null;
@@ -897,7 +942,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private boolean setupData(ApnContext apnContext) {
- if (DBG) log("enter setupData!");
+ if (DBG) log("setupData: apnContext=" + apnContext);
ApnSetting apn;
GsmDataConnection dc;
@@ -918,7 +963,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
if (dc == null) {
- dc = createDataConnection(apnContext);
+ dc = createDataConnection(apnContext.getApnType());
}
if (dc == null) {
@@ -926,17 +971,19 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return false;
}
- apnContext.setApnSetting(apn);
- apnContext.setDataConnection(dc);
dc.setProfileId( profileId );
dc.setActiveApnType(apnContext.getApnType());
+ int refCount = dc.incAndGetRefCount();
+ if (DBG) log("setupData: init dc and apnContext refCount=" + refCount);
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(dc.getDataConnectionId());
+ apnContext.setDataConnectionAc(mDataConnectionAsyncChannels.get(dc.getDataConnectionId()));
+ apnContext.setApnSetting(apn);
+ apnContext.setDataConnection(dc);
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = apnContext;
-
- if (DBG) log("dc connect!");
- dc.connect(msg, apn);
+ dc.bringUp(msg, apn);
apnContext.setState(State.INITING);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
@@ -979,7 +1026,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// TODO: It'd be nice to only do this if the changed entrie(s)
// match the current operator.
- if (DBG) log("onApnChanged createAllApnList and cleanUpAllConnections");
+ if (DBG) log("onApnChanged: createAllApnList and cleanUpAllConnections");
createAllApnList();
cleanUpAllConnections(isConnected, Phone.REASON_APN_CHANGED);
if (!isConnected) {
@@ -996,25 +1043,30 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void onDataStateChanged (AsyncResult ar) {
ArrayList<DataCallState> dataCallStates;
+ if (DBG) log("onDataStateChanged(ar) E");
dataCallStates = (ArrayList<DataCallState>)(ar.result);
if (ar.exception != null) {
// This is probably "radio not available" or something
// of that sort. If so, the whole connection is going
// to come down soon anyway
+ if (DBG) log("onDataStateChanged(ar): exception; likely radio not available, ignore");
return;
}
for (ApnContext apnContext : mApnContexts.values()) {
onDataStateChanged(dataCallStates, apnContext);
}
+ if (DBG) log("onDataStateChanged(ar) X");
}
private void onDataStateChanged (ArrayList<DataCallState> dataCallStates,
ApnContext apnContext) {
+ if (DBG) log("onDataStateChanged(dataCallState, apnContext): apnContext=" + apnContext);
if (apnContext == null) {
// Should not happen
+ if (DBG) log("onDataStateChanged(dataCallState, apnContext): ignore apnContext=null");
return;
}
@@ -1025,28 +1077,37 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// context is still listed with active = false, which
// makes it hard to distinguish an activating context from
// an activated-and-then deactivated one.
- if (!dataCallStatesHasCID(dataCallStates, apnContext.getDataConnection().getCid())) {
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac == null) {
+ if (DBG) log("onDataStateChanged(dataCallState, apnContext): dcac==null BAD NEWS");
+ return;
+ }
+ int cid = dcac.getCidSync();
+ if (!dataCallStatesHasCID(dataCallStates, cid)) {
// It looks like the PDP context has deactivated.
// Tear everything down and try to reconnect.
- Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting");
-
+ if (DBG) {
+ log("onDataStateChanged(dataCallStates,apnContext) " +
+ "PDP connection has dropped. Reconnecting");
+ }
// Add an event log when the network drops PDP
- int cid = getCellLocationId();
- EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
+ int cellLocationId = getCellLocationId();
+ EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cellLocationId,
TelephonyManager.getDefault().getNetworkType());
cleanUpConnection(true, apnContext);
- return;
} else if (!dataCallStatesHasActiveCID(dataCallStates,
- apnContext.getDataConnection().getCid())) {
+ apnContext.getDataConnectionAc().getCidSync())) {
- Log.i(LOG_TAG, "PDP connection has dropped (active=false case). "
- + " Reconnecting");
+ if (DBG) {
+ log("onDataStateChanged(dataCallStates,apnContext) " +
+ "PDP connection has dropped (active=false case). Reconnecting");
+ }
// Log the network drop on the event log.
- int cid = getCellLocationId();
- EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
+ int cellLocationId = getCellLocationId();
+ EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cellLocationId,
TelephonyManager.getDefault().getNetworkType());
cleanUpConnection(true, apnContext);
@@ -1055,9 +1116,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
private void notifyDefaultData(ApnContext apnContext) {
- if (DBG)
- log("notifyDefaultData for type: " + apnContext.getApnType()
+ if (DBG) {
+ log("notifyDefaultData: type=" + apnContext.getApnType()
+ ", reason:" + apnContext.getReason());
+ }
apnContext.setState(State.CONNECTED);
// setState(State.CONNECTED);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
@@ -1089,21 +1151,25 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (mPdpResetCount < maxPdpReset) {
mPdpResetCount++;
EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv);
+ if (DBG) log("doRecovery() cleanup all connections mPdpResetCount < max");
cleanUpAllConnections(true, Phone.REASON_PDP_RESET);
} else {
mPdpResetCount = 0;
EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv);
+ if (DBG) log("doRecovery() re-register getting preferred network type");
mPhone.getServiceStateTracker().reRegisterNetwork(null);
}
// TODO: Add increasingly drastic recovery steps, eg,
// reset the radio, reset the device.
+ } else {
+ if (DBG) log("doRecovery(): ignore, we're not connected");
}
}
@Override
protected void startNetStatPoll() {
if (getOverallState() == State.CONNECTED && mNetStatPollEnabled == false) {
- log("[DataConnection] Start poll NetStat");
+ if (DBG) log("startNetStatPoll");
resetPollStats();
mNetStatPollEnabled = true;
mPollNetStat.run();
@@ -1114,12 +1180,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void stopNetStatPoll() {
mNetStatPollEnabled = false;
removeCallbacks(mPollNetStat);
- log("[DataConnection] Stop poll NetStat");
+ if (DBG) log("stopNetStatPoll");
}
@Override
protected void restartRadio() {
- log("************TURN OFF RADIO**************");
+ if (DBG) log("restartRadio: ************TURN OFF RADIO**************");
cleanUpAllConnections(true, Phone.REASON_RADIO_TURNED_OFF);
mPhone.getServiceStateTracker().powerOffRadioSafely(this);
/* Note: no need to call setRadioPower(true). Assuming the desired
@@ -1200,7 +1266,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (mNoRecvPollCount < noRecvPollLimit) {
// It's possible the PDP context went down and we weren't notified.
// Start polling the context list in an attempt to recover.
- if (DBG) log("no DATAIN in a while; polling PDP");
+ if (DBG) log("Polling: no DATAIN in a while; polling PDP");
mPhone.mCM.getDataCallList(obtainMessage(EVENT_DATA_STATE_CHANGED));
mNoRecvPollCount++;
@@ -1210,7 +1276,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
Settings.Secure.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
POLL_NETSTAT_SLOW_MILLIS);
} else {
- if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) +
+ if (DBG) log("Polling: Sent " + String.valueOf(mSentSinceLastRecv) +
" pkts since last received start recovery process");
stopNetStatPoll();
sendMessage(obtainMessage(EVENT_START_RECOVERY));
@@ -1260,13 +1326,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void reconnectAfterFail(FailCause lastFailCauseCode, ApnContext apnContext) {
if (apnContext == null) {
- Log.d(LOG_TAG, "It is impossible");
+ loge("reconnectAfterFail: apnContext == null, impossible");
return;
}
if (apnContext.getState() == State.FAILED) {
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.
+ if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)) {
notifyDataConnection(Phone.REASON_APN_FAILED);
return;
}
@@ -1275,7 +1340,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.getDataConnection().retryForeverUsingLastTimeout();
} else {
// Try to Re-register to the network.
- log("PDP activate failed, Reregistering to the network");
+ if (DBG) log("reconnectAfterFail: activate failed, Reregistering to network");
mReregisterOnReconnectFailure = true;
mPhone.getServiceStateTracker().reRegisterNetwork(null);
apnContext.getDataConnection().resetRetryCount();
@@ -1284,8 +1349,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
int nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
- log("PDP activate failed. Scheduling next attempt for "
+ if (DBG) {
+ log("reconnectAfterFail: activate failed. Scheduling next attempt for "
+ (nextReconnectDelay / 1000) + "s");
+ }
AlarmManager am =
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
@@ -1302,8 +1369,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
apnContext.getDataConnection().increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
- Log.d(LOG_TAG, "NOT Posting GPRS Unavailable notification "
+ if (DBG) {
+ log("reconnectAfterFail: NOT Posting GPRS Unavailable notification "
+ "-- likely transient error");
+ }
} else {
notifyNoData(lastFailCauseCode, apnContext);
}
@@ -1312,7 +1381,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode,
ApnContext apnContext) {
- if (DBG) log( "notifyNoData for type:" + apnContext.getApnType());
+ if (DBG) log( "notifyNoData: type=" + apnContext.getApnType());
apnContext.setState(State.FAILED);
if (lastFailCauseCode.isPermanentFail()
&& (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT))) {
@@ -1323,6 +1392,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);
}
@@ -1330,7 +1403,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void onSetDependencyMet(String apnType, boolean met) {
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext == null) {
- log("ApnContext not found in onSetDependencyMet(" + apnType + ", " + met + ")");
+ loge("onSetDependencyMet: ApnContext not found in onSetDependencyMet(" +
+ apnType + ", " + met + ")");
return;
}
applyNewState(apnContext, apnContext.isEnabled(), met);
@@ -1366,12 +1440,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
trySetup = true;
} else {
- // TODO send notifications
+ int refCount = conn.incAndGetRefCount();
+ apnContext.setDataConnection(conn);
+ apnContext.setDataConnectionAc(
+ mDataConnectionAsyncChannels.get(conn.getDataConnectionId()));
if (DBG) {
- log("Found existing connection for " + apnContext.getApnType() +
- ": " + conn);
+ log("applyNewState: Found existing connection for " +
+ apnContext.getApnType() + " inc refCount=" + refCount +
+ " conn=" + conn);
}
- apnContext.setDataConnection(conn);
}
}
}
@@ -1388,9 +1465,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
DataConnection conn = c.getDataConnection();
if (conn != null) {
ApnSetting apnSetting = c.getApnSetting();
- if (apnSetting != null && apnSetting.canHandleType(apnType)) return conn;
+ if (apnSetting != null && apnSetting.canHandleType(apnType)) {
+ if (DBG) {
+ log("checkForConnectionForApnContext: apnContext=" + apnContext +
+ " found conn=" + conn);
+ }
+ return conn;
+ }
}
}
+ if (DBG) log("checkForConnectionForApnContext: apnContext=" + apnContext + " NO conn");
return null;
}
@@ -1398,49 +1482,55 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void onEnableApn(int apnId, int enabled) {
ApnContext apnContext = mApnContexts.get(apnIdToType(apnId));
if (apnContext == null) {
- log("ApnContext not found in onEnableApn(" + apnId + ", " + enabled + ")");
+ loge("onEnableApn(" + apnId + ", " + enabled + "): NO ApnContext");
return;
}
// TODO change our retry manager to use the appropriate numbers for the new APN
- log("onEnableApn with ApnContext E");
+ if (DBG) log("onEnableApn: apnContext=" + apnContext + " call applyNewState");
applyNewState(apnContext, enabled == ENABLED, apnContext.getDependencyMet());
}
@Override
// TODO: We shouldnt need this.
protected boolean onTrySetupData(String reason) {
+ if (DBG) log("onTrySetupData: reason=" + reason);
setupDataOnReadyApns(reason);
return true;
}
protected boolean onTrySetupData(ApnContext apnContext) {
+ if (DBG) log("onTrySetupData: apnContext=" + apnContext);
return trySetupData(apnContext);
}
@Override
protected void onRoamingOff() {
+ if (DBG) log("onRoamingOff");
setupDataOnReadyApns(Phone.REASON_ROAMING_OFF);
}
@Override
protected void onRoamingOn() {
if (getDataOnRoamingEnabled()) {
+ if (DBG) log("onRoamingOn: setup data on roaming");
setupDataOnReadyApns(Phone.REASON_ROAMING_ON);
} else {
- if (DBG) log("Tear down data connection on roaming.");
+ if (DBG) log("onRoamingOn: Tear down data connection on roaming.");
cleanUpAllConnections(true, Phone.REASON_ROAMING_ON);
}
}
@Override
protected void onRadioAvailable() {
+ if (DBG) log("onRadioAvailable");
+ mRadioAvailable = true;
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
// setState(State.CONNECTED);
notifyDataConnection(null);
- log("We're on the simulator; assuming data is connected");
+ log("onRadioAvailable: We're on the simulator; assuming data is connected");
}
if (mPhone.mSIMRecords.getRecordsLoaded()) {
@@ -1461,15 +1551,17 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
dc.resetRetryCount();
}
mReregisterOnReconnectFailure = false;
+ mRadioAvailable = false;
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
log("We're on the simulator; assuming radio off is meaningless");
} else {
- if (DBG) log("Radio is off and clean up all connection");
+ if (DBG) log("onRadioOffOrNotAvailable: is off and clean up all connections");
cleanUpAllConnections(false, Phone.REASON_RADIO_TURNED_OFF);
}
+ notifyDataAvailability(null);
}
@Override
@@ -1479,27 +1571,29 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if(ar.userObj instanceof ApnContext){
apnContext = (ApnContext)ar.userObj;
+ } else {
+ throw new RuntimeException("onDataSetupComplete: No apnContext");
+ }
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac == null) {
+ throw new RuntimeException("onDataSetupCompete: No dcac");
}
+ DataConnection dc = apnContext.getDataConnection();
if (ar.exception == null) {
- // Everything is setup
- // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
if (DBG) {
log(String.format("onDataSetupComplete: success apn=%s",
- apnContext.getWaitingApns().get(0).apn));
+ apnContext.getWaitingApns().get(0).apn) + " refCount=" + dc.getRefCount());
}
- mLinkProperties = getLinkProperties(apnContext.getApnType());
- mLinkCapabilities = getLinkCapabilities(apnContext.getApnType());
-
ApnSetting apn = apnContext.getApnSetting();
if (apn.proxy != null && apn.proxy.length() != 0) {
try {
ProxyProperties proxy = new ProxyProperties(apn.proxy,
Integer.parseInt(apn.port), null);
- mLinkProperties.setHttpProxy(proxy);
+ dcac.setLinkPropertiesHttpProxySync(proxy);
} catch (NumberFormatException e) {
- loge("NumberFormatException making ProxyProperties (" + apn.port +
- "): " + e);
+ loge("onDataSetupComplete: NumberFormatException making ProxyProperties (" +
+ apn.port + "): " + e);
}
}
@@ -1507,7 +1601,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if(TextUtils.equals(apnContext.getApnType(),Phone.APN_TYPE_DEFAULT)) {
SystemProperties.set("gsm.defaultpdpcontext.active", "true");
if (canSetPreferApn && mPreferredApn == null) {
- log("PREFERED APN is null");
+ if (DBG) log("onDataSetupComplete: PREFERED APN is null");
mPreferredApn = apnContext.getApnSetting();
if (mPreferredApn != null) {
setPreferredApn(mPreferredApn.id);
@@ -1517,15 +1611,13 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
SystemProperties.set("gsm.defaultpdpcontext.active", "false");
}
notifyDefaultData(apnContext);
-
- // TODO: For simultaneous PDP support, we need to build another
- // trigger another TRY_SETUP_DATA for the next APN type. (Note
- // that the existing connection may service that type, in which
- // case we should try the next type, etc.
- // I dont believe for simultaneous PDP you need to trigger. Each
- // Connection should be independent and they can be setup simultaneously
- // So, dont have to wait till one is finished.
} else {
+ int refCount = releaseApnContext(apnContext, false);
+ if (DBG) {
+ log(String.format("onDataSetupComplete: error apn=%s",
+ apnContext.getWaitingApns().get(0).apn) + " refCount=" + refCount);
+ }
+
GsmDataConnection.FailCause cause;
cause = (GsmDataConnection.FailCause) (ar.result);
if (DBG) {
@@ -1585,7 +1677,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void onDisconnectDone(int connId, AsyncResult ar) {
ApnContext apnContext = null;
- if(DBG) log("EVENT_DISCONNECT_DONE connId=" + connId);
+ if(DBG) log("onDisconnectDone: EVENT_DISCONNECT_DONE connId=" + connId);
if (ar.userObj instanceof ApnContext) {
apnContext = (ApnContext) ar.userObj;
} else {
@@ -1598,7 +1690,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// Check if APN disabled.
if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE) {
- apnContext.setEnabled(false);
apnContext.setPendingAction(ApnContext.PENDING_ACTION_NONE);
}
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
@@ -1618,7 +1709,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);
}
}
@@ -1632,7 +1726,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
protected void onVoiceCallStarted() {
+ if (DBG) log("onVoiceCallStarted");
if (isConnected() && ! mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
+ if (DBG) log("onVoiceCallStarted stop polling");
stopNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
}
@@ -1640,6 +1736,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
protected void onVoiceCallEnded() {
+ if (DBG) log("onVoiceCallEnded");
if (isConnected()) {
if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
startNetStatPoll();
@@ -1672,10 +1769,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
protected void notifyDataConnection(String reason) {
- if (DBG) log("notify all enabled connection for:" + reason);
+ if (DBG) log("notifyDataConnection: reason=" + reason);
for (ApnContext apnContext : mApnContexts.values()) {
if (apnContext.isReady()) {
- if (DBG) log("notify for type:"+apnContext.getApnType());
+ if (DBG) log("notifyDataConnection: type:"+apnContext.getApnType());
mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
apnContext.getApnType());
}
@@ -1722,17 +1819,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
/** Return the id for a new data connection */
- private GsmDataConnection createDataConnection(ApnContext apnContext) {
- String apnType = apnContext.getApnType();
- log("createDataConnection(" + apnType + ") E");
+ private GsmDataConnection createDataConnection(String apnType) {
+ if (DBG) log("createDataConnection(" + apnType + ") E");
RetryManager rm = new RetryManager();
if (apnType.equals(Phone.APN_TYPE_DEFAULT)) {
if (!rm.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
// Should never happen, log an error and default to a simple linear sequence.
- log("Could not configure using DEFAULT_DATA_RETRY_CONFIG="
- + DEFAULT_DATA_RETRY_CONFIG);
+ loge("createDataConnection: Could not configure using " +
+ "DEFAULT_DATA_RETRY_CONFIG=" + DEFAULT_DATA_RETRY_CONFIG);
rm.configure(20, 2000, 1000);
}
}
@@ -1740,8 +1836,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (!rm.configure(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) {
if (!rm.configure(SECONDARY_DATA_RETRY_CONFIG)) {
// Should never happen, log an error and default to a simple sequence.
- log("Could note configure using SECONDARY_DATA_RETRY_CONFIG="
- + SECONDARY_DATA_RETRY_CONFIG);
+ loge("createDataConnection: Could note configure using " +
+ "SECONDARY_DATA_RETRY_CONFIG=" + SECONDARY_DATA_RETRY_CONFIG);
rm.configure("max_retries=3, 333, 333, 333");
}
}
@@ -1751,18 +1847,25 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
GsmDataConnection conn = GsmDataConnection.makeDataConnection(mPhone, id, rm);
conn.resetRetryCount();
mDataConnections.put(id, conn);
- apnContext.setDataConnection(conn);
+ DataConnectionAc dcac = new DataConnectionAc(conn, LOG_TAG);
+ int status = dcac.fullyConnectSync(mPhone.getContext(), this, conn.getHandler());
+ if (status == AsyncChannel.STATUS_SUCCESSFUL) {
+ mDataConnectionAsyncChannels.put(dcac.dataConnection.getDataConnectionId(), dcac);
+ } else {
+ loge("createDataConnection: Could not connect to dcac.mDc=" + dcac.dataConnection +
+ " status=" + status);
+ }
- log("createDataConnection(" + apnType + ") X id=" + id);
+ if (DBG) log("createDataConnection(" + apnType + ") X id=" + id);
return conn;
}
private void destroyDataConnections() {
if(mDataConnections != null) {
- log("destroyDataConnectionList clear mDataConnectionList");
+ if (DBG) log("destroyDataConnections: clear mDataConnectionList");
mDataConnections.clear();
} else {
- log("destroyDataConnectionList mDataConnecitonList is empty, ignore");
+ if (DBG) log("destroyDataConnectionList mDataConnecitonList is empty, ignore");
}
}
@@ -1786,8 +1889,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
String operator = mPhone.mSIMRecords.getSIMOperatorNumeric();
if (requestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
if (canSetPreferApn && mPreferredApn != null) {
- log("Preferred APN:" + operator + ":"
+ if (DBG) {
+ log("buildWaitingApns: Preferred APN:" + operator + ":"
+ mPreferredApn.numeric + ":" + mPreferredApn);
+ }
if (mPreferredApn.numeric.equals(operator)) {
apnList.add(mPreferredApn);
if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList);
@@ -1878,10 +1983,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
public void handleMessage (Message msg) {
- if (DBG) log("GSMDataConnTrack handleMessage "+msg);
+ if (DBG) log("handleMessage msg=" + msg);
if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
- log("Ignore GSM msgs since GSM phone is inactive");
+ loge("handleMessage: Ignore GSM msgs since GSM phone is inactive");
return;
}
@@ -1925,7 +2030,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* PDP context and notify us with PDP_CONTEXT_CHANGED.
* But we should stop the network polling and prevent reset PDP.
*/
- log("EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
+ if (DBG) log("EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
stopNetStatPoll();
mIsPsRestricted = true;
break;
@@ -1935,7 +2040,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* When PS restrict is removed, we need setup PDP connection if
* PDP connection is down.
*/
- log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
+ if (DBG) log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
mIsPsRestricted = false;
if (isConnected()) {
startNetStatPoll();
@@ -1952,19 +2057,20 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
case EVENT_TRY_SETUP_DATA:
if (msg.obj instanceof ApnContext) {
onTrySetupData((ApnContext)msg.obj);
+ } else if (msg.obj instanceof String) {
+ onTrySetupData((String)msg.obj);
} else {
- if (msg.obj instanceof String) {
- onTrySetupData((String)msg.obj);
- }
+ loge("EVENT_TRY_SETUP request w/o apnContext or String");
}
break;
case EVENT_CLEAN_UP_CONNECTION:
boolean tearDown = (msg.arg1 == 0) ? false : true;
+ if (DBG) log("EVENT_CLEAN_UP_CONNECTION tearDown=" + tearDown);
if (msg.obj instanceof ApnContext) {
cleanUpConnection(tearDown, (ApnContext)msg.obj);
} else {
- loge("[GsmDataConnectionTracker] connectpion cleanup request w/o apn context");
+ loge("EVENT_CLEAN_UP_CONNECTION request w/o apn context");
}
break;
default:
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 31b2ddd..6285880 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,24 @@
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="GLTextureViewActivity"
+ android:label="_TextureViewGL">
+ <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/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
new file mode 100644
index 0000000..7f97098
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
@@ -0,0 +1,274 @@
+/*
+ * 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.opengl.GLES20;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.TextureView;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGL11;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+import javax.microedition.khronos.opengles.GL;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class GLTextureViewActivity extends Activity implements TextureView.SurfaceTextureListener {
+ private RenderThread mRenderThread;
+ 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();
+ mRenderThread.finish();
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface) {
+ mRenderThread = new RenderThread(surface);
+ mRenderThread.start();
+
+ 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();
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ }
+
+ private static class RenderThread extends Thread {
+ private static final String LOG_TAG = "GLTextureView";
+
+ static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+ static final int EGL_SURFACE_TYPE = 0x3033;
+ static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
+ static final int EGL_OPENGL_ES2_BIT = 4;
+
+ private volatile boolean mFinished;
+
+ private SurfaceTexture mSurface;
+
+ private EGL10 mEgl;
+ private EGLDisplay mEglDisplay;
+ private EGLConfig mEglConfig;
+ private EGLContext mEglContext;
+ private EGLSurface mEglSurface;
+ private GL mGL;
+
+ RenderThread(SurfaceTexture surface) {
+ mSurface = surface;
+ }
+
+ @Override
+ public void run() {
+ initGL();
+
+ float red = 0.0f;
+ while (!mFinished) {
+ checkCurrent();
+
+ GLES20.glClearColor(red, 0.0f, 0.0f, 1.0f);
+ int error = GLES20.glGetError();
+ if (error != GLES20.GL_NO_ERROR) {
+ Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
+ }
+
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+ error = GLES20.glGetError();
+ if (error != GLES20.GL_NO_ERROR) {
+ Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
+ }
+
+ if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
+ throw new RuntimeException("Cannot swap buffers");
+ }
+
+ try {
+ Thread.sleep(20);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+
+ red += 0.021f;
+ if (red > 1.0f) red = 0.0f;
+ }
+
+ finishGL();
+ }
+
+ private void finishGL() {
+ mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+ mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+ }
+
+ private void checkCurrent() {
+ if (!mEglContext.equals(mEgl.eglGetCurrentContext()) ||
+ !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
+ if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+ throw new RuntimeException("eglMakeCurrent failed "
+ + getEGLErrorString(mEgl.eglGetError()));
+ }
+ }
+ }
+
+ private void initGL() {
+ mEgl = (EGL10) EGLContext.getEGL();
+
+ mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+ if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
+ throw new RuntimeException("eglGetDisplay failed "
+ + getEGLErrorString(mEgl.eglGetError()));
+ }
+
+ int[] version = new int[2];
+ if (!mEgl.eglInitialize(mEglDisplay, version)) {
+ throw new RuntimeException("eglInitialize failed " +
+ getEGLErrorString(mEgl.eglGetError()));
+ }
+
+ mEglConfig = chooseEglConfig();
+ if (mEglConfig == null) {
+ throw new RuntimeException("eglConfig not initialized");
+ }
+
+ mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
+
+ mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null);
+
+ if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
+ int error = mEgl.eglGetError();
+ if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
+ Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
+ return;
+ }
+ throw new RuntimeException("createWindowSurface failed "
+ + getEGLErrorString(error));
+ }
+
+ if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+ throw new RuntimeException("eglMakeCurrent failed "
+ + getEGLErrorString(mEgl.eglGetError()));
+ }
+
+ mGL = mEglContext.getGL();
+ }
+
+
+ EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
+ int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
+ return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+ }
+
+ private EGLConfig chooseEglConfig() {
+ int[] configsCount = new int[1];
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] configSpec = getConfig();
+ if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
+ throw new IllegalArgumentException("eglChooseConfig failed " +
+ getEGLErrorString(mEgl.eglGetError()));
+ } else if (configsCount[0] > 0) {
+ return configs[0];
+ }
+ return null;
+ }
+
+ private int[] getConfig() {
+ return new int[] {
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL10.EGL_RED_SIZE, 8,
+ EGL10.EGL_GREEN_SIZE, 8,
+ EGL10.EGL_BLUE_SIZE, 8,
+ EGL10.EGL_ALPHA_SIZE, 8,
+ EGL10.EGL_DEPTH_SIZE, 0,
+ EGL10.EGL_STENCIL_SIZE, 0,
+ EGL10.EGL_NONE
+ };
+ }
+
+ static String getEGLErrorString(int error) {
+ switch (error) {
+ case EGL10.EGL_SUCCESS:
+ return "EGL_SUCCESS";
+ case EGL10.EGL_NOT_INITIALIZED:
+ return "EGL_NOT_INITIALIZED";
+ case EGL10.EGL_BAD_ACCESS:
+ return "EGL_BAD_ACCESS";
+ case EGL10.EGL_BAD_ALLOC:
+ return "EGL_BAD_ALLOC";
+ case EGL10.EGL_BAD_ATTRIBUTE:
+ return "EGL_BAD_ATTRIBUTE";
+ case EGL10.EGL_BAD_CONFIG:
+ return "EGL_BAD_CONFIG";
+ case EGL10.EGL_BAD_CONTEXT:
+ return "EGL_BAD_CONTEXT";
+ case EGL10.EGL_BAD_CURRENT_SURFACE:
+ return "EGL_BAD_CURRENT_SURFACE";
+ case EGL10.EGL_BAD_DISPLAY:
+ return "EGL_BAD_DISPLAY";
+ case EGL10.EGL_BAD_MATCH:
+ return "EGL_BAD_MATCH";
+ case EGL10.EGL_BAD_NATIVE_PIXMAP:
+ return "EGL_BAD_NATIVE_PIXMAP";
+ case EGL10.EGL_BAD_NATIVE_WINDOW:
+ return "EGL_BAD_NATIVE_WINDOW";
+ case EGL10.EGL_BAD_PARAMETER:
+ return "EGL_BAD_PARAMETER";
+ case EGL10.EGL_BAD_SURFACE:
+ return "EGL_BAD_SURFACE";
+ case EGL11.EGL_CONTEXT_LOST:
+ return "EGL_CONTEXT_LOST";
+ default:
+ return "0x" + Integer.toHexString(error);
+ }
+ }
+
+ void finish() {
+ mFinished = true;
+ }
+ }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
index 55fab3f..7173a85 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
@@ -86,6 +86,14 @@ public class Lines2Activity extends Activity {
canvas.drawLines(copyPoints, 0, 12, p);
}
+ private void drawVerticalLine(Canvas canvas, Paint p, float length, float x, float y) {
+ canvas.drawLine(x, y, x, y + length, p);
+ }
+
+ private void drawDiagonalLine(Canvas canvas, Paint p, float length, float x, float y) {
+ canvas.drawLine(x, y, x + length, y + length, p);
+ }
+
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
@@ -145,6 +153,99 @@ public class Lines2Activity extends Activity {
canvas.translate(60, 0);
drawLines(canvas, p, mOffset/2, yOffset/2);
canvas.restore();
+
+ yOffset += 100;
+ canvas.save();
+ p.setStrokeWidth(1);
+ float x = 10 + mOffset;
+ for (float length = 1; length <= 10; length +=1 ) {
+ p.setAntiAlias(false);
+ drawVerticalLine(canvas, p, length, x, yOffset);
+ x += 5;
+ p.setAntiAlias(true);
+ drawVerticalLine(canvas, p, length, x, yOffset);
+ x += 5;
+ }
+ p.setStrokeWidth(5);
+ for (float length = 1; length <= 10; length +=1 ) {
+ p.setAntiAlias(false);
+ drawVerticalLine(canvas, p, length, x, yOffset);
+ x += 10;
+ p.setAntiAlias(true);
+ drawVerticalLine(canvas, p, length, x, yOffset);
+ x += 10;
+ }
+ canvas.restore();
+
+ yOffset += 20;
+ canvas.save();
+ p.setStrokeWidth(1);
+ x = 10 + mOffset;
+ for (float length = 1; length <= 10; length +=1 ) {
+ p.setAntiAlias(false);
+ drawDiagonalLine(canvas, p, length, x, yOffset);
+ x += 5;
+ p.setAntiAlias(true);
+ drawDiagonalLine(canvas, p, length, x, yOffset);
+ x += 5;
+ }
+ p.setStrokeWidth(2);
+ for (float length = 1; length <= 10; length +=1 ) {
+ p.setAntiAlias(false);
+ drawDiagonalLine(canvas, p, length, x, yOffset);
+ x += 10;
+ p.setAntiAlias(true);
+ drawDiagonalLine(canvas, p, length, x, yOffset);
+ x += 10;
+ }
+ canvas.restore();
+
+ yOffset += 20;
+ canvas.save();
+ p.setStrokeWidth(1);
+ x = 10 + mOffset;
+ for (float length = 1; length <= 10; length +=1 ) {
+ p.setAntiAlias(false);
+ canvas.drawLine(x, yOffset, x + 1, yOffset + length, p);
+ x += 5;
+ p.setAntiAlias(true);
+ canvas.drawLine(x, yOffset, x + 1, yOffset + length, p);
+ x += 5;
+ }
+ p.setStrokeWidth(2);
+ for (float length = 1; length <= 10; length +=1 ) {
+ p.setAntiAlias(false);
+ canvas.drawLine(x, yOffset, x + 1, yOffset + length, p);
+ x += 10;
+ p.setAntiAlias(true);
+ canvas.drawLine(x, yOffset, x + 1, yOffset + length, p);
+ x += 10;
+ }
+ canvas.restore();
+
+ yOffset += 20;
+ canvas.save();
+ p.setStrokeWidth(1);
+ x = 10 + mOffset;
+ for (float length = 1; length <= 10; length +=1 ) {
+ p.setAntiAlias(false);
+ canvas.drawLine(x, yOffset, x + length, yOffset + 1, p);
+ x += 5;
+ p.setAntiAlias(true);
+ canvas.drawLine(x, yOffset, x + length, yOffset + 1, p);
+ x += 5;
+ }
+ p.setStrokeWidth(2);
+ for (float length = 1; length <= 10; length +=1 ) {
+ p.setAntiAlias(false);
+ canvas.drawLine(x, yOffset, x + length, yOffset + 1, p);
+ x += 10;
+ p.setAntiAlias(true);
+ canvas.drawLine(x, yOffset, x + length, yOffset + 1, p);
+ x += 10;
+ }
+ canvas.restore();
+
}
}
}
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 0000000..2feda57
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
@@ -0,0 +1,92 @@
+/*
+ * 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();
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ // Ignored, the Camera does all the work for us
+ }
+}
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs
index 31dd3e9..d44fd2b 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 3679068..f046952 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 4c38745..809f02c 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 a663d35..3fc59fc 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 67c2b86..aeae13f 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/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 6455d84..7f9fc31 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -23,6 +23,7 @@ import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.net.ProxyProperties;
+import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration.IpAssignment;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.ProxySettings;
@@ -120,7 +121,7 @@ class WifiConfigStore {
private static final String ipConfigFile = Environment.getDataDirectory() +
"/misc/wifi/ipconfig.txt";
- private static final int IPCONFIG_FILE_VERSION = 1;
+ private static final int IPCONFIG_FILE_VERSION = 2;
/* IP and proxy configuration keys */
private static final String ID_KEY = "id";
@@ -445,9 +446,8 @@ class WifiConfigStore {
if (iter.hasNext()) {
LinkAddress linkAddress = iter.next();
dhcpInfoInternal.ipAddress = linkAddress.getAddress().getHostAddress();
- Iterator<InetAddress>gateways = linkProperties.getGateways().iterator();
- if (gateways.hasNext()) {
- dhcpInfoInternal.gateway = gateways.next().getHostAddress();
+ for (RouteInfo route : linkProperties.getRoutes()) {
+ dhcpInfoInternal.addRoute(route);
}
dhcpInfoInternal.prefixLength = linkAddress.getNetworkPrefixLength();
Iterator<InetAddress> dnsIterator = linkProperties.getDnses().iterator();
@@ -604,9 +604,22 @@ class WifiConfigStore {
out.writeUTF(linkAddr.getAddress().getHostAddress());
out.writeInt(linkAddr.getNetworkPrefixLength());
}
- for (InetAddress gateway : linkProperties.getGateways()) {
+ for (RouteInfo route : linkProperties.getRoutes()) {
out.writeUTF(GATEWAY_KEY);
- out.writeUTF(gateway.getHostAddress());
+ LinkAddress dest = route.getDestination();
+ if (dest != null) {
+ out.writeInt(1);
+ out.writeUTF(dest.getAddress().getHostAddress());
+ out.writeInt(dest.getNetworkPrefixLength());
+ } else {
+ out.writeInt(0);
+ }
+ if (route.getGateway() != null) {
+ out.writeInt(1);
+ out.writeUTF(route.getGateway().getHostAddress());
+ } else {
+ out.writeInt(0);
+ }
}
for (InetAddress inetAddr : linkProperties.getDnses()) {
out.writeUTF(DNS_KEY);
@@ -682,7 +695,8 @@ class WifiConfigStore {
in = new DataInputStream(new BufferedInputStream(new FileInputStream(
ipConfigFile)));
- if (in.readInt() != IPCONFIG_FILE_VERSION) {
+ int version = in.readInt();
+ if (version != 2 && version != 1) {
Log.e(TAG, "Bad version on IP configuration file, ignore read");
return;
}
@@ -709,8 +723,22 @@ class WifiConfigStore {
NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
linkProperties.addLinkAddress(linkAddr);
} else if (key.equals(GATEWAY_KEY)) {
- linkProperties.addGateway(
- NetworkUtils.numericToInetAddress(in.readUTF()));
+ LinkAddress dest = null;
+ InetAddress gateway = null;
+ if (version == 1) {
+ // only supported default gateways - leave the dest/prefix empty
+ gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+ } else {
+ if (in.readInt() == 1) {
+ dest = new LinkAddress(
+ NetworkUtils.numericToInetAddress(in.readUTF()),
+ in.readInt());
+ }
+ if (in.readInt() == 1) {
+ gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+ }
+ }
+ linkProperties.addRoute(new RouteInfo(dest, gateway));
} else if (key.equals(DNS_KEY)) {
linkProperties.addDns(
NetworkUtils.numericToInetAddress(in.readUTF()));
@@ -1022,22 +1050,21 @@ class WifiConfigStore {
.getLinkAddresses();
Collection<InetAddress> currentDnses = currentConfig.linkProperties.getDnses();
Collection<InetAddress> newDnses = newConfig.linkProperties.getDnses();
- Collection<InetAddress> currentGateways =
- currentConfig.linkProperties.getGateways();
- Collection<InetAddress> newGateways = newConfig.linkProperties.getGateways();
+ Collection<RouteInfo> currentRoutes = currentConfig.linkProperties.getRoutes();
+ Collection<RouteInfo> newRoutes = newConfig.linkProperties.getRoutes();
boolean linkAddressesDiffer =
(currentLinkAddresses.size() != newLinkAddresses.size()) ||
!currentLinkAddresses.containsAll(newLinkAddresses);
boolean dnsesDiffer = (currentDnses.size() != newDnses.size()) ||
!currentDnses.containsAll(newDnses);
- boolean gatewaysDiffer = (currentGateways.size() != newGateways.size()) ||
- !currentGateways.containsAll(newGateways);
+ boolean routesDiffer = (currentRoutes.size() != newRoutes.size()) ||
+ !currentRoutes.containsAll(newRoutes);
if ((currentConfig.ipAssignment != newConfig.ipAssignment) ||
linkAddressesDiffer ||
dnsesDiffer ||
- gatewaysDiffer) {
+ routesDiffer) {
ipChanged = true;
}
break;
@@ -1112,8 +1139,8 @@ class WifiConfigStore {
for (LinkAddress linkAddr : config.linkProperties.getLinkAddresses()) {
linkProperties.addLinkAddress(linkAddr);
}
- for (InetAddress gateway : config.linkProperties.getGateways()) {
- linkProperties.addGateway(gateway);
+ for (RouteInfo route : config.linkProperties.getRoutes()) {
+ linkProperties.addRoute(route);
}
for (InetAddress dns : config.linkProperties.getDnses()) {
linkProperties.addDns(dns);
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 16611d8..9125037 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -48,6 +48,7 @@ import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.DhcpInfoInternal;
+import android.net.DhcpStateMachine;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -73,6 +74,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;
@@ -151,6 +153,7 @@ public class WifiStateMachine extends StateMachine {
private NetworkInfo mNetworkInfo;
private SupplicantStateTracker mSupplicantStateTracker;
private WpsStateMachine mWpsStateMachine;
+ private DhcpStateMachine mDhcpStateMachine;
private AlarmManager mAlarmManager;
private PendingIntent mScanIntent;
@@ -165,95 +168,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;
- /* Indicates DHCP succeded */
- static final int CMD_IP_CONFIG_SUCCESS = 15;
- /* Indicates DHCP failed */
- static final int CMD_IP_CONFIG_FAILURE = 16;
+ static final int CMD_STOP_DRIVER = BASE + 14;
+ /* Indicates Static IP succeded */
+ static final int CMD_STATIC_IP_SUCCESS = BASE + 15;
+ /* Indicates Static IP failed */
+ static final int CMD_STATIC_IP_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 +272,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 +293,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;
@@ -335,8 +340,11 @@ public class WifiStateMachine extends StateMachine {
*/
private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
- private static final int POWER_MODE_ACTIVE = 1;
- private static final int POWER_MODE_AUTO = 0;
+ static final int POWER_MODE_ACTIVE = 1;
+ static final int POWER_MODE_AUTO = 0;
+
+ /* Tracks the power mode for restoration after a DHCP request/renewal goes through */
+ private int mPowerMode = POWER_MODE_AUTO;
/**
* Default framework scan interval in milliseconds. This is used in the scenario in which
@@ -1405,8 +1413,10 @@ public class WifiStateMachine extends StateMachine {
*/
NetworkUtils.resetConnections(mInterfaceName);
- if (!NetworkUtils.stopDhcp(mInterfaceName)) {
- Log.e(TAG, "Could not stop DHCP");
+ if (mDhcpStateMachine != null) {
+ mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
+ mDhcpStateMachine.quit();
+ mDhcpStateMachine = null;
}
/* Disable interface */
@@ -1432,6 +1442,100 @@ public class WifiStateMachine extends StateMachine {
}
+ void handlePreDhcpSetup() {
+ if (!mBluetoothConnectionActive) {
+ /*
+ * There are problems setting the Wi-Fi driver's power
+ * mode to active when bluetooth coexistence mode is
+ * enabled or sense.
+ * <p>
+ * We set Wi-Fi to active mode when
+ * obtaining an IP address because we've found
+ * compatibility issues with some routers with low power
+ * mode.
+ * <p>
+ * In order for this active power mode to properly be set,
+ * we disable coexistence mode until we're done with
+ * obtaining an IP address. One exception is if we
+ * are currently connected to a headset, since disabling
+ * coexistence would interrupt that connection.
+ */
+ // Disable the coexistence mode
+ WifiNative.setBluetoothCoexistenceModeCommand(
+ WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
+ }
+
+ mPowerMode = WifiNative.getPowerModeCommand();
+ if (mPowerMode < 0) {
+ // Handle the case where supplicant driver does not support
+ // getPowerModeCommand.
+ mPowerMode = WifiStateMachine.POWER_MODE_AUTO;
+ }
+ if (mPowerMode != WifiStateMachine.POWER_MODE_ACTIVE) {
+ WifiNative.setPowerModeCommand(WifiStateMachine.POWER_MODE_ACTIVE);
+ }
+ }
+
+
+ void handlePostDhcpSetup() {
+ /* restore power mode */
+ WifiNative.setPowerModeCommand(mPowerMode);
+
+ // Set the coexistence mode back to its default value
+ WifiNative.setBluetoothCoexistenceModeCommand(
+ WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
+ }
+
+ private void handleSuccessfulIpConfiguration(DhcpInfoInternal dhcpInfoInternal) {
+ synchronized (mDhcpInfoInternal) {
+ mDhcpInfoInternal = dhcpInfoInternal;
+ }
+ mLastSignalLevel = -1; // force update of signal strength
+ WifiConfigStore.setIpConfiguration(mLastNetworkId, dhcpInfoInternal);
+ InetAddress addr = NetworkUtils.numericToInetAddress(dhcpInfoInternal.ipAddress);
+ mWifiInfo.setInetAddress(addr);
+ if (getNetworkDetailedState() == DetailedState.CONNECTED) {
+ //DHCP renewal in connected state
+ LinkProperties linkProperties = dhcpInfoInternal.makeLinkProperties();
+ linkProperties.setHttpProxy(WifiConfigStore.getProxyProperties(mLastNetworkId));
+ linkProperties.setInterfaceName(mInterfaceName);
+ if (!linkProperties.equals(mLinkProperties)) {
+ Log.d(TAG, "Link configuration changed for netId: " + mLastNetworkId
+ + " old: " + mLinkProperties + "new: " + linkProperties);
+ NetworkUtils.resetConnections(mInterfaceName);
+ mLinkProperties = linkProperties;
+ sendLinkConfigurationChangedBroadcast();
+ }
+ } else {
+ configureLinkProperties();
+ setNetworkDetailedState(DetailedState.CONNECTED);
+ sendNetworkStateChangeBroadcast(mLastBssid);
+ }
+ }
+
+ private void handleFailedIpConfiguration() {
+ Log.e(TAG, "IP configuration failed");
+
+ mWifiInfo.setInetAddress(null);
+ /**
+ * If we've exceeded the maximum number of retries for DHCP
+ * to a given network, disable the network
+ */
+ if (++mReconnectCount > getMaxDhcpRetries()) {
+ Log.e(TAG, "Failed " +
+ mReconnectCount + " times, Disabling " + mLastNetworkId);
+ WifiConfigStore.disableNetwork(mLastNetworkId);
+ mReconnectCount = 0;
+ }
+
+ /* DHCP times out after about 30 seconds, we do a
+ * disconnect and an immediate reconnect to try again
+ */
+ WifiNative.disconnectCommand();
+ WifiNative.reconnectCommand();
+
+ }
+
/*********************************************************
* Notifications from WifiMonitor
@@ -1603,6 +1707,8 @@ public class WifiStateMachine extends StateMachine {
case CMD_FORGET_NETWORK:
case CMD_RSSI_POLL:
case CMD_ENABLE_ALL_NETWORKS:
+ case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+ case DhcpStateMachine.CMD_POST_DHCP_ACTION:
break;
case CMD_START_WPS:
/* Return failure when the state machine cannot handle WPS initiation*/
@@ -2480,74 +2586,18 @@ public class WifiStateMachine extends StateMachine {
}
class ConnectingState extends State {
- boolean mModifiedBluetoothCoexistenceMode;
- int mPowerMode;
- boolean mUseStaticIp;
- Thread mDhcpThread;
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- mUseStaticIp = WifiConfigStore.isUsingStaticIp(mLastNetworkId);
- if (!mUseStaticIp) {
- mDhcpThread = null;
- mModifiedBluetoothCoexistenceMode = false;
- mPowerMode = POWER_MODE_AUTO;
-
- if (!mBluetoothConnectionActive) {
- /*
- * There are problems setting the Wi-Fi driver's power
- * mode to active when bluetooth coexistence mode is
- * enabled or sense.
- * <p>
- * We set Wi-Fi to active mode when
- * obtaining an IP address because we've found
- * compatibility issues with some routers with low power
- * mode.
- * <p>
- * In order for this active power mode to properly be set,
- * we disable coexistence mode until we're done with
- * obtaining an IP address. One exception is if we
- * are currently connected to a headset, since disabling
- * coexistence would interrupt that connection.
- */
- mModifiedBluetoothCoexistenceMode = true;
-
- // Disable the coexistence mode
- WifiNative.setBluetoothCoexistenceModeCommand(
- WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
- }
-
- mPowerMode = WifiNative.getPowerModeCommand();
- if (mPowerMode < 0) {
- // Handle the case where supplicant driver does not support
- // getPowerModeCommand.
- mPowerMode = POWER_MODE_AUTO;
- }
- if (mPowerMode != POWER_MODE_ACTIVE) {
- WifiNative.setPowerModeCommand(POWER_MODE_ACTIVE);
- }
- Log.d(TAG, "DHCP request started");
- mDhcpThread = new Thread(new Runnable() {
- public void run() {
- DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
- if (NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal)) {
- Log.d(TAG, "DHCP request succeeded");
- synchronized (mDhcpInfoInternal) {
- mDhcpInfoInternal = dhcpInfoInternal;
- }
- WifiConfigStore.setIpConfiguration(mLastNetworkId, dhcpInfoInternal);
- sendMessage(CMD_IP_CONFIG_SUCCESS);
- } else {
- Log.d(TAG, "DHCP request failed: " +
- NetworkUtils.getDhcpError());
- sendMessage(CMD_IP_CONFIG_FAILURE);
- }
- }
- });
- mDhcpThread.start();
+ if (!WifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
+ //start DHCP
+ mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(
+ mContext, WifiStateMachine.this, mInterfaceName);
+ mDhcpStateMachine.registerForPreDhcpNotification();
+ mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
} else {
DhcpInfoInternal dhcpInfoInternal = WifiConfigStore.getIpConfiguration(
mLastNetworkId);
@@ -2559,16 +2609,13 @@ public class WifiStateMachine extends StateMachine {
try {
netd.setInterfaceConfig(mInterfaceName, ifcg);
Log.v(TAG, "Static IP configuration succeeded");
- synchronized (mDhcpInfoInternal) {
- mDhcpInfoInternal = dhcpInfoInternal;
- }
- sendMessage(CMD_IP_CONFIG_SUCCESS);
+ sendMessage(CMD_STATIC_IP_SUCCESS, dhcpInfoInternal);
} catch (RemoteException re) {
Log.v(TAG, "Static IP configuration failed: " + re);
- sendMessage(CMD_IP_CONFIG_FAILURE);
+ sendMessage(CMD_STATIC_IP_FAILURE);
} catch (IllegalStateException e) {
Log.v(TAG, "Static IP configuration failed: " + e);
- sendMessage(CMD_IP_CONFIG_FAILURE);
+ sendMessage(CMD_STATIC_IP_FAILURE);
}
}
}
@@ -2577,44 +2624,26 @@ public class WifiStateMachine extends StateMachine {
if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
switch(message.what) {
- case CMD_IP_CONFIG_SUCCESS:
- mLastSignalLevel = -1; // force update of signal strength
- InetAddress addr;
- synchronized (mDhcpInfoInternal) {
- addr = NetworkUtils.numericToInetAddress(mDhcpInfoInternal.ipAddress);
- }
- mWifiInfo.setInetAddress(addr);
- configureLinkProperties();
- if (getNetworkDetailedState() == DetailedState.CONNECTED) {
- sendLinkConfigurationChangedBroadcast();
- } else {
- setNetworkDetailedState(DetailedState.CONNECTED);
- sendNetworkStateChangeBroadcast(mLastBssid);
+ case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+ handlePreDhcpSetup();
+ mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE);
+ break;
+ case DhcpStateMachine.CMD_POST_DHCP_ACTION:
+ handlePostDhcpSetup();
+ if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) {
+ handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj);
+ transitionTo(mConnectedState);
+ } else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) {
+ handleFailedIpConfiguration();
+ transitionTo(mDisconnectingState);
}
- //TODO: The framework is not detecting a DHCP renewal and a possible
- //IP change. we should detect this and send out a config change broadcast
+ break;
+ case CMD_STATIC_IP_SUCCESS:
+ handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj);
transitionTo(mConnectedState);
break;
- case CMD_IP_CONFIG_FAILURE:
- mWifiInfo.setInetAddress(null);
-
- Log.e(TAG, "IP configuration failed");
- /**
- * If we've exceeded the maximum number of retries for DHCP
- * to a given network, disable the network
- */
- if (++mReconnectCount > getMaxDhcpRetries()) {
- Log.e(TAG, "Failed " +
- mReconnectCount + " times, Disabling " + mLastNetworkId);
- WifiConfigStore.disableNetwork(mLastNetworkId);
- mReconnectCount = 0;
- }
-
- /* DHCP times out after about 30 seconds, we do a
- * disconnect and an immediate reconnect to try again
- */
- WifiNative.disconnectCommand();
- WifiNative.reconnectCommand();
+ case CMD_STATIC_IP_FAILURE:
+ handleFailedIpConfiguration();
transitionTo(mDisconnectingState);
break;
case CMD_DISCONNECT:
@@ -2658,23 +2687,6 @@ public class WifiStateMachine extends StateMachine {
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
return HANDLED;
}
-
- @Override
- public void exit() {
- /* reset power state & bluetooth coexistence if on DHCP */
- if (!mUseStaticIp) {
- if (mPowerMode != POWER_MODE_ACTIVE) {
- WifiNative.setPowerModeCommand(mPowerMode);
- }
-
- if (mModifiedBluetoothCoexistenceMode) {
- // Set the coexistence mode back to its default value
- WifiNative.setBluetoothCoexistenceModeCommand(
- WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
- }
- }
-
- }
}
class ConnectedState extends State {
@@ -2692,6 +2704,19 @@ public class WifiStateMachine extends StateMachine {
if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
boolean eventLoggingEnabled = true;
switch (message.what) {
+ case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+ handlePreDhcpSetup();
+ mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE);
+ break;
+ case DhcpStateMachine.CMD_POST_DHCP_ACTION:
+ handlePostDhcpSetup();
+ if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) {
+ handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj);
+ } else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) {
+ handleFailedIpConfiguration();
+ transitionTo(mDisconnectingState);
+ }
+ break;
case CMD_DISCONNECT:
WifiNative.disconnectCommand();
transitionTo(mDisconnectingState);