summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/14.txt12
-rw-r--r--api/current.txt74
-rw-r--r--cmds/bootanimation/BootAnimation.cpp3
-rw-r--r--cmds/stagefright/stagefright.cpp21
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java4
-rw-r--r--core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl33
-rw-r--r--core/java/android/app/Fragment.java6
-rw-r--r--core/java/android/content/pm/PackageManager.java20
-rw-r--r--core/java/android/content/res/Configuration.java50
-rw-r--r--core/java/android/net/EthernetDataTracker.java19
-rw-r--r--core/java/android/net/SSLCertificateSocketFactory.java2
-rw-r--r--core/java/android/nfc/INfcTag.aidl3
-rw-r--r--core/java/android/nfc/tech/IsoDep.java6
-rw-r--r--core/java/android/nfc/tech/MifareClassic.java29
-rw-r--r--core/java/android/nfc/tech/MifareUltralight.java30
-rw-r--r--core/java/android/nfc/tech/NfcA.java29
-rw-r--r--core/java/android/nfc/tech/NfcF.java6
-rw-r--r--core/java/android/os/Build.java42
-rw-r--r--core/java/android/pim/RecurrenceSet.java68
-rw-r--r--core/java/android/provider/CalendarContract.java (renamed from core/java/android/provider/Calendar.java)83
-rw-r--r--core/java/android/provider/ContactsContract.java5
-rw-r--r--core/java/android/provider/Settings.java7
-rwxr-xr-xcore/java/android/speech/tts/TextToSpeech.java15
-rw-r--r--core/java/android/speech/tts/TtsEngines.java36
-rw-r--r--core/java/android/view/GLES20Canvas.java1
-rw-r--r--core/java/android/view/GLES20Layer.java7
-rw-r--r--core/java/android/view/Gravity.java15
-rw-r--r--core/java/android/view/HardwareRenderer.java20
-rw-r--r--core/java/android/view/TextureView.java94
-rw-r--r--core/java/android/view/View.java109
-rw-r--r--core/java/android/view/ViewAncestor.java75
-rw-r--r--core/java/android/view/WindowManager.java14
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java159
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java126
-rw-r--r--core/java/android/view/accessibility/AccessibilityRecord.java119
-rw-r--r--core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl4
-rw-r--r--core/java/android/webkit/HTML5VideoFullScreen.java23
-rw-r--r--core/java/android/webkit/WebView.java34
-rw-r--r--core/java/android/widget/AbsListView.java1
-rw-r--r--core/java/android/widget/AdapterView.java2
-rw-r--r--core/java/android/widget/FrameLayout.java7
-rw-r--r--core/java/android/widget/GridLayout.java20
-rw-r--r--core/java/android/widget/GridView.java3
-rw-r--r--core/java/android/widget/ImageView.java8
-rw-r--r--core/java/android/widget/LinearLayout.java6
-rw-r--r--core/java/android/widget/ProgressBar.java7
-rw-r--r--core/java/android/widget/RelativeLayout.java3
-rw-r--r--core/java/android/widget/Switch.java5
-rw-r--r--core/java/android/widget/TableRow.java3
-rw-r--r--core/java/android/widget/TextView.java24
-rw-r--r--core/java/com/android/internal/os/WrapperInit.java6
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java8
-rw-r--r--core/java/com/android/internal/view/menu/IconMenuItemView.java4
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java3
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java113
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/Tweener.java7
-rw-r--r--core/jni/android/graphics/ParcelSurfaceTexture.cpp4
-rw-r--r--core/jni/android/graphics/SurfaceTexture.h31
-rw-r--r--core/jni/android_media_AudioSystem.cpp2
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp6
-rw-r--r--core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.pngbin0 -> 688 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.pngbin0 -> 698 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.pngbin0 -> 538 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.pngbin0 -> 536 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.pngbin0 -> 859 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.pngbin0 -> 845 bytes
-rw-r--r--core/res/res/layout/keyguard_screen_tab_unlock.xml1
-rw-r--r--core/res/res/layout/keyguard_screen_tab_unlock_land.xml3
-rwxr-xr-xcore/res/res/values/attrs.xml10
-rwxr-xr-xcore/res/res/values/config.xml3
-rw-r--r--core/res/res/values/public.xml2
-rwxr-xr-xcore/res/res/values/strings.xml2
-rw-r--r--core/tests/bluetoothtests/AndroidManifest.xml1
-rw-r--r--core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java2
-rw-r--r--core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java2
-rw-r--r--core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java136
-rw-r--r--core/tests/coretests/src/android/content/res/ConfigurationTest.java114
-rw-r--r--core/tests/coretests/src/android/pim/RecurrenceSetTest.java18
-rw-r--r--core/tests/coretests/src/android/view/GravityTest.java4
-rw-r--r--data/etc/handheld_core_hardware.xml2
-rw-r--r--data/etc/tablet_core_hardware.xml2
-rw-r--r--docs/html/guide/guide_toc.cs20
-rw-r--r--docs/html/guide/topics/graphics/animation.jd103
-rw-r--r--docs/html/guide/topics/graphics/renderscript.html10
-rw-r--r--docs/html/guide/topics/graphics/renderscript.jd716
-rw-r--r--docs/html/guide/topics/renderscript/compute.jd38
-rw-r--r--docs/html/guide/topics/renderscript/graphics.jd619
-rw-r--r--docs/html/guide/topics/renderscript/index.jd640
-rw-r--r--docs/html/guide/topics/resources/animation-resource.jd373
-rw-r--r--docs/html/guide/topics/resources/providing-resources.jd120
-rw-r--r--docs/html/guide/topics/usb/adk.jd23
-rw-r--r--docs/html/sdk/sdk_toc.cs3
-rw-r--r--drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp65
-rw-r--r--graphics/java/android/graphics/drawable/BitmapDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/ClipDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java17
-rw-r--r--graphics/java/android/graphics/drawable/ScaleDrawable.java4
-rw-r--r--graphics/java/android/renderscript/Allocation.java45
-rw-r--r--graphics/java/android/renderscript/AllocationAdapter.java48
-rw-r--r--graphics/java/android/renderscript/RenderScript.java20
-rw-r--r--graphics/jni/android_renderscript_RenderScript.cpp27
-rw-r--r--include/android_runtime/android_graphics_ParcelSurfaceTexture.h5
-rw-r--r--include/android_runtime/android_graphics_SurfaceTexture.h4
-rw-r--r--include/gui/SurfaceTexture.h17
-rw-r--r--include/media/AudioSystem.h2
-rw-r--r--include/media/IAudioPolicyService.h2
-rw-r--r--include/media/stagefright/MetaData.h1
-rw-r--r--include/media/stagefright/OMXCodec.h6
-rw-r--r--include/private/surfaceflinger/SharedBufferStack.h348
-rw-r--r--include/surfaceflinger/IGraphicBufferAlloc.h2
-rw-r--r--include/surfaceflinger/ISurface.h25
-rw-r--r--include/surfaceflinger/ISurfaceComposer.h13
-rw-r--r--include/surfaceflinger/ISurfaceComposerClient.h6
-rw-r--r--include/surfaceflinger/Surface.h73
-rw-r--r--include/surfaceflinger/SurfaceComposerClient.h6
-rw-r--r--include/utils/BlobCache.h181
-rw-r--r--include/utils/RefBase.h21
-rw-r--r--include/utils/threads.h1
-rw-r--r--libs/gui/Android.mk1
-rw-r--r--libs/gui/ISurface.cpp47
-rw-r--r--libs/gui/ISurfaceComposer.cpp25
-rw-r--r--libs/gui/ISurfaceComposerClient.cpp56
-rw-r--r--libs/gui/SharedBufferStack.cpp714
-rw-r--r--libs/gui/Surface.cpp634
-rw-r--r--libs/gui/SurfaceComposerClient.cpp17
-rw-r--r--libs/gui/SurfaceTexture.cpp12
-rw-r--r--libs/gui/SurfaceTextureClient.cpp6
-rw-r--r--libs/gui/tests/SurfaceTextureClient_test.cpp475
-rw-r--r--libs/gui/tests/SurfaceTexture_test.cpp534
-rw-r--r--libs/hwui/LayerRenderer.cpp90
-rw-r--r--libs/hwui/LayerRenderer.h3
-rw-r--r--libs/hwui/OpenGLRenderer.cpp66
-rw-r--r--libs/hwui/OpenGLRenderer.h70
-rw-r--r--libs/rs/RenderScriptDefines.h12
-rw-r--r--libs/rs/driver/rsdAllocation.cpp26
-rw-r--r--libs/rs/driver/rsdAllocation.h21
-rw-r--r--libs/rs/driver/rsdCore.cpp3
-rw-r--r--libs/rs/driver/rsdRuntimeStubs.cpp23
-rw-r--r--libs/rs/rs.spec15
-rw-r--r--libs/rs/rsAllocation.cpp17
-rw-r--r--libs/rs/rsRuntime.h15
-rw-r--r--libs/rs/rsScriptC_Lib.cpp23
-rw-r--r--libs/rs/rs_hal.h21
-rw-r--r--libs/rs/scriptc/rs_graphics.rsh11
-rw-r--r--libs/rs/scriptc/rs_math.rsh52
-rw-r--r--libs/rs/scriptc/rs_types.rsh17
-rw-r--r--libs/utils/Android.mk1
-rw-r--r--libs/utils/BlobCache.cpp232
-rw-r--r--libs/utils/RefBase.cpp34
-rw-r--r--libs/utils/Threads.cpp24
-rw-r--r--libs/utils/tests/Android.mk1
-rw-r--r--libs/utils/tests/BlobCache_test.cpp257
-rw-r--r--media/java/android/media/MediaPlayer.java53
-rw-r--r--media/java/android/media/MediaRecorder.java10
-rw-r--r--media/jni/android_media_MediaPlayer.cpp41
-rw-r--r--media/libmedia/AudioTrack.cpp2
-rw-r--r--media/libstagefright/CameraSourceTimeLapse.cpp3
-rw-r--r--media/libstagefright/MPEG4Writer.cpp129
-rw-r--r--media/libstagefright/OMXCodec.cpp24
-rw-r--r--media/libstagefright/TimedEventQueue.cpp3
-rw-r--r--media/libstagefright/omx/OMX.cpp2
-rw-r--r--packages/SettingsProvider/res/values/defaults.xml2
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java3
-rw-r--r--policy/src/com/android/internal/policy/impl/LockScreen.java8
-rw-r--r--services/audioflinger/AudioFlinger.cpp2
-rw-r--r--services/audioflinger/AudioFlinger.h2
-rw-r--r--services/audioflinger/AudioPolicyService.cpp2
-rw-r--r--services/audioflinger/AudioPolicyService.h2
-rw-r--r--services/input/EventHub.cpp1
-rw-r--r--services/input/EventHub.h35
-rw-r--r--services/input/InputDispatcher.cpp81
-rw-r--r--services/input/InputDispatcher.h19
-rw-r--r--services/input/InputReader.cpp9
-rw-r--r--services/input/InputWindow.h4
-rw-r--r--services/input/tests/InputReader_test.cpp3
-rwxr-xr-xservices/java/com/android/server/NotificationManagerService.java76
-rw-r--r--services/java/com/android/server/SystemServer.java22
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java91
-rw-r--r--services/java/com/android/server/connectivity/Vpn.java8
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java5
-rw-r--r--services/java/com/android/server/usb/UsbDeviceManager.java92
-rw-r--r--services/jni/com_android_server_connectivity_Vpn.cpp80
-rw-r--r--services/sensorservice/Fusion.cpp57
-rw-r--r--services/surfaceflinger/Android.mk22
-rw-r--r--services/surfaceflinger/Layer.cpp870
-rw-r--r--services/surfaceflinger/Layer.h168
-rw-r--r--services/surfaceflinger/LayerBase.cpp208
-rw-r--r--services/surfaceflinger/LayerBase.h84
-rw-r--r--services/surfaceflinger/LayerDim.cpp2
-rw-r--r--services/surfaceflinger/LayerDim.h2
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp214
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h42
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.cpp76
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.h55
-rw-r--r--services/surfaceflinger/clz.h10
-rw-r--r--telephony/java/com/android/internal/telephony/CallManager.java20
-rw-r--r--telephony/java/com/android/internal/telephony/CallerInfo.java83
-rw-r--r--telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java31
-rw-r--r--telephony/java/com/android/internal/telephony/DataConnectionTracker.java6
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java35
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java14
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java6
-rw-r--r--tests/BiDiTests/res/layout/frame_layout_rtl.xml2
-rw-r--r--tests/GridLayoutTest/res/layout/grid3.xml12
-rw-r--r--tests/GridLayoutTest/src/com/android/test/layout/Activity2.java28
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml1
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java4
-rw-r--r--tools/aapt/Command.cpp156
-rw-r--r--wifi/java/android/net/wifi/SupplicantState.java22
-rw-r--r--wifi/java/android/net/wifi/WifiMonitor.java8
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java130
212 files changed, 6912 insertions, 5418 deletions
diff --git a/api/14.txt b/api/14.txt
index 5c4732e0e87f..050540bd4a82 100644
--- a/api/14.txt
+++ b/api/14.txt
@@ -22239,7 +22239,6 @@ package android.view.accessibility {
}
public class AccessibilityRecord {
- ctor protected AccessibilityRecord();
method public int getAddedCount();
method public java.lang.CharSequence getBeforeText();
method public java.lang.CharSequence getClassName();
@@ -22269,17 +22268,6 @@ package android.view.accessibility {
method public void setParcelableData(android.os.Parcelable);
method public void setPassword(boolean);
method public void setRemovedCount(int);
- field protected int mAddedCount;
- field protected java.lang.CharSequence mBeforeText;
- field protected int mBooleanProperties;
- field protected java.lang.CharSequence mClassName;
- field protected java.lang.CharSequence mContentDescription;
- field protected int mCurrentItemIndex;
- field protected int mFromIndex;
- field protected int mItemCount;
- field protected android.os.Parcelable mParcelableData;
- field protected int mRemovedCount;
- field protected final java.util.List mText;
}
}
diff --git a/api/current.txt b/api/current.txt
index f06df4b4794b..7c9c851c4bad 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -259,6 +259,7 @@ package android {
field public static final int borderlessButtonStyle = 16843563; // 0x101032b
field public static final int bottom = 16843184; // 0x10101b0
field public static final int bottomBright = 16842957; // 0x10100cd
+ field public static final int bottomChevronDrawable = 16843661; // 0x101038d
field public static final int bottomDark = 16842953; // 0x10100c9
field public static final int bottomLeftRadius = 16843179; // 0x10101ab
field public static final int bottomMedium = 16842958; // 0x10100ce
@@ -425,7 +426,7 @@ package android {
field public static final int fastScrollTextColor = 16843609; // 0x1010359
field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
- field public static final int feedbackCount = 16843665; // 0x1010391
+ field public static final int feedbackCount = 16843667; // 0x1010393
field public static final int fillAfter = 16843197; // 0x10101bd
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillEnabled = 16843343; // 0x101024f
@@ -488,12 +489,12 @@ package android {
field public static final int headerDividersEnabled = 16843310; // 0x101022e
field public static final int height = 16843093; // 0x1010155
field public static final int hint = 16843088; // 0x1010150
- field public static final int hitRadius = 16843662; // 0x101038e
+ field public static final int hitRadius = 16843664; // 0x1010390
field public static final int homeAsUpIndicator = 16843531; // 0x101030b
field public static final int homeLayout = 16843549; // 0x101031d
field public static final int horizontalDivider = 16843053; // 0x101012d
field public static final int horizontalGap = 16843327; // 0x101023f
- field public static final int horizontalOffset = 16843667; // 0x1010393
+ field public static final int horizontalOffset = 16843669; // 0x1010395
field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
field public static final int horizontalSpacing = 16843028; // 0x1010114
field public static final int host = 16842792; // 0x1010028
@@ -686,7 +687,7 @@ package android {
field public static final int orderingFromXml = 16843239; // 0x10101e7
field public static final int orientation = 16842948; // 0x10100c4
field public static final int outAnimation = 16843128; // 0x1010178
- field public static final int outerRadius = 16843661; // 0x101038d
+ field public static final int outerRadius = 16843663; // 0x101038f
field public static final int overScrollFooter = 16843459; // 0x10102c3
field public static final int overScrollHeader = 16843458; // 0x10102c2
field public static final int overScrollMode = 16843457; // 0x10102c1
@@ -851,7 +852,7 @@ package android {
field public static final int smallIcon = 16843422; // 0x101029e
field public static final int smallScreens = 16843396; // 0x1010284
field public static final int smoothScrollbar = 16843313; // 0x1010231
- field public static final int snapMargin = 16843664; // 0x1010390
+ field public static final int snapMargin = 16843666; // 0x1010392
field public static final int soundEffectsEnabled = 16843285; // 0x1010215
field public static final int spacing = 16843027; // 0x1010113
field public static final int spinnerDropDownItemStyle = 16842887; // 0x1010087
@@ -1006,6 +1007,7 @@ package android {
field public static final int toYScale = 16843205; // 0x10101c5
field public static final int top = 16843182; // 0x10101ae
field public static final int topBright = 16842955; // 0x10100cb
+ field public static final int topChevronDrawable = 16843660; // 0x101038c
field public static final int topDark = 16842951; // 0x10100c7
field public static final int topLeftRadius = 16843177; // 0x10101a9
field public static final int topOffset = 16843352; // 0x1010258
@@ -1035,10 +1037,10 @@ package android {
field public static final int verticalCorrection = 16843322; // 0x101023a
field public static final int verticalDivider = 16843054; // 0x101012e
field public static final int verticalGap = 16843328; // 0x1010240
- field public static final int verticalOffset = 16843666; // 0x1010392
+ field public static final int verticalOffset = 16843668; // 0x1010394
field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
field public static final int verticalSpacing = 16843029; // 0x1010115
- field public static final int vibrationDuration = 16843663; // 0x101038f
+ field public static final int vibrationDuration = 16843665; // 0x1010391
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -1055,7 +1057,7 @@ package android {
field public static final int wallpaperIntraOpenExitAnimation = 16843416; // 0x1010298
field public static final int wallpaperOpenEnterAnimation = 16843411; // 0x1010293
field public static final int wallpaperOpenExitAnimation = 16843412; // 0x1010294
- field public static final int waveDrawable = 16843660; // 0x101038c
+ field public static final int waveDrawable = 16843662; // 0x101038e
field public static final int webTextViewStyle = 16843449; // 0x10102b9
field public static final int webViewStyle = 16842885; // 0x1010085
field public static final int weekDayTextAppearance = 16843592; // 0x1010348
@@ -5819,6 +5821,8 @@ package android.content.pm {
field public static final java.lang.String FEATURE_LOCATION_NETWORK = "android.hardware.location.network";
field public static final java.lang.String FEATURE_MICROPHONE = "android.hardware.microphone";
field public static final java.lang.String FEATURE_NFC = "android.hardware.nfc";
+ field public static final java.lang.String FEATURE_SCREEN_LANDSCAPE = "android.hardware.screen.landscape";
+ field public static final java.lang.String FEATURE_SCREEN_PORTRAIT = "android.hardware.screen.portrait";
field public static final java.lang.String FEATURE_SENSOR_ACCELEROMETER = "android.hardware.sensor.accelerometer";
field public static final java.lang.String FEATURE_SENSOR_BAROMETER = "android.hardware.sensor.barometer";
field public static final java.lang.String FEATURE_SENSOR_COMPASS = "android.hardware.sensor.compass";
@@ -8508,11 +8512,11 @@ package android.graphics.drawable {
method public int getMinimumWidth();
method public abstract int getOpacity();
method public boolean getPadding(android.graphics.Rect);
+ method public int getResolvedLayoutDirectionSelf();
method public int[] getState();
method public android.graphics.Region getTransparentRegion();
method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void invalidateSelf();
- method public boolean isLayoutRtlSelf();
method public boolean isStateful();
method public final boolean isVisible();
method public void jumpToCurrentState();
@@ -8544,7 +8548,7 @@ package android.graphics.drawable {
}
public static abstract interface Drawable.Callback2 implements android.graphics.drawable.Drawable.Callback {
- method public abstract boolean isLayoutRtl(android.graphics.drawable.Drawable);
+ method public abstract int getResolvedLayoutDirection(android.graphics.drawable.Drawable);
}
public static abstract class Drawable.ConstantState {
@@ -11180,6 +11184,8 @@ package android.net {
method public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
method public static javax.net.ssl.SSLSocketFactory getInsecure(int, android.net.SSLSessionCache);
method public java.lang.String[] getSupportedCipherSuites();
+ method public void setKeyManagers(javax.net.ssl.KeyManager[]);
+ method public void setTrustManagers(javax.net.ssl.TrustManager[]);
}
public final class SSLSessionCache {
@@ -13586,6 +13592,7 @@ package android.os {
public class Build {
ctor public Build();
+ method public static java.lang.String getRadioVersion();
field public static final java.lang.String BOARD;
field public static final java.lang.String BOOTLOADER;
field public static final java.lang.String BRAND;
@@ -13600,7 +13607,7 @@ package android.os {
field public static final java.lang.String MANUFACTURER;
field public static final java.lang.String MODEL;
field public static final java.lang.String PRODUCT;
- field public static final java.lang.String RADIO;
+ field public static final deprecated java.lang.String RADIO;
field public static final java.lang.String SERIAL;
field public static final java.lang.String TAGS;
field public static final long TIME;
@@ -16493,6 +16500,7 @@ package android.renderscript {
method public void copy1DRangeFrom(int, int, short[]);
method public void copy1DRangeFrom(int, int, byte[]);
method public void copy1DRangeFrom(int, int, float[]);
+ method public void copy1DRangeFrom(int, int, android.renderscript.Allocation, int);
method public void copy1DRangeFromUnchecked(int, int, int[]);
method public void copy1DRangeFromUnchecked(int, int, short[]);
method public void copy1DRangeFromUnchecked(int, int, byte[]);
@@ -16501,6 +16509,7 @@ package android.renderscript {
method public void copy2DRangeFrom(int, int, int, int, short[]);
method public void copy2DRangeFrom(int, int, int, int, int[]);
method public void copy2DRangeFrom(int, int, int, int, float[]);
+ method public void copy2DRangeFrom(int, int, int, int, android.renderscript.Allocation, int, int);
method public void copy2DRangeFrom(int, int, android.graphics.Bitmap);
method public void copyFrom(android.renderscript.BaseObj[]);
method public void copyFrom(int[]);
@@ -16565,8 +16574,10 @@ package android.renderscript {
method public void subData1D(int, int, short[]);
method public void subData1D(int, int, byte[]);
method public void subData1D(int, int, float[]);
+ method public void subData1D(int, int, android.renderscript.AllocationAdapter, int);
method public void subData2D(int, int, int, int, int[]);
method public void subData2D(int, int, int, int, float[]);
+ method public void subData2D(int, int, int, int, android.renderscript.AllocationAdapter, int, int);
method public void subElementData(int, int, android.renderscript.FieldPacker);
}
@@ -17599,7 +17610,7 @@ package android.speech.tts {
method public boolean isSpeaking();
method public int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
method public int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>);
- method public int setEngineByPackageName(java.lang.String);
+ method public deprecated int setEngineByPackageName(java.lang.String);
method public int setLanguage(java.util.Locale);
method public int setOnUtteranceCompletedListener(android.speech.tts.TextToSpeech.OnUtteranceCompletedListener);
method public int setPitch(float);
@@ -20572,7 +20583,7 @@ package android.view {
method public static void apply(int, int, int, android.graphics.Rect, android.graphics.Rect);
method public static void apply(int, int, int, android.graphics.Rect, int, int, android.graphics.Rect);
method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect);
- method public static int getAbsoluteGravity(int, boolean);
+ method public static int getAbsoluteGravity(int, int);
method public static boolean isHorizontal(int);
method public static boolean isVertical(int);
field public static final int AXIS_CLIP = 8; // 0x8
@@ -21555,8 +21566,12 @@ package android.view {
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.Bitmap getBitmap();
+ method public android.graphics.Bitmap getBitmap(int, int);
+ method public android.graphics.Bitmap getBitmap(android.graphics.Bitmap);
method public android.graphics.SurfaceTexture getSurfaceTexture();
method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
+ method public boolean isAvailable();
method protected final void onDraw(android.graphics.Canvas);
method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener);
}
@@ -21606,6 +21621,8 @@ package android.view {
method public void buildDrawingCache();
method public void buildDrawingCache(boolean);
method public void buildLayer();
+ method public boolean canScrollHorizontally(int);
+ method public boolean canScrollVertically(int);
method public void cancelLongPress();
method public boolean checkInputConnectionProxy(android.view.View);
method public void clearAnimation();
@@ -21711,6 +21728,7 @@ package android.view {
method public final android.view.ViewParent getParent();
method public float getPivotX();
method public float getPivotY();
+ method public int getResolvedLayoutDirection(android.graphics.drawable.Drawable);
method public android.content.res.Resources getResources();
method public final int getRight();
method protected float getRightFadingEdgeStrength();
@@ -21776,8 +21794,6 @@ package android.view {
method public boolean isInEditMode();
method public boolean isInTouchMode();
method public boolean isLayoutRequested();
- method public boolean isLayoutRtl();
- method public boolean isLayoutRtl(android.graphics.drawable.Drawable);
method public boolean isLongClickable();
method public boolean isOpaque();
method protected boolean isPaddingOffsetRequired();
@@ -22719,13 +22735,11 @@ package android.view.accessibility {
method public void appendRecord(android.view.accessibility.AccessibilityRecord);
method public int describeContents();
method public static java.lang.String eventTypeToString(int);
- method public int getAccessibilityWindowId();
method public long getEventTime();
method public int getEventType();
method public java.lang.CharSequence getPackageName();
method public android.view.accessibility.AccessibilityRecord getRecord(int);
method public int getRecordCount();
- method public android.view.accessibility.AccessibilityNodeInfo getSource();
method public void initFromParcel(android.os.Parcel);
method public static android.view.accessibility.AccessibilityEvent obtain(int);
method public static android.view.accessibility.AccessibilityEvent obtain(android.view.accessibility.AccessibilityEvent);
@@ -22733,7 +22747,6 @@ package android.view.accessibility {
method public void setEventTime(long);
method public void setEventType(int);
method public void setPackageName(java.lang.CharSequence);
- method public void setSource(android.view.View);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int INVALID_POSITION = -1; // 0xffffffff
@@ -22749,6 +22762,7 @@ package android.view.accessibility {
field public static final int TYPE_VIEW_LONG_CLICKED = 2; // 0x2
field public static final int TYPE_VIEW_SELECTED = 4; // 0x4
field public static final int TYPE_VIEW_TEXT_CHANGED = 16; // 0x10
+ field public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800
field public static final int TYPE_WINDOW_STATE_CHANGED = 32; // 0x20
}
@@ -22776,9 +22790,10 @@ package android.view.accessibility {
method public void addAction(int);
method public void addChild(android.view.View);
method public int describeContents();
- method public int getAccessibilityWindowId();
+ method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String);
method public int getActions();
- method public void getBounds(android.graphics.Rect);
+ method public void getBoundsInParent(android.graphics.Rect);
+ method public void getBoundsInScreen(android.graphics.Rect);
method public android.view.accessibility.AccessibilityNodeInfo getChild(int);
method public int getChildCount();
method public java.lang.CharSequence getClassName();
@@ -22786,6 +22801,7 @@ package android.view.accessibility {
method public java.lang.CharSequence getPackageName();
method public android.view.accessibility.AccessibilityNodeInfo getParent();
method public java.lang.CharSequence getText();
+ method public int getWindowId();
method public boolean isCheckable();
method public boolean isChecked();
method public boolean isClickable();
@@ -22799,7 +22815,8 @@ package android.view.accessibility {
method public static android.view.accessibility.AccessibilityNodeInfo obtain();
method public boolean performAction(int);
method public void recycle();
- method public void setBounds(android.graphics.Rect);
+ method public void setBoundsInParent(android.graphics.Rect);
+ method public void setBoundsInScreen(android.graphics.Rect);
method public void setCheckable(boolean);
method public void setChecked(boolean);
method public void setClassName(java.lang.CharSequence);
@@ -22824,7 +22841,6 @@ package android.view.accessibility {
}
public class AccessibilityRecord {
- ctor protected AccessibilityRecord();
method public int getAddedCount();
method public java.lang.CharSequence getBeforeText();
method public java.lang.CharSequence getClassName();
@@ -22834,7 +22850,9 @@ package android.view.accessibility {
method public int getItemCount();
method public android.os.Parcelable getParcelableData();
method public int getRemovedCount();
+ method public android.view.accessibility.AccessibilityNodeInfo getSource();
method public java.util.List<java.lang.CharSequence> getText();
+ method public int getWindowId();
method public boolean isChecked();
method public boolean isEnabled();
method public boolean isFullScreen();
@@ -22855,17 +22873,7 @@ package android.view.accessibility {
method public void setParcelableData(android.os.Parcelable);
method public void setPassword(boolean);
method public void setRemovedCount(int);
- field protected int mAddedCount;
- field protected java.lang.CharSequence mBeforeText;
- field protected int mBooleanProperties;
- field protected java.lang.CharSequence mClassName;
- field protected java.lang.CharSequence mContentDescription;
- field protected int mCurrentItemIndex;
- field protected int mFromIndex;
- field protected int mItemCount;
- field protected android.os.Parcelable mParcelableData;
- field protected int mRemovedCount;
- field protected final java.util.List mText;
+ method public void setSource(android.view.View);
}
}
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 69c459705e2e..0acba8bc516b 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -313,9 +313,6 @@ bool BootAnimation::android()
const GLint yc = (mHeight - mAndroid[0].h) / 2;
const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
- // draw and update only what we need
- mFlingerSurface->setSwapRectangle(updateRect);
-
glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
updateRect.height());
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 01262fa7a136..ca771856d20d 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -66,6 +66,7 @@ static long gNumRepetitions;
static long gMaxNumFrames; // 0 means decode all available.
static long gReproduceBug; // if not -1.
static bool gPreferSoftwareCodec;
+static bool gForceToUseHardwareCodec;
static bool gPlaybackAudio;
static bool gWriteMP4;
static bool gDisplayHistogram;
@@ -144,10 +145,18 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) {
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) {
rawSource = source;
} else {
+ int flags = 0;
+ if (gPreferSoftwareCodec) {
+ flags |= OMXCodec::kPreferSoftwareCodecs;
+ }
+ if (gForceToUseHardwareCodec) {
+ CHECK(!gPreferSoftwareCodec);
+ flags |= OMXCodec::kHardwareCodecsOnly;
+ }
rawSource = OMXCodec::Create(
client->interface(), meta, false /* createEncoder */, source,
NULL /* matchComponentName */,
- gPreferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0,
+ flags,
gSurface);
if (rawSource == NULL) {
@@ -545,6 +554,7 @@ static void usage(const char *me) {
fprintf(stderr, " -p(rofiles) dump decoder profiles supported\n");
fprintf(stderr, " -t(humbnail) extract video thumbnail or album art\n");
fprintf(stderr, " -s(oftware) prefer software codec\n");
+ fprintf(stderr, " -r(hardware) force to use hardware codec\n");
fprintf(stderr, " -o playback audio\n");
fprintf(stderr, " -w(rite) filename (write to .mp4 file)\n");
fprintf(stderr, " -k seek test\n");
@@ -566,6 +576,7 @@ int main(int argc, char **argv) {
gMaxNumFrames = 0;
gReproduceBug = -1;
gPreferSoftwareCodec = false;
+ gForceToUseHardwareCodec = false;
gPlaybackAudio = false;
gWriteMP4 = false;
gDisplayHistogram = false;
@@ -575,7 +586,7 @@ int main(int argc, char **argv) {
sp<LiveSession> liveSession;
int res;
- while ((res = getopt(argc, argv, "han:lm:b:ptsow:kxS")) >= 0) {
+ while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxS")) >= 0) {
switch (res) {
case 'a':
{
@@ -636,6 +647,12 @@ int main(int argc, char **argv) {
break;
}
+ case 'r':
+ {
+ gForceToUseHardwareCodec = true;
+ break;
+ }
+
case 'o':
{
gPlaybackAudio = true;
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 8bb305d4d55e..164acbcdf71f 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -190,9 +190,9 @@ public abstract class AccessibilityService extends Service {
* <li>
* Register for all event types with no notification timeout and keep track
* for the active window by calling
- * {@link AccessibilityEvent#getAccessibilityWindowId()} of the last received
+ * {@link AccessibilityEvent#getWindowId()} of the last received
* event and compare this with the
- * {@link AccessibilityNodeInfo#getAccessibilityWindowId()} before calling
+ * {@link AccessibilityNodeInfo#getWindowId()} before calling
* retrieval methods on the latter.
* </li>
* <li>
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 19f0bf033a78..8b4e7aee7398 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -47,7 +47,9 @@ interface IAccessibilityServiceConnection {
/**
* Finds {@link AccessibilityNodeInfo}s by View text. The match is case
- * insensitive containment.
+ * insensitive containment. The search is performed in the window whose
+ * id is specified and starts from the View whose accessibility id is
+ * specified.
* <p>
* <strong>
* It is a client responsibility to recycle the received infos by
@@ -57,12 +59,35 @@ interface IAccessibilityServiceConnection {
* </p>
*
* @param text The searched text.
+ * @param accessibilityId The id of the view from which to start searching.
+ * Use {@link android.view.View#NO_ID} to start from the root.
* @return A list of node info.
*/
- List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(String text);
+ List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(String text,
+ int accessibilityWindowId, int accessibilityViewId);
/**
- * Finds an {@link AccessibilityNodeInfo} by View id.
+ * Finds {@link AccessibilityNodeInfo}s by View text. The match is case
+ * insensitive containment. The search is performed in the currently
+ * active window and start from the root View in the window.
+ * <p>
+ * <strong>
+ * It is a client responsibility to recycle the received infos by
+ * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
+ * of multiple instances.
+ * </strong>
+ * </p>
+ *
+ * @param text The searched text.
+ * @param accessibilityId The id of the view from which to start searching.
+ * Use {@link android.view.View#NO_ID} to start from the root.
+ * @return A list of node info.
+ */
+ List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow(String text);
+
+ /**
+ * Finds an {@link AccessibilityNodeInfo} by View id. The search is performed
+ * in the currently active window and start from the root View in the window.
* <p>
* <strong>
* It is a client responsibility to recycle the received info by
@@ -74,7 +99,7 @@ interface IAccessibilityServiceConnection {
* @param id The id of the node.
* @return The node info.
*/
- AccessibilityNodeInfo findAccessibilityNodeInfoByViewId(int viewId);
+ AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId);
/**
* Performs an accessibility action on an {@link AccessibilityNodeInfo}.
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index f2be9ad9ba3f..557c8710c26b 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -244,12 +244,12 @@ final class FragmentState implements Parcelable {
* on {@link ListFragment} for most of its work. Note the implementation of
* clicking an item: depending on the current activity's layout, it can either
* create and display a new fragment to show the details in-place (more about
- * this later), or start a new activity show the details.</p>
+ * this later), or start a new activity to show the details.</p>
*
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
* titles}
*
- * <p>The details fragment showing the contents of selected item here just
+ * <p>The details fragment showing the contents of a selected item just
* displays a string of text based on an index of a string array built in to
* the app:</p>
*
@@ -257,7 +257,7 @@ final class FragmentState implements Parcelable {
* details}
*
* <p>In this case when the user clicks on a title, there is no details
- * container in the current activity, so the title title fragment's click code will
+ * container in the current activity, so the titles fragment's click code will
* launch a new activity to display the details fragment:</p>
*
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 33c2937aa983..1cd8ec0f5b4a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -925,6 +925,26 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports portrait orientation
+ * screens. For backwards compatibility, you can assume that if neither
+ * this nor {@link #FEATURE_SCREEN_LANDSCAPE} is set then the device supports
+ * both portrait and landscape.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_SCREEN_PORTRAIT = "android.hardware.screen.portrait";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports landscape orientation
+ * screens. For backwards compatibility, you can assume that if neither
+ * this nor {@link #FEATURE_SCREEN_PORTRAIT} is set then the device supports
+ * both portrait and landscape.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_SCREEN_LANDSCAPE = "android.hardware.screen.landscape";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports live wallpapers.
*/
@SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 906a5649880f..9bd45d347e0f 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -277,24 +277,24 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public int compatSmallestScreenWidthDp;
/**
- * @hide
+ * @hide Do not use. Implementation not finished.
*/
- public static final int LAYOUT_DIRECTION_UNDEFINED = -1;
+ public static final int TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE = -1;
/**
- * @hide
+ * @hide Do not use. Implementation not finished.
*/
- public static final int LAYOUT_DIRECTION_LTR = 0;
+ public static final int TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE = 0;
/**
- * @hide
+ * @hide Do not use. Implementation not finished.
*/
- public static final int LAYOUT_DIRECTION_RTL = 1;
+ public static final int TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE = 1;
/**
- * @hide The layout direction associated to the current Locale
+ * @hide The text layout direction associated to the current Locale
*/
- public int layoutDirection;
+ public int textLayoutDirection;
/**
* @hide Internal book-keeping.
@@ -322,7 +322,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
mnc = o.mnc;
if (o.locale != null) {
locale = (Locale) o.locale.clone();
- layoutDirection = o.layoutDirection;
+ textLayoutDirection = o.textLayoutDirection;
}
userSetLocale = o.userSetLocale;
touchscreen = o.touchscreen;
@@ -358,6 +358,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
} else {
sb.append(" (no locale)");
}
+ switch (textLayoutDirection) {
+ case TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE: sb.append(" ?layoutdir"); break;
+ case TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE: sb.append(" rtl"); break;
+ default: sb.append(" layoutdir="); sb.append(textLayoutDirection); break;
+ }
if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
} else {
@@ -450,11 +455,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration
case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
default: sb.append("/"); sb.append(navigationHidden); break;
}
- switch (layoutDirection) {
- case LAYOUT_DIRECTION_UNDEFINED: sb.append(" ?layoutdir"); break;
- case LAYOUT_DIRECTION_LTR: sb.append(" ltr"); break;
- case LAYOUT_DIRECTION_RTL: sb.append(" rtl"); break;
- }
if (seq != 0) {
sb.append(" s.");
sb.append(seq);
@@ -483,8 +483,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
+ textLayoutDirection = TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
seq = 0;
- layoutDirection = LAYOUT_DIRECTION_LTR;
}
/** {@hide} */
@@ -519,7 +519,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
changed |= ActivityInfo.CONFIG_LOCALE;
locale = delta.locale != null
? (Locale) delta.locale.clone() : null;
- layoutDirection = getLayoutDirectionFromLocale(locale);
+ textLayoutDirection = getLayoutDirectionFromLocale(locale);
}
if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
{
@@ -611,23 +611,25 @@ public final class Configuration implements Parcelable, Comparable<Configuration
/**
* Return the layout direction for a given Locale
* @param locale the Locale for which we want the layout direction. Can be null.
- * @return the layout direction. This may be one of {@link #LAYOUT_DIRECTION_UNDEFINED},
- * {@link #LAYOUT_DIRECTION_LTR} or {@link #LAYOUT_DIRECTION_RTL}.
+ * @return the layout direction. This may be one of:
+ * {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or
+ * {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
+ * {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
*
* @hide
*/
public static int getLayoutDirectionFromLocale(Locale locale) {
- if (locale == null || locale.equals(Locale.ROOT)) return LAYOUT_DIRECTION_UNDEFINED;
+ if (locale == null || locale.equals(Locale.ROOT)) return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
// Be careful: this code will need to be changed when vertical scripts will be supported
// OR if ICU4C is updated to have the "likelySubtags" file
switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) {
case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
- return LAYOUT_DIRECTION_LTR;
+ return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
- return LAYOUT_DIRECTION_RTL;
+ return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
default:
- return LAYOUT_DIRECTION_UNDEFINED;
+ return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
}
}
@@ -810,7 +812,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
dest.writeInt(compatScreenWidthDp);
dest.writeInt(compatScreenHeightDp);
dest.writeInt(compatSmallestScreenWidthDp);
- dest.writeInt(layoutDirection);
+ dest.writeInt(textLayoutDirection);
dest.writeInt(seq);
}
@@ -838,7 +840,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
compatScreenWidthDp = source.readInt();
compatScreenHeightDp = source.readInt();
compatSmallestScreenWidthDp = source.readInt();
- layoutDirection = source.readInt();
+ textLayoutDirection = source.readInt();
seq = source.readInt();
}
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 55850c90ca32..6f922476d06c 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -63,6 +63,7 @@ public class EthernetDataTracker implements NetworkStateTracker {
private Context mContext;
private static EthernetDataTracker sInstance;
+ private static String sIfaceMatch = "";
private static String mIface = "";
private static class InterfaceObserver extends INetworkManagementEventObserver.Stub {
@@ -96,7 +97,7 @@ public class EthernetDataTracker implements NetworkStateTracker {
}
private void interfaceAdded(String iface) {
- if (!iface.matches("eth\\d"))
+ if (!iface.matches(sIfaceMatch))
return;
Log.d(TAG, "Adding " + iface);
@@ -187,6 +188,22 @@ public class EthernetDataTracker implements NetworkStateTracker {
} catch (RemoteException e) {
Log.e(TAG, "Could not register InterfaceObserver " + e);
}
+
+ // connect to an ethernet interface that already exists
+ sIfaceMatch = context.getResources().getString(
+ com.android.internal.R.string.config_ethernet_iface_regex);
+ try {
+ final String[] ifaces = service.listInterfaces();
+ for (String iface : ifaces) {
+ if (iface.matches(sIfaceMatch)) {
+ mIface = iface;
+ reconnect();
+ break;
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not get list of interfaces " + e);
+ }
}
/**
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 8e50cd5577e3..5c4b258a8fda 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -240,7 +240,6 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory {
/**
* Sets the {@link TrustManager}s to be used for connections made by this factory.
- * @hide
*/
public void setTrustManagers(TrustManager[] trustManager) {
mTrustManagers = trustManager;
@@ -253,7 +252,6 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory {
/**
* Sets the {@link KeyManager}s to be used for connections made by this factory.
- * @hide
*/
public void setKeyManagers(KeyManager[] keyManagers) {
mKeyManagers = keyManagers;
diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl
index b66035ff881e..aa5937ee9deb 100644
--- a/core/java/android/nfc/INfcTag.aidl
+++ b/core/java/android/nfc/INfcTag.aidl
@@ -43,7 +43,6 @@ interface INfcTag
int formatNdef(int nativeHandle, in byte[] key);
Tag rediscover(int nativehandle);
- void setIsoDepTimeout(int timeout);
- void setFelicaTimeout(int timeout);
+ int setTimeout(int technology, int timeout);
void resetTimeouts();
}
diff --git a/core/java/android/nfc/tech/IsoDep.java b/core/java/android/nfc/tech/IsoDep.java
index 38b2bbd9e7ea..d02086ffcf1f 100644
--- a/core/java/android/nfc/tech/IsoDep.java
+++ b/core/java/android/nfc/tech/IsoDep.java
@@ -16,6 +16,7 @@
package android.nfc.tech;
+import android.nfc.ErrorCodes;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.RemoteException;
@@ -90,7 +91,10 @@ public final class IsoDep extends BasicTagTechnology {
*/
public void setTimeout(int timeout) {
try {
- mTag.getTagService().setIsoDepTimeout(timeout);
+ int err = mTag.getTagService().setTimeout(TagTechnology.ISO_DEP, timeout);
+ if (err != ErrorCodes.SUCCESS) {
+ throw new IllegalArgumentException("The supplied timeout is not valid");
+ }
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
}
diff --git a/core/java/android/nfc/tech/MifareClassic.java b/core/java/android/nfc/tech/MifareClassic.java
index c4b771878ce2..5cafe5ba6126 100644
--- a/core/java/android/nfc/tech/MifareClassic.java
+++ b/core/java/android/nfc/tech/MifareClassic.java
@@ -16,9 +16,11 @@
package android.nfc.tech;
+import android.nfc.ErrorCodes;
import android.nfc.Tag;
import android.nfc.TagLostException;
import android.os.RemoteException;
+import android.util.Log;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -69,6 +71,8 @@ import java.nio.ByteOrder;
* require the {@link android.Manifest.permission#NFC} permission.
*/
public final class MifareClassic extends BasicTagTechnology {
+ private static final String TAG = "NFC";
+
/**
* The default factory key.
*/
@@ -568,6 +572,31 @@ public final class MifareClassic extends BasicTagTechnology {
return transceive(data, true);
}
+ /**
+ * Set the timeout of {@link #transceive} in milliseconds.
+ * <p>The timeout only applies to MifareUltralight {@link #transceive},
+ * and is reset to a default value when {@link #close} is called.
+ * <p>Setting a longer timeout may be useful when performing
+ * transactions that require a long processing time on the tag
+ * such as key generation.
+ *
+ * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param timeout timeout value in milliseconds
+ * @hide
+ */
+ // TODO Unhide for ICS
+ public void setTimeout(int timeout) {
+ try {
+ int err = mTag.getTagService().setTimeout(TagTechnology.MIFARE_CLASSIC, timeout);
+ if (err != ErrorCodes.SUCCESS) {
+ throw new IllegalArgumentException("The supplied timeout is not valid");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "NFC service dead", e);
+ }
+ }
+
private static void validateSector(int sector) {
// Do not be too strict on upper bounds checking, since some cards
// have more addressable memory than they report. For example,
diff --git a/core/java/android/nfc/tech/MifareUltralight.java b/core/java/android/nfc/tech/MifareUltralight.java
index 6c2754bcc05d..3d4cdd1a8dff 100644
--- a/core/java/android/nfc/tech/MifareUltralight.java
+++ b/core/java/android/nfc/tech/MifareUltralight.java
@@ -16,10 +16,12 @@
package android.nfc.tech;
+import android.nfc.ErrorCodes;
import android.nfc.Tag;
import android.nfc.TagLostException;
import android.os.Bundle;
import android.os.RemoteException;
+import android.util.Log;
import java.io.IOException;
@@ -57,6 +59,8 @@ import java.io.IOException;
* require the {@link android.Manifest.permission#NFC} permission.
*/
public final class MifareUltralight extends BasicTagTechnology {
+ private static final String TAG = "NFC";
+
/** A MIFARE Ultralight compatible tag of unknown type */
public static final int TYPE_UNKNOWN = -1;
/** A MIFARE Ultralight tag */
@@ -208,6 +212,32 @@ public final class MifareUltralight extends BasicTagTechnology {
return transceive(data, true);
}
+ /**
+ * Set the timeout of {@link #transceive} in milliseconds.
+ * <p>The timeout only applies to MifareUltralight {@link #transceive},
+ * and is reset to a default value when {@link #close} is called.
+ * <p>Setting a longer timeout may be useful when performing
+ * transactions that require a long processing time on the tag
+ * such as key generation.
+ *
+ * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param timeout timeout value in milliseconds
+ * @hide
+ */
+ // TODO Unhide for ICS
+ public void setTimeout(int timeout) {
+ try {
+ int err = mTag.getTagService().setTimeout(
+ TagTechnology.MIFARE_ULTRALIGHT, timeout);
+ if (err != ErrorCodes.SUCCESS) {
+ throw new IllegalArgumentException("The supplied timeout is not valid");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "NFC service dead", e);
+ }
+ }
+
private static void validatePageIndex(int pageIndex) {
// Do not be too strict on upper bounds checking, since some cards
// may have more addressable memory than they report.
diff --git a/core/java/android/nfc/tech/NfcA.java b/core/java/android/nfc/tech/NfcA.java
index 1843eaed24db..08095e6cb163 100644
--- a/core/java/android/nfc/tech/NfcA.java
+++ b/core/java/android/nfc/tech/NfcA.java
@@ -16,9 +16,11 @@
package android.nfc.tech;
+import android.nfc.ErrorCodes;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.RemoteException;
+import android.util.Log;
import java.io.IOException;
@@ -33,6 +35,8 @@ import java.io.IOException;
* require the {@link android.Manifest.permission#NFC} permission.
*/
public final class NfcA extends BasicTagTechnology {
+ private static final String TAG = "NFC";
+
/** @hide */
public static final String EXTRA_SAK = "sak";
/** @hide */
@@ -112,4 +116,29 @@ public final class NfcA extends BasicTagTechnology {
public byte[] transceive(byte[] data) throws IOException {
return transceive(data, true);
}
+
+ /**
+ * Set the timeout of {@link #transceive} in milliseconds.
+ * <p>The timeout only applies to NfcA {@link #transceive}, and is
+ * reset to a default value when {@link #close} is called.
+ * <p>Setting a longer timeout may be useful when performing
+ * transactions that require a long processing time on the tag
+ * such as key generation.
+ *
+ * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param timeout timeout value in milliseconds
+ * @hide
+ */
+ // TODO Unhide for ICS
+ public void setTimeout(int timeout) {
+ try {
+ int err = mTag.getTagService().setTimeout(TagTechnology.NFC_A, timeout);
+ if (err != ErrorCodes.SUCCESS) {
+ throw new IllegalArgumentException("The supplied timeout is not valid");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "NFC service dead", e);
+ }
+ }
}
diff --git a/core/java/android/nfc/tech/NfcF.java b/core/java/android/nfc/tech/NfcF.java
index 250c9b31cf0d..85abf89e6dfd 100644
--- a/core/java/android/nfc/tech/NfcF.java
+++ b/core/java/android/nfc/tech/NfcF.java
@@ -16,6 +16,7 @@
package android.nfc.tech;
+import android.nfc.ErrorCodes;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.RemoteException;
@@ -131,7 +132,10 @@ public final class NfcF extends BasicTagTechnology {
// TODO Unhide for ICS
public void setTimeout(int timeout) {
try {
- mTag.getTagService().setFelicaTimeout(timeout);
+ int err = mTag.getTagService().setTimeout(TagTechnology.NFC_F, timeout);
+ if (err != ErrorCodes.SUCCESS) {
+ throw new IllegalArgumentException("The supplied timeout is not valid");
+ }
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 8ff5beb035cc..1b28aa2bcc6b 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -16,6 +16,8 @@
package android.os;
+import com.android.internal.telephony.TelephonyProperties;
+
/**
* Information about the current build, extracted from system properties.
*/
@@ -56,8 +58,16 @@ public class Build {
/** The system bootloader version number. */
public static final String BOOTLOADER = getString("ro.bootloader");
- /** The radio firmware version number. */
- public static final String RADIO = getString("gsm.version.baseband");
+ /**
+ * The radio firmware version number.
+ *
+ * @deprecated The radio firmware version is frequently not
+ * available when this class is initialized, leading to a blank or
+ * "unknown" value for this string. Use
+ * {@link #getRadioVersion} instead.
+ */
+ @Deprecated
+ public static final String RADIO = getString(TelephonyProperties.PROPERTY_BASEBAND_VERSION);
/** The name of the hardware (from the kernel command line or /proc). */
public static final String HARDWARE = getString("ro.hardware");
@@ -243,6 +253,26 @@ public class Build {
* later. Applications that don't support a screen size at least as
* large as the current screen will provide the user with a UI to
* switch them in to screen size compatibility mode.</p>
+ *
+ * <p>This version introduces new screen size resource qualifiers
+ * based on the screen size in dp: see
+ * {@link android.content.res.Configuration#screenWidthDp},
+ * {@link android.content.res.Configuration#screenHeightDp}, and
+ * {@link android.content.res.Configuration#smallestScreenWidthDp}.
+ * Supplying these in &lt;supports-screens&gt; as per
+ * {@link android.content.pm.ApplicationInfo#requiresSmallestWidthDp},
+ * {@link android.content.pm.ApplicationInfo#compatibleWidthLimitDp}, and
+ * {@link android.content.pm.ApplicationInfo#largestWidthLimitDp} is
+ * preferred over the older screen size buckets and for older devices
+ * the appropriate buckets will be inferred from them.</p>
+ *
+ * <p>New {@link android.content.pm.PackageManager#FEATURE_SCREEN_PORTRAIT}
+ * and {@link android.content.pm.PackageManager#FEATURE_SCREEN_LANDSCAPE}
+ * features are introduced in this release. Applications that target
+ * previous platform versions are assumed to require both portrait and
+ * landscape support in the device; when targeting Honeycomb MR1 or
+ * greater the application is responsible for specifying any specific
+ * orientation it requires.</p>
*/
public static final int HONEYCOMB_MR2 = 13;
@@ -266,6 +296,14 @@ public class Build {
public static final String USER = getString("ro.build.user");
public static final String HOST = getString("ro.build.host");
+ /**
+ * Returns the version string for the radio firmware. May return
+ * null (if, for instance, the radio is not currently on).
+ */
+ public static String getRadioVersion() {
+ return SystemProperties.get(TelephonyProperties.PROPERTY_BASEBAND_VERSION, null);
+ }
+
private static String getString(String property) {
return SystemProperties.get(property, UNKNOWN);
}
diff --git a/core/java/android/pim/RecurrenceSet.java b/core/java/android/pim/RecurrenceSet.java
index fdd078311316..b7fb3200dcd3 100644
--- a/core/java/android/pim/RecurrenceSet.java
+++ b/core/java/android/pim/RecurrenceSet.java
@@ -18,7 +18,7 @@ package android.pim;
import android.content.ContentValues;
import android.database.Cursor;
-import android.provider.Calendar;
+import android.provider.CalendarContract;
import android.text.TextUtils;
import android.text.format.Time;
import android.util.Log;
@@ -50,10 +50,10 @@ public class RecurrenceSet {
*/
public RecurrenceSet(ContentValues values)
throws EventRecurrence.InvalidFormatException {
- String rruleStr = values.getAsString(Calendar.Events.RRULE);
- String rdateStr = values.getAsString(Calendar.Events.RDATE);
- String exruleStr = values.getAsString(Calendar.Events.EXRULE);
- String exdateStr = values.getAsString(Calendar.Events.EXDATE);
+ String rruleStr = values.getAsString(CalendarContract.Events.RRULE);
+ String rdateStr = values.getAsString(CalendarContract.Events.RDATE);
+ String exruleStr = values.getAsString(CalendarContract.Events.EXRULE);
+ String exdateStr = values.getAsString(CalendarContract.Events.EXDATE);
init(rruleStr, rdateStr, exruleStr, exdateStr);
}
@@ -68,10 +68,10 @@ public class RecurrenceSet {
*/
public RecurrenceSet(Cursor cursor)
throws EventRecurrence.InvalidFormatException {
- int rruleColumn = cursor.getColumnIndex(Calendar.Events.RRULE);
- int rdateColumn = cursor.getColumnIndex(Calendar.Events.RDATE);
- int exruleColumn = cursor.getColumnIndex(Calendar.Events.EXRULE);
- int exdateColumn = cursor.getColumnIndex(Calendar.Events.EXDATE);
+ int rruleColumn = cursor.getColumnIndex(CalendarContract.Events.RRULE);
+ int rdateColumn = cursor.getColumnIndex(CalendarContract.Events.RDATE);
+ int exruleColumn = cursor.getColumnIndex(CalendarContract.Events.EXRULE);
+ int exdateColumn = cursor.getColumnIndex(CalendarContract.Events.EXDATE);
String rruleStr = cursor.getString(rruleColumn);
String rdateStr = cursor.getString(rdateColumn);
String exruleStr = cursor.getString(exruleColumn);
@@ -208,7 +208,7 @@ public class RecurrenceSet {
start.timezone = Time.TIMEZONE_UTC;
}
long millis = start.toMillis(false /* use isDst */);
- values.put(Calendar.Events.DTSTART, millis);
+ values.put(CalendarContract.Events.DTSTART, millis);
if (millis == -1) {
if (false) {
Log.d(TAG, "DTSTART is out of range: " + component.toString());
@@ -216,13 +216,13 @@ public class RecurrenceSet {
return false;
}
- values.put(Calendar.Events.RRULE, rrule);
- values.put(Calendar.Events.RDATE, rdate);
- values.put(Calendar.Events.EXRULE, exrule);
- values.put(Calendar.Events.EXDATE, exdate);
- values.put(Calendar.Events.EVENT_TIMEZONE, tzid);
- values.put(Calendar.Events.DURATION, duration);
- values.put(Calendar.Events.ALL_DAY, allDay ? 1 : 0);
+ values.put(CalendarContract.Events.RRULE, rrule);
+ values.put(CalendarContract.Events.RDATE, rdate);
+ values.put(CalendarContract.Events.EXRULE, exrule);
+ values.put(CalendarContract.Events.EXDATE, exdate);
+ values.put(CalendarContract.Events.EVENT_TIMEZONE, tzid);
+ values.put(CalendarContract.Events.DURATION, duration);
+ values.put(CalendarContract.Events.ALL_DAY, allDay ? 1 : 0);
return true;
}
@@ -230,14 +230,14 @@ public class RecurrenceSet {
public static boolean populateComponent(Cursor cursor,
ICalendar.Component component) {
- int dtstartColumn = cursor.getColumnIndex(Calendar.Events.DTSTART);
- int durationColumn = cursor.getColumnIndex(Calendar.Events.DURATION);
- int tzidColumn = cursor.getColumnIndex(Calendar.Events.EVENT_TIMEZONE);
- int rruleColumn = cursor.getColumnIndex(Calendar.Events.RRULE);
- int rdateColumn = cursor.getColumnIndex(Calendar.Events.RDATE);
- int exruleColumn = cursor.getColumnIndex(Calendar.Events.EXRULE);
- int exdateColumn = cursor.getColumnIndex(Calendar.Events.EXDATE);
- int allDayColumn = cursor.getColumnIndex(Calendar.Events.ALL_DAY);
+ int dtstartColumn = cursor.getColumnIndex(CalendarContract.Events.DTSTART);
+ int durationColumn = cursor.getColumnIndex(CalendarContract.Events.DURATION);
+ int tzidColumn = cursor.getColumnIndex(CalendarContract.Events.EVENT_TIMEZONE);
+ int rruleColumn = cursor.getColumnIndex(CalendarContract.Events.RRULE);
+ int rdateColumn = cursor.getColumnIndex(CalendarContract.Events.RDATE);
+ int exruleColumn = cursor.getColumnIndex(CalendarContract.Events.EXRULE);
+ int exdateColumn = cursor.getColumnIndex(CalendarContract.Events.EXDATE);
+ int allDayColumn = cursor.getColumnIndex(CalendarContract.Events.ALL_DAY);
long dtstart = -1;
@@ -299,16 +299,16 @@ public class RecurrenceSet {
public static boolean populateComponent(ContentValues values,
ICalendar.Component component) {
long dtstart = -1;
- if (values.containsKey(Calendar.Events.DTSTART)) {
- dtstart = values.getAsLong(Calendar.Events.DTSTART);
+ if (values.containsKey(CalendarContract.Events.DTSTART)) {
+ dtstart = values.getAsLong(CalendarContract.Events.DTSTART);
}
- String duration = values.getAsString(Calendar.Events.DURATION);
- String tzid = values.getAsString(Calendar.Events.EVENT_TIMEZONE);
- String rruleStr = values.getAsString(Calendar.Events.RRULE);
- String rdateStr = values.getAsString(Calendar.Events.RDATE);
- String exruleStr = values.getAsString(Calendar.Events.EXRULE);
- String exdateStr = values.getAsString(Calendar.Events.EXDATE);
- Integer allDayInteger = values.getAsInteger(Calendar.Events.ALL_DAY);
+ String duration = values.getAsString(CalendarContract.Events.DURATION);
+ String tzid = values.getAsString(CalendarContract.Events.EVENT_TIMEZONE);
+ String rruleStr = values.getAsString(CalendarContract.Events.RRULE);
+ String rdateStr = values.getAsString(CalendarContract.Events.RDATE);
+ String exruleStr = values.getAsString(CalendarContract.Events.EXRULE);
+ String exdateStr = values.getAsString(CalendarContract.Events.EXDATE);
+ Integer allDayInteger = values.getAsInteger(CalendarContract.Events.ALL_DAY);
boolean allDay = (null != allDayInteger) ? (allDayInteger == 1) : false;
if ((dtstart == -1) ||
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/CalendarContract.java
index bb6ed9c82b7c..3db1827b1dc2 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -39,11 +39,55 @@ import android.text.format.Time;
import android.util.Log;
/**
- * The Calendar provider contains all calendar events.
+ * <p>
+ * The contract between the calendar provider and applications. Contains
+ * definitions for the supported URIs and data columns.
+ * </p>
+ * <h3>Overview</h3>
+ * <p>
+ * CalendarContract defines the data model of calendar and event related
+ * information. This data is stored in a number of tables:
+ * </p>
+ * <ul>
+ * <li>The {@link Calendars} table holds the calendar specific information. Each
+ * row in this table contains the details for a single calendar, such as the
+ * name, color, sync info, etc.</li>
+ * <li>The {@link Events} table holds the event specific information. Each row
+ * in this table has the info for a single event. It contains information such
+ * as event title, location, start time, end time, etc. The event can occur
+ * one-time or can recur multiple times. Attendees, reminders, and extended
+ * properties are stored on separate tables and reference the {@link Events#_ID}
+ * to link them with the event.</li>
+ * <li>The {@link Instances} table holds the start and end time for occurrences
+ * of an event. Each row in this table represents a single occurrence. For
+ * one-time events there will be a 1:1 mapping of instances to events. For
+ * recurring events, multiple rows will automatically be generated which
+ * correspond to multiple occurrences of that event.</li>
+ * <li>The {@link Attendees} table holds the event attendee or guest
+ * information. Each row represents a single guest of an event. It specifies the
+ * type of guest they are and their attendance response for the event.</li>
+ * <li>The {@link Reminders} table holds the alert/notification data. Each row
+ * represents a single alert for an event. An event can have multiple reminders.
+ * The number of reminders per event is specified in
+ * {@link Calendars#MAX_REMINDERS} which is set by the Sync Adapter that owns
+ * the given calendar. Reminders are specified in minutes before the event and
+ * have a type.</li>
+ * <li>The {@link ExtendedProperties} table hold opaque data fields used by the
+ * sync adapter. The provider takes no action with items in this table except to
+ * delete them when their related events are deleted.</li>
+ * </ul>
+ * <p>
+ * Other tables include:
+ * </p>
+ * <ul>
+ * <li>
+ * {@link SyncState}, which contains free-form data maintained by the sync
+ * adapters</li>
+ * </ul>
*
* @hide
*/
-public final class Calendar {
+public final class CalendarContract {
private static final String TAG = "Calendar";
/**
@@ -178,9 +222,8 @@ public final class Calendar {
* have specific uses which are expected to be consistent by the app and
* sync adapter.
*
- * @hide
*/
- public interface SyncColumns extends CalendarSyncColumns {
+ protected interface SyncColumns extends CalendarSyncColumns {
/**
* The account that was used to sync the entry to the device. If the
* account_type is not {@link #ACCOUNT_TYPE_LOCAL} then the name and
@@ -223,7 +266,7 @@ public final class Calendar {
/**
* If set to 1 this causes events on this calendar to be duplicated with
- * {@link EventsColumns#LAST_SYNCED} set to 1 whenever the event
+ * {@link Events#LAST_SYNCED} set to 1 whenever the event
* transitions from non-dirty to dirty. The duplicated event will not be
* expanded in the instances table and will only show up in sync adapter
* queries of the events table. It will also be deleted when the
@@ -236,7 +279,7 @@ public final class Calendar {
/**
* Columns specific to the Calendars Uri that other Uris can query.
*/
- private interface CalendarsColumns {
+ protected interface CalendarsColumns {
/**
* The color of the calendar
* <P>Type: INTEGER (color value)</P>
@@ -485,7 +528,7 @@ public final class Calendar {
*/
public static int deleteCalendarsForAccount(ContentResolver cr, Account account) {
// delete all calendars that match this account
- return Calendar.Calendars.delete(cr,
+ return CalendarContract.Calendars.delete(cr,
WHERE_DELETE_FOR_ACCOUNT,
new String[] { account.name, account.type });
}
@@ -549,7 +592,7 @@ public final class Calendar {
/**
* Columns from the Attendees table that other tables join into themselves.
*/
- private interface AttendeesColumns {
+ protected interface AttendeesColumns {
/**
* The id of the event. Column name.
@@ -639,7 +682,7 @@ public final class Calendar {
/**
* Columns from the Events table that other tables join into themselves.
*/
- private interface EventsColumns {
+ protected interface EventsColumns {
/**
* The {@link Calendars#_ID} of the calendar the event belongs to.
@@ -1525,7 +1568,7 @@ public final class Calendar {
* time zone for the instaces. These settings are stored using a key/value
* scheme.
*/
- private interface CalendarCacheColumns {
+ protected interface CalendarCacheColumns {
/**
* The key for the setting. Keys are defined in {@link CalendarCache}.
*/
@@ -1597,7 +1640,7 @@ public final class Calendar {
* the Instances table and these are all stored in the first (and only)
* row of the CalendarMetaData table.
*/
- private interface CalendarMetaDataColumns {
+ protected interface CalendarMetaDataColumns {
/**
* The local timezone that was used for precomputing the fields
* in the Instances table.
@@ -1637,7 +1680,7 @@ public final class Calendar {
public static final class CalendarMetaData implements CalendarMetaDataColumns, BaseColumns {
}
- private interface EventDaysColumns {
+ protected interface EventDaysColumns {
/**
* The Julian starting day number. Column name.
* <P>Type: INTEGER (int)</P>
@@ -1655,7 +1698,7 @@ public final class Calendar {
* Fields and helpers for querying for a list of days that contain events.
*/
public static final class EventDays implements EventDaysColumns {
- private static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ "/instances/groupbyday");
/**
@@ -1690,7 +1733,7 @@ public final class Calendar {
}
}
- private interface RemindersColumns {
+ protected interface RemindersColumns {
/**
* The event the reminder belongs to. Column name.
* <P>Type: INTEGER (foreign key to the Events table)</P>
@@ -1731,7 +1774,7 @@ public final class Calendar {
* Fields and helpers for accessing reminders for an event.
*/
public static final class Reminders implements BaseColumns, RemindersColumns, EventsColumns {
- private static final String REMINDERS_WHERE = Calendar.Reminders.EVENT_ID + "=?";
+ private static final String REMINDERS_WHERE = CalendarContract.Reminders.EVENT_ID + "=?";
/**
* The projection used by the reminders query.
*/
@@ -1755,7 +1798,7 @@ public final class Calendar {
}
}
- private interface CalendarAlertsColumns {
+ protected interface CalendarAlertsColumns {
/**
* The event that the alert belongs to. Column name.
* <P>Type: INTEGER (foreign key to the Events table)</P>
@@ -2023,7 +2066,7 @@ public final class Calendar {
}
Intent intent = new Intent(EVENT_REMINDER_ACTION);
- intent.setData(ContentUris.withAppendedId(Calendar.CONTENT_URI, alarmTime));
+ intent.setData(ContentUris.withAppendedId(CalendarContract.CONTENT_URI, alarmTime));
intent.putExtra(ALARM_TIME, alarmTime);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
manager.set(AlarmManager.RTC_WAKEUP, alarmTime, pi);
@@ -2069,7 +2112,7 @@ public final class Calendar {
}
}
- private interface ExtendedPropertiesColumns {
+ protected interface ExtendedPropertiesColumns {
/**
* The event the extended property belongs to. Column name.
* <P>Type: INTEGER (foreign key to the Events table)</P>
@@ -2122,13 +2165,13 @@ public final class Calendar {
* The content:// style URI for this table
*/
public static final Uri CONTENT_URI =
- Uri.withAppendedPath(Calendar.CONTENT_URI, CONTENT_DIRECTORY);
+ Uri.withAppendedPath(CalendarContract.CONTENT_URI, CONTENT_DIRECTORY);
}
/**
* Columns from the EventsRawTimes table
*/
- private interface EventsRawTimesColumns {
+ protected interface EventsRawTimesColumns {
/**
* The corresponding event id. Column name.
* <P>Type: INTEGER (long)</P>
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 6c14119aba2f..00e29984c6e7 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -6300,9 +6300,10 @@ public final class ContactsContract {
* <p>
* Example:
* <pre>
- * Uri uri = DataUsageFeedback.UPDATE_URI.buildUpon()
+ * Uri uri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
* .appendPath(TextUtils.join(",", dataIds))
- * .appendQueryParameter(DataUsageFeedback.METHOD, DataUsageFeedback.METHOD_CALL)
+ * .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
+ * DataUsageFeedback.USAGE_TYPE_CALL)
* .build();
* boolean successful = resolver.update(uri, new ContentValues(), null, null) > 0;
* </pre>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1025b20afec0..01e028e7c981 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1768,12 +1768,6 @@ public final class Settings {
public static final String UNLOCK_SOUND = "unlock_sound";
/**
- * True if we should appear as a PTP device instead of MTP.
- * @hide
- */
- public static final String USE_PTP_INTERFACE = "use_ptp_interface";
-
- /**
* Receive incoming SIP calls?
* 0 = no
* 1 = yes
@@ -1879,7 +1873,6 @@ public final class Settings {
LOCKSCREEN_SOUNDS_ENABLED,
SHOW_WEB_SUGGESTIONS,
NOTIFICATION_LIGHT_PULSE,
- USE_PTP_INTERFACE,
SIP_CALL_OPTIONS,
SIP_RECEIVE_CALLS,
POINTER_SPEED,
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 23fd96fbdd70..6823b73ba057 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -505,12 +505,14 @@ public class TextToSpeech {
// Try requested engine
if (connectToEngine(engine)) {
+ mCurrentEngine = engine;
return SUCCESS;
}
// Fall back to user's default engine if different from the already tested one
if (!engine.equals(defaultEngine)) {
if (connectToEngine(defaultEngine)) {
+ mCurrentEngine = engine;
return SUCCESS;
}
}
@@ -520,10 +522,12 @@ public class TextToSpeech {
if (!defaultEngine.equals(highestRanked)
&& !engine.equals(highestRanked)) {
if (connectToEngine(highestRanked)) {
+ mCurrentEngine = engine;
return SUCCESS;
}
}
+ dispatchOnInit(ERROR);
return ERROR;
}
@@ -534,10 +538,9 @@ public class TextToSpeech {
boolean bound = mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE);
if (!bound) {
Log.e(TAG, "Failed to bind to " + engine);
- dispatchOnInit(ERROR);
return false;
} else {
- mCurrentEngine = engine;
+ Log.i(TAG, "Sucessfully bound to " + engine);
return true;
}
}
@@ -1052,13 +1055,15 @@ public class TextToSpeech {
/**
* Sets the TTS engine to use.
*
+ * @deprecated This doesn't inform callers when the TTS engine has been
+ * initialized. {@link #TextToSpeech(Context, OnInitListener, String)}
+ * can be used with the appropriate engine name.
+ *
* @param enginePackageName The package name for the synthesis engine (e.g. "com.svox.pico")
*
* @return {@link #ERROR} or {@link #SUCCESS}.
*/
- // TODO: add @Deprecated{This method does not tell the caller when the new engine
- // has been initialized. You should create a new TextToSpeech object with the new
- // engine instead.}
+ @Deprecated
public int setEngineByPackageName(String enginePackageName) {
mRequestedEngine = enginePackageName;
return initTts();
diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java
index e8d74eb32893..715894f71406 100644
--- a/core/java/android/speech/tts/TtsEngines.java
+++ b/core/java/android/speech/tts/TtsEngines.java
@@ -48,14 +48,14 @@ public class TtsEngines {
}
/**
- * @return the default TTS engine. If the user has set a default, that
- * value is returned else the highest ranked engine is returned,
- * as per {@link EngineInfoComparator}.
+ * @return the default TTS engine. If the user has set a default, and the engine
+ * is available on the device, the default is returned. Otherwise,
+ * the highest ranked engine is returned as per {@link EngineInfoComparator}.
*/
public String getDefaultEngine() {
String engine = Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.TTS_DEFAULT_SYNTH);
- return engine != null ? engine : getHighestRankedEngineName();
+ return isEngineInstalled(engine) ? engine : getHighestRankedEngineName();
}
/**
@@ -124,7 +124,14 @@ public class TtsEngines {
public boolean isEngineEnabled(String engine) {
// System engines are enabled by default always.
EngineInfo info = getEngineInfo(engine);
- if (info != null && info.system) {
+ if (info == null) {
+ // The engine is not installed, and therefore cannot
+ // be enabled.
+ return false;
+ }
+
+ if (info.system) {
+ // All system engines are enabled by default.
return true;
}
@@ -141,6 +148,25 @@ public class TtsEngines {
return appInfo != null && (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
+ /**
+ * @return true if a given engine is installed on the system. Useful to deal
+ * with cases where an engine has been uninstalled by the user or removed
+ * for any other reason.
+ */
+ private boolean isEngineInstalled(String engine) {
+ if (engine == null) {
+ return false;
+ }
+
+ for (EngineInfo info : getEngines()) {
+ if (engine.equals(info.name)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private EngineInfo getEngineInfo(ResolveInfo resolve, PackageManager pm) {
ServiceInfo service = resolve.serviceInfo;
if (service != null) {
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index d5cad9634106..383bfb3b3137 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -166,6 +166,7 @@ class GLES20Canvas extends HardwareCanvas {
static native void nUpdateTextureLayer(int layerId, int width, int height, int surface);
static native void nDestroyLayer(int layerId);
static native void nDestroyLayerDeferred(int layerId);
+ static native boolean nCopyLayer(int layerId, int bitmap);
///////////////////////////////////////////////////////////////////////////
// Canvas management
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
index bc191a6fae9b..69dfc2bc5367 100644
--- a/core/java/android/view/GLES20Layer.java
+++ b/core/java/android/view/GLES20Layer.java
@@ -17,6 +17,8 @@
package android.view;
+import android.graphics.Bitmap;
+
/**
* An OpenGL ES 2.0 implementation of {@link HardwareLayer}.
*/
@@ -40,7 +42,10 @@ abstract class GLES20Layer extends HardwareLayer {
return mLayer;
}
-
+ boolean copyInto(Bitmap bitmap) {
+ return GLES20Canvas.nCopyLayer(mLayer, bitmap.mNativeBitmap);
+ }
+
@Override
void destroy() {
if (mFinalizer != null) mFinalizer.destroy();
diff --git a/core/java/android/view/Gravity.java b/core/java/android/view/Gravity.java
index 69e64898e343..63f5ec1659a6 100644
--- a/core/java/android/view/Gravity.java
+++ b/core/java/android/view/Gravity.java
@@ -151,13 +151,13 @@ public class Gravity
* width and height of the object.
* @param outRect Receives the computed frame of the object in its
* container.
- * @param isRtl Whether the layout is right-to-left.
+ * @param layoutDirection The layout direction.
*
* @hide
*/
public static void apply(int gravity, int w, int h, Rect container,
- Rect outRect, boolean isRtl) {
- int absGravity = getAbsoluteGravity(gravity, isRtl);
+ Rect outRect, int layoutDirection) {
+ int absGravity = getAbsoluteGravity(gravity, layoutDirection);
apply(absGravity, w, h, container, 0, 0, outRect);
}
@@ -347,18 +347,19 @@ public class Gravity
* if horizontal direction is LTR, then START will set LEFT and END will set RIGHT.
* if horizontal direction is RTL, then START will set RIGHT and END will set LEFT.
*
+ *
* @param gravity The gravity to convert to absolute (horizontal) values.
- * @param isRtl Whether the layout is right-to-left.
+ * @param layoutDirection The layout direction.
* @return gravity converted to absolute (horizontal) values.
*/
- public static int getAbsoluteGravity(int gravity, boolean isRtl) {
+ public static int getAbsoluteGravity(int gravity, int layoutDirection) {
int result = gravity;
// If layout is script specific and gravity is horizontal relative (START or END)
if ((result & RELATIVE_LAYOUT_DIRECTION) > 0) {
if ((result & Gravity.START) == Gravity.START) {
// Remove the START bit
result &= ~START;
- if (isRtl) {
+ if (layoutDirection == View.LAYOUT_DIRECTION_RTL) {
// Set the RIGHT bit
result |= RIGHT;
} else {
@@ -368,7 +369,7 @@ public class Gravity
} else if ((result & Gravity.END) == Gravity.END) {
// Remove the END bit
result &= ~END;
- if (isRtl) {
+ if (layoutDirection == View.LAYOUT_DIRECTION_RTL) {
// Set the LEFT bit
result |= LEFT;
} else {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 2611ec0752c2..5944bd493b53 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -17,6 +17,7 @@
package android.view;
+import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
@@ -204,8 +205,18 @@ public abstract class HardwareRenderer {
* @param surface The surface to update
*/
abstract void updateTextureLayer(HardwareLayer layer, int width, int height,
- SurfaceTexture surface);
-
+ SurfaceTexture surface);
+
+ /**
+ * Copies the content of the specified layer into the specified bitmap.
+ *
+ * @param layer The hardware layer to copy
+ * @param bitmap The bitmap to copy the layer into
+ *
+ * @return True if the copy was successful, false otherwise
+ */
+ abstract boolean copyLayer(HardwareLayer layer, Bitmap bitmap);
+
/**
* Initializes the hardware renderer for the specified surface and setup the
* renderer for drawing, if needed. This is invoked when the ViewAncestor has
@@ -814,6 +825,11 @@ public abstract class HardwareRenderer {
((GLES20TextureLayer) layer).update(width, height, surface.mSurfaceTexture);
}
+ @Override
+ boolean copyLayer(HardwareLayer layer, Bitmap bitmap) {
+ return ((GLES20Layer) layer).copyInto(bitmap);
+ }
+
static HardwareRenderer create(boolean translucent) {
if (GLES20Canvas.isAvailable()) {
return new Gl20Renderer(translucent);
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index bc1ad3c8e92c..4daa892d3e35 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -17,6 +17,7 @@
package android.view;
import android.content.Context;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.SurfaceTexture;
@@ -89,6 +90,8 @@ import android.util.Log;
* @see SurfaceTexture
*/
public class TextureView extends View {
+ private static final String LOG_TAG = "TextureView";
+
private HardwareLayer mLayer;
private SurfaceTexture mSurface;
private SurfaceTextureListener mListener;
@@ -148,7 +151,7 @@ public class TextureView extends View {
super.onAttachedToWindow();
if (!isHardwareAccelerated()) {
- Log.w("TextureView", "A TextureView or a subclass can only be "
+ Log.w(LOG_TAG, "A TextureView or a subclass can only be "
+ "used with hardware acceleration enabled.");
}
}
@@ -293,8 +296,95 @@ public class TextureView extends View {
}
/**
+ * <p>Returns a {@link android.graphics.Bitmap} representation of the content
+ * of the associated surface texture. If the surface texture is not available,
+ * this method returns null.</p>
+ *
+ * <p>The bitmap returned by this method uses the {@link Bitmap.Config#ARGB_8888}
+ * pixel format and its dimensions are the same as this view's.</p>
+ *
+ * <p><strong>Do not</strong> invoke this method from a drawing method
+ * ({@link #onDraw(android.graphics.Canvas)} for instance).</p>
+ *
+ * @return A valid {@link Bitmap.Config#ARGB_8888} bitmap, or null if the surface
+ * texture is not available or the width &lt;= 0 or the height &lt;= 0
+ *
+ * @see #isAvailable()
+ * @see #getBitmap(android.graphics.Bitmap)
+ * @see #getBitmap(int, int)
+ */
+ public Bitmap getBitmap() {
+ return getBitmap(getWidth(), getHeight());
+ }
+
+ /**
+ * <p>Returns a {@link android.graphics.Bitmap} representation of the content
+ * of the associated surface texture. If the surface texture is not available,
+ * this method returns null.</p>
+ *
+ * <p>The bitmap returned by this method uses the {@link Bitmap.Config#ARGB_8888}
+ * pixel format.</p>
+ *
+ * <p><strong>Do not</strong> invoke this method from a drawing method
+ * ({@link #onDraw(android.graphics.Canvas)} for instance).</p>
+ *
+ * @param width The width of the bitmap to create
+ * @param height The height of the bitmap to create
+ *
+ * @return A valid {@link Bitmap.Config#ARGB_8888} bitmap, or null if the surface
+ * texture is not available or width is &lt;= 0 or height is &lt;= 0
+ *
+ * @see #isAvailable()
+ * @see #getBitmap(android.graphics.Bitmap)
+ * @see #getBitmap()
+ */
+ public Bitmap getBitmap(int width, int height) {
+ if (isAvailable() && width > 0 && height > 0) {
+ return getBitmap(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888));
+ }
+ return null;
+ }
+
+ /**
+ * <p>Copies the content of this view's surface texture into the specified
+ * bitmap. If the surface texture is not available, the copy is not executed.
+ * The content of the surface texture will be scaled to fit exactly inside
+ * the specified bitmap.</p>
+ *
+ * <p><strong>Do not</strong> invoke this method from a drawing method
+ * ({@link #onDraw(android.graphics.Canvas)} for instance).</p>
+ *
+ * @param bitmap The bitmap to copy the content of the surface texture into,
+ * cannot be null, all configurations are supported
+ *
+ * @return The bitmap specified as a parameter
+ *
+ * @see #isAvailable()
+ * @see #getBitmap(int, int)
+ * @see #getBitmap()
+ */
+ public Bitmap getBitmap(Bitmap bitmap) {
+ if (bitmap != null && isAvailable()) {
+ mAttachInfo.mHardwareRenderer.copyLayer(mLayer, bitmap);
+ }
+ return bitmap;
+ }
+
+ /**
+ * Returns true if the {@link SurfaceTexture} associated with this
+ * TextureView is available for rendering. When this method returns
+ * true, {@link #getSurfaceTexture()} returns a valid surface texture.
+ */
+ public boolean isAvailable() {
+ return mSurface != null;
+ }
+
+ /**
* Returns the {@link SurfaceTexture} used by this view. This method
- * may return null if the view is not attached to a window.
+ * may return null if the view is not attached to a window or if the surface
+ * texture has not been initialized yet.
+ *
+ * @see #isAvailable()
*/
public SurfaceTexture getSurfaceTexture() {
return mSurface;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 441cdc14db8a..1dfb858e6ea2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3704,7 +3704,8 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
* The base implementation sets:
* <ul>
* <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
- * <li>{@link AccessibilityNodeInfo#setBounds(Rect)},</li>
+ * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
+ * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
* <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
* <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
* <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
@@ -3724,7 +3725,12 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
Rect bounds = mAttachInfo.mTmpInvalRect;
getDrawingRect(bounds);
- info.setBounds(bounds);
+ info.setBoundsInParent(bounds);
+
+ int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation;
+ getLocationOnScreen(locationOnScreen);
+ bounds.offset(locationOnScreen[0], locationOnScreen[1]);
+ info.setBoundsInScreen(bounds);
ViewParent parent = getParent();
if (parent instanceof View) {
@@ -4266,6 +4272,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
* {@link #LAYOUT_DIRECTION_INHERIT} or
* {@link #LAYOUT_DIRECTION_LOCALE}.
* @attr ref android.R.styleable#View_layoutDirection
+ *
* @hide
*/
@ViewDebug.ExportedProperty(category = "layout", mapping = {
@@ -4286,6 +4293,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
* {@link #LAYOUT_DIRECTION_INHERIT} or
* {@link #LAYOUT_DIRECTION_LOCALE}.
* @attr ref android.R.styleable#View_layoutDirection
+ *
* @hide
*/
@RemotableViewMethod
@@ -4294,6 +4302,37 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
}
/**
+ * Returns the resolved layout direction for this view.
+ *
+ * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
+ * {@link #LAYOUT_DIRECTION_LTR} id the layout direction is not RTL.
+ *
+ * @hide
+ */
+ @ViewDebug.ExportedProperty(category = "layout", mapping = {
+ @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
+ @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
+ })
+ public int getResolvedLayoutDirection() {
+ resolveLayoutDirection();
+ return ((mPrivateFlags2 & RESOLVED_LAYOUT_RTL) == RESOLVED_LAYOUT_RTL) ?
+ LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
+ }
+
+ /**
+ * <p>Indicates whether or not this view's layout is right-to-left. This is resolved from
+ * layout attribute and/or the inherited value from the parent.</p>
+ *
+ * @return true if the layout is right-to-left.
+ *
+ * @hide
+ */
+ @ViewDebug.ExportedProperty(category = "layout")
+ public boolean isLayoutRtl() {
+ return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
+ }
+
+ /**
* If this view doesn't do any drawing on its own, set this flag to
* allow further optimizations. By default, this flag is not set on
* View, but could be set on some View subclasses such as ViewGroup.
@@ -8451,6 +8490,40 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
}
/**
+ * Check if this view can be scrolled horizontally in a certain direction.
+ *
+ * @param direction Negative to check scrolling left, positive to check scrolling right.
+ * @return true if this view can be scrolled in the specified direction, false otherwise.
+ */
+ public boolean canScrollHorizontally(int direction) {
+ final int offset = computeHorizontalScrollOffset();
+ final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
+ if (range == 0) return false;
+ if (direction < 0) {
+ return offset > 0;
+ } else {
+ return offset < range - 1;
+ }
+ }
+
+ /**
+ * Check if this view can be scrolled vertically in a certain direction.
+ *
+ * @param direction Negative to check scrolling up, positive to check scrolling down.
+ * @return true if this view can be scrolled in the specified direction, false otherwise.
+ */
+ public boolean canScrollVertically(int direction) {
+ final int offset = computeVerticalScrollOffset();
+ final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
+ if (range == 0) return false;
+ if (direction < 0) {
+ return offset > 0;
+ } else {
+ return offset < range - 1;
+ }
+ }
+
+ /**
* <p>Request the drawing of the horizontal and the vertical scrollbar. The
* scrollbars are painted only if they have been awakened first.</p>
*
@@ -8673,8 +8746,9 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
switch (getLayoutDirection()) {
case LAYOUT_DIRECTION_INHERIT:
// If this is root view, no need to look at parent's layout dir.
- if (mParent != null && mParent instanceof ViewGroup &&
- ((ViewGroup) mParent).isLayoutRtl()) {
+ if (mParent != null &&
+ mParent instanceof ViewGroup &&
+ ((ViewGroup) mParent).getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
mPrivateFlags2 |= RESOLVED_LAYOUT_RTL;
}
break;
@@ -10197,17 +10271,6 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
}
/**
- * <p>Indicates whether or not this view's layout is right-to-left. This is resolved from
- * layout attribute and/or the inherited value from the parent.</p>
- *
- * @return true if the layout is right-to-left.
- */
- @ViewDebug.ExportedProperty(category = "layout")
- public boolean isLayoutRtl() {
- return (mPrivateFlags2 & RESOLVED_LAYOUT_RTL) == RESOLVED_LAYOUT_RTL;
- }
-
- /**
* Assign a size and position to a view and all of its
* descendants
*
@@ -10419,13 +10482,15 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
}
}
- /**
- * Check if a given Drawable is in RTL layout direction.
- *
- * @param who the recipient of the action
- */
- public boolean isLayoutRtl(Drawable who) {
- return (who == mBGDrawable) && isLayoutRtl();
+ /**
+ * Return the layout direction of a given Drawable.
+ *
+ * @param who the Drawable to query
+ *
+ * @hide
+ */
+ public int getResolvedLayoutDirection(Drawable who) {
+ return (who == mBGDrawable) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
}
/**
diff --git a/core/java/android/view/ViewAncestor.java b/core/java/android/view/ViewAncestor.java
index 17d745485130..914973ed41b1 100644
--- a/core/java/android/view/ViewAncestor.java
+++ b/core/java/android/view/ViewAncestor.java
@@ -136,6 +136,13 @@ public final class ViewAncestor extends Handler implements ViewParent,
static final ArrayList<ComponentCallbacks> sConfigCallbacks
= new ArrayList<ComponentCallbacks>();
+ /**
+ * Delay before dispatching an accessibility event that the window
+ * content has changed. The window content is considered changed
+ * after a layout pass.
+ */
+ private static final long SEND_WINDOW_CONTENT_CHANGED_DELAY_MILLIS = 500;
+
long mLastTrackballTime = 0;
final TrackballAxis mTrackballAxisX = new TrackballAxis();
final TrackballAxis mTrackballAxisY = new TrackballAxis();
@@ -277,6 +284,8 @@ public final class ViewAncestor extends Handler implements ViewParent,
AccessibilityInteractionConnectionManager mAccessibilityInteractionConnectionManager;
+ SendWindowContentChanged mSendWindowContentChanged;
+
private final int mDensity;
/**
@@ -1427,6 +1436,10 @@ public final class ViewAncestor extends Handler implements ViewParent,
if (triggerGlobalLayoutListener) {
attachInfo.mRecomputeGlobalAttributes = false;
attachInfo.mTreeObserver.dispatchOnGlobalLayout();
+
+ if (AccessibilityManager.getInstance(host.mContext).isEnabled()) {
+ postSendWindowContentChangedCallback();
+ }
}
if (computesInternalInsets) {
@@ -2086,6 +2099,7 @@ public final class ViewAncestor extends Handler implements ViewParent,
mAccessibilityInteractionConnectionManager.ensureNoConnection();
mAccessibilityManager.removeAccessibilityStateChangeListener(
mAccessibilityInteractionConnectionManager);
+ removeSendWindowContentChangedCallback();
mView = null;
mAttachInfo.mRootView = null;
@@ -3671,6 +3685,29 @@ public final class ViewAncestor extends Handler implements ViewParent,
}
}
+ /**
+ * Post a callback to send a
+ * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
+ */
+ private void postSendWindowContentChangedCallback() {
+ if (mSendWindowContentChanged == null) {
+ mSendWindowContentChanged = new SendWindowContentChanged();
+ } else {
+ removeCallbacks(mSendWindowContentChanged);
+ }
+ postDelayed(mSendWindowContentChanged, SEND_WINDOW_CONTENT_CHANGED_DELAY_MILLIS);
+ }
+
+ /**
+ * Remove a posted callback to send a
+ * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
+ */
+ private void removeSendWindowContentChangedCallback() {
+ if (mSendWindowContentChanged != null) {
+ removeCallbacks(mSendWindowContentChanged);
+ }
+ }
+
public boolean showContextMenuForChild(View originalView) {
return false;
}
@@ -4268,12 +4305,12 @@ public final class ViewAncestor extends Handler implements ViewParent,
}
}
- public void findAccessibilityNodeInfosByViewText(String text, int interactionId,
- IAccessibilityInteractionConnectionCallback callback) {
+ public void findAccessibilityNodeInfosByViewText(String text, int accessibilityId,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback) {
if (mViewAncestor.get() != null) {
getAccessibilityInteractionController()
- .findAccessibilityNodeInfosByViewTextClientThread(text, interactionId,
- callback);
+ .findAccessibilityNodeInfosByViewTextClientThread(text, accessibilityId,
+ interactionId, callback);
}
}
}
@@ -4414,13 +4451,15 @@ public final class ViewAncestor extends Handler implements ViewParent,
}
}
- public void findAccessibilityNodeInfosByViewTextClientThread(String text, int interactionId,
+ public void findAccessibilityNodeInfosByViewTextClientThread(String text,
+ int accessibilityViewId, int interactionId,
IAccessibilityInteractionConnectionCallback callback) {
Message message = Message.obtain();
message.what = DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT;
SomeArgs args = mPool.acquire();
args.arg1 = text;
- args.argi1 = interactionId;
+ args.argi1 = accessibilityViewId;
+ args.argi2 = interactionId;
args.arg2 = callback;
message.obj = args;
sendMessage(message);
@@ -4429,18 +4468,28 @@ public final class ViewAncestor extends Handler implements ViewParent,
public void findAccessibilityNodeInfosByViewTextUiThread(Message message) {
SomeArgs args = (SomeArgs) message.obj;
final String text = (String) args.arg1;
- final int interactionId = args.argi1;
+ final int accessibilityViewId = args.argi1;
+ final int interactionId = args.argi2;
final IAccessibilityInteractionConnectionCallback callback =
(IAccessibilityInteractionConnectionCallback) args.arg2;
mPool.release(args);
List<AccessibilityNodeInfo> infos = null;
try {
- View root = ViewAncestor.this.mView;
-
ArrayList<View> foundViews = mAttachInfo.mFocusablesTempList;
foundViews.clear();
+ View root = null;
+ if (accessibilityViewId != View.NO_ID) {
+ root = findViewByAccessibilityId(accessibilityViewId);
+ } else {
+ root = ViewAncestor.this.mView;
+ }
+
+ if (root == null) {
+ return;
+ }
+
root.findViewsWithText(foundViews, text);
if (foundViews.isEmpty()) {
return;
@@ -4577,4 +4626,12 @@ public final class ViewAncestor extends Handler implements ViewParent,
}
}
}
+
+ private class SendWindowContentChanged implements Runnable {
+ public void run() {
+ if (mView != null) {
+ mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ }
+ }
+ }
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index b0181bbc3de0..6b6aee3c37d0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -685,7 +685,19 @@ public interface WindowManager extends ViewManager {
// ----- HIDDEN FLAGS.
// These start at the high bit and go down.
-
+
+ /** Window flag: Enable touches to slide out of a window into neighboring
+ * windows in mid-gesture instead of being captured for the duration of
+ * the gesture.
+ *
+ * This flag changes the behavior of touch focus for this window only.
+ * Touches can slide out of the window but they cannot necessarily slide
+ * back in (unless the other window with touch focus permits it).
+ *
+ * {@hide}
+ */
+ public static final int FLAG_SLIPPERY = 0x04000000;
+
/**
* Flag for a window belonging to an activity that responds to {@link KeyEvent#KEYCODE_MENU}
* and therefore needs a Menu key. For devices where Menu is a physical button this flag is
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 06e4827ae371..5ef7763bff73 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -19,11 +19,10 @@ package android.view.accessibility;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.RemoteException;
import android.text.TextUtils;
-import android.view.View;
import java.util.ArrayList;
+import java.util.List;
/**
* This class represents accessibility events that are sent by the system when
@@ -130,7 +129,7 @@ import java.util.ArrayList;
* <p>
* <b>TRANSITION TYPES</b> <br>
* <p>
- * <b>Window state changed</b> - represents the event of opening/closing a
+ * <b>Window state changed</b> - represents the event of opening a
* {@link android.widget.PopupWindow}, {@link android.view.Menu},
* {@link android.app.Dialog}, etc. <br>
* Type: {@link #TYPE_WINDOW_STATE_CHANGED} <br>
@@ -140,6 +139,16 @@ import java.util.ArrayList;
* {@link #getEventTime()},
* {@link #getText()}
* <p>
+ * <b>Window content changed</b> - represents the event of change in the
+ * content of a window. This change can be adding/removing view, changing
+ * a view size, etc.<br>
+ * Type: {@link #TYPE_WINDOW_CONTENT_CHANGED} <br>
+ * Properties:
+ * {@link #getClassName()},
+ * {@link #getPackageName()},
+ * {@link #getEventTime()},
+ * {@link #getText()}
+ * <p>
* <b>NOTIFICATION TYPES</b> <br>
* <p>
* <b>Notification state changed</b> - represents the event showing/hiding
@@ -244,6 +253,11 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400;
/**
+ * Represents the event of changing the content of a window.
+ */
+ public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
+
+ /**
* Mask for {@link AccessibilityEvent} all types.
*
* @see #TYPE_VIEW_CLICKED
@@ -264,15 +278,11 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
private boolean mIsInPool;
private int mEventType;
- private int mSourceAccessibilityViewId = View.NO_ID;
- private int mSourceAccessibilityWindowId = View.NO_ID;
private CharSequence mPackageName;
private long mEventTime;
private final ArrayList<AccessibilityRecord> mRecords = new ArrayList<AccessibilityRecord>();
- private IAccessibilityServiceConnection mConnection;
-
/*
* Hide constructor from clients.
*/
@@ -288,10 +298,43 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
super.init(event);
mEventType = event.mEventType;
mEventTime = event.mEventTime;
- mSourceAccessibilityWindowId = event.mSourceAccessibilityWindowId;
- mSourceAccessibilityViewId = event.mSourceAccessibilityViewId;
mPackageName = event.mPackageName;
- mConnection = event.mConnection;
+ }
+
+ /**
+ * Sets the connection for interacting with the AccessibilityManagerService.
+ *
+ * @param connection The connection.
+ *
+ * @hide
+ */
+ @Override
+ public void setConnection(IAccessibilityServiceConnection connection) {
+ super.setConnection(connection);
+ List<AccessibilityRecord> records = mRecords;
+ final int recordCount = records.size();
+ for (int i = 0; i < recordCount; i++) {
+ AccessibilityRecord record = records.get(i);
+ record.setConnection(connection);
+ }
+ }
+
+ /**
+ * Sets if this instance is sealed.
+ *
+ * @param sealed Whether is sealed.
+ *
+ * @hide
+ */
+ @Override
+ public void setSealed(boolean sealed) {
+ super.setSealed(sealed);
+ List<AccessibilityRecord> records = mRecords;
+ final int recordCount = records.size();
+ for (int i = 0; i < recordCount; i++) {
+ AccessibilityRecord record = records.get(i);
+ record.setSealed(sealed);
+ }
}
/**
@@ -335,81 +378,6 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
}
/**
- * Sets the event source.
- *
- * @param source The source.
- *
- * @throws IllegalStateException If called from an AccessibilityService.
- */
- public void setSource(View source) {
- enforceNotSealed();
- if (source != null) {
- mSourceAccessibilityWindowId = source.getAccessibilityWindowId();
- mSourceAccessibilityViewId = source.getAccessibilityViewId();
- } else {
- mSourceAccessibilityWindowId = View.NO_ID;
- mSourceAccessibilityViewId = View.NO_ID;
- }
- }
-
- /**
- * Gets the {@link AccessibilityNodeInfo} of the event source.
- * <p>
- * <strong>
- * It is a client responsibility to recycle the received info by
- * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
- * of multiple instances.
- * </strong>
- * </p>
- * @return The info.
- */
- public AccessibilityNodeInfo getSource() {
- enforceSealed();
- if (mSourceAccessibilityWindowId == View.NO_ID
- || mSourceAccessibilityViewId == View.NO_ID) {
- return null;
- }
- try {
- return mConnection.findAccessibilityNodeInfoByAccessibilityId(
- mSourceAccessibilityWindowId, mSourceAccessibilityViewId);
- } catch (RemoteException e) {
- return null;
- }
- }
-
- /**
- * Gets the id of the window from which the event comes from.
- *
- * @return The window id.
- */
- public int getAccessibilityWindowId() {
- return mSourceAccessibilityWindowId;
- }
-
- /**
- * Sets the client token for the accessibility service that
- * provided this node info.
- *
- * @param connection The connection.
- *
- * @hide
- */
- public final void setConnection(IAccessibilityServiceConnection connection) {
- mConnection = connection;
- }
-
- /**
- * Gets the accessibility window id of the source window.
- *
- * @return The id.
- *
- * @hide
- */
- public int getSourceAccessibilityWindowId() {
- return mSourceAccessibilityWindowId;
- }
-
- /**
* Sets the event type.
*
* @param eventType The event type.
@@ -548,10 +516,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
@Override
protected void clear() {
super.clear();
- mConnection = null;
mEventType = 0;
- mSourceAccessibilityViewId = View.NO_ID;
- mSourceAccessibilityWindowId = View.NO_ID;
mPackageName = null;
mEventTime = 0;
while (!mRecords.isEmpty()) {
@@ -572,8 +537,6 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
}
setSealed(parcel.readInt() == 1);
mEventType = parcel.readInt();
- mSourceAccessibilityWindowId = parcel.readInt();
- mSourceAccessibilityViewId = parcel.readInt();
mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
mEventTime = parcel.readLong();
readAccessibilityRecordFromParcel(this, parcel);
@@ -583,6 +546,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
for (int i = 0; i < recordCount; i++) {
AccessibilityRecord record = AccessibilityRecord.obtain();
readAccessibilityRecordFromParcel(record, parcel);
+ // Do this to write the connection only once.
+ record.setConnection(mConnection);
mRecords.add(record);
}
}
@@ -606,6 +571,9 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
record.mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
record.mParcelableData = parcel.readParcelable(null);
parcel.readList(record.mText, null);
+ record.mSourceWindowId = parcel.readInt();
+ record.mSourceViewId = parcel.readInt();
+ record.mSealed = (parcel.readInt() == 1);
}
/**
@@ -620,8 +588,6 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
}
parcel.writeInt(isSealed() ? 1 : 0);
parcel.writeInt(mEventType);
- parcel.writeInt(mSourceAccessibilityWindowId);
- parcel.writeInt(mSourceAccessibilityViewId);
TextUtils.writeToParcel(mPackageName, parcel, 0);
parcel.writeLong(mEventTime);
writeAccessibilityRecordToParcel(this, parcel, flags);
@@ -654,6 +620,9 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
TextUtils.writeToParcel(record.mBeforeText, parcel, flags);
parcel.writeParcelable(record.mParcelableData, flags);
parcel.writeList(record.mText);
+ parcel.writeInt(record.mSourceWindowId);
+ parcel.writeInt(record.mSourceViewId);
+ parcel.writeInt(record.mSealed ? 1 : 0);
}
/**
@@ -672,8 +641,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
builder.append(super.toString());
if (DEBUG) {
builder.append("\n");
- builder.append("; sourceAccessibilityWindowId: ").append(mSourceAccessibilityWindowId);
- builder.append("; sourceAccessibilityViewId: ").append(mSourceAccessibilityViewId);
+ builder.append("; sourceWindowId: ").append(mSourceWindowId);
+ builder.append("; sourceViewId: ").append(mSourceViewId);
for (int i = 0; i < mRecords.size(); i++) {
AccessibilityRecord record = mRecords.get(i);
builder.append(" Record ");
@@ -733,6 +702,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
return "TYPE_TOUCH_EXPLORATION_GESTURE_START";
case TYPE_TOUCH_EXPLORATION_GESTURE_END:
return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
+ case TYPE_WINDOW_CONTENT_CHANGED:
+ return "TYPE_WINDOW_CONTENT_CHANGED";
default:
return null;
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 5fa65b450e42..18ef38af7476 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -26,6 +26,9 @@ import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.View;
+import java.util.Collections;
+import java.util.List;
+
/**
* This class represents a node of the screen content. From the point of
* view of an accessibility service the screen content is presented as tree
@@ -97,7 +100,8 @@ public class AccessibilityNodeInfo implements Parcelable {
private int mAccessibilityWindowId = View.NO_ID;
private int mParentAccessibilityViewId = View.NO_ID;
private int mBooleanProperties;
- private final Rect mBounds = new Rect();
+ private final Rect mBoundsInParent = new Rect();
+ private final Rect mBoundsInScreen = new Rect();
private CharSequence mPackageName;
private CharSequence mClassName;
@@ -132,7 +136,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*
* @return The window id.
*/
- public int getAccessibilityWindowId() {
+ public int getWindowId() {
return mAccessibilityWindowId;
}
@@ -163,12 +167,16 @@ public class AccessibilityNodeInfo implements Parcelable {
public AccessibilityNodeInfo getChild(int index) {
enforceSealed();
final int childAccessibilityViewId = mChildAccessibilityIds.get(index);
+ if (!canPerformRequestOverConnection(childAccessibilityViewId)) {
+ return null;
+ }
try {
return mConnection.findAccessibilityNodeInfoByAccessibilityId(mAccessibilityWindowId,
childAccessibilityViewId);
- } catch (RemoteException e) {
- return null;
+ } catch (RemoteException re) {
+ /* ignore*/
}
+ return null;
}
/**
@@ -230,12 +238,37 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public boolean performAction(int action) {
enforceSealed();
+ if (!canPerformRequestOverConnection(mAccessibilityViewId)) {
+ return false;
+ }
try {
return mConnection.performAccessibilityAction(mAccessibilityWindowId,
mAccessibilityViewId, action);
} catch (RemoteException e) {
- return false;
+ /* ignore */
}
+ return false;
+ }
+
+ /**
+ * Finds {@link AccessibilityNodeInfo}s by text. The match is case
+ * insensitive containment.
+ *
+ * @param text The searched text.
+ * @return A list of node info.
+ */
+ public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
+ enforceSealed();
+ if (!canPerformRequestOverConnection(mAccessibilityViewId)) {
+ return null;
+ }
+ try {
+ return mConnection.findAccessibilityNodeInfosByViewText(text, mAccessibilityWindowId,
+ mAccessibilityViewId);
+ } catch (RemoteException e) {
+ /* ignore */
+ }
+ return Collections.emptyList();
}
/**
@@ -251,12 +284,16 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getParent() {
enforceSealed();
+ if (!canPerformRequestOverConnection(mAccessibilityViewId)) {
+ return null;
+ }
try {
- return mConnection.findAccessibilityNodeInfoByAccessibilityId(mAccessibilityWindowId,
- mParentAccessibilityViewId);
+ return mConnection.findAccessibilityNodeInfoByAccessibilityId(
+ mAccessibilityWindowId, mParentAccessibilityViewId);
} catch (RemoteException e) {
- return null;
+ /* ignore */
}
+ return null;
}
/**
@@ -279,8 +316,9 @@ public class AccessibilityNodeInfo implements Parcelable {
*
* @param outBounds The output node bounds.
*/
- public void getBounds(Rect outBounds) {
- outBounds.set(mBounds.left, mBounds.top, mBounds.right, mBounds.bottom);
+ public void getBoundsInParent(Rect outBounds) {
+ outBounds.set(mBoundsInParent.left, mBoundsInParent.top,
+ mBoundsInParent.right, mBoundsInParent.bottom);
}
/**
@@ -293,9 +331,34 @@ public class AccessibilityNodeInfo implements Parcelable {
*
* @throws IllegalStateException If called from an AccessibilityService.
*/
- public void setBounds(Rect bounds) {
+ public void setBoundsInParent(Rect bounds) {
enforceNotSealed();
- mBounds.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
+ mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
+ }
+
+ /**
+ * Gets the node bounds in screen coordinates.
+ *
+ * @param outBounds The output node bounds.
+ */
+ public void getBoundsInScreen(Rect outBounds) {
+ outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top,
+ mBoundsInScreen.right, mBoundsInScreen.bottom);
+ }
+
+ /**
+ * Sets the node bounds in screen coordinates.
+ * <p>
+ * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * This class is made immutable before being delivered to an AccessibilityService.
+ * </p>
+ * @param bounds The node bounds.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setBoundsInScreen(Rect bounds) {
+ enforceNotSealed();
+ mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
}
/**
@@ -636,6 +699,7 @@ public class AccessibilityNodeInfo implements Parcelable {
* @hide
*/
public final void setConnection(IAccessibilityServiceConnection connection) {
+ enforceNotSealed();
mConnection = connection;
}
@@ -777,10 +841,15 @@ public class AccessibilityNodeInfo implements Parcelable {
parcel.writeInt(childIds.valueAt(i));
}
- parcel.writeInt(mBounds.top);
- parcel.writeInt(mBounds.bottom);
- parcel.writeInt(mBounds.left);
- parcel.writeInt(mBounds.right);
+ parcel.writeInt(mBoundsInParent.top);
+ parcel.writeInt(mBoundsInParent.bottom);
+ parcel.writeInt(mBoundsInParent.left);
+ parcel.writeInt(mBoundsInParent.right);
+
+ parcel.writeInt(mBoundsInScreen.top);
+ parcel.writeInt(mBoundsInScreen.bottom);
+ parcel.writeInt(mBoundsInScreen.left);
+ parcel.writeInt(mBoundsInScreen.right);
parcel.writeInt(mActions);
@@ -818,10 +887,15 @@ public class AccessibilityNodeInfo implements Parcelable {
childIds.put(i, childId);
}
- mBounds.top = parcel.readInt();
- mBounds.bottom = parcel.readInt();
- mBounds.left = parcel.readInt();
- mBounds.right = parcel.readInt();
+ mBoundsInParent.top = parcel.readInt();
+ mBoundsInParent.bottom = parcel.readInt();
+ mBoundsInParent.left = parcel.readInt();
+ mBoundsInParent.right = parcel.readInt();
+
+ mBoundsInScreen.top = parcel.readInt();
+ mBoundsInScreen.bottom = parcel.readInt();
+ mBoundsInScreen.left = parcel.readInt();
+ mBoundsInScreen.right = parcel.readInt();
mActions = parcel.readInt();
@@ -842,7 +916,8 @@ public class AccessibilityNodeInfo implements Parcelable {
mAccessibilityViewId = View.NO_ID;
mParentAccessibilityViewId = View.NO_ID;
mChildAccessibilityIds.clear();
- mBounds.set(0, 0, 0, 0);
+ mBoundsInParent.set(0, 0, 0, 0);
+ mBoundsInScreen.set(0, 0, 0, 0);
mBooleanProperties = 0;
mPackageName = null;
mClassName = null;
@@ -869,6 +944,12 @@ public class AccessibilityNodeInfo implements Parcelable {
return actionSymbolicNames.get(action);
}
+ private boolean canPerformRequestOverConnection(int accessibilityViewId) {
+ return (mAccessibilityWindowId != View.NO_ID
+ && accessibilityViewId != View.NO_ID
+ && mConnection != null);
+ }
+
@Override
public boolean equals(Object object) {
if (this == object) {
@@ -918,7 +999,8 @@ public class AccessibilityNodeInfo implements Parcelable {
builder.append("]");
}
- builder.append("; bounds: " + mBounds);
+ builder.append("; boundsInParent: " + mBoundsInParent);
+ builder.append("; boundsInScreen: " + mBoundsInScreen);
builder.append("; packageName: ").append(mPackageName);
builder.append("; className: ").append(mClassName);
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 4bf03a7bed8e..9c495e2126cb 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -16,7 +16,10 @@
package android.view.accessibility;
+import android.accessibilityservice.IAccessibilityServiceConnection;
import android.os.Parcelable;
+import android.os.RemoteException;
+import android.view.View;
import java.util.ArrayList;
import java.util.List;
@@ -45,26 +48,29 @@ public class AccessibilityRecord {
private static int sPoolSize;
private AccessibilityRecord mNext;
private boolean mIsInPool;
- private boolean mSealed;
- protected int mBooleanProperties;
- protected int mCurrentItemIndex;
- protected int mItemCount;
- protected int mFromIndex;
- protected int mAddedCount;
- protected int mRemovedCount;
+ boolean mSealed;
+ int mBooleanProperties;
+ int mCurrentItemIndex;
+ int mItemCount;
+ int mFromIndex;
+ int mAddedCount;
+ int mRemovedCount;
+ int mSourceViewId = View.NO_ID;
+ int mSourceWindowId = View.NO_ID;
- protected CharSequence mClassName;
- protected CharSequence mContentDescription;
- protected CharSequence mBeforeText;
- protected Parcelable mParcelableData;
+ CharSequence mClassName;
+ CharSequence mContentDescription;
+ CharSequence mBeforeText;
+ Parcelable mParcelableData;
- protected final List<CharSequence> mText = new ArrayList<CharSequence>();
+ final List<CharSequence> mText = new ArrayList<CharSequence>();
+ IAccessibilityServiceConnection mConnection;
/*
* Hide constructor.
*/
- protected AccessibilityRecord() {
+ AccessibilityRecord() {
}
@@ -74,7 +80,7 @@ public class AccessibilityRecord {
* @param record The to initialize from.
*/
void init(AccessibilityRecord record) {
- mSealed = record.isSealed();
+ mSealed = record.mSealed;
mBooleanProperties = record.mBooleanProperties;
mCurrentItemIndex = record.mCurrentItemIndex;
mItemCount = record.mItemCount;
@@ -86,6 +92,73 @@ public class AccessibilityRecord {
mBeforeText = record.mBeforeText;
mParcelableData = record.mParcelableData;
mText.addAll(record.mText);
+ mSourceWindowId = record.mSourceWindowId;
+ mSourceViewId = record.mSourceViewId;
+ mConnection = record.mConnection;
+ }
+
+ /**
+ * Sets the event source.
+ *
+ * @param source The source.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setSource(View source) {
+ enforceNotSealed();
+ if (source != null) {
+ mSourceWindowId = source.getAccessibilityWindowId();
+ mSourceViewId = source.getAccessibilityViewId();
+ } else {
+ mSourceWindowId = View.NO_ID;
+ mSourceViewId = View.NO_ID;
+ }
+ }
+
+ /**
+ * Gets the {@link AccessibilityNodeInfo} of the event source.
+ * <p>
+ * <strong>
+ * It is a client responsibility to recycle the received info by
+ * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
+ * of multiple instances.
+ * </strong>
+ * </p>
+ * @return The info.
+ */
+ public AccessibilityNodeInfo getSource() {
+ enforceSealed();
+ if (mSourceWindowId == View.NO_ID || mSourceViewId == View.NO_ID || mConnection == null) {
+ return null;
+ }
+ try {
+ return mConnection.findAccessibilityNodeInfoByAccessibilityId(mSourceWindowId,
+ mSourceViewId);
+ } catch (RemoteException e) {
+ /* ignore */
+ }
+ return null;
+ }
+
+ /**
+ * Sets the connection for interacting with the AccessibilityManagerService.
+ *
+ * @param connection The connection.
+ *
+ * @hide
+ */
+ public void setConnection(IAccessibilityServiceConnection connection) {
+ enforceNotSealed();
+ mConnection = connection;
+ }
+
+ /**
+ * Gets the id of the window from which the event comes from.
+ *
+ * @return The window id.
+ */
+ public int getWindowId() {
+ return mSourceWindowId;
}
/**
@@ -386,10 +459,8 @@ public class AccessibilityRecord {
* Gets if this instance is sealed.
*
* @return Whether is sealed.
- *
- * @hide
*/
- public boolean isSealed() {
+ boolean isSealed() {
return mSealed;
}
@@ -397,10 +468,8 @@ public class AccessibilityRecord {
* Enforces that this instance is sealed.
*
* @throws IllegalStateException If this instance is not sealed.
- *
- * @hide
*/
- protected void enforceSealed() {
+ void enforceSealed() {
if (!isSealed()) {
throw new IllegalStateException("Cannot perform this "
+ "action on a not sealed instance.");
@@ -411,10 +480,8 @@ public class AccessibilityRecord {
* Enforces that this instance is not sealed.
*
* @throws IllegalStateException If this instance is sealed.
- *
- * @hide
*/
- protected void enforceNotSealed() {
+ void enforceNotSealed() {
if (isSealed()) {
throw new IllegalStateException("Cannot perform this "
+ "action on an sealed instance.");
@@ -502,10 +569,8 @@ public class AccessibilityRecord {
/**
* Clears the state of this instance.
- *
- * @hide
*/
- protected void clear() {
+ void clear() {
mSealed = false;
mBooleanProperties = 0;
mCurrentItemIndex = INVALID_POSITION;
@@ -518,6 +583,8 @@ public class AccessibilityRecord {
mBeforeText = null;
mParcelableData = null;
mText.clear();
+ mSourceViewId = View.NO_ID;
+ mSourceWindowId = View.NO_ID;
}
@Override
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 77dcd0747ed8..d35186b823ce 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -33,8 +33,8 @@ oneway interface IAccessibilityInteractionConnection {
void findAccessibilityNodeInfoByViewId(int id, int interactionId,
IAccessibilityInteractionConnectionCallback callback);
- void findAccessibilityNodeInfosByViewText(String text, int interactionId,
- IAccessibilityInteractionConnectionCallback callback);
+ void findAccessibilityNodeInfosByViewText(String text, int accessibilityViewId,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback);
void performAccessibilityAction(int accessibilityId, int action, int interactionId,
IAccessibilityInteractionConnectionCallback callback);
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index 44229a42be9a..4cae9d80d614 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -253,18 +253,19 @@ public class HTML5VideoFullScreen extends HTML5VideoView
mLayout.setVisibility(View.VISIBLE);
WebChromeClient client = webView.getWebChromeClient();
- client.onShowCustomView(mLayout, mCallback);
- // Plugins like Flash will draw over the video so hide
- // them while we're playing.
- if (webView.getViewManager() != null)
- webView.getViewManager().hideAll();
-
- mProgressView = client.getVideoLoadingProgressView();
- if (mProgressView != null) {
- mLayout.addView(mProgressView, layoutParams);
- mProgressView.setVisibility(View.VISIBLE);
+ if (client != null) {
+ client.onShowCustomView(mLayout, mCallback);
+ // Plugins like Flash will draw over the video so hide
+ // them while we're playing.
+ if (webView.getViewManager() != null)
+ webView.getViewManager().hideAll();
+
+ mProgressView = client.getVideoLoadingProgressView();
+ if (mProgressView != null) {
+ mLayout.addView(mProgressView, layoutParams);
+ mProgressView.setVisibility(View.VISIBLE);
+ }
}
-
}
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 95e48808665d..bfab8a995bab 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1395,6 +1395,10 @@ public class WebView extends AbsoluteLayout
*/
public int getVisibleTitleHeight() {
checkThread();
+ return getVisibleTitleHeightImpl();
+ }
+
+ private int getVisibleTitleHeightImpl() {
// need to restrict mScrollY due to over scroll
return Math.max(getTitleHeight() - Math.max(0, mScrollY), 0);
}
@@ -1405,7 +1409,7 @@ public class WebView extends AbsoluteLayout
* Note: this can be called from WebCoreThread.
*/
/* package */ int getViewHeight() {
- return getViewHeightWithTitle() - getVisibleTitleHeight();
+ return getViewHeightWithTitle() - getVisibleTitleHeightImpl();
}
int getViewHeightWithTitle() {
@@ -2768,7 +2772,7 @@ public class WebView extends AbsoluteLayout
// the visible height back in to account for the fact that if the title
// bar is partially visible, the part of the visible rect which is
// displaying our content is displaced by that amount.
- r.top = viewToContentY(r.top + getVisibleTitleHeight());
+ r.top = viewToContentY(r.top + getVisibleTitleHeightImpl());
r.right = viewToContentX(r.right);
r.bottom = viewToContentY(r.bottom);
}
@@ -2785,7 +2789,7 @@ public class WebView extends AbsoluteLayout
// the visible height back in to account for the fact that if the title
// bar is partially visible, the part of the visible rect which is
// displaying our content is displaced by that amount.
- r.top = viewToContentYf(ri.top + getVisibleTitleHeight());
+ r.top = viewToContentYf(ri.top + getVisibleTitleHeightImpl());
r.right = viewToContentXf(ri.right);
r.bottom = viewToContentYf(ri.bottom);
}
@@ -2934,7 +2938,7 @@ public class WebView extends AbsoluteLayout
if (mScrollY < 0) {
t -= mScrollY;
}
- scrollBar.setBounds(l, t + getVisibleTitleHeight(), r, b);
+ scrollBar.setBounds(l, t + getVisibleTitleHeightImpl(), r, b);
scrollBar.draw(canvas);
}
@@ -5179,7 +5183,7 @@ public class WebView extends AbsoluteLayout
Rect rect = nativeCursorNodeBounds();
mSelectX = contentToViewX(rect.left);
mSelectY = contentToViewY(rect.top);
- } else if (mLastTouchY > getVisibleTitleHeight()) {
+ } else if (mLastTouchY > getVisibleTitleHeightImpl()) {
mSelectX = mScrollX + mLastTouchX;
mSelectY = mScrollY + mLastTouchY;
} else {
@@ -5497,7 +5501,7 @@ public class WebView extends AbsoluteLayout
int rootViewHeight = rootView.getHeight();
mViewRectViewport.set(mGLRectViewport);
int savedWebViewBottom = mGLRectViewport.bottom;
- mGLRectViewport.bottom = rootViewHeight - mGLRectViewport.top - getVisibleTitleHeight();
+ mGLRectViewport.bottom = rootViewHeight - mGLRectViewport.top - getVisibleTitleHeightImpl();
mGLRectViewport.top = rootViewHeight - savedWebViewBottom;
mGLViewportEmpty = false;
} else {
@@ -5554,7 +5558,7 @@ public class WebView extends AbsoluteLayout
if (!mInOverScrollMode) {
sendOurVisibleRect();
// update WebKit if visible title bar height changed. The logic is same
- // as getVisibleTitleHeight.
+ // as getVisibleTitleHeightImpl.
int titleHeight = getTitleHeight();
if (Math.max(titleHeight - t, 0) != Math.max(titleHeight - oldt, 0)) {
sendViewSizeZoom(false);
@@ -5605,8 +5609,8 @@ public class WebView extends AbsoluteLayout
* Adjustable parameters. Angle is the radians on a unit circle, limited
* to quadrant 1. Values range from 0f (horizontal) to PI/2 (vertical)
*/
- private static final float HSLOPE_TO_START_SNAP = .1f;
- private static final float HSLOPE_TO_BREAK_SNAP = .2f;
+ private static final float HSLOPE_TO_START_SNAP = .25f;
+ private static final float HSLOPE_TO_BREAK_SNAP = .4f;
private static final float VSLOPE_TO_START_SNAP = 1.25f;
private static final float VSLOPE_TO_BREAK_SNAP = .95f;
/*
@@ -5617,6 +5621,11 @@ public class WebView extends AbsoluteLayout
*/
private static final float ANGLE_VERT = 2f;
private static final float ANGLE_HORIZ = 0f;
+ /*
+ * The modified moving average weight.
+ * Formula: MAV[t]=MAV[t-1] + (P[t]-MAV[t-1])/n
+ */
+ private static final float MMA_WEIGHT_N = 5;
private boolean hitFocusedPlugin(int contentX, int contentY) {
if (DebugFlags.WEB_VIEW) {
@@ -6003,8 +6012,9 @@ public class WebView extends AbsoluteLayout
if (deltaX == 0 && deltaY == 0) {
keepScrollBarsVisible = done = true;
} else {
- mAverageAngle = (mAverageAngle +
- calculateDragAngle(deltaX, deltaY)) / 2;
+ mAverageAngle +=
+ (calculateDragAngle(deltaX, deltaY) - mAverageAngle)
+ / MMA_WEIGHT_N;
if (mSnapScrollMode != SNAP_NONE) {
if (mSnapScrollMode == SNAP_Y) {
// radical change means getting out of snap mode
@@ -8318,7 +8328,7 @@ public class WebView extends AbsoluteLayout
(Math.min(maxHeight, y + viewHeight) - viewHeight));
// We need to take into account the visible title height
// when scrolling since y is an absolute view position.
- y = Math.max(0, y - getVisibleTitleHeight());
+ y = Math.max(0, y - getVisibleTitleHeightImpl());
scrollTo(x, y);
}
break;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 82dd5dbba4b2..3fe81498aad9 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -55,7 +55,6 @@ import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
-import android.view.accessibility.AccessibilityEvent;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index c4d05e91662b..755d4e09c039 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -904,8 +904,10 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup {
public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
// Add a record for ourselves as well.
AccessibilityEvent record = AccessibilityEvent.obtain();
+ record.setSource(this);
// Set the class since it is not populated in #dispatchPopulateAccessibilityEvent
record.setClassName(getClass().getName());
+ child.onInitializeAccessibilityEvent(record);
child.dispatchPopulateAccessibilityEvent(record);
event.appendRecord(record);
return true;
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 6b498feb3f2e..5eba1a0b2e3f 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -364,7 +364,8 @@ public class FrameLayout extends ViewGroup {
gravity = DEFAULT_CHILD_GRAVITY;
}
- final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, isLayoutRtl());
+ final int layoutDirection = getResolvedLayoutDirection();
+ final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
@@ -435,8 +436,10 @@ public class FrameLayout extends ViewGroup {
selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
}
+ final int layoutDirection = getResolvedLayoutDirection();
Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
- foreground.getIntrinsicHeight(), selfBounds, overlayBounds, isLayoutRtl());
+ foreground.getIntrinsicHeight(), selfBounds, overlayBounds,
+ layoutDirection);
foreground.setBounds(overlayBounds);
}
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index bda82a384254..092c2f75d66a 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -494,6 +494,14 @@ public class GridLayout extends ViewGroup {
requestLayout();
}
+ private static int max2(int[] a, int valueIfEmpty) {
+ int result = valueIfEmpty;
+ for (int i = 0, N = a.length; i < N; i++) {
+ result = Math.max(result, a[i]);
+ }
+ return result;
+ }
+
private static int sum(float[] a) {
int result = 0;
for (int i = 0, length = a.length; i < length; i++) {
@@ -1409,7 +1417,7 @@ public class GridLayout extends ViewGroup {
// External entry points
private int size(int[] locations) {
- return locations[locations.length - 1] - locations[0];
+ return max2(locations, 0) - locations[0];
}
private int getMin() {
@@ -1878,21 +1886,13 @@ public class GridLayout extends ViewGroup {
return result;
}
- private static int max(int[] a, int valueIfEmpty) {
- int result = valueIfEmpty;
- for (int i = 0, length = a.length; i < length; i++) {
- result = Math.max(result, a[i]);
- }
- return result;
- }
-
/*
Create a compact array of keys or values using the supplied index.
*/
private static <K> K[] compact(K[] a, int[] index) {
int size = a.length;
Class<?> componentType = a.getClass().getComponentType();
- K[] result = (K[]) Array.newInstance(componentType, max(index, -1) + 1);
+ K[] result = (K[]) Array.newInstance(componentType, max2(index, -1) + 1);
// this overwrite duplicates, retaining the last equivalent entry
for (int i = 0; i < size; i++) {
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 732cedcbaadd..5d406de007dc 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1408,7 +1408,8 @@ public class GridView extends AbsListView {
int childLeft;
final int childTop = flow ? y : y - h;
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity,isLayoutRtl());
+ final int layoutDirection = getResolvedLayoutDirection();
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.LEFT:
childLeft = childrenLeft;
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 4b870ec2d10b..161b40401327 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -186,9 +186,13 @@ public class ImageView extends View {
}
}
+ /**
+ * @hide
+ */
@Override
- public boolean isLayoutRtl(Drawable dr) {
- return (dr == mDrawable) ? isLayoutRtl() : super.isLayoutRtl(dr);
+ public int getResolvedLayoutDirection(Drawable dr) {
+ return (dr == mDrawable) ?
+ getResolvedLayoutDirection() : super.getResolvedLayoutDirection(dr);
}
@Override
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 0cdbc5b53f1d..e3bc94669f92 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -1446,7 +1446,8 @@ public class LinearLayout extends ViewGroup {
if (gravity < 0) {
gravity = minorGravity;
}
- final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, isLayoutRtl());
+ final int layoutDirection = getResolvedLayoutDirection();
+ final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.CENTER_HORIZONTAL:
childLeft = paddingLeft + ((childSpace - childWidth) / 2)
@@ -1509,7 +1510,8 @@ public class LinearLayout extends ViewGroup {
final int[] maxAscent = mMaxAscent;
final int[] maxDescent = mMaxDescent;
- switch (Gravity.getAbsoluteGravity(majorGravity, isLayoutRtl())) {
+ final int layoutDirection = getResolvedLayoutDirection();
+ switch (Gravity.getAbsoluteGravity(majorGravity, layoutDirection)) {
case Gravity.RIGHT:
// mTotalLength contains the padding already
childLeft = mPaddingLeft + mRight - mLeft - mTotalLength;
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index ed9114a33819..b2c3051c20a1 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -915,10 +915,13 @@ public class ProgressBar extends View {
}
}
+ /**
+ * @hide
+ */
@Override
- public boolean isLayoutRtl(Drawable who) {
+ public int getResolvedLayoutDirection(Drawable who) {
return (who == mProgressDrawable || who == mIndeterminateDrawable) ?
- isLayoutRtl() : super.isLayoutRtl(who);
+ getResolvedLayoutDirection() : super.getResolvedLayoutDirection(who);
}
@Override
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index a4771d5c9519..a5cf62e71796 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -495,8 +495,9 @@ public class RelativeLayout extends ViewGroup {
height - mPaddingBottom);
final Rect contentBounds = mContentBounds;
+ final int layoutDirection = getResolvedLayoutDirection();
Gravity.apply(mGravity, right - left, bottom - top, selfBounds, contentBounds,
- isLayoutRtl());
+ layoutDirection);
final int horizontalOffset = contentBounds.left - left;
final int verticalOffset = contentBounds.top - top;
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 5c6a26f3fb10..b7565f3129d5 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -387,7 +387,7 @@ public class Switch extends CompoundButton {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
- if (hitThumb(x, y)) {
+ if (isEnabled() && hitThumb(x, y)) {
mTouchMode = TOUCH_MODE_DOWN;
mTouchX = x;
mTouchY = y;
@@ -460,7 +460,8 @@ public class Switch extends CompoundButton {
*/
private void stopDrag(MotionEvent ev) {
mTouchMode = TOUCH_MODE_IDLE;
- boolean commitChange = ev.getAction() == MotionEvent.ACTION_UP;
+ // Up and not canceled, also checks the switch has not been disabled during the drag
+ boolean commitChange = ev.getAction() == MotionEvent.ACTION_UP && isEnabled();
cancelSuperTouch(ev);
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index 5f20c85d1310..3fd46316d465 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -224,7 +224,8 @@ public class TableRow extends LinearLayout {
final int childWidth = child.getMeasuredWidth();
lp.mOffset[LayoutParams.LOCATION_NEXT] = columnWidth - childWidth;
- final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, isLayoutRtl());
+ final int layoutDirection = getResolvedLayoutDirection();
+ final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.LEFT:
// don't offset on X axis
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9a5977a0b517..470a23d6a77d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4145,17 +4145,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
+ /**
+ * @hide
+ */
@Override
- public boolean isLayoutRtl(Drawable who) {
- if (who == null) return false;
+ public int getResolvedLayoutDirection(Drawable who) {
+ if (who == null) return View.LAYOUT_DIRECTION_LTR;
if (mDrawables != null) {
final Drawables drawables = mDrawables;
if (who == drawables.mDrawableLeft || who == drawables.mDrawableRight ||
who == drawables.mDrawableTop || who == drawables.mDrawableBottom) {
- return isLayoutRtl();
+ return getResolvedLayoutDirection();
}
}
- return super.isLayoutRtl(who);
+ return super.getResolvedLayoutDirection(who);
}
@Override
@@ -4397,7 +4400,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);
}
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, isLayoutRtl());
+ final int layoutDirection = getResolvedLayoutDirection();
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
if (!mSingleLine && getLineCount() == 1 && canMarquee() &&
(absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
@@ -5545,8 +5549,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
hintWidth = 0;
}
+ final int layoutDirection = getResolvedLayoutDirection();
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
+
Layout.Alignment alignment;
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, isLayoutRtl());
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.CENTER_HORIZONTAL:
alignment = Layout.Alignment.ALIGN_CENTER;
@@ -7582,7 +7588,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return 0.0f;
}
} else if (getLineCount() == 1) {
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, isLayoutRtl());
+ final int layoutDirection = getResolvedLayoutDirection();
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.LEFT:
return 0.0f;
@@ -7606,7 +7613,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final Marquee marquee = mMarquee;
return (marquee.mMaxFadeScroll - marquee.mScroll) / getHorizontalFadingEdgeLength();
} else if (getLineCount() == 1) {
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, isLayoutRtl());
+ final int layoutDirection = getResolvedLayoutDirection();
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.LEFT:
final int textWidth = (mRight - mLeft) - getCompoundPaddingLeft() -
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 18d6caa710a8..860a08c3e538 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -54,6 +54,8 @@ public class WrapperInit {
*/
public static void main(String[] args) {
try {
+ // Tell the Zygote what our actual PID is (since it only knows about the
+ // wrapper that it directly forked).
int fdNum = Integer.parseInt(args[0], 10);
if (fdNum != 0) {
try {
@@ -67,6 +69,10 @@ public class WrapperInit {
}
}
+ // Mimic Zygote preloading.
+ ZygoteInit.preload();
+
+ // Launch the application.
String[] runtimeArgs = new String[args.length - 1];
System.arraycopy(args, 1, runtimeArgs, 0, runtimeArgs.length);
RuntimeInit.wrapperInit(runtimeArgs);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 157c0bf0ec13..b4a7e52c6bb3 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -228,6 +228,11 @@ public class ZygoteInit {
}
}
+ static void preload() {
+ preloadClasses();
+ preloadResources();
+ }
+
/**
* Performs Zygote process initialization. Loads and initializes
* commonly used classes.
@@ -509,8 +514,7 @@ public class ZygoteInit {
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
- preloadClasses();
- preloadResources();
+ preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
index c337a5db01e4..a743cfa368d7 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -281,8 +281,10 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie
Rect tmpRect = mPositionIconOutput;
getLineBounds(0, tmpRect);
mPositionIconAvailable.set(0, 0, getWidth(), tmpRect.top);
+ final int layoutDirection = getResolvedLayoutDirection();
Gravity.apply(Gravity.CENTER_VERTICAL | Gravity.LEFT, mIcon.getIntrinsicWidth(), mIcon
- .getIntrinsicHeight(), mPositionIconAvailable, mPositionIconOutput, isLayoutRtl());
+ .getIntrinsicHeight(), mPositionIconAvailable, mPositionIconOutput,
+ layoutDirection);
mIcon.setBounds(mPositionIconOutput);
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index e3286dda28a3..9d8d361fee2a 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -302,6 +302,9 @@ public class ActionBarView extends AbsActionBarView {
}
public void setEmbeddedTabView(ScrollingTabContainerView tabs) {
+ if (mTabScrollView != null) {
+ removeView(mTabScrollView);
+ }
mTabScrollView = tabs;
mIncludeTabs = tabs != null;
if (mIncludeTabs && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 026ad2763d99..1e9882796f6d 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -134,18 +134,26 @@ public class MultiWaveView extends View implements AnimatorUpdateListener {
mTapRadius = mHandleDrawable.getWidth()/2;
mOuterRing = new TargetDrawable(res, a.getDrawable(R.styleable.MultiWaveView_waveDrawable));
- // Read animation drawables
+ // Read chevron animation drawables
Drawable leftChevron = a.getDrawable(R.styleable.MultiWaveView_leftChevronDrawable);
- if (leftChevron != null) {
- for (int i = 0; i < mFeedbackCount; i++) {
- mChevronDrawables.add(new TargetDrawable(res, leftChevron));
- }
+ for (int i = 0; i < mFeedbackCount; i++) {
+ mChevronDrawables.add(
+ leftChevron != null ? new TargetDrawable(res, leftChevron) : null);
}
Drawable rightChevron = a.getDrawable(R.styleable.MultiWaveView_rightChevronDrawable);
- if (rightChevron != null) {
- for (int i = 0; i < mFeedbackCount; i++) {
- mChevronDrawables.add(new TargetDrawable(res, rightChevron));
- }
+ for (int i = 0; i < mFeedbackCount; i++) {
+ mChevronDrawables.add(
+ rightChevron != null ? new TargetDrawable(res, rightChevron) : null);
+ }
+ Drawable topChevron = a.getDrawable(R.styleable.MultiWaveView_topChevronDrawable);
+ for (int i = 0; i < mFeedbackCount; i++) {
+ mChevronDrawables.add(
+ topChevron != null ? new TargetDrawable(res, topChevron) : null);
+ }
+ Drawable bottomChevron = a.getDrawable(R.styleable.MultiWaveView_bottomChevronDrawable);
+ for (int i = 0; i < mFeedbackCount; i++) {
+ mChevronDrawables.add(
+ bottomChevron != null ? new TargetDrawable(res, bottomChevron) : null);
}
// Read array of target drawables
@@ -190,7 +198,6 @@ public class MultiWaveView extends View implements AnimatorUpdateListener {
private void switchToState(int state, float x, float y) {
switch (state) {
case STATE_IDLE:
- stopChevronAnimation();
deactivateTargets();
mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
break;
@@ -221,33 +228,32 @@ public class MultiWaveView extends View implements AnimatorUpdateListener {
* followed by right chevrons.
*/
private void startChevronAnimation() {
- final int icons = mChevronDrawables.size();
- for (Tweener tween : mChevronAnimations) {
- tween.animator.cancel();
- }
- for (int i = 0; i < icons; i++) {
- TargetDrawable icon = mChevronDrawables.get(i);
- icon.setY(mWaveCenterY);
- icon.setAlpha(1.0f);
- mChevronAnimations.clear();
- int delay = (int) (Math.abs(0.5f + i - icons / 2) * CHEVRON_INCREMENTAL_DELAY);
- if (i < icons/2) {
- // Left chevrons
- icon.setX(mWaveCenterX - mHandleDrawable.getWidth() / 2);
- mChevronAnimations.add(Tweener.to(icon, CHEVRON_ANIMATION_DURATION,
- "ease", mChevronAnimationInterpolator,
- "delay", delay,
- "x", mWaveCenterX - mOuterRadius,
- "alpha", 0.0f,
- "onUpdate", this));
- } else {
- // Right chevrons
- icon.setX(mWaveCenterX + mHandleDrawable.getWidth() / 2);
+ final float r = mHandleDrawable.getWidth() / 2;
+ final float from[][] = {
+ {mWaveCenterX - r, mWaveCenterY}, // left
+ {mWaveCenterX + r, mWaveCenterY}, // right
+ {mWaveCenterX, mWaveCenterY - r}, // top
+ {mWaveCenterX, mWaveCenterY + r} }; // bottom
+ final float to[][] = {
+ {mWaveCenterX - mOuterRadius, mWaveCenterY}, // left
+ {mWaveCenterX + mOuterRadius, mWaveCenterY}, // right
+ {mWaveCenterX, mWaveCenterY - mOuterRadius}, // top
+ {mWaveCenterX, mWaveCenterY + mOuterRadius} }; // bottom
+
+ mChevronAnimations.clear();
+ for (int direction = 0; direction < 4; direction++) {
+ for (int count = 0; count < mFeedbackCount; count++) {
+ int delay = count * CHEVRON_INCREMENTAL_DELAY;
+ final TargetDrawable icon = mChevronDrawables.get(direction*mFeedbackCount + count);
+ if (icon == null) {
+ continue;
+ }
mChevronAnimations.add(Tweener.to(icon, CHEVRON_ANIMATION_DURATION,
"ease", mChevronAnimationInterpolator,
"delay", delay,
- "x", mWaveCenterX + mOuterRadius,
- "alpha", 0.0f,
+ "x", new float[] { from[direction][0], to[direction][0] },
+ "y", new float[] { from[direction][1], to[direction][1] },
+ "alpha", new float[] {1.0f, 0.0f},
"onUpdate", this));
}
}
@@ -330,8 +336,6 @@ public class MultiWaveView extends View implements AnimatorUpdateListener {
if (targetHit) {
mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
}
-
- stopChevronAnimation();
}
private void hideTargets(boolean animate) {
@@ -392,11 +396,12 @@ public class MultiWaveView extends View implements AnimatorUpdateListener {
Resources res = getContext().getResources();
TypedArray array = res.obtainTypedArray(resourceId);
int count = array.length();
- mTargetDrawables = new ArrayList<TargetDrawable>(count);
+ ArrayList<TargetDrawable> targetDrawables = new ArrayList<TargetDrawable>(count);
for (int i = 0; i < count; i++) {
Drawable drawable = array.getDrawable(i);
- mTargetDrawables.add(new TargetDrawable(res, drawable));
+ targetDrawables.add(new TargetDrawable(res, drawable));
}
+ mTargetDrawables = targetDrawables;
}
/**
@@ -472,12 +477,19 @@ public class MultiWaveView extends View implements AnimatorUpdateListener {
return handled ? true : super.onTouchEvent(event);
}
+ private void moveHandleTo(float x, float y, boolean animate) {
+ // TODO: animate the handle based on the current state/position
+ mHandleDrawable.setX(x);
+ mHandleDrawable.setY(y);
+ }
+
private void handleDown(float x, float y) {
final float dx = x - mWaveCenterX;
final float dy = y - mWaveCenterY;
if (dist2(dx,dy) <= square(mTapRadius)) {
if (DEBUG) Log.v(TAG, "** Handle HIT");
switchToState(STATE_FIRST_TOUCH, x, y);
+ moveHandleTo(x, y, false);
mDragging = true;
} else {
mDragging = false;
@@ -528,11 +540,14 @@ public class MultiWaveView extends View implements AnimatorUpdateListener {
best = dist2;
}
}
+ x = limitX;
+ y = limitY;
}
if (activeTarget != -1) {
switchToState(STATE_SNAP, x,y);
- mHandleDrawable.setX(singleTarget ? limitX : mTargetDrawables.get(activeTarget).getX());
- mHandleDrawable.setY(singleTarget ? limitY : mTargetDrawables.get(activeTarget).getY());
+ float newX = singleTarget ? limitX : mTargetDrawables.get(activeTarget).getX();
+ float newY = singleTarget ? limitY : mTargetDrawables.get(activeTarget).getY();
+ moveHandleTo(newX, newY, false);
TargetDrawable currentTarget = mTargetDrawables.get(activeTarget);
if (currentTarget.hasState(TargetDrawable.STATE_FOCUSED)) {
currentTarget.setState(TargetDrawable.STATE_FOCUSED);
@@ -540,8 +555,7 @@ public class MultiWaveView extends View implements AnimatorUpdateListener {
}
} else {
switchToState(STATE_TRACKING, x, y);
- mHandleDrawable.setX(x);
- mHandleDrawable.setY(y);
+ moveHandleTo(x, y, false);
mHandleDrawable.setAlpha(1.0f);
}
// Draw handle outside parent's bounds
@@ -577,8 +591,7 @@ public class MultiWaveView extends View implements AnimatorUpdateListener {
mWaveCenterX = mHorizontalOffset + Math.max(width, mOuterRing.getWidth() ) / 2;
mWaveCenterY = mVerticalOffset + Math.max(height, mOuterRing.getHeight()) / 2;
- mHandleDrawable.setX(mWaveCenterX);
- mHandleDrawable.setY(mWaveCenterY);
+ moveHandleTo(mWaveCenterX, mWaveCenterY, false);
mOuterRing.setX(mWaveCenterX);
mOuterRing.setY(Math.max(mWaveCenterY, mWaveCenterY));
mOuterRing.setAlpha(0.0f);
@@ -609,7 +622,9 @@ public class MultiWaveView extends View implements AnimatorUpdateListener {
private void hideChevrons() {
for (TargetDrawable chevron : mChevronDrawables) {
- chevron.setAlpha(0.0f);
+ if (chevron != null) {
+ chevron.setAlpha(0.0f);
+ }
}
}
@@ -617,10 +632,14 @@ public class MultiWaveView extends View implements AnimatorUpdateListener {
protected void onDraw(Canvas canvas) {
mOuterRing.draw(canvas);
for (TargetDrawable target : mTargetDrawables) {
- target.draw(canvas);
+ if (target != null) {
+ target.draw(canvas);
+ }
}
for (TargetDrawable target : mChevronDrawables) {
- target.draw(canvas);
+ if (target != null) {
+ target.draw(canvas);
+ }
}
mHandleDrawable.draw(canvas);
}
diff --git a/core/java/com/android/internal/widget/multiwaveview/Tweener.java b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
index c2746d97a323..0cff00a514ab 100644
--- a/core/java/com/android/internal/widget/multiwaveview/Tweener.java
+++ b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
@@ -63,14 +63,15 @@ class Tweener {
delay = ((Number) value).longValue();
} else if ("syncWith".equals(key)) {
// TODO
- } else if (value instanceof Number[]) {
- // TODO: support Tween.from()
+ } else if (value instanceof float[]) {
+ props.add(PropertyValuesHolder.ofFloat(key,
+ ((float[])value)[0], ((float[])value)[1]));
} else if (value instanceof Number) {
float floatValue = ((Number)value).floatValue();
props.add(PropertyValuesHolder.ofFloat(key, floatValue));
} else {
throw new IllegalArgumentException(
- "Bad argument for key \"" + key + "with value" + value);
+ "Bad argument for key \"" + key + "\" with value " + value.getClass());
}
}
diff --git a/core/jni/android/graphics/ParcelSurfaceTexture.cpp b/core/jni/android/graphics/ParcelSurfaceTexture.cpp
index 517d7e28f71b..40966e1135c4 100644
--- a/core/jni/android/graphics/ParcelSurfaceTexture.cpp
+++ b/core/jni/android/graphics/ParcelSurfaceTexture.cpp
@@ -19,6 +19,7 @@
#include <gui/SurfaceTextureClient.h>
#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
#include <utils/Log.h>
@@ -27,7 +28,6 @@
#include "android_util_Binder.h"
#include "jni.h"
#include "JNIHelp.h"
-#include "SurfaceTexture.h"
// ----------------------------------------------------------------------------
@@ -59,7 +59,7 @@ static void ParcelSurfaceTexture_setISurfaceTexture(
env->SetIntField(thiz, fields.iSurfaceTexture, (int)iSurfaceTexture.get());
}
-static sp<ISurfaceTexture> ParcelSurfaceTexture_getISurfaceTexture(
+sp<ISurfaceTexture> ParcelSurfaceTexture_getISurfaceTexture(
JNIEnv* env, jobject thiz)
{
sp<ISurfaceTexture> iSurfaceTexture(
diff --git a/core/jni/android/graphics/SurfaceTexture.h b/core/jni/android/graphics/SurfaceTexture.h
deleted file mode 100644
index 79d8dd3cbc50..000000000000
--- a/core/jni/android/graphics/SurfaceTexture.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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_GRAPHICS_SURFACETEXTURE_H
-#define _ANDROID_GRAPHICS_SURFACETEXTURE_H
-
-#include <gui/SurfaceTexture.h>
-#include <utils/StrongPointer.h>
-#include "jni.h"
-
-namespace android {
-
-/* Gets the underlying SurfaceTexture from a SurfaceTexture Java object. */
-sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz);
-
-} // namespace android
-
-#endif // _ANDROID_GRAPHICS_SURFACETEXTURE_H
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 246c0e506bd6..0c5101f73700 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -31,7 +31,7 @@
#include <media/AudioTrack.h>
#include <system/audio.h>
-#include <hardware/audio_policy.h>
+#include <system/audio_policy.h>
// ----------------------------------------------------------------------------
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 57a97bd89572..7e82efb302ef 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -667,6 +667,11 @@ static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
renderer->drawLayer(layer, x, y, paint);
}
+static jboolean android_view_GLES20Canvas_copyLayer(JNIEnv* env, jobject clazz,
+ Layer* layer, SkBitmap* bitmap) {
+ return LayerRenderer::copyLayer(layer, bitmap);
+}
+
#endif // USE_OPENGL_RENDERER
// ----------------------------------------------------------------------------
@@ -792,6 +797,7 @@ static JNINativeMethod gMethods[] = {
{ "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer },
{ "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred },
{ "nDrawLayer", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawLayer },
+ { "nCopyLayer", "(II)Z", (void*) android_view_GLES20Canvas_copyLayer },
#endif
};
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png
new file mode 100644
index 000000000000..620844ec374f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png
new file mode 100644
index 000000000000..4ffa833b93cf
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png
new file mode 100644
index 000000000000..d3cfd17ea104
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png
new file mode 100644
index 000000000000..35aca4e82450
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png
new file mode 100644
index 000000000000..c655d93b0cc7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png
new file mode 100644
index 000000000000..53794fde8cf7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png
Binary files differ
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 24891dce7882..7ae357a86006 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -176,7 +176,6 @@
android:snapMargin="@*android:dimen/multiwaveview_snap_margin"
android:hitRadius="@*android:dimen/multiwaveview_hit_radius"
android:vibrationDuration="20"
- android:leftChevronDrawable="@drawable/ic_lockscreen_chevron_left"
android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"
android:feedbackCount="3"
android:horizontalOffset="0dip"
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 02994a9bf841..df29a4b3c09e 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -176,8 +176,7 @@
android:snapMargin="@*android:dimen/multiwaveview_snap_margin"
android:hitRadius="@*android:dimen/multiwaveview_hit_radius"
android:vibrationDuration="20"
- android:leftChevronDrawable="@drawable/ic_lockscreen_chevron_left"
- android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"
+ android:topChevronDrawable="@drawable/ic_lockscreen_chevron_up"
android:feedbackCount="3"
android:horizontalOffset="60dip"
android:verticalOffset="0dip"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index acfdfc90cf6c..5d357c55421d 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5019,12 +5019,18 @@
<!-- Sets a drawable as the drag center. -->
<attr name="handleDrawable" format="reference" />
- <!-- Drawable to use for chevron animation on the left. -->
+ <!-- Drawable to use for chevron animation on the left. May be null. -->
<attr name="leftChevronDrawable" format="reference" />
- <!-- Drawable to use for chevron animation on the right. -->
+ <!-- Drawable to use for chevron animation on the right. May be null. -->
<attr name="rightChevronDrawable" format="reference" />
+ <!-- Drawable to use for chevron animation on the top. May be null. -->
+ <attr name="topChevronDrawable" format="reference" />
+
+ <!-- Drawable to use for chevron animation on the bottom. May be null. -->
+ <attr name="bottomChevronDrawable" format="reference" />
+
<!-- Drawable to use for wave ripple animation. -->
<attr name="waveDrawable" format="reference" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c95b0ae76bb3..3b4798eda033 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -160,6 +160,9 @@
<string-array translatable="false" name="config_tether_upstream_regexs">
</string-array>
+ <!-- Regex of wired ethernet ifaces -->
+ <string translatable="false" name="config_ethernet_iface_regex">eth\\d</string>
+
<!-- Boolean indicating if we require the use of DUN on mobile for tethering.
Note that this defaults to false so that if you move to a carrier that
hasn't configured anything tethering will still work. If you'd rather
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 4108c1b9a5ea..17b23da054a2 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1756,6 +1756,8 @@
<public type="attr" name="handleDrawable" />
<public type="attr" name="leftChevronDrawable" />
<public type="attr" name="rightChevronDrawable" />
+ <public type="attr" name="topChevronDrawable" />
+ <public type="attr" name="bottomChevronDrawable" />
<public type="attr" name="waveDrawable" />
<public type="attr" name="outerRadius" />
<public type="attr" name="hitRadius" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b264b411ff86..966dbe58a87b 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1788,6 +1788,8 @@
<string name="lockscreen_missing_sim_message" product="default">No SIM card in phone.</string>
<!-- Shown in the lock screen to ask the user to insert a SIM card. -->
<string name="lockscreen_missing_sim_instructions">Please insert a SIM card.</string>
+ <!-- Shown in the lock screen to ask the user to insert a SIM card when sim is missing or not readable. -->
+ <string name="lockscreen_missing_sim_instructions_long">The SIM card is missing or not readable. Please insert a SIM card.</string>
<!-- Shown in the lock screen when there is emergency calls only mode. -->
<string name="emergency_calls_only" msgid="2485604591272668370">Emergency calls only</string>
diff --git a/core/tests/bluetoothtests/AndroidManifest.xml b/core/tests/bluetoothtests/AndroidManifest.xml
index 96db035d3e44..58f158ce410f 100644
--- a/core/tests/bluetoothtests/AndroidManifest.xml
+++ b/core/tests/bluetoothtests/AndroidManifest.xml
@@ -19,6 +19,7 @@
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java
index 64d2c1257ea0..56e691d8c246 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestRunner.java
@@ -47,7 +47,7 @@ import android.util.Log;
* [-e pan_address <address>] \
* [-e pair_pin <pin>] \
* [-e pair_passkey <passkey>] \
- * -w com.android.frameworks.coretests/android.bluetooth.BluetoothTestRunner
+ * -w com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner
* }
* </pre>
*/
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
index 5f4c226c8d4d..047481e56784 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
@@ -290,7 +290,7 @@ public class BluetoothTestUtils extends Assert {
@Override
public void onReceive(Context context, Intent intent) {
- if (AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED.equals(intent.getAction())) {
+ if (AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED.equals(intent.getAction())) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
AudioManager.SCO_AUDIO_STATE_ERROR);
assertNotSame(AudioManager.SCO_AUDIO_STATE_ERROR, state);
diff --git a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
index 32606168c61e..99d534c7950d 100644
--- a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
+++ b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
@@ -29,6 +29,7 @@ import android.os.SystemClock;
import android.provider.Settings;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -49,6 +50,9 @@ import java.util.Queue;
*/
public class InterrogationActivityTest
extends ActivityInstrumentationTestCase2<InterrogationActivity> {
+ private static final boolean DEBUG = true;
+
+ private static String LOG_TAG = "InterrogationActivityTest";
// Timeout before give up wait for the system to process an accessibility setting change.
private static final int TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING = 2000;
@@ -62,7 +66,7 @@ public class InterrogationActivityTest
private static IAccessibilityServiceConnection sConnection;
// The last received accessibility event
- private static volatile AccessibilityEvent sLastAccessibilityEvent;
+ private static volatile AccessibilityEvent sLastFocusAccessibilityEvent;
public InterrogationActivityTest() {
super(InterrogationActivity.class);
@@ -72,18 +76,19 @@ public class InterrogationActivityTest
@LargeTest
public void testFindAccessibilityNodeInfoByViewId() throws Exception {
beforeClassIfNeeded();
+ final long startTimeMillis = SystemClock.uptimeMillis();
try {
// bring up the activity
getActivity();
- AccessibilityNodeInfo button = getConnection().findAccessibilityNodeInfoByViewId(
- R.id.button5);
+ AccessibilityNodeInfo button =
+ getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertNotNull(button);
assertEquals(0, button.getChildCount());
// bounds
Rect bounds = new Rect();
- button.getBounds(bounds);
+ button.getBoundsInParent(bounds);
assertEquals(0, bounds.left);
assertEquals(0, bounds.top);
assertEquals(73, bounds.right);
@@ -111,28 +116,40 @@ public class InterrogationActivityTest
button.getActions());
} finally {
afterClassIfNeeded();
+ if (DEBUG) {
+ final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+ Log.i(LOG_TAG, "testFindAccessibilityNodeInfoByViewId: "
+ + elapsedTimeMillis + "ms");
+ }
}
}
@LargeTest
public void testFindAccessibilityNodeInfoByViewText() throws Exception {
beforeClassIfNeeded();
+ final long startTimeMillis = SystemClock.uptimeMillis();
try {
// bring up the activity
getActivity();
// find a view by text
List<AccessibilityNodeInfo> buttons =
- getConnection().findAccessibilityNodeInfosByViewText("butto");
+ getConnection().findAccessibilityNodeInfosByViewTextInActiveWindow("butto");
assertEquals(9, buttons.size());
} finally {
afterClassIfNeeded();
+ if (DEBUG) {
+ final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+ Log.i(LOG_TAG, "testFindAccessibilityNodeInfoByViewText: "
+ + elapsedTimeMillis + "ms");
+ }
}
}
@LargeTest
public void testTraverseAllViews() throws Exception {
beforeClassIfNeeded();
+ final long startTimeMillis = SystemClock.uptimeMillis();
try {
// bring up the activity
getActivity();
@@ -153,8 +170,8 @@ public class InterrogationActivityTest
classNameAndTextList.add("android.widget.ButtonButton8");
classNameAndTextList.add("android.widget.ButtonButton9");
- AccessibilityNodeInfo root = getConnection().findAccessibilityNodeInfoByViewId(
- R.id.root);
+ AccessibilityNodeInfo root =
+ getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.root);
assertNotNull("We must find the existing root.", root);
Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
@@ -181,125 +198,152 @@ public class InterrogationActivityTest
}
} finally {
afterClassIfNeeded();
+ if (DEBUG) {
+ final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+ Log.i(LOG_TAG, "testTraverseAllViews: " + elapsedTimeMillis + "ms");
+ }
}
}
@LargeTest
public void testPerformAccessibilityActionFocus() throws Exception {
beforeClassIfNeeded();
+ final long startTimeMillis = SystemClock.uptimeMillis();
try {
// bring up the activity
getActivity();
// find a view and make sure it is not focused
- AccessibilityNodeInfo button = getConnection().findAccessibilityNodeInfoByViewId(
- R.id.button5);
+ AccessibilityNodeInfo button =
+ getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isFocused());
// focus the view
assertTrue(button.performAction(ACTION_FOCUS));
// find the view again and make sure it is focused
- button = getConnection().findAccessibilityNodeInfoByViewId(R.id.button5);
+ button = getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertTrue(button.isFocused());
} finally {
afterClassIfNeeded();
+ if (DEBUG) {
+ final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+ Log.i(LOG_TAG, "testPerformAccessibilityActionFocus: " + elapsedTimeMillis + "ms");
+ }
}
}
@LargeTest
public void testPerformAccessibilityActionClearFocus() throws Exception {
beforeClassIfNeeded();
+ final long startTimeMillis = SystemClock.uptimeMillis();
try {
// bring up the activity
getActivity();
// find a view and make sure it is not focused
- AccessibilityNodeInfo button = getConnection().findAccessibilityNodeInfoByViewId(
- R.id.button5);
+ AccessibilityNodeInfo button =
+ getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isFocused());
// focus the view
assertTrue(button.performAction(ACTION_FOCUS));
// find the view again and make sure it is focused
- button = getConnection().findAccessibilityNodeInfoByViewId(R.id.button5);
+ button = getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertTrue(button.isFocused());
// unfocus the view
assertTrue(button.performAction(ACTION_CLEAR_FOCUS));
// find the view again and make sure it is not focused
- button = getConnection().findAccessibilityNodeInfoByViewId(R.id.button5);
+ button = getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isFocused());
} finally {
afterClassIfNeeded();
+ if (DEBUG) {
+ final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+ Log.i(LOG_TAG, "testPerformAccessibilityActionClearFocus: "
+ + elapsedTimeMillis + "ms");
+ }
}
}
@LargeTest
public void testPerformAccessibilityActionSelect() throws Exception {
beforeClassIfNeeded();
+ final long startTimeMillis = SystemClock.uptimeMillis();
try {
// bring up the activity
getActivity();
// find a view and make sure it is not selected
- AccessibilityNodeInfo button = getConnection().findAccessibilityNodeInfoByViewId(
- R.id.button5);
+ AccessibilityNodeInfo button =
+ getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isSelected());
// select the view
assertTrue(button.performAction(ACTION_SELECT));
// find the view again and make sure it is selected
- button = getConnection().findAccessibilityNodeInfoByViewId(R.id.button5);
+ button = getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertTrue(button.isSelected());
} finally {
afterClassIfNeeded();
+ if (DEBUG) {
+ final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+ Log.i(LOG_TAG, "testPerformAccessibilityActionSelect: " + elapsedTimeMillis + "ms");
+ }
}
}
@LargeTest
public void testPerformAccessibilityActionClearSelection() throws Exception {
beforeClassIfNeeded();
+ final long startTimeMillis = SystemClock.uptimeMillis();
try {
// bring up the activity
getActivity();
// find a view and make sure it is not selected
- AccessibilityNodeInfo button = getConnection().findAccessibilityNodeInfoByViewId(
- R.id.button5);
+ AccessibilityNodeInfo button =
+ getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isSelected());
// select the view
assertTrue(button.performAction(ACTION_SELECT));
// find the view again and make sure it is selected
- button = getConnection().findAccessibilityNodeInfoByViewId(R.id.button5);
+ button = getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertTrue(button.isSelected());
// unselect the view
assertTrue(button.performAction(ACTION_CLEAR_SELECTION));
// find the view again and make sure it is not selected
- button = getConnection().findAccessibilityNodeInfoByViewId(R.id.button5);
+ button = getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isSelected());
} finally {
afterClassIfNeeded();
+ if (DEBUG) {
+ final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+ Log.i(LOG_TAG, "testPerformAccessibilityActionClearSelection: "
+ + elapsedTimeMillis + "ms");
+ }
}
}
@LargeTest
public void testAccessibilityEventGetSource() throws Exception {
beforeClassIfNeeded();
+ final long startTimeMillis = SystemClock.uptimeMillis();
try {
// bring up the activity
getActivity();
// find a view and make sure it is not focused
- AccessibilityNodeInfo button = getConnection().findAccessibilityNodeInfoByViewId(
- R.id.button5);
+ AccessibilityNodeInfo button =
+ getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isSelected());
// focus the view
@@ -314,14 +358,14 @@ public class InterrogationActivityTest
}
// check that last event source
- AccessibilityNodeInfo source = sLastAccessibilityEvent.getSource();
+ AccessibilityNodeInfo source = sLastFocusAccessibilityEvent.getSource();
assertNotNull(source);
// bounds
Rect buttonBounds = new Rect();
- button.getBounds(buttonBounds);
+ button.getBoundsInParent(buttonBounds);
Rect sourceBounds = new Rect();
- source.getBounds(sourceBounds);
+ source.getBoundsInParent(sourceBounds);
assertEquals(buttonBounds.left, sourceBounds.left);
assertEquals(buttonBounds.right, sourceBounds.right);
@@ -346,6 +390,42 @@ public class InterrogationActivityTest
assertSame(button.isChecked(), source.isChecked());
} finally {
afterClassIfNeeded();
+ if (DEBUG) {
+ final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+ Log.i(LOG_TAG, "testAccessibilityEventGetSource: " + elapsedTimeMillis + "ms");
+ }
+ }
+ }
+
+ @LargeTest
+ public void testObjectContract() throws Exception {
+ beforeClassIfNeeded();
+ final long startTimeMillis = SystemClock.uptimeMillis();
+ try {
+ // bring up the activity
+ getActivity();
+
+ // find a view and make sure it is not focused
+ AccessibilityNodeInfo button =
+ getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+ AccessibilityNodeInfo parent = button.getParent();
+ final int childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ AccessibilityNodeInfo child = parent.getChild(i);
+ assertNotNull(child);
+ if (child.equals(button)) {
+ assertEquals("Equal objects must have same hasCode.", button.hashCode(),
+ child.hashCode());
+ return;
+ }
+ }
+ fail("Parent's children do not have the info whose parent is the parent.");
+ } finally {
+ afterClassIfNeeded();
+ if (DEBUG) {
+ final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+ Log.i(LOG_TAG, "testObjectContract: " + elapsedTimeMillis + "ms");
+ }
}
}
@@ -442,7 +522,9 @@ public class InterrogationActivityTest
public void onInterrupt() {}
public void onAccessibilityEvent(AccessibilityEvent event) {
- sLastAccessibilityEvent = AccessibilityEvent.obtain(event);
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
+ sLastFocusAccessibilityEvent = AccessibilityEvent.obtain(event);
+ }
synchronized (sConnection) {
sConnection.notifyAll();
}
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationTest.java b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
index f1f745ea9be9..54a5e4e48359 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
@@ -30,169 +30,169 @@ public class ConfigurationTest extends AndroidTestCase {
args = {Locale.class}
)
public void testGetLayoutDirectionFromLocale() {
- assertEquals(Configuration.LAYOUT_DIRECTION_UNDEFINED,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(null));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.ENGLISH));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.CANADA));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.CANADA_FRENCH));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.FRANCE));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.FRENCH));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.GERMAN));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.GERMANY));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.ITALIAN));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.ITALY));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.UK));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.US));
- assertEquals(Configuration.LAYOUT_DIRECTION_UNDEFINED,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.ROOT));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.CHINA));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.CHINESE));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.JAPAN));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.JAPANESE));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.KOREA));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.KOREAN));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.PRC));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.SIMPLIFIED_CHINESE));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.TAIWAN));
- assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(Locale.TRADITIONAL_CHINESE));
Locale locale = new Locale("ar");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "AE");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "BH");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "DZ");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "EG");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "IQ");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "JO");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "KW");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "LB");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "LY");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "MA");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "OM");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "QA");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "SA");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "SD");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "SY");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "TN");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ar", "YE");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("fa");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("fa", "AF");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("fa", "IR");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("iw");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("iw", "IL");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("he");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("he", "IL");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
// The following test will not pass until we are able to take care about the scrip subtag
// thru having the "likelySubTags" file into ICU4C
// locale = new Locale("pa_Arab");
-// assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
// Configuration.getLayoutDirectionFromLocale(locale));
// locale = new Locale("pa_Arab", "PK");
-// assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
// Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ps");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
locale = new Locale("ps", "AF");
- assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+ assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
Configuration.getLayoutDirectionFromLocale(locale));
// The following test will not work as the localized display name would be "Urdu" with ICU 4.4
// We will need ICU 4.6 to get the correct localized display name
// locale = new Locale("ur");
-// assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
// Configuration.getLayoutDirectionFromLocale(locale));
// locale = new Locale("ur", "IN");
-// assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
// Configuration.getLayoutDirectionFromLocale(locale));
// locale = new Locale("ur", "PK");
-// assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
// Configuration.getLayoutDirectionFromLocale(locale));
// The following test will not pass until we are able to take care about the scrip subtag
// thru having the "likelySubTags" file into ICU4C
// locale = new Locale("uz_Arab");
-// assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
// Configuration.getLayoutDirectionFromLocale(locale));
// locale = new Locale("uz_Arab", "AF");
-// assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+// assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
// Configuration.getLayoutDirectionFromLocale(locale));
}
}
diff --git a/core/tests/coretests/src/android/pim/RecurrenceSetTest.java b/core/tests/coretests/src/android/pim/RecurrenceSetTest.java
index 5d01ba0e0ee9..e5ab179f470e 100644
--- a/core/tests/coretests/src/android/pim/RecurrenceSetTest.java
+++ b/core/tests/coretests/src/android/pim/RecurrenceSetTest.java
@@ -21,7 +21,7 @@ import android.pim.ICalendar;
import android.pim.RecurrenceSet;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
-import android.provider.Calendar;
+import android.provider.CalendarContract;
import junit.framework.TestCase;
/**
@@ -69,14 +69,14 @@ public class RecurrenceSetTest extends TestCase {
RecurrenceSet.populateContentValues(recurrenceComponent, values);
Log.d("KS", "values " + values);
- assertEquals(rrule, values.get(android.provider.Calendar.Events.RRULE));
- assertEquals(rdate, values.get(android.provider.Calendar.Events.RDATE));
- assertEquals(exrule, values.get(android.provider.Calendar.Events.EXRULE));
- assertEquals(exdate, values.get(android.provider.Calendar.Events.EXDATE));
- assertEquals(dtstart, (long) values.getAsLong(Calendar.Events.DTSTART));
- assertEquals(tzid, values.get(android.provider.Calendar.Events.EVENT_TIMEZONE));
- assertEquals(duration, values.get(android.provider.Calendar.Events.DURATION));
+ assertEquals(rrule, values.get(android.provider.CalendarContract.Events.RRULE));
+ assertEquals(rdate, values.get(android.provider.CalendarContract.Events.RDATE));
+ assertEquals(exrule, values.get(android.provider.CalendarContract.Events.EXRULE));
+ assertEquals(exdate, values.get(android.provider.CalendarContract.Events.EXDATE));
+ assertEquals(dtstart, (long) values.getAsLong(CalendarContract.Events.DTSTART));
+ assertEquals(tzid, values.get(android.provider.CalendarContract.Events.EVENT_TIMEZONE));
+ assertEquals(duration, values.get(android.provider.CalendarContract.Events.DURATION));
assertEquals(allDay,
- (int) values.getAsInteger(android.provider.Calendar.Events.ALL_DAY));
+ (int) values.getAsInteger(android.provider.CalendarContract.Events.ALL_DAY));
}
}
diff --git a/core/tests/coretests/src/android/view/GravityTest.java b/core/tests/coretests/src/android/view/GravityTest.java
index 2a7a64f18bd5..d8ef650af6b7 100644
--- a/core/tests/coretests/src/android/view/GravityTest.java
+++ b/core/tests/coretests/src/android/view/GravityTest.java
@@ -67,6 +67,8 @@ public class GravityTest extends AndroidTestCase {
}
private void assertOneGravity(int expected, int initial, boolean isRtl) {
- assertEquals(expected, Gravity.getAbsoluteGravity(initial, isRtl));
+ final int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
+
+ assertEquals(expected, Gravity.getAbsoluteGravity(initial, layoutDirection));
}
}
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 7f87b7923d86..9d2a0cbb60e9 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -31,6 +31,8 @@
<feature name="android.hardware.bluetooth" />
<feature name="android.hardware.touchscreen" />
<feature name="android.hardware.microphone" />
+ <feature name="android.hardware.screen.portrait" />
+ <feature name="android.hardware.screen.landscape" />
<!-- devices with GPS must include android.hardware.location.gps.xml -->
<!-- devices with an autofocus camera and/or flash must include either
android.hardware.camera.autofocus.xml or
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 952d078253da..bf29fe4b7003 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -32,6 +32,8 @@
<feature name="android.hardware.touchscreen.multitouch" />
<feature name="android.hardware.touchscreen.multitouch.distinct" />
<feature name="android.hardware.microphone" />
+ <feature name="android.hardware.screen.portrait" />
+ <feature name="android.hardware.screen.landscape" />
<!-- devices with GPS must include android.hardware.location.gps.xml -->
<!-- devices with a rear-facing camera must include one of these as appropriate:
android.hardware.camera.xml or
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 916da0994d79..55d711f7adf2 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -244,9 +244,6 @@
<li><a href="<?cs var:toroot ?>guide/topics/graphics/opengl.html">
<span class="en">3D with OpenGL</span>
</a></li>
- <li><a href="<?cs var:toroot ?>guide/topics/graphics/renderscript.html">
- <span class="en">3D with Renderscript</span>
- </a></li>
<li><a href="<?cs var:toroot ?>guide/topics/graphics/animation.html">
<span class="en">Property Animation</span>
</a></li>
@@ -255,6 +252,23 @@
</a></li>
</ul>
</li>
+ <li class="toggle-list">
+ <div><a href="<?cs var:toroot ?>guide/topics/renderscript/index.html">
+ <span class="en">RenderScript</span>
+ </a>
+ <span class="new-child">new!</span></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>guide/topics/renderscript/graphics.html">
+ <span class="en">3D Graphics</span>
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>guide/topics/renderscript/compute.html">
+ <span class="en">Compute</span>
+ </a>
+ </li>
+ </ul>
+ </li>
+
<li><a href="<?cs var:toroot ?>guide/topics/media/index.html">
<span class="en">Audio and Video</span>
</a></li>
diff --git a/docs/html/guide/topics/graphics/animation.jd b/docs/html/guide/topics/graphics/animation.jd
index 0b02ee767e7d..31e7c4b79e9e 100644
--- a/docs/html/guide/topics/graphics/animation.jd
+++ b/docs/html/guide/topics/graphics/animation.jd
@@ -81,6 +81,12 @@ parent.link=index.html
If view animation accomplishes everything that you need to do, or if your existing code already
works the way you want, there is no need to use the property animation system.</p>
+ <p class="note"><strong>Tip:</strong> To see how the ADT layout editor allows you to develop and
+preview animations in your layout, watch the <a
+href="http://www.youtube.com/watch?v=Oq05KqjXTvs&feature=player_detailpage#t=1709s">Android
+Developer Tools session</a> from Google I/O '11</p>
+
+
<h2 id="what">What is Property Animation?</h2>
A property animation changes a property's (a field in
an object) value over a specified length of time. To animate something, you specify the
@@ -108,6 +114,7 @@ parent.link=index.html
default is set to refresh every 10 ms, but the speed in which your application can refresh frames is
ultimately dependent on how busy the system is overall and how fast the system can service the underlying timer.</li>
</ul>
+
<h3 id="how">How the property animation system works</h3>
@@ -894,99 +901,5 @@ resources.</p>
<li>{@link android.animation.AnimatorSet} - <code>&lt;set&gt;</code></li>
</ul>
- <p>Both <code>&lt;animator&gt;</code> ({@link android.animation.ValueAnimator}) and
- <code>&lt;objectAnimator&gt;</code> ({@link android.animation.ObjectAnimator}) have the following
- attributes:</p>
-
- <dl>
- <dt><code>android:duration</code></dt>
-
- <dd>The number of milliseconds that the animation runs. The default is 300 ms.</dd>
-
- <dt><code>android:valueFrom</code> and <code>android:valueTo</code></dt>
-
- <dd>The values being animated between. These are restricted to numbers (<code>float</code> or
- <code>int</code>) and color values (such as #00ff00). They can be <code>float</code>, <code>int</code>, colors,
- or any kind of <code>Object</code> when creating animations programmatically.</dd>
-
- <dt><code>android:valueType</code></dt>
-
- <dd>Set to either <code>"floatType"</code> or <code>"intType"</code>. The default is
- <code>"floatType"</code> unless you specify something else or if the <code>valuesFrom</code>
- and <code>valuesTo</code> values are colors.</dd>
-
- <dt><code>android:startOffset</code></dt>
-
- <dd>The delay, in milliseconds, before the animation begins playing (after calling {@link
- android.animation.ValueAnimator#start start()}).</dd>
+<p>See <a href="{@docRoot}guide/topics/resources/animation-resource.html#Property">Animation Resources</a>
- <dt><code>android:repeatCount</code></dt>
-
- <dd>How many times to repeat an animation. Set to <code>"-1"</code> to infinitely repeat or
- to a positive integer. For example, a value of <code>"1"</code> means that the animation is
- repeated once after the initial run of the animation, so the animation plays a total of two
- times. The default value is <code>"0"</code>, which means no repetition.</dd>
-
- <dt><code>android:repeatMode</code></dt>
-
- <dd>How an animation behaves when it reaches the end of the animation.
- <code>android:repeatCount</code> must be set to a positive integer or <code>"-1"</code> for
- this attribute to have an effect. Set to <code>"reverse"</code> to have the animation reverse
- direction with each iteration or <code>"repeat"</code> to have the animation loop from the
- beginning each time.</dd>
- </dl>
-
- <p>The <code>&lt;objectAnimator&gt;</code> ({@link android.animation.ObjectAnimator}) element has the
- additional attribute <code>android:propertyName</code>, that lets you specify the name of the
-property
- being animated. The <code>&lt;objectAnimator&gt;</code> element does not expose a <code>target</code>
- attribute, however, so you cannot set the object to animate in the XML declaration. You have to
- inflate the XML resource by calling {@link android.animation.AnimatorInflater#loadAnimator
- loadAnimator()} and call {@link android.animation.ObjectAnimator#setTarget setTarget()} to set
- the target object unlike the underlying {@link android.animation.ObjectAnimator},
- before calling {@link android.animation.ObjectAnimator#start start()}.</p>
-
- <p>The <code>&lt;set&gt;</code> element ({@link android.animation.AnimatorSet}) exposes a single
- attribute, <code>android:ordering</code>. Set this attribute to <code>"together"</code> (default)
-to play
- all the animations in this set at once. Set this attribute to <code>"sequentially"</code> to play
- the animations in the order they are declared.</p>
-
- <p>You can specify nested <code>&lt;set&gt;</code> elements to further group animations together.
-The
- animations that you want to group together should be children of the <code>&lt;set&gt;</code> tag and can
- define their own <code>ordering</code> attribute.</p>
-
- <p>As an example, this XML code creates an {@link android.animation.AnimatorSet} object that
- animates x and y at the same time, then runs an animation that fades an object out:</p>
- <pre>
-&lt;set android:ordering="sequentially"&gt;
- &lt;set&gt;
- &lt;objectAnimator
- android:propertyName="x"
- android:duration="500"
- android:valueTo="400"
- android:valueType="int"/&gt;
- &lt;objectAnimator
- android:propertyName="y"
- android:duration="500"
- android:valueTo="300"
- android:valueType="int"/&gt;
- &lt;/set&gt;
- &lt;objectAnimator
- android:propertyName="alpha"
- android:duration="500"
- android:valueTo="0f"/&gt;
-&lt;/set&gt;
-</pre>
-
- <p>In order to run this animation, you must inflate the XML resources in your code to an {@link
- android.animation.AnimatorSet} object, and then set the target objects for all of the animations
- before starting the animation set. Calling {@link android.animation.AnimatorSet#setTarget
- setTarget()} sets a single target object for all children of the {@link
- android.animation.AnimatorSet}.</p>
-
-<p class="note"><strong>Tip:</strong> To see how the ADT layout editor allows you to develop and
-preview animations in your layout, watch the <a
-href="http://www.youtube.com/watch?v=Oq05KqjXTvs&feature=player_detailpage#t=1709s">Android
-Developer Tools session</a> from Google I/O '11</p>
diff --git a/docs/html/guide/topics/graphics/renderscript.html b/docs/html/guide/topics/graphics/renderscript.html
new file mode 100644
index 000000000000..454d39288d73
--- /dev/null
+++ b/docs/html/guide/topics/graphics/renderscript.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0;url=http://developer.android.com/guide/topics/renderscript/index.html">
+<title>Redirecting...</title>
+</head>
+<body>
+<p>You should be redirected. Please <a
+href="http://developer.android.com/guide/topics/renderscript/index.html">click here</a>.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/html/guide/topics/graphics/renderscript.jd b/docs/html/guide/topics/graphics/renderscript.jd
deleted file mode 100644
index 180322f55435..000000000000
--- a/docs/html/guide/topics/graphics/renderscript.jd
+++ /dev/null
@@ -1,716 +0,0 @@
-page.title=3D Rendering and Computation with Renderscript
-parent.title=Graphics
-parent.link=index.html
-@jd:body
-
- <div id="qv-wrapper">
- <div id="qv">
- <h2>In this document</h2>
-
- <ol>
- <li><a href="#overview">Renderscript System Overview</a></li>
-
- <li>
- <a href="#api">API Overview</a>
-
- <ol>
- <li><a href="#native-api">Native Renderscript APIs</a></li>
-
- <li><a href="#reflective-api">Reflected layer APIs</a></li>
-
- <li><a href="#graphics-api">Graphics APIs</a></li>
- </ol>
- </li>
-
- <li>
- <a href="#developing">Developing a Renderscript application</a>
-
- <ol>
- <li><a href="#hello-graphics">The Hello Graphics application</a></li>
- </ol>
- </li>
- </ol>
- <h2>Related Samples</h2>
- <ol>
- <li><a href="{@docRoot}resources/samples/Renderscript/Balls/index.html">Balls</a></li>
- <li><a href="{@docRoot}resources/samples/Renderscript/Fountain/index.html">Fountain</a></li>
- <li><a href="{@docRoot}resources/samples/Renderscript/HelloCompute/index.html">Hello Compute</a></li>
- <li><a href="{@docRoot}resources/samples/Renderscript/HelloWorld/index.html">Hello World</a></li>
- <li><a href="{@docRoot}resources/samples/Renderscript/Samples/index.html">Samples</a></li>
- </ol>
- </div>
- </div>
-
- <p>The Renderscript system offers high performance 3D rendering and mathematical computation at
- the native level. The Renderscript APIs are intended for developers who are comfortable with
- developing in C (C99 standard) and want to maximize performance in their applications. The
- Renderscript system improves performance by running as native code on the device, but it also
- features cross-platform functionality. To achieve this, the Android build tools compile your
- Renderscript <code>.rs</code> file to intermediate bytecode and package it inside your
- application's <code>.apk</code> file. On the device, the bytecode is compiled (just-in-time) to
- machine code that is further optimized for the device that it is running on. This eliminates the
- need to target a specific architecture during the development process. The compiled code on the
- device is cached, so subsequent uses of the Renderscript enabled application do not recompile the
- intermediate code.</p>
-
- <p>The disadvantage of the Renderscript system is that it adds complexity to the development and
- debugging processes. Debugging visibility can be limited, because the
- Renderscript system can execute on processors other than the main CPU (such as the GPU), so if
- this occurs, debugging becomes more difficult. The target use is for performance
- critical code where the traditional framework APIs (such as using {@link android.opengl}) are not sufficient.
- If what you are rendering or computing is very simple and does not require much processing power, you should still use the
- traditional framework APIs for ease of development. Remember the tradeoffs between development and
- debugging complexity versus performance when deciding to use Renderscript. </p>
-
- <p>For an example of Renderscript in action, see the 3D carousel view in the Android 3.0 versions
- of Google Books and YouTube or install the Renderscript sample applications that are shipped with
- the SDK in <code>&lt;sdk_root&gt;/samples/android-11/Renderscript</code>.</p>
-
- <h2 id="overview">Renderscript System Overview</h2>
-
- <p>The Renderscript system adopts a control and slave architecture where the low-level native
- code is controlled by the higher level Android system that runs in the virtual machine (VM). When
- you use the Renderscript system, there are three layers that exist:</p>
-
- <ul>
- <li>The native Renderscript layer consists of native libraries that are packaged with the SDK.
- The native Renderscript <code>.rs</code> files compute mathematical operations, render graphics,
- or both. This layer does the intensive computation or graphics rendering and returns the result
- back to the Android VM through the reflected layer.</li>
-
- <li>The reflected layer is a set of generated Android framework classes reflected from
- the native Renderscript code that you wrote. This layer acts as a bridge between the native
- Renderscript layer and the Android system layer. The Android build tools automatically generate
- the classes for this layer during the build process. This layer also includes a set of Android
- framework APIs that provide the memory and resource allocation classes to support this layer.</li>
-
- <li>The Android system layer consists of the traditional framework APIs, which include the Renderscript
- APIs in {@link android.renderscript}. This layer handles things such as the Activity lifecycle
- management of your application and calls the reflected layer to communicate with the native Renderscript code.</li>
- </ul>
-
- <p>To fully understand how the Renderscript system works, you must understand how the reflected
- layer is generated and how it interacts with the native Renderscript layer and Android system
- layer. The reflected layer provides the entry points into the native code, enabling the Android
- system to give high level commands like, "rotate the view" or "filter the bitmap" to the
- native layer, which does the heavy lifting. To accomplish this, you need to create logic
- to hook together all of these layers so that they can correctly communicate.</p>
-
- <p>At the root of everything is your Renderscript, which is the actual C code that you write and
- save to a <code>.rs</code> file in your project. There are two kinds of Renderscripts: compute
- and graphics. A compute Renderscript does not do any graphics rendering while a graphics
- Renderscript does.</p>
-
- <p>When you create Renderscript <code>.rs</code> files, equivalent, reflected classes
- are generated by the build tools and expose the native functions and data types and structures
- to the Android system. The following list describes the major components of your native Renderscript
- code that is reflected:</p>
-
- <ul>
- <li>The non-static functions in your Renderscript (<code>.rs</code> file) are reflected into
- <code><em>ScriptC_renderscript_filename</em></code> of type {@link
- android.renderscript.ScriptC}.</li>
-
- <li>Any non-static, global Renderscript variables are reflected into
- <code><em>ScriptC_renderscript_filename</em></code>.
- Accessor methods are generated, so the Android system layer can access the values.
- The <code>get</code> method comes with a one-way communication restriction.
- The Android system layer always caches the last value that is set and returns that during a call to a <code>get</code> method.
- If the native Renderscript code changes the value, the change does not propagate back to the Android system layer.
- If the global variables are initialized in the native Renderscript code, those values are used
- to initialize the corresponding values in the Android system. If global variables are marked as <code>const</code>,
- then a <code>set</code> method is not generated.
- </li>
-
- <li>Structs are reflected into their own classes, one for each struct, into a class named
- <code>ScriptField_<em>struct_name</em></code> of type {@link
- android.renderscript.Script.FieldBase}.</li>
-
- <li>Global pointers have a special property. They provide attachment points where the Android system can attach allocations.
- If the global pointer is a user defined structure type, it must be a type that is legal for reflection (primitives
- or Renderscript data types). The Android system can call the reflected class to allocate memory and
- optionally populate data, then attach it to the Renderscript.
- For arrays of basic types, the procedure is similar, except a reflected class is not needed.
- Renderscripts should not directly set the exported global pointers.</li>
- </ul>
-
- <p>The Android framework API also has a corresponding Renderscript context object, {@link
- android.renderscript.RenderScript} (for a compute Renderscript) or {@link
- android.renderscript.RenderScriptGL} (for a graphics Renderscript). This context object allows
- you to bind to the reflected Renderscript class, so that the Renderscript context knows what its
- corresponding native Renderscript is. If you have a graphics Renderscript context, you can also
- specify a variety of Programs (stages in the graphics pipeline) to tweek how your graphics are
- rendered. A graphics Renderscript context also needs a surface to render on, {@link
- android.renderscript.RSSurfaceView}, which gets passed into its constructor.</p>
-
- <h2 id="api">API overview</h2>
-
- <p>Renderscript code is compiled and executed in a compact and well defined runtime, which has
- access to a limited amount of functions. Renderscript cannot use the NDK or standard C functions,
- because these functions are assumed to be running on a standard CPU. The Renderscript runtime
- chooses the best processor to execute the code, which may not be the CPU, so it cannot guarantee
- support for standard C libraries. What Renderscript does offer is an API that supports intensive
- computation with an extensive collection of math APIs. The following sections group the APIs
- into three distinct categories.</p>
-
-
- <h3 id="native-api">Native Renderscript APIs</h3>
-
- <p>The Renderscript headers are located in the <code>include</code> and
- <code>clang-include</code> directories in the
- <code>&lt;sdk_root&gt;/platforms/android-11/renderscript</code> directory of the Android SDK.
- The headers are automatically included for you, except for the graphics specific header,
- which you can define as follows:</p>
-
-<pre>#include "rs_graphics.rsh"</pre>
-
-<p>Some key features of the native Renderscript libraries include:
- <ul>
- <li>A large collection of math functions with both scalar and vector typed overloaded versions
- of many common routines. Operations such as adding, multiplying, dot product, and cross product
- are available.</li>
- <li>Conversion routines for primitive data types and vectors, matrix routines, date and time
- routines, and graphics routines.</li>
- <li>Logging functions</li>
- <li>Graphics rendering functions</li>
- <li>Memory allocation request features</li>
- <li>Data types and structures to support the Renderscript system such as
- Vector types for defining two-, three-, or four-vectors.</li>
- </ul>
-
- <h3 id="reflective-api">Reflected layer APIs</h3>
-
- <p>These classes are mainly used by the reflected classes that are generated from your native Renderscript
- code. They allocate and manage memory for your Renderscript on the Android system side.
- You normally do not need to call these classes directly.</p>
-
- <p>Because of the constraints of the Renderscript native layer, you cannot do any dynamic
- memory allocation in your Renderscript <code>.rs</code> file.
- The native Renderscript layer can request memory from the Android system layer, which allocates memory
- for you and does reference counting to figure out when to free the memory. A memory allocation
- is taken care of by the {@link android.renderscript.Allocation} class and memory is requested
- in your Renderscript code with the <code>the rs_allocation</code> type.
- All references to Renderscript objects are counted, so when your Renderscript native code
- or system code no longer references a particular {@link android.renderscript.Allocation}, it destroys itself.
- Alternatively, you can call {@link android.renderscript.Allocation#destroy destroy()} from the
- Android system level, which decreases the reference to the {@link android.renderscript.Allocation}.
- If no references exist after the decrease, the {@link android.renderscript.Allocation} destroys itself.
- The Android system object, which at this point is just an empty shell, is eventually garbage collected.
- </p>
-
- <p>The following classes are mainly used by the reflected layer classes:</p>
-
- <table>
- <tr>
- <th>Android Object Type</th>
-
- <th>Renderscript Native Type</th>
-
- <th>Description</th>
- </tr>
-
- <tr>
- <td>{@link android.renderscript.Element}</td>
-
- <td>rs_element</td>
-
- <td>
- An {@link android.renderscript.Element} is the most basic element of a memory type. An
- element represents one cell of a memory allocation. An element can have two forms: Basic or
- Complex. They are typically created from C structures in your Renderscript
- code during the reflection process. Elements cannot contain pointers or nested arrays.
- The other common source of elements is bitmap formats.
-
- <p>A basic element contains a single component of data of any valid Renderscript data type.
- Examples of basic element data types include a single float value, a float4 vector, or a
- single RGB-565 color.</p>
-
- <p>Complex elements contain a list of sub-elements and names that is basically a reflection
- of a C struct. You access the sub-elements by name from a script or vertex program. The
- most basic primitive type determines the data alignment of the structure. For example, a
- float4 vector is alligned to <code>sizeof(float)</code> and not
- <code>sizeof(float4)</code>. The ordering of the elements in memory are the order in which
- they were added, with each component aligned as necessary.</p>
- </td>
- </tr>
-
- <tr>
- <td>{@link android.renderscript.Type}</td>
-
- <td>rs_type</td>
-
- <td>A Type is an allocation template that consists of an element and one or more dimensions.
- It describes the layout of the memory but does not allocate storage for the data that it
- describes. A Type consists of five dimensions: X, Y, Z, LOD (level of detail), and Faces (of
- a cube map). You can assign the X,Y,Z dimensions to any positive integer value within the
- constraints of available memory. A single dimension allocation has an X dimension of greater
- than zero while the Y and Z dimensions are zero to indicate not present. For example, an
- allocation of x=10, y=1 is considered two dimensional and x=10, y=0 is considered one
- dimensional. The LOD and Faces dimensions are booleans to indicate present or not
- present.</td>
- </tr>
-
- <tr>
- <td>{@link android.renderscript.Allocation}</td>
-
- <td>rs_allocation</td>
-
- <td>
- <p>An {@link android.renderscript.Allocation} provides the memory for applications. An {@link
- android.renderscript.Allocation} allocates memory based on a description of the memory that
- is represented by a {@link android.renderscript.Type}. The type describes an array of elements that
- represent the memory to be allocated. Allocations are the primary way data moves into and
- out of scripts.</p>
-
- <p>Memory is user-synchronized and it's possible for allocations to exist in multiple
- memory spaces concurrently. For example, if you make a call to the graphics card to load a
- bitmap, you give it the bitmap to load from in the system memory. After that call returns,
- the graphics memory contains its own copy of the bitmap so you can choose whether or not to
- maintain the bitmap in the system memory. If the Renderscript system modifies an allocation
- that is used by other targets, it must call {@link android.renderscript#syncAll syncAll()} to push the updates to
- the memory. Otherwise, the results are undefined.</p>
-
- <p>Allocation data is uploaded in one of two primary ways: type checked and type unchecked.
- For simple arrays there are <code>copyFrom()</code> functions that take an array from the
- Android system and copy it to the native layer memory store. Both type checked and
- unchecked copies are provided. The unchecked variants allow the Android system to copy over
- arrays of structures because it does not support structures. For example, if
- there is an allocation that is an array n floats, you can copy the data contained in a
- float[n] array or a byte[n*4] array.</p>
- </td>
- </tr>
-
- <tr>
- <td>{@link android.renderscript.Script}</td>
-
- <td>rs_script</td>
-
- <td>Renderscript scripts do much of the work in the native layer. This class is generated
- from a Renderscript file that has the <code>.rs</code> file extension. This class is named
- <code>ScriptC_<em>rendersript_filename</em></code> when it gets generated.</td>
- </tr>
- </table>
-
- <h3 id="graphics-api">Graphics API</h3>
-
- <p>Renderscript provides a number of graphics APIs for hardware-accelerated 3D rendering. The
- Renderscript graphics APIs include a stateful context, {@link
- android.renderscript.RenderScriptGL} that contains the current rendering state. The primary state
- consists of the objects that are attached to the rendering context, which are the graphics Renderscript
- and the four program types. The main working function of the graphics Renderscript is the code that is
- defined in the <code>root()</code> function. The <code>root()</code> function is called each time the surface goes through a frame
- refresh. The four program types mirror a traditional graphical rendering pipeline and are:</p>
-
- <ul>
- <li>Vertex</li>
-
- <li>Fragment</li>
-
- <li>Store</li>
-
- <li>Raster</li>
- </ul>
-
- <p>Graphical scripts have more properties beyond a basic computational script, and they call the
- 'rsg'-prefixed functions defined in the <code>rs_graphics.rsh</code> header file. A graphics
- Renderscript can also set four pragmas that control the default bindings to the {@link
- android.renderscript.RenderScriptGL} context when the script is executing:</p>
-
- <ul>
- <li>stateVertex</li>
-
- <li>stateFragment</li>
-
- <li>stateRaster</li>
-
- <li>stateStore</li>
- </ul>
-
- <p>The possible values are <code>parent</code> or <code>default</code> for each pragma. Using
- <code>default</code> says that when a script is executed, the bindings to the graphical context
- are the system defaults. Using <code>parent</code> says that the state should be the same as it
- is in the calling script. If this is a root script, the parent
- state is taken from the bind points as set in the {@link android.renderscript.RenderScriptGL}
- bind methods in the control environment (VM environment).</p>
-
- <p>For example, you can define this at the top of your native graphics Renderscript code:</p>
- <pre>
-#pragma stateVertex(parent)
-#pragma stateStore(parent)
-</pre>
-
- <p>The following table describes the major graphics specific APIs that are available to you:</p>
-
- <table>
- <tr>
- <th>Android Object Type</th>
-
- <th>Renderscript Native Type</th>
-
- <th>Description</th>
- </tr>
-
- <tr>
- <td>{@link android.renderscript.ProgramVertex}</td>
-
- <td>rs_program_vertex</td>
-
- <td>
- <p>The Renderscript vertex program, also known as a vertex shader, describes the stage in the
- graphics pipeline responsible for manipulating geometric data in a user-defined way. The
- object is constructed by providing Renderscript with the following data:</p>
-
- <ul>
- <li>An Element describing its varying inputs or attributes</li>
-
- <li>GLSL shader string that defines the body of the program</li>
-
- <li>a Type that describes the layout of an Allocation containing constant or uniform
- inputs</li>
- </ul>
-
- <p>Once the program is created, bind it to the {@link android.renderscript.RenderScriptGL}
- graphics context by calling
- {@link android.renderscript.RenderScriptGL#bindProgramVertex bindProgramVertex()}. It is then used for all
- subsequent draw calls until you bind a new program. If the program has constant inputs, the
- user needs to bind an allocation containing those inputs. The allocation's type must match
- the one provided during creation. The Renderscript library then does all the necessary
- plumbing to send those constants to the graphics hardware. Varying inputs to the shader,
- such as position, normal, and texture coordinates are matched by name between the input
- Element and the Mesh object being drawn. The signatures don't have to be exact or in any
- strict order. As long as the input name in the shader matches a channel name and size
- available on the mesh, the run-time would take care of connecting the two. Unlike OpenGL,
- there is no need to link the vertex and fragment programs.</p>
- <p> To bind shader constructs to the Program, declare a struct containing the necessary shader constants in your native Renderscript code.
- This struct is generated into a reflected class that you can use as a constant input element
- during the Program's creation. It is an easy way to create an instance of this struct as an allocation.
- You would then bind this Allocation to the Program and the Renderscript system sends the data that
- is contained in the struct to the hardware when necessary. To update shader constants, you change the values
- in the Allocation and notify the native Renderscript code of the change.</p>
- </td>
- </tr>
-
- <tr>
- <td>{@link android.renderscript.ProgramFragment}</td>
-
- <td>rs_program_fragment</td>
-
- <td><p>The Renderscript fragment program, also known as the fragment shader, is responsible for
- manipulating pixel data in a user-defined way. It's constructed from a GLSL shader string
- containing the program body, textures inputs, and a Type object describing the constants used
- by the program. Like the vertex programs, when an allocation with constant input values is
- bound to the shader, its values are sent to the graphics program automatically. Note that the
- values inside the allocation are not explicitly tracked. If they change between two draw
- calls using the same program object, notify the runtime of that change by calling
- rsgAllocationSyncAll so it could send the new values to hardware. Communication between the
- vertex and fragment programs is handled internally in the GLSL code. For example, if the
- fragment program is expecting a varying input called varTex0, the GLSL code inside the
- program vertex must provide it.</p>
- <p> To bind shader constructs to the this Program, declare a struct containing the necessary shader constants in your native Renderscript code.
- This struct is generated into a reflected class that you can use as a constant input element
- during the Program's creation. It is an easy way to create an instance of this struct as an allocation.
- You would then bind this Allocation to the Program and the Renderscript system sends the data that
- is contained in the struct to the hardware when necessary. To update shader constants, you change the values
- in the Allocation and notify the native Renderscript code of the change.</p></td>
- </tr>
-
- <tr>
- <td>{@link android.renderscript.ProgramStore}</td>
-
- <td>rs_program_store</td>
-
- <td>The Renderscript ProgramStore contains a set of parameters that control how the graphics
- hardware writes to the framebuffer. It could be used to enable and disable depth writes and
- testing, setup various blending modes for effects like transparency and define write masks
- for color components.</td>
- </tr>
-
- <tr>
- <td>{@link android.renderscript.ProgramRaster}</td>
-
- <td>rs_program_raster</td>
-
- <td>Program raster is primarily used to specify whether point sprites are enabled and to
- control the culling mode. By default back faces are culled.</td>
- </tr>
-
- <tr>
- <td>{@link android.renderscript.Sampler}</td>
-
- <td>rs_sampler</td>
-
- <td>A Sampler object defines how data is extracted from textures. Samplers are bound to
- Program objects (currently only a Fragment Program) alongside the texture whose sampling they
- control. These objects are used to specify such things as edge clamping behavior, whether
- mip-maps are used and the amount of anisotropy required. There may be situations where
- hardware limitations prevent the exact behavior from being matched. In these cases, the
- runtime attempts to provide the closest possible approximation. For example, the user
- requested 16x anisotropy, but only 8x was set because it's the best available on the
- hardware.</td>
- </tr>
-
- <tr>
- <td>{@link android.renderscript.Mesh}</td>
-
- <td>rs_mesh</td>
-
- <td>A collection of allocations that represent vertex data (positions, normals, texture
- coordinates) and index data such as triangles and lines. Vertex data can be interleaved
- within one allocation, provided separately as multiple allocation objects, or done as a
- combination of the above. The layout of these allocations will be extracted from their
- Elements. When a vertex channel name matches an input in the vertex program, Renderscript
- automatically connects the two. Moreover, even allocations that cannot be directly mapped to
- graphics hardware can be stored as part of the mesh. Such allocations can be used as a
- working area for vertex-related computation and will be ignored by the hardware. Parts of the
- mesh could be rendered with either explicit index sets or primitive types.</td>
- </tr>
-
- <tr>
- <td>{@link android.renderscript.Font}</td>
-
- <td>rs_font</td>
-
- <td>
- <p>This class gives you a way to draw hardware accelerated text. Internally, the glyphs are
- rendered using the Freetype library, and an internal cache of rendered glyph bitmaps is
- maintained. Each font object represents a combination of a typeface and point sizes.
- Multiple font objects can be created to represent faces such as bold and italic and to
- create different font sizes. During creation, the framework determines the device screen's
- DPI to ensure proper sizing across multiple configurations.</p>
-
- <p>Font rendering can impact performance. Even though though the state changes are
- transparent to the user, they are happening internally. It is more efficient to render
- large batches of text in sequence, and it is also more efficient to render multiple
- characters at once instead of one by one.</p>
-
- <p>Font color and transparency are not part of the font object and can be freely modified
- in the script to suit the your needs. Font colors work as a state machine, and every new
- call to draw text will use the last color set in the script.</p>
- </td>
- </tr>
- </table>
-
-
- <h2 id="developing">Developing a Renderscript application</h2>
-
- <p>The basic workflow of developing a Renderscript application is:</p>
-
- <ol>
- <li>Analyze your application's requirements and figure out what you want to develop with
- Renderscript. To take full advantage of the Renderscript system, you want to use it when the computation
- or graphics performance you're getting with the traditional framework APIs is
- insufficient.</li>
-
- <li>Design the interface of your Renderscript code and implement it using the native
- Renderscript APIs that are included in the Android SDK in
- <code>&lt;sdk_root&gt;/platforms/android-11/renderscript</code>.</li>
-
- <li>Create an Android project as you would normally, in Eclipse or with the
- <code>android</code> tool.</li>
-
- <li>Place your Renderscript files in <code>src</code> folder of the Android project so that the
- build tools can generate the reflected layer classes.</li>
-
- <li>Create your application, calling the Renderscript through the reflected class layer when
- you need to.</li>
-
- <li>Build, install, and run your application as you would normally.</li>
- </ol>
-
- <p>To see how a simple Renderscript application is put together, see the
- <a href="{@docRoot}resources/samples/Renderscript/index.html">Renderscript samples</a>
- and <a href="#hello-graphics">The Hello Graphics Application</a> section of the documentation.</p>
-
- <h3 id="hello-graphics">The Hello Graphics Application</h3>
-
- <p>This small application demonstrates the structure of a simple Renderscript application. You
- can model your Renderscript application after the basic structure of this application. You can
- find the complete source in the SDK in the
- <code>&lt;android-sdk&gt;/samples/android-11/HelloWorldRS directory</code>. The
- application uses Renderscript to draw the string, "Hello World!" to the screen and redraws the
- text whenever the user touches the screen at the location of the touch. This application is only
- a demonstration and you should not use the Renderscript system to do something this trivial. The
- application contains the following source files:</p>
-
- <ul>
- <li><code>HelloWorld</code>: The main Activity for the application. This class is present to
- provide Activity lifecycle management. It mainly delegates work to HelloWorldView, which is the
- Renderscript surface that the sample actually draws on.</li>
-
- <li><code>HelloWorldView</code>: The Renderscript surface that the graphics render on. If you
- are using Renderscript for graphics rendering, you must have a surface to render on. If you are
- using it for computatational operations only, then you do not need this.</li>
-
- <li><code>HelloWorldRS</code>: The class that calls the native Renderscript code through high
- level entry points that are generated by the Android build tools.</li>
-
- <li><code>helloworld.rs</code>: The Renderscript native code that draws the text on the
- screen.</li>
-
- <li>
- <p>The <code>&lt;project_root&gt;/gen</code> directory contains the reflected layer classes
- that are generated by the Android build tools. You will notice a
- <code>ScriptC_helloworld</code> class, which is the reflective version of the Renderscript
- and contains the entry points into the <code>helloworld.rs</code> native code. This file does
- not appear until you run a build.</p>
- </li>
- </ul>
-
- <p>Each file has its own distinct use. The following files comprise the main parts of the sample and
- demonstrate in detail how the sample works:</p>
-
- <dl>
- <dt><code>helloworld.rs</code></dt>
-
- <dd>
- The native Renderscript code is contained in the <code>helloworld.rs</code> file. Every
- <code>.rs</code> file must contain two pragmas that define the version of Renderscript
- that it is using (1 is the only version for now), and the package name that the reflected
- classes should be generated with. For example:
-<pre>
-#pragma version(1)
-
-#pragma rs java_package_name(com.my.package.name)
-</pre>
- <p>An <code>.rs</code> file can also declare two special functions:</p>
-
- <ul>
- <li>
- <code>init()</code>: This function is called once for each instance of this Renderscript
- file that is loaded on the device, before the script is accessed in any other way by the
- Renderscript system. The <code>init()</code> is ideal for doing one time setup after the
- machine code is loaded such as initializing complex constant tables. The
- <code>init()</code> function for the <code>helloworld.rs</code> script sets the initial
- location of the text that is rendered to the screen:
- <pre>
-void init(){
- gTouchX = 50.0f;
- gTouchY = 50.0f;
-}
-</pre>
- </li>
-
- <li>
- <code>root()</code>: This function is the default worker function for this Renderscript
- file. For graphics Renderscript applications, like this one, the Renderscript system
- expects this function to render the frame that is going to be displayed. It is called
- every time the frame refreshes. The <code>root()</code> function for the
- <code>helloworld.rs</code> script sets the background color of the frame, the color of
- the text, and then draws the text where the user last touched the screen:
-<pre>
-int root(int launchID) {
- // Clear the background color
- rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- // Tell the runtime what the font color should be
- rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
- // Introduce ourselves to the world by drawing a greeting
- // at the position that the user touched on the screen
- rsgDrawText("Hello World!", gTouchX, gTouchY);
-
- // Return value tells RS roughly how often to redraw
- // in this case 20 ms
- return 20;
-}
-</pre>
-
- <p>The return value, <code>20</code>, is the desired frame refresh rate in milliseconds.
- The real screen refresh rate depends on the hardware, computation, and rendering
- complexity that the <code>root()</code> function has to execute. A value of
- <code>0</code> tells the screen to render only once and to only render again when a
- change has been made to one of the properties that are being modified by the Renderscript
- code.</p>
-
- <p>Besides the <code>init()</code> and <code>root()</code> functions, you can define the
- other native functions, structs, data types, and any other logic for your Renderscript.
- You can even define separate header files as <code>.rsh</code> files.</p>
- </li>
- </ul>
- </dd>
-
- <dt><code>ScriptC_helloworld</code></dt>
-
- <dd>This class is generated by the Android build tools and is the reflected version of the
- <code>helloworld.rs</code> Renderscript. It provides a high level entry point into the
- <code>helloworld.rs</code> native code by defining the corresponding methods that you can call
- from the traditional framework APIs.</dd>
-
- <dt><code>helloworld.bc</code> bytecode</dt>
-
- <dd>This file is the intermediate, platform-independent bytecode that gets compiled on the
- device when the Renderscript application runs. It is generated by the Android build tools and
- is packaged with the <code>.apk</code> file and subsequently compiled on the device at runtime.
- This file is located in the <code>&lt;project_root&gt;/res/raw/</code> directory and is named
- <code>rs_filename.bc</code>. You need to bind these files to your Renderscript context before
- call any Renderscript code from your Android application. You can reference them in your code
- with <code>R.id.rs_filename</code>.</dd>
-
- <dt><code>HelloWorldView</code> class</dt>
-
- <dd>
- This class represents the Surface View that the Renderscript graphics are drawn on. It does
- some administrative tasks in the <code>ensureRenderScript()</code> method that sets up the
- Renderscript system. This method creates a {@link android.renderscript.RenderScriptGL}
- object, which represents the context of the Renderscript and creates a default surface to
- draw on (you can set the surface properties such as alpha and bit depth in the {@link
- android.renderscript.RenderScriptGL.SurfaceConfig} class ). When a {@link
- android.renderscript.RenderScriptGL} is instantiated, this class calls the
- <code>HelloRS</code> class and creates the instance of the actual Renderscript graphics
- renderer.
- <pre>
-// Renderscipt context
-private RenderScriptGL mRS;
-// Script that does the rendering
-private HelloWorldRS mRender;
-
- private void ensureRenderScript() {
- if (mRS == null) {
- // Initialize Renderscript with desired surface characteristics.
- // In this case, just use the defaults
- RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
- mRS = createRenderScriptGL(sc);
-
- // Create an instance of the Renderscript that does the rendering
- mRender = new HelloWorldRS();
- mRender.init(mRS, getResources());
- }
- }
-</pre>
-
- <p>This class also handles the important lifecycle events and relays touch events to the
- Renderscript renderer. When a user touches the screen, it calls the renderer,
- <code>HelloWorldRS</code> and asks it to draw the text on the screen at the new location.</p>
- <pre>
-public boolean onTouchEvent(MotionEvent ev) {
- // Pass touch events from the system to the rendering script
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mRender.onActionDown((int)ev.getX(), (int)ev.getY());
- return true;
- }
- return false;
-}
-</pre>
- </dd>
-
- <dt><code>HelloWorldRS</code></dt>
-
- <dd>
- This class represents the Renderscript renderer for the <code>HelloWorldView</code> Surface
- View. It interacts with the native Renderscript code that is defined in
- <code>helloworld.rs</code> through the interfaces exposed by <code>ScriptC_helloworld</code>.
- To be able to call the native code, it creates an instance of the Renderscript reflected
- class, <code>ScriptC_helloworld</code>. The reflected Renderscript object binds the
- Renderscript bytecode (<code>R.raw.helloworld</code>) and the Renderscript context, {@link
- android.renderscript.RenderScriptGL}, so the context knows to use the right Renderscript to
- render its surface.
- <pre>
-private Resources mRes;
-private RenderScriptGL mRS;
-private ScriptC_helloworld mScript;
-
-private void initRS() {
- mScript = new ScriptC_helloworld(mRS, mRes, R.raw.helloworld);
- mRS.bindRootScript(mScript);
-}
-</pre>
- </dd>
- </dl> \ No newline at end of file
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
new file mode 100644
index 000000000000..e4c22830fc32
--- /dev/null
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -0,0 +1,38 @@
+page.title=Compute
+parent.title=RenderScript
+parent.link=index.html
+@jd:body
+
+ <div id="qv-wrapper">
+ <div id="qv">
+
+ <h2>Related Samples</h2>
+
+ <ol>
+ <li><a href="{@docRoot}resources/samples/RenderScript/HelloCompute/index.html">Hello
+ Compute</a></li>
+ <li><a href="{@docRoot}resources/samples/RenderScript/Balls/index.html">Balls</a></li>
+ </ol>
+ </div>
+ </div>
+
+ <p>RenderScript exposes a set of compute APIs that you can use to do intensive computational operations.
+ You can use the compute APIs in the context of a graphics RenderScript such as calculating the
+ transformation of many geometric objects in a scene. You can also create a standalone compute RenderScript that does not
+ draw anything to the screen such as bitmap image processing for a photo editor application.
+ The RenderScript compute APIs are mainly defined in the <code>rs_cl.rsh</code> header</p>
+
+ <p>Compute RenderScripts are simpler to setup and implement as there is no graphics rendering involved.
+ You can offload computational aspects of your application to RenderScript by creating a native RenderScript
+ file (.rs) and using the generated reflected layer class to call functions in the <code>.rs</code> file.
+
+ <p>See the <a href="{@docRoot}resources/samples/RenderScript/HelloCompute/index.html">HelloCompute</a>
+ sample in the Android SDK for more
+ information on how to create a simple compute RenderScript.</p>
+ <p>
+ See the <a href="{@docRoot}resources/samples/RenderScript/Balls/index.html">Balls</a>
+ sample in the Android SDK for more
+ information on how to create a compute RenderScript that is used in a graphics RenderScript.
+ The compute RenderScript is contained in
+ <a href="{@docRoot}resources/samples/RenderScript/Balls/src/com/example/android/rs/balls/ball_physics.html">balls_physics.rs</a>.
+ </p> \ No newline at end of file
diff --git a/docs/html/guide/topics/renderscript/graphics.jd b/docs/html/guide/topics/renderscript/graphics.jd
new file mode 100644
index 000000000000..d8be85f124b1
--- /dev/null
+++ b/docs/html/guide/topics/renderscript/graphics.jd
@@ -0,0 +1,619 @@
+page.title=3D Graphics
+parent.title=RenderScript
+parent.link=index.html
+@jd:body
+
+ <div id="qv-wrapper">
+ <div id="qv">
+ <h2>In this document</h2>
+
+ <ol>
+ <li>
+ <a href="#developing">Developing a RenderScript application</a>
+
+ <ol>
+ <li><a href="#hello-graphics">The Hello Graphics application</a></li>
+ </ol>
+ </li>
+ </ol>
+
+ <h2>Related Samples</h2>
+
+ <ol>
+ <li><a href="{@docRoot}resources/samples/RenderScript/Balls/index.html">Balls</a></li>
+
+ <li><a href=
+ "{@docRoot}resources/samples/Renderscript/Fountain/index.html">Fountain</a></li>
+
+ <li><a href="{@docRoot}resources/samples/RenderScript/HelloWorld/index.html">Hello
+ World</a></li>
+
+ <li><a href="{@docRoot}resources/samples/RenderScript/Samples/index.html">Samples</a></li>
+ </ol>
+ </div>
+ </div>
+
+ <p>RenderScript provides a number of graphics APIs for 3D rendering, both at the Android
+ framework level as well as at the native level. For instance, the Android framework APIs let you
+ create meshes and define shaders to customize the graphical rendering pipeline. The native
+ RenderScript graphics APIs lets you draw the actual meshes to render your scene. In general, you
+ will need to be familiar with APIs to appropriately render 3D graphics on an Android-powered
+ device.</p>
+
+ <h2>Creating a Graphics RenderScript</h2>
+
+ <p>Because of the various layers of code when writing a RenderScript application, it is useful to
+ create the following files for a scene that you want to render:</p>
+
+ <ul>
+ <li>The native RenderScript <code>.rs</code> file. This file contains the logic to do the
+ graphics rendering.</li>
+
+ <li>The RenderScript entry point class that allows your view to interact with the code defined
+ in the <code>.rs</code> file. This class contains a RenderScript object(instance of
+ <code>ScriptC_<em>renderscript_file</em></code>), which allows your Android framework code to
+ call the native RenderScript code. This class also creates the {@link
+ android.renderscript.RenderScriptGL} context object, which contains the current rendering state
+ of the RenderScript such as programs (vertex and fragment shaders, for example) that you want
+ to define and bind to the graphics pipeline. The context object attaches to the RenderScript
+ object (instance of <code><em>ScriptC_renderscript_file</em></code>) that does the rendering.
+ Our example names this class <code>HelloWorldRS</code>.</li>
+
+ <li>Create a class that extends {@link android.renderscript.RSSurfaceView} to provide a surface
+ to render on. If you want to implement callbacks from events inherited from {@link
+ android.view.View}, such as {@link android.view.View#onTouchEvent onTouchEvent()} and {@link
+ android.view.View#onKeyDown onKeyDown()}, do so in this class as well.</li>
+
+ <li>Create a class that is the main Activity class, like you would with any Android
+ application. This class sets your {@link android.renderscript.RSSurfaceView} as the content
+ view for this Activity.</li>
+ </ul>
+
+ <p>The following sections describe how to implement these three classes by using the HelloWorld
+ RenderScript sample that is provided in the SDK as a guide (some code has been modified from its
+ original form for simplicity).</p>
+
+ <h3>Creating the native RenderScript file</h3>
+
+ <p>Your native RenderScript code resides in a <code>.rs</code> file in the
+ <code>&lt;project_root&gt;/src/</code> directory. You can also define <code>.rsh</code> header
+ files. This code contains the logic to render your graphics and declares all necessary variables
+ and pointers. Every graphics <code>.rs</code> file generally contains the following items:</p>
+
+ <ul>
+ <li>A pragma (<code>#pragma rs java_package_name(<em>package.name</em>)</code>) that declares
+ the package name of the <code>.java</code> reflection of this RenderScript.</li>
+
+ <li>A pragma (<code>#pragma version(1)</code>) that declares the version of RenderScript that
+ you are using (1 is the only value for now).</li>
+
+ <li>A <code>#include</code> of the rs_graphics.rsh header file.</li>
+
+ <li>A <code>root()</code> function. This is the main worker function for your RenderScript and
+ calls RenderScript graphics APIs to draw meshes to the surface. This function is called every
+ time a frame refresh occurs, which is specified as its return value. A <code>0</code> specified
+ for the return value says to only render the frame when a property of the scene that you are
+ rendering changes. A non-zero positive integer specifies the refresh rate of the frame in
+ milliseconds.
+
+ <p class="note"><strong>Note:</strong> The RenderScript runtime makes its best effort to
+ refresh the frame at the specified rate. For example, if you are creating a live wallpaper
+ and set the return value to 50, the runtime renders the wallpaper at 20fps if it has just
+ enough or more resources to do so, and renders as fast as it can if it does not.</p>
+
+ <p>For more
+ information on using the RenderScript graphics functions, see <a href=
+ "using-graphics-api">Using the Graphics APIs</a>.</p>
+ </li>
+
+ <li>An <code>init()</code> function. This allows you to do any initialization of your
+ RenderScript before the <code>root()</code> function runs, such as initializing variables. This
+ function runs once and is called automatically when the RenderScript starts, before anything
+ else in your RenderScript. Creating this function is optional.</li>
+
+ <li>Any variables, pointers, and structures that you wish to use in your RenderScript code (can
+ be declared in <code>.rsh</code> files if desired)</li>
+ </ul>
+
+ <p>The following code shows how the <code>helloworld.rs</code> file is implemented:</p>
+ <pre>
+#pragma version(1)
+
+// Tell which java package name the reflected files should belong to
+#pragma rs java_package_name(com.android.rs.helloworld)
+
+// Built-in header with graphics APIs
+#include "rs_graphics.rsh"
+
+// gTouchX and gTouchY are variables that are reflected for use
+// by the Android framework API. This RenderScript uses them to be notified of touch events.
+int gTouchX;
+int gTouchY;
+
+// This is invoked automatically when the script is created and initializes the variables
+// in the Android framework layer as well.
+void init() {
+ gTouchX = 50.0f;
+ gTouchY = 50.0f;
+}
+
+int root(int launchID) {
+
+ // Clear the background color
+ rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ // Tell the runtime what the font color should be
+ rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+ // Introuduce ourselves to the world by drawing a greeting
+ // at the position user touched on the screen
+ rsgDrawText("Hello World!", gTouchX, gTouchY);
+
+ // Return value tells RS roughly how often to redraw
+ // in this case 20 ms
+ return 20;
+}
+</pre>
+
+ <h3>Creating the RenderScript entry point class</h3>
+
+ <p>When you create a RenderScript (<code>.rs</code>) file, it is helpful to create a
+ corresponding Android framework class that is an entry point into the <code>.rs</code> file. In
+ this entry point class, you create a RenderScript object by instantiating a
+ <code>ScriptC_<em>rs_filename</em></code> and binding it to the RenderScript context. The
+ RenderScript object is attached to the RenderScript bytecode, which is platform-independent and
+ gets compiled on the device when the RenderScript application runs. Both the
+ <code>ScriptC_<em>rs_filename</em></code> class and bytecode is generated by the Android build
+ tools and is packaged with the <code>.apk</code> file. The bytecode file is located in the
+ <code>&lt;project_root&gt;/res/raw/</code> directory and is named <code>rs_filename.bc</code>.
+ You refer to the bytecode as a resource (<code>R.raw.<em>rs_filename</em></code>). when creating
+ the RenderScript object..</p>
+
+ <p>You then bind the RenderScript object to the RenderScript context, so that the surface view
+ knows what code to use to render graphics. The following code shows how the
+ <code>HelloWorldRS</code> class is implemented:</p>
+ <pre>
+package com.android.rs.helloworld;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class HelloWorldRS {
+ //context and resources are obtained from RSSurfaceView, which calls init()
+ private Resources mRes;
+ private RenderScriptGL mRS;
+
+ //Declare the RenderScript object
+ private ScriptC_helloworld mScript;
+
+ public HelloWorldRS() {
+ }
+
+ /**
+ * This provides us with the RenderScript context and resources
+ * that allow us to create the RenderScript object
+ */
+ public void init(RenderScriptGL rs, Resources res) {
+ mRS = rs;
+ mRes = res;
+ initRS();
+ }
+ /**
+ * Calls native RenderScript functions (set_gTouchX and set_gTouchY)
+ * through the reflected layer class ScriptC_helloworld to pass in
+ * touch point data.
+ */
+ public void onActionDown(int x, int y) {
+ mScript.set_gTouchX(x);
+ mScript.set_gTouchY(y);
+ }
+ /**
+ * Binds the RenderScript object to the RenderScript context
+ */
+ private void initRS() {
+ //create the RenderScript object
+ mScript = new ScriptC_helloworld(mRS, mRes, R.raw.helloworld);
+ //bind the RenderScript object to the RenderScript context
+ mRS.bindRootScript(mScript);
+ }
+}
+
+</pre>
+
+ <h3>Creating the surface view</h3>
+
+ <p>To create a surface view to render graphics on, create a class that extends {@link
+ android.renderscript.RSSurfaceView}. This class also creates a RenderScript context object
+ ({@link android.renderscript.RenderScriptGL} and passes it to the Rendscript entry point class to
+ bind the two. The following code shows how the <code>HelloWorldView</code> class is
+ implemented:</p>
+ <pre>
+package com.android.rs.helloworld;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScriptGL;
+import android.content.Context;
+import android.view.MotionEvent;
+
+public class HelloWorldView extends RSSurfaceView {
+ // RenderScript context
+ private RenderScriptGL mRS;
+ // RenderScript entry point object that does the rendering
+ private HelloWorldRS mRender;
+
+ public HelloWorldView(Context context) {
+ super(context);
+ initRS();
+ }
+
+ private void initRS() {
+ if (mRS == null) {
+ // Initialize RenderScript with default surface characteristics.
+ RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+ //Create the RenderScript context
+ mRS = createRenderScriptGL(sc);
+ // Create an instance of the RenderScript entry point class
+ mRender = new HelloWorldRS();
+ // Call the entry point class to bind it to this context
+ mRender.init(mRS, getResources());
+ }
+ }
+
+ /**
+ * Rebind everything when the window becomes attached
+ */
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ initRS();
+ }
+
+ /**
+ * Stop rendering when window becomes detached
+ */
+ protected void onDetachedFromWindow() {
+ // Handle the system event and clean up
+ mRender = null;
+ if (mRS != null) {
+ mRS = null;
+ destroyRenderScriptGL();
+ }
+ }
+
+ /**
+ * Use callbacks to relay data to RenderScript entry point class
+ */
+ public boolean onTouchEvent(MotionEvent ev) {
+ // Pass touch events from the system to the rendering script
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mRender.onActionDown((int)ev.getX(), (int)ev.getY());
+ return true;
+ }
+
+ return false;
+ }
+}
+
+</pre>
+
+ <h3>Creating the Activity</h3>
+
+ <p>Applications that use RenderScript still adhere to activity lifecyle, and are part of the same
+ view hierarchy as traditional Android applications, which is handled by the Android VM. This
+ Activity class sets its view to be the {@link android.renderscript.RSSurfaceView} and handles
+ lifecycle callback events appropriately. The following code shows how the <code>HelloWorld</code>
+ class is implemented:</p>
+ <pre>
+public class HelloWorldActivity extends Activity {
+
+ //Custom view to use with RenderScript
+ private HelloWorldView view;
+
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ // Create surface view and set it as the content of our Activity
+ mView = new HelloWorldView(this);
+ setContentView(view);
+ }
+
+ protected void onResume() {
+ // Ideally an app should implement onResume() and onPause()
+ // to take appropriate action when the activity loses focus
+ super.onResume();
+ view.resume();
+ }
+
+ protected void onPause() {
+ // Ideally an app should implement onResume() and onPause()
+ // to take appropriate action when the activity loses focus
+ super.onPause();
+ view.pause();
+ }
+}
+</pre>
+
+ <h2>Drawing</h2>
+
+ <h3>Drawing using the rsgDraw functions</h3>
+
+ <p>The native RenderScript APIs provide a few convenient functions to easily draw a polygon to
+ the screen. You call these in your <code>root()</code> function to have them render to the
+ surface view. These functions are available for simple drawing and should not be used for complex
+ graphics rendering:</p>
+
+ <ul>
+ <li><code>rsgDrawRect()</code>: Sets up a mesh and draws a rectangle to the screen. It uses the
+ top left vertex and bottom right vertex of the rectangle to draw.</li>
+
+ <li><code>rsgDrawQuad()</code>: Sets up a mesh and draws a quadrilateral to the screen.</li>
+
+ <li><code>rsgDrawQuadTexCoords()</code>: Sets up a mesh and draws a textured quadrilateral to
+ the screen.</li>
+ </ul>
+
+ <h3>Drawing with a mesh</h3>
+
+ <p>When you want to draw complex shapes and textures to the screen, instantiate a {@link
+ android.renderscript.Mesh} and draw it to the screen with <code>rsgDrawMesh()</code>. A {@link
+ android.renderscript.Mesh} is a collection of allocations that represent vertex data (positions,
+ normals, texture coordinates) and index data such as triangles and lines. You can build a Mesh in
+ three different ways:</p>
+
+ <ul>
+ <li>Build the mesh with the {@link android.renderscript.Mesh.TriangleMeshBuilder} class, which
+ allows you to specify a set of vertices and indices for each triangle that you want to draw.
+ The downside of doing it this way is there is no way to specify the vertices in your native
+ RenderScript code.</li>
+
+ <li>Build the mesh using an {@link android.renderscript.Allocation} or a set of {@link
+ android.renderscript.Allocation}s with the {@link android.renderscript.Mesh.AllocationBuilder}
+ class. This allows you to build a mesh with vertices already stored in memory, which allows you
+ to set the vertices in native or Android code.</li>
+
+ <li>Build the mesh with the {@link android.renderscript.Mesh.Builder} class. This is a
+ convenience method for when you know what data types you want to use to build your mesh, but
+ don't want to make separate memory allocations like with {@link
+ android.renderscript.Mesh.AllocationBuilder}. You can specify the types that you want and this
+ mesh builder automatically creates the memory allocations for you.</li>
+ </ul>
+
+ <p>To create a mesh using the {@link android.renderscript.Mesh.TriangleMeshBuilder}, you need to
+ supply it with a set of vertices and the indices for the vertices that comprise the triangle. For
+ example, the following code specifies three vertices, which are added to an internal array,
+ indexed in the order they were added. The call to {@link
+ android.renderscript.Mesh.TriangleMeshBuilder#addTriangle addTriangle()} draws the triangle with
+ vertex 0, 1, and 2 (the vertices are drawn counter-clockwise).</p>
+ <pre>
+int float2VtxSize = 2;
+Mesh.TriangleMeshBuilder triangle = new Mesh.TriangleMeshBuilder(renderscriptGL,
+float2VtxSize, Mesh.TriangleMeshBuilder.COLOR);
+triangles.addVertex(300.f, 300.f);
+triangles.addVertex(150.f, 450.f);
+triangles.addVertex(450.f, 450.f);
+triangles.addTriangle(0 , 1, 2);
+Mesh smP = triangle.create(true);
+script.set_mesh(smP);
+</pre>
+
+ <p>To draw a mesh using the {@link android.renderscript.Mesh.AllocationBuilder}, you need to
+ supply it with one or more allocations that contain the vertex data:</p>
+ <pre>
+Allocation vertices;
+
+...
+Mesh.AllocationBuilder triangle = new Mesh.AllocationBuilder(mRS);
+smb.addVertexAllocation(vertices.getAllocation());
+smb.addIndexSetType(Mesh.Primitive.TRIANGLE);
+Mesh smP = smb.create();
+script.set_mesh(smP);
+</pre>
+
+ <p>In your native RenderScript code, draw the built mesh to the screen:</p>
+ <pre>
+rs_mesh mesh;
+...
+
+int root(){
+...
+rsgDrawMesh(mesh);
+...
+return 0; //specify a non zero, positive integer to specify the frame refresh.
+ //0 refreshes the frame only when the mesh changes.
+}
+</pre>
+
+ <h2 id="shaders">Shaders</h2>
+
+ <p>You can attach four program objects to the {@link android.renderscript.RenderScriptGL} context
+ to customize the rendering pipeline. For example, you can create vertex and fragment shaders in
+ GLSL or build a raster program object with provided methods without writing GLSL code. The four
+ program objects mirror a traditional graphical rendering pipeline:</p>
+
+ <table>
+ <tr>
+ <th>Android Object Type</th>
+
+ <th>RenderScript Native Type</th>
+
+ <th>Description</th>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.ProgramVertex}</td>
+
+ <td>rs_program_vertex</td>
+
+ <td>
+ <p>The RenderScript vertex program, also known as a vertex shader, describes the stage in
+ the graphics pipeline responsible for manipulating geometric data in a user-defined way.
+ The object is constructed by providing RenderScript with the following data:</p>
+
+ <ul>
+ <li>An Element describing its varying inputs or attributes</li>
+
+ <li>GLSL shader string that defines the body of the program</li>
+
+ <li>a Type that describes the layout of an Allocation containing constant or uniform
+ inputs</li>
+ </ul>
+
+ <p>Once the program is created, bind it to the {@link android.renderscript.RenderScriptGL}
+ graphics context by calling {@link android.renderscript.RenderScriptGL#bindProgramVertex
+ bindProgramVertex()}. It is then used for all subsequent draw calls until you bind a new
+ program. If the program has constant inputs, the user needs to bind an allocation
+ containing those inputs. The allocation's type must match the one provided during creation.
+ The RenderScript library then does all the necessary plumbing to send those constants to
+ the graphics hardware. Varying inputs to the shader, such as position, normal, and texture
+ coordinates are matched by name between the input Element and the Mesh object being drawn.
+ The signatures don't have to be exact or in any strict order. As long as the input name in
+ the shader matches a channel name and size available on the mesh, the run-time would take
+ care of connecting the two. Unlike OpenGL, there is no need to link the vertex and fragment
+ programs.</p>
+
+ <p>To bind shader constructs to the Program, declare a struct containing the necessary
+ shader constants in your native RenderScript code. This struct is generated into a
+ reflected class that you can use as a constant input element during the Program's creation.
+ It is an easy way to create an instance of this struct as an allocation. You would then
+ bind this Allocation to the Program and the RenderScript system sends the data that is
+ contained in the struct to the hardware when necessary. To update shader constants, you
+ change the values in the Allocation and notify the native RenderScript code of the
+ change.</p>
+ </td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.ProgramFragment}</td>
+
+ <td>rs_program_fragment</td>
+
+ <td>
+ <p>The RenderScript fragment program, also known as the fragment shader, is responsible for
+ manipulating pixel data in a user-defined way. It's constructed from a GLSL shader string
+ containing the program body, textures inputs, and a Type object describing the constants
+ used by the program. Like the vertex programs, when an allocation with constant input
+ values is bound to the shader, its values are sent to the graphics program automatically.
+ Note that the values inside the allocation are not explicitly tracked. If they change
+ between two draw calls using the same program object, notify the runtime of that change by
+ calling rsgAllocationSyncAll so it could send the new values to hardware. Communication
+ between the vertex and fragment programs is handled internally in the GLSL code. For
+ example, if the fragment program is expecting a varying input called varTex0, the GLSL code
+ inside the program vertex must provide it.</p>
+
+ <p>To bind shader constants to this program, declare a struct containing the necessary
+ shader constants in your native RenderScript code. This struct is generated into a
+ reflected class that you can use as a constant input element during the Program's creation.
+ It is an easy way to create an instance of this struct as an allocation. You would then
+ bind this Allocation to the Program and the RenderScript system sends the data that is
+ contained in the struct to the hardware when necessary. To update shader constants, you
+ change the values in the Allocation and notify the native RenderScript code of the
+ change.</p>
+ </td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.ProgramStore}</td>
+
+ <td>rs_program_store</td>
+
+ <td>The RenderScript ProgramStore contains a set of parameters that control how the graphics
+ hardware writes to the framebuffer. It could be used to enable and disable depth writes and
+ testing, setup various blending modes for effects like transparency and define write masks
+ for color components.</td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.ProgramRaster}</td>
+
+ <td>rs_program_raster</td>
+
+ <td>Program raster is primarily used to specify whether point sprites are enabled and to
+ control the culling mode. By default back faces are culled.</td>
+ </tr>
+ </table>
+
+ <p>The following example defines a vertex shader in GLSL and binds it to the RenderScript:</p>
+ <pre>
+ private RenderScriptGL glRenderer; //rendering context
+ private ScriptField_Point mPoints; //vertices
+ private ScriptField_VpConsts mVpConsts; //shader constants
+
+ ...
+
+ ProgramVertex.Builder sb = new ProgramVertex.Builder(glRenderer);
+ String t = "varying vec4 varColor;\n" +
+ "void main() {\n" +
+ " vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n" +
+ " pos.xy = ATTRIB_position;\n" +
+ " gl_Position = UNI_MVP * pos;\n" +
+ " varColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +
+ " gl_PointSize = ATTRIB_size;\n" +
+ "}\n";
+ sb.setShader(t);
+ sb.addConstant(mVpConsts.getType());
+ sb.addInput(mPoints.getElement());
+ ProgramVertex pvs = sb.create();
+ pvs.bindConstants(mVpConsts.getAllocation(), 0);
+ glRenderer.bindProgramVertex(pvs);
+
+
+</pre>
+
+ <p>The <a href=
+ "{@docRoot}resources/samples/RenderScript/MiscSamples/src/com/example/android/rs/miscsamples/RsRenderStatesRS.html">
+ RsRenderStatesRS</a> sample has many examples on how to create a shader without writing GLSL.</p>
+
+ <h3>Shader bindings</h3>
+
+ <p>You can also set four pragmas that control the shaders' default bindings to the {@link
+ android.renderscript.RenderScriptGL} context when the script is executing:</p>
+
+ <ul>
+ <li>stateVertex</li>
+
+ <li>stateFragment</li>
+
+ <li>stateRaster</li>
+
+ <li>stateStore</li>
+ </ul>
+
+ <p>The possible values for each pragma are <code>parent</code> or <code>default</code>. Using
+ <code>default</code> binds the shaders to the graphical context with the system defaults. The
+ default shader is defined below:</p>
+ <pre>
+("varying vec4 varColor;\n");
+("varying vec2 varTex0;\n");
+("void main() {\n");
+(" gl_Position = UNI_MVP * ATTRIB_position;\n");
+(" gl_PointSize = 1.0;\n");
+(" varColor = ATTRIB_color;\n");
+(" varTex0 = ATTRIB_texture0;\n");
+("}\n");
+</pre>
+
+ <p>Using <code>parent</code> binds the shaders in the same manner as it is bound in the calling
+ script. If this is the root script, the parent state is taken from the bind points that are set
+ by the {@link android.renderscript.RenderScriptGL} bind methods.</p>
+
+ <p>For example, you can define this at the top of your native graphics RenderScript code to have
+ the Vertex and Store shaders inherent the bind properties from their parent scripts:</p>
+ <pre>
+#pragma stateVertex(parent)
+#pragma stateStore(parent)
+</pre>
+
+ <h3>Defining a sampler</h3>
+
+ <p>A {@link android.renderscript.Sampler} object defines how data is extracted from textures.
+ Samplers are bound to Program objects (currently only a Fragment Program) alongside the texture
+ whose sampling they control. These objects are used to specify such things as edge clamping
+ behavior, whether mip-maps are used, and the amount of anisotropy required. There might be
+ situations where hardware does not support the desired behavior of the sampler. In these cases,
+ the runtime attempts to provide the closest possible approximation. For example, the user
+ requested 16x anisotropy, but only 8x was set because it's the best available on the
+ hardware.</p>
+
+ <p>The <a href=
+ "{@docRoot}resources/samples/RenderScript/MiscSamples/src/com/example/android/rs/miscsamples/RsRenderStatesRS.html">
+ RsRenderStatesRS</a> sample has many examples on how to create a sampler and bind it to a
+ Fragment program.</p>
+
+</body>
+</html>
diff --git a/docs/html/guide/topics/renderscript/index.jd b/docs/html/guide/topics/renderscript/index.jd
new file mode 100644
index 000000000000..eb773109e427
--- /dev/null
+++ b/docs/html/guide/topics/renderscript/index.jd
@@ -0,0 +1,640 @@
+page.title=RenderScript
+@jd:body
+
+ <div id="qv-wrapper">
+ <div id="qv">
+ <h2>In this document</h2>
+
+ <ol>
+ <li><a href="#overview">RenderScript System Overview</a></li>
+ <li>
+ <ol>
+ <li><a href="#native">Native RenderScript layer</a></li>
+
+ <li><a href="#reflected">Reflected layer</a></li>
+
+ <li><a href="#framework">Android framework layer</a></li>
+ </ol>
+ </li>
+
+ <li>
+ <a href="#mem-allocation">Memory Allocation APIs</a>
+ </li>
+ <li>
+ <a href="#dynamic">Dynamic Memory Allocations</a>
+ <ol>
+ <li><a href="#pointers">Declaring pointers</a></li>
+
+ <li><a href="#struct-pointer-reflection">How pointers are reflected</a></li>
+
+ <li><a href="#binding">Allocating and binding memory to the RenderScript</a></li>
+
+ <li><a href="#read-write-dynamic">Reading and writing to memory</a></li>
+
+ </ol>
+ </li>
+ <li>
+ <a href="#static">Static Memory Allocations</a>
+ </li>
+ </ol>
+ </div>
+ </div>
+
+ <p>RenderScript offers a high performance 3D graphics rendering and compute API at the native
+ level, which you write in the C (C99 standard). The main advantages of RenderScript are:</p>
+ <ul>
+ <li>Portability: RenderScript is designed to run on many types of devices with different CPU
+ and GPU architectures. It supports all of these architectures without having to target each
+ device, because the code is compiled and cached on the device at runtime.</li>
+
+ <li>Performance: RenderScript provides similar performance to OpenGL with the NDK while
+ offering the portability of the OpenGL APIs provided by the Android framework ({@link
+ android.opengl}). In addition, it also offers a high performance compute API that is not
+ offered by OpenGL.</li>
+
+ <li>Usability: RenderScript simplifies development when possible, such as eliminating JNI glue code
+ and simplifying mesh setup.</li>
+ </ul>
+
+ <p>The main disadvantages are:</p>
+
+ <ul>
+ <li>Development complexity: RenderScript introduces a new set of APIs that you have to learn.
+ RenderScript also handles memory differently compared to OpenGL with the Android framework APIs
+ or NDK.</li>
+
+ <li>Debugging visibility: RenderScript can potentially execute (planned feature for later releases)
+ on processors other than the main CPU (such as the GPU), so if this occurs, debugging becomes more difficult.
+ </li>
+
+ <li>Less features: RenderScript does not provide as many features as OpenGL such as all the compressed
+ texture formats or GL extensions.</li>
+ </ul>
+
+ <p>You need to consider all of the aspects of RenderScript before deciding when to use it. The following list describes
+ general guidelines on when to use OpenGL (framework APIs or NDK) or RenderScript:</p>
+ <ul>
+ <li>If you are doing simple graphics rendering and performance is not critical, you probably want to use the
+ Android framework OpenGL APIs, which still provide adequate performance, to eliminate the added coding and debugging complexity of
+ RenderScript.</li>
+
+ <li>If you want the most flexibility and features while maintaining relatively good debugging
+ support, you probably want to use OpenGL and the NDK. Applications that require this are high end
+ or complicated games, for example.</li>
+
+ <li>If you want a solution that is portable, has good performance,
+ and you don't need the full feature set of OpenGL, RenderScript is a good solution. If you also
+ need a high performance compute language, then RenderScript offers that as well.
+ Good candidates for RenderScript are graphics intensive UIs that require 3D rendering, live wallpapers,
+ or applications that require intensive mathematical computation.</li>
+ </ul>
+
+ <p>For an example of RenderScript in action, install the RenderScript sample applications that
+ are shipped with the SDK in <code>&lt;sdk_root&gt;/samples/android-11/RenderScript</code>.
+ You can also see a typical use of RenderScript with the 3D carousel view in the Android 3.x
+ versions of Google Books and YouTube.</p>
+
+ <h2 id="overview">RenderScript System Overview</h2>
+
+ <p>The RenderScript system adopts a control and slave architecture where the low-level native
+ code is controlled by the higher level Android system that runs in a virtual machine (VM). The
+ Android VM still retains all control of memory and lifecycle management and calls the native
+ RenderScript code when necessary. The native code is compiled to intermediate bytecode (LLVM) and
+ packaged inside your application's <code>.apk</code> file. On the device, the bytecode is
+ compiled (just-in-time) to machine code that is further optimized for the device that it is
+ running on. The compiled code on the device is cached, so subsequent uses of the RenderScript
+ enabled application do not recompile the intermediate code. RenderScript has three layers of code
+ to enable communication between the native and Android framework code:</p>
+
+ <ul>
+ <li>The native RenderScript layer does the intensive computation or graphics rendering. You
+ define your native code in <code>.rs</code> and <code>.rsh</code> files.</li>
+
+ <li>The reflected layer is a set of classes that are reflected from the native code. It is basically
+ a wrapper around the native code that allows the Android framework to interact with native RenderScripts.
+ The Android build tools automatically generate the classes for this layer during
+ the build process and eliminates the need to write JNI glue code, like with the NDK.</li>
+
+ <li>The Android framework layer is comprised of the Android framework
+ APIs, which include the {@link android.renderscript} package. This layer gives high level commands
+ like, "rotate the view" or "filter the bitmap", by calling the reflected layer, which in turn calls
+ the native layer. </li>
+ </ul>
+
+ <h3 id="native">Native RenderScript layer</h3>
+
+ <p>The native RenderScript layer consists of your RenderScript code, which is compiled and
+ executed in a compact and well defined runtime. Your RenderScript code has access to a limited
+ amount of functions because it cannot access the NDK or standard C functions, since they must be guaranteed to
+ run on a standard CPU. The RenderScript runtime was designed to run on different types of processors,
+ which may not be the CPU, so it cannot guarantee support for standard C libraries. What
+ RenderScript does offer is an API that supports intensive computation and graphics rendering with a collection of math
+ and graphics APIs.</p>
+
+ <p>Some key features of the native RenderScript libraries include:</p>
+
+ <ul>
+ <li>A large collection of math functions with both scalar and vector typed overloaded versions
+ of many common routines. Operations such as adding, multiplying, dot product, and cross product
+ are available.</li>
+
+ <li>Conversion routines for primitive data types and vectors, matrix routines, date and time
+ routines, and graphics routines.</li>
+
+ <li>Logging functions</li>
+
+ <li>Graphics rendering functions</li>
+
+ <li>Memory allocation request features</li>
+
+ <li>Data types and structures to support the RenderScript system such as Vector types for
+ defining two-, three-, or four-vectors.</li>
+ </ul>
+
+ <p>The <a href="{@docRoot}guide/topics/renderscript/rs-api/files.html">RenderScript header files</a>
+ and LLVM front-end libraries are located in the <code>include</code> and
+ <code>clang-include</code> directories in the
+ <code>&lt;sdk_root&gt;/platforms/android-11/renderscript</code> directory of the Android SDK. The
+ headers are automatically included for you, except for the RenderScript graphics specific header file, which
+ you can include as follows:</p>
+ <pre>
+#include "rs_graphics.rsh"
+</pre>
+
+ <h3 id="reflected">Reflected layer</h3>
+
+ <p>The reflected layer is a set of classes that the Android build tools generate to allow access
+ to the native RenderScript code from the Android VM. This layer defines entry points for
+ RenderScript functions and variables, so that you can interact with them with the Android
+ framework. This layer also provides methods and constructors that allow you to allocate memory
+ for pointers that are defined in your RenderScript code. The following list describes the major
+ components that are reflected:</p>
+
+ <ul>
+ <li>Every <code>.rs</code> file that you create is generated into a class named
+ <code>ScriptC_<em>renderscript_filename</em></code> of type {@link
+ android.renderscript.ScriptC}. This is the <code>.java</code> version of your <code>.rs</code>
+ file, which you can call from the Android framework. This class contains the following
+ reflections:
+
+ <ul>
+ <li>Non-static functions in your <code>.rs</code> file.</li>
+
+ <li>Non-static, global RenderScript variables. Accessor methods are generated for each
+ variable, so you can read and write the natively declared variables from the Android
+ framework. The <code>get</code> method comes with a one-way communication restriction. The
+ last value that is set from the Android framework is always returned during a call to a
+ <code>get</code> method. If the native RenderScript code changes the value, the change does
+ not propagate back to the Android framework layer.
+ If the global variables are initialized
+ in the native RenderScript code, those values are used to initialize the corresponding
+ values in the Android framework layer. If global variables are marked as
+ <code>const</code>, then a <code>set</code> method is not generated.</li>
+ <li>Global pointers generate a special method named <code>bind_<em>pointer_name</em></code>
+ instead of a <code>set()</code> method. This method allows you to bind the memory that is
+ allocated in the Android VM for the pointer to the native RenderScript (you cannot allocate
+ memory in your <code>.rs</code> file). You can read and write to this memory from both the
+ Android framework and RenderScript code. For more information, see <a href="mem-mgmt">Working
+ with Memory and Data</a></li>
+ </ul>
+ </li>
+
+ <li>A <code>struct</code> is reflected into its own class named
+ <code>ScriptField_<em>struct_name</em></code>, which extends {@link
+ android.renderscript.Script.FieldBase}. This class represents an array of the
+ <code>struct</code>, which allows you to allocate memory for one or more instances of this
+ <code>struct</code>.</li>
+ </ul>
+
+ <h3 id="framework">Android framework layer</h3>
+
+ <p>The Android framework layer consists of the usual Android framework APIs, which include the
+ RenderScript APIs in {@link android.renderscript}. This layer handles things such as the
+ Activity lifecycle and memory management of your application. It issues high level commands to
+ the native RenderScript code through the reflected layer and receives events from the user such
+ as touch and input events and relays them to your RenderScript code, if needed.
+ </p>
+
+ <h2 id="mem-allocation">Memory Allocation APIs</h2>
+
+ <p>Before you begin writing your first RenderScript application, you must understand how
+ memory is allocated for your RenderScript code and how data is shared between the native and VM
+ spaces. RenderScript allows you to access allocated memory in both the native layer
+ and Android system layer. All dynamic and static memory is allocated by the Android VM.
+ The Android VM also does reference counting and garbage collection for you.
+ You can also explicitly free memory that you no longer need.</p>
+
+ <p class="note"><strong>Note:</strong> To declare temporary memory in your native RenderScript
+ code without allocating it in the Android VM, you can still do things like instantiate a scratch
+ buffer using an array.</p>
+
+ <p>The following classes support the memory management features of RenderScript in the Android
+ VM. You normally do not need to work with these classes directly, because the reflected layer
+ classes provide constructors and methods that set up the memory allocation for you. There are
+ some situations where you would want to use these classes directly to allocate memory on your
+ own, such as loading a bitmap from a resource or when you want to allocate memory for pointers to
+ primitive types.</p>
+
+ <table id="mem-mgmt-table">
+ <tr>
+ <th>Android Object Type</th>
+
+ <th>Description</th>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.Element}</td>
+
+ <td>
+ <p>An element represents one cell of a memory allocation and can have two forms: Basic or
+ Complex.</p>
+
+ <p>A basic element contains a single component of data of any valid RenderScript data type.
+ Examples of basic element data types include a single float value, a float4 vector, or a
+ single RGB-565 color.</p>
+
+ <p>Complex elements contain a list of basic elements and are created from
+ <code>struct</code>s that you declare in your RenderScript code. The most basic primitive
+ type determines the data alignment of the memory. For example, a float4 vector subelement
+ is alligned to <code>sizeof(float)</code> and not <code>sizeof(float4)</code>. The ordering
+ of the elements in memory are the order in which they were added, with each component
+ aligned as necessary.</p>
+ </td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.Type}</td>
+
+ <td>
+ A type is a memory allocation template and consists of an element and one or more
+ dimensions. It describes the layout of the memory (basically an array of {@link
+ android.renderscript.Element}s) but does not allocate the memory for the data that it
+ describes.
+
+ <p>A type consists of five dimensions: X, Y, Z, LOD (level of detail), and Faces (of a cube
+ map). You can assign the X,Y,Z dimensions to any positive integer value within the
+ constraints of available memory. A single dimension allocation has an X dimension of
+ greater than zero while the Y and Z dimensions are zero to indicate not present. For
+ example, an allocation of x=10, y=1 is considered two dimensional and x=10, y=0 is
+ considered one dimensional. The LOD and Faces dimensions are booleans to indicate present
+ or not present.</p>
+ </td>
+ </tr>
+
+ <tr>
+ <td>{@link android.renderscript.Allocation}</td>
+
+ <td>
+ <p>An allocation provides the memory for applications based on a description of the memory
+ that is represented by a {@link android.renderscript.Type}. Allocated memory can exist in
+ many memory spaces concurrently. If memory is modified in one space, you must explicitly
+ synchronize the memory, so that it is updated in all the other spaces that it exists
+ in.</p>
+
+ <p>Allocation data is uploaded in one of two primary ways: type checked and type unchecked.
+ For simple arrays there are <code>copyFrom()</code> functions that take an array from the
+ Android system and copy it to the native layer memory store. The unchecked variants allow
+ the Android system to copy over arrays of structures because it does not support
+ structures. For example, if there is an allocation that is an array of n floats, the data
+ contained in a float[n] array or a byte[n*4] array can be copied.</p>
+ </td>
+ </tr>
+ </table>
+
+ <h2 id="dynamic">Working with dynamic memory allocations</h2>
+
+ <p>RenderScript has support for pointers, but you must allocate the memory in your Android framework
+ code. When you declare a global pointer in your <code>.rs</code> file, you allocate memory
+ through the appropriate reflected layer class and bind that memory to the native
+ RenderScript layer. You can read and write to this memory from the Android framework layer as well as the
+ RenderScript layer, which offers you the flexibility to modify variables in the most appropriate
+ layer. The following sections show you how to work with pointers, allocate memory for them, and
+ read and write to the memory.</p>
+
+ <h3 id="pointers">Declaring pointers</h3>
+
+ <p>Because RenderScript is written in C99, declaring a pointer is done in a familiar way. You can
+ declare pointers to a <code>struct</code> or a primitive type, but a <code>struct</code> cannot
+ contain pointers or nested arrays. The following code declares a <code>struct</code>, a pointer
+ to that <code>struct</code>, and a pointer of primitive type <code>int32_t</code> in an <code>.rs</code> file:</p>
+ <pre>
+#pragma version(1)
+#pragma rs java_package_name(com.example.renderscript)
+
+...
+
+typedef struct Point {
+ float2 point;
+ } Point_t;
+
+ Point_t *touchPoints;
+ int32_t *intPointer;
+
+...
+</pre>
+
+<p>You cannot allocate memory for these pointers in your RenderScript code, but the Android
+build tools generate classes for you that allow you to allocate memory in the Android VM for use by
+your RenderScript code. These classes also let you read and write to the memory. The next section
+describes how these classes are generated through reflection.</p>
+
+ <h3>How pointers are reflected</h3>
+
+ <p>Global variables have a getter and setter method generated. A global pointer generates a
+ <code>bind_pointerName()</code> method instead of a set() method. This method allows you to bind
+ the memory that is allocated in the Android VM to the native RenderScript. For example, the two
+ pointers in the previous section generate the following accessor methods in the <code>ScriptC_<em>rs_filename</em></code> file:</p>
+ <pre>
+
+ private ScriptField_Point mExportVar_touchPoints;
+ public void bind_touchPoints(ScriptField_Point v) {
+ mExportVar_touchPoints = v;
+ if (v == null) bindAllocation(null, mExportVarIdx_touchPoints);
+ else bindAllocation(v.getAllocation(), mExportVarIdx_touchPoints);
+ }
+
+ public ScriptField_Point get_touchPoints() {
+ return mExportVar_touchPoints;
+ }
+
+ private Allocation mExportVar_intPointer;
+ public void bind_intPointer(Allocation v) {
+ mExportVar_intPointer = v;
+ if (v == null) bindAllocation(null, mExportVarIdx_intPointer);
+ else bindAllocation(v, mExportVarIdx_intPointer);
+ }
+
+ public Allocation get_intPointer() {
+ return mExportVar_intPointer;
+ }
+
+</pre>
+
+ <h3>Allocating and binding memory to the RenderScript</h3>
+
+ <p>When the build tools generate the reflected layer, you can use the appropriate class
+ (<code>ScriptField_Point</code>, in our example) to allocate memory for a pointer. To do this,
+ you call the constructor for the {@link android.renderscript.Script.FieldBase} class and specify
+ the amount of structures that you want to allocate memory for. To allocate memory for a primitive
+ type pointer, you must build an allocation manually, using the memory management classes
+ described in <a href="mem-mgmt-table">Table 1</a>. The example below allocates memory for both
+ the <code>intPointer</code> and <code>touchPoints</code> pointer and binds it to the
+ RenderScript:</p>
+ <pre>
+private RenderScriptGL glRenderer;
+private ScriptC_example script;
+private Resources resources;
+
+public void init(RenderScriptGL rs, Resources res) {
+ //get the rendering context and resources from the calling method
+ glRenderer = rs;
+ resources = res;
+
+ //allocate memory for the struct pointer, calling the constructor
+ ScriptField_Point touchPoints = new ScriptField_Point(glRenderer, 2);
+
+ //Create an element manually and allocate memory for the int pointer
+ intPointer = Allocation.createSized(glRenderer, Element.I32(glRenderer), 2);
+
+ //create an instance of the RenderScript, pointing it to the bytecode resource
+ mScript = new ScriptC_example(glRenderer, resources, R.raw.example);
+
+ // bind the struct and int pointers to the RenderScript
+ mScript.bind_touchPoints(touchPoints);
+ script.bind_intPointer(intPointer);
+
+ //bind the RenderScript to the rendering context
+ glRenderer.bindRootScript(script);
+}
+</pre>
+
+ <h3>Reading and writing to memory</h3>
+
+ <p>Although you have to allocate memory within the Android VM, you can work with the memory both
+ in your native RenderScript code and in your Android code. Once memory is bound, the native
+ RenderScript can read and write to the memory directly. You can also just use the accessor
+ methods in the reflected classes to access the memory. If you modify memory in the Android
+ framework, it gets automatically synchronized to the native layer. If you modify memory in the <code>.rs</code>
+ file, these changes do not get propagated back to the Android framework.
+ For example, you can modify the struct in your Android code like this:</p>
+ <pre>
+int index = 0;
+boolean copyNow = true;
+Float2 point = new Float2(0.0f, 0.0f);
+touchPoints.set_point(index, point, copyNow);
+</pre>then read it in your native RenderScript code like this:
+ <pre>
+rsDebug("Printing out a Point", touchPoints[0].point.x, touchPoints[0].point.y);
+</pre>
+
+ <h2>Working with statically allocated memory</h2>
+
+ <p>Non-static, global primitives and structs that you declare in your RenderScript are easier to work with,
+ because the memory is statically allocated at compile time. Accessor methods to set and get these
+ variables are generated when the Android build tools generate the reflected layer classes. You
+ can get and set these variables using the provided accessor methods.
+ <p class="note"><strong>Note:</strong> The <code>get</code> method comes with a one-way communication restriction. The last value
+ that is set from the Android framework is always returned during a call to a <code>get</code>
+ method. If the native RenderScript code changes the value, the change does not propagate back to
+ the Android framework layer. If the global variables are initialized in the native RenderScript
+ code, those values are used to initialize the corresponding values in the Android framework
+ layer. If global variables are marked as <code>const</code>, then a <code>set</code> method is
+ not generated.</p>
+ </p>
+
+ <p>For example, if you declare the following primitive in your RenderScript code:</p>
+ <pre>
+ uint32_t unsignedInteger = 1;
+
+</pre>
+<p>then the following code is generated in <code>ScriptC_<em>script_name</em>.java</code>:</p>
+ <pre>
+ private final static int mExportVarIdx_unsignedInteger = 9;
+ private long mExportVar_unsignedInteger;
+ public void set_unsignedInteger(long v) {
+ mExportVar_unsignedInteger = v;
+ setVar(mExportVarIdx_unsignedInteger, v);
+ }
+
+ public long get_unsignedInteger() {
+ return mExportVar_unsignedInteger;
+ }
+</pre>
+
+ <p class="note"><strong>Note:</strong> The mExportVarIdx_unsignedInteger variable represents the
+ index of the <code>unsignedInteger</code>'s in an array of statically allocated primitives. You do
+ not need to work with or be aware of this index.</p>
+
+ <p>For a <code>struct</code>, the Android build tools generate a class named
+ <code>&lt;project_root&gt;/gen/com/example/renderscript/ScriptField_struct_name</code>. This
+ class represents an array of the <code>struct</code> and allows you to allocate memory for a
+ specified number of <code>struct</code>s. This class defines:</p>
+
+ <ul>
+ <li>Overloaded constructors that allow you to allocate memory. The
+ <code>ScriptField_<em>struct_name</em>(RenderScript rs, int count)</code> constructor allows
+ you to define the number of structures that you want to allocate memory for with the
+ <code>count</code> parameter. The <code>ScriptField_<em>struct_name</em>(RenderScript rs, int
+ count, int usages)</code> constructor defines an extra parameter, <code>usages</code>, that
+ lets you specify the memory space of this memory allocation. There are four memory space
+ possibilities:
+
+ <ul>
+ <li>{@link android.renderscript.Allocation#USAGE_SCRIPT}: Allocates in the script memory
+ space. This is the default memory space if you do not specify a memory space.</li>
+
+ <li>{@link android.renderscript.Allocation#USAGE_GRAPHICS_TEXTURE}: Allocates in the
+ texture memory space of the GPU.</li>
+
+ <li>{@link android.renderscript.Allocation#USAGE_GRAPHICS_VERTEX}: Allocates in the vertex
+ memory space of the GPU.</li>
+
+ <li>{@link android.renderscript.Allocation#USAGE_GRAPHICS_CONSTANTS}: Allocates in the
+ constants memory space of the GPU that is used by the various program objects.</li>
+ </ul>
+
+ <p>You can specify one or all of these memory spaces by OR'ing them together. Doing so notifies
+ the RenderScript runtime that you intend on accessing the data in the specified memory spaces. The following
+ example allocates memory for a custom data type in both the script and vertex memory spaces:</p>
+<pre>
+ScriptField_Point touchPoints = new ScriptField_Point(glRenderer, 2,
+Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_VERTEX);
+</pre>
+
+ <p>If you modify the memory in one memory space and want to push the updates to the rest of
+ the memory spaces, call <code>rsgAllocationSyncAll()</code> in your RenderScript code to
+ synchronize the memory.</p>
+ </li>
+
+ <li>A static nested class, <code>Item</code>, allows you to create an instance of the
+ <code>struct</code>, in the form of an object. This is useful if it makes more sense to work
+ with the <code>struct</code> in your Android code. When you are done manipulating the object,
+ you can push the object to the allocated memory by calling <code>set(Item i, int index, boolean
+ copyNow)</code> and setting the <code>Item</code> to the desired position in the array. The
+ native RenderScript code automatically has access to the newly written memory.
+
+ <li>Accessor methods to get and set the values of each field in a struct. Each of these
+ accessor methods have an <code>index</code> parameter to specify the <code>struct</code> in the
+ array that you want to read or write to. Each setter method also has a <code>copyNow</code>
+ parameter that specifies whether or not to immediately sync this memory to the native
+ RenderScript layer. To sync any memory that has not been synced, call <code>copyAll()</code>.</li>
+
+ <li>The createElement() method creates an object that describes the memory layout of the struct.</li>
+
+ <li>resize() works much like a <code>realloc</code>, allowing you to expand previously
+ allocated memory, maintaining the current values that were previously set.</li>
+
+ <li>copyAll() synchronizes memory that was set on the framework level to the native level. When you call
+ a set accessor method on a member, there is an optional <code>copyNow</code> boolean parameter that you can specify. Specifying
+ <code>true</code> synchronizes the memory when you call the method. If you specify false, you can call <code>copyAll()</code>
+ once, and it synchronizes memory for the all the properties that are not synchronized.</li>
+ </ul>
+
+ <p>The following example shows the reflected class, <code>ScriptField_Point.java</code> that is
+ generated from the Point <code>struct</code>.</p>
+ <pre>
+package com.example.renderscript;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+
+public class ScriptField_Point extends android.renderscript.Script.FieldBase {
+ static public class Item {
+ public static final int sizeof = 8;
+
+ Float2 point;
+
+ Item() {
+ point = new Float2();
+ }
+
+ }
+
+ private Item mItemArray[];
+ private FieldPacker mIOBuffer;
+ public static Element createElement(RenderScript rs) {
+ Element.Builder eb = new Element.Builder(rs);
+ eb.add(Element.F32_2(rs), "point");
+ return eb.create();
+ }
+
+ public ScriptField_Point(RenderScript rs, int count) {
+ mItemArray = null;
+ mIOBuffer = null;
+ mElement = createElement(rs);
+ init(rs, count);
+ }
+
+ public ScriptField_Point(RenderScript rs, int count, int usages) {
+ mItemArray = null;
+ mIOBuffer = null;
+ mElement = createElement(rs);
+ init(rs, count, usages);
+ }
+
+ private void copyToArray(Item i, int index) {
+ if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */);
+ mIOBuffer.reset(index * Item.sizeof);
+ mIOBuffer.addF32(i.point);
+ }
+
+ public void set(Item i, int index, boolean copyNow) {
+ if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+ mItemArray[index] = i;
+ if (copyNow) {
+ copyToArray(i, index);
+ mAllocation.setFromFieldPacker(index, mIOBuffer);
+ }
+
+ }
+
+ public Item get(int index) {
+ if (mItemArray == null) return null;
+ return mItemArray[index];
+ }
+
+ public void set_point(int index, Float2 v, boolean copyNow) {
+ if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */)fnati;
+ if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
+ if (mItemArray[index] == null) mItemArray[index] = new Item();
+ mItemArray[index].point = v;
+ if (copyNow) {
+ mIOBuffer.reset(index * Item.sizeof);
+ mIOBuffer.addF32(v);
+ FieldPacker fp = new FieldPacker(8);
+ fp.addF32(v);
+ mAllocation.setFromFieldPacker(index, 0, fp);
+ }
+
+ }
+
+ public Float2 get_point(int index) {
+ if (mItemArray == null) return null;
+ return mItemArray[index].point;
+ }
+
+ public void copyAll() {
+ for (int ct = 0; ct &lt; mItemArray.length; ct++) copyToArray(mItemArray[ct], ct);
+ mAllocation.setFromFieldPacker(0, mIOBuffer);
+ }
+
+ public void resize(int newSize) {
+ if (mItemArray != null) {
+ int oldSize = mItemArray.length;
+ int copySize = Math.min(oldSize, newSize);
+ if (newSize == oldSize) return;
+ Item ni[] = new Item[newSize];
+ System.arraycopy(mItemArray, 0, ni, 0, copySize);
+ mItemArray = ni;
+ }
+
+ mAllocation.resize(newSize);
+ if (mIOBuffer != null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */);
+ }
+
+}
+</pre>
+
+</body>
+</html>
diff --git a/docs/html/guide/topics/resources/animation-resource.jd b/docs/html/guide/topics/resources/animation-resource.jd
index 972dd729cb1d..3df669c06eb7 100644
--- a/docs/html/guide/topics/resources/animation-resource.jd
+++ b/docs/html/guide/topics/resources/animation-resource.jd
@@ -5,28 +5,348 @@ parent.link=available-resources.html
<div id="qv-wrapper">
<div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#Property">Property Animation</a></li>
+ <li><a href="#View">View Animation</a>
+ <ol>
+ <li><a href="Tween">Tween animation</li>
+ <li><a href="Frame">Frame animation</li>
+ </ol>
+ </li>
+ </ol>
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}guide/topics/graphics/2d-graphics.html#tween-animation">2D
-Graphics</a></li>
+ <li><a href="{@docRoot}guide/topics/graphics/view-animation.html">View Animation</a></li>
+ <li><a href="{@docRoot}guide/topics/graphics/animation.html">Property Animation</a></li>
</ol>
</div>
</div>
<p>An animation resource can define one of two types of animations:</p>
+
<dl>
- <dt><a href="#Tween">Tween Animation</a></dt>
- <dd>Creates an animation by performing a series of transformations on a single image.
- An {@link android.view.animation.Animation}.</dd>
- <dt><a href="#Frame">Frame Animation</a></dt>
- <dd>Creates an animation by showing a sequence of images in order.
- An {@link android.graphics.drawable.AnimationDrawable}.</dd>
+ <dt><a href="#Property">Property Animation</a></dt>
+ <dd>Creates an animation by modifying an object's property values over a set period
+ of time with an {@link android.animation.Animator}.</dd>
+ <dt><a href="#View">View Animation</a></dt>
+ <dd>
+ <p>There are two types of animations that you can do with the view animation framework:</p>
+ <ul>
+ <li><a href="#Tween">Tween animation</a>: Creates an animation by performing a series of transformations on a single image
+ with an {@link android.view.animation.Animation}</li>
+ <li><a href="#Frame">Frame animation</a>: or creates an animation by showing a sequence of images in order
+ with an {@link android.graphics.drawable.AnimationDrawable}.</li>
+ </ul>
+ </dd>
</dl>
+<h2 id="Property">Property Animation</h2>
+<p>An animation defined in XML that modifies properties of the target object, such as
+background color or alpha value, over a set amount of time.</p>
-<h2 id="Tween">Tween Animation</h2>
+<dl class="xml">
+
+<dt>file location:</dt>
+<dd><code>res/animator/<em>filename</em>.xml</code><br/>
+The filename will be used as the resource ID.</dd>
+
+<dt>compiled resource datatype:</dt>
+<dd>Resource pointer to a {@link android.animation.ValueAnimator}, {@link android.animation.ObjectAnimator},
+or {@link android.animation.AnimatorSet}.</dd>
+
+<dt>resource reference:</dt>
+<dd>
+In Java: <code>R.animator.<em>filename</em></code><br/>
+In XML: <code>@[<em>package</em>:]animator/<em>filename</em></code>
+</dd>
+
+<dt>syntax:</dt>
+<dd>
+<pre class="stx">
+&lt;<a href="#animator-set-element">set</a>
+ android:ordering=["together" | "sequentially"]&gt;
+
+ &lt;<a href="#obj-animator-element">objectAnimator</a>
+ android:propertyName="<em>string</em>"
+ android:duration="<em>int</em>"
+ android:valueFrom="<em>float</em> | <em>int</em> | <em>color</em>"
+ android:valueTo="<em>float</em> | <em>int</em> | <em>color</em>"
+ android:startOffset="<em>int</em>"
+ android:repeatCount="<em>int</em>"
+ android:repeatMode=["repeat" | "reverse"]
+ android:valueType=["intType" | "floatType"]/&gt;
+
+ &lt;<a href="#val-animator-element">animator</a>
+ android:duration="<em>int</em>"
+ android:valueFrom="<em>float</em> | <em>int</em> | <em>color</em>"
+ android:valueTo="<em>float</em> | <em>int</em> | <em>color</em>"
+ android:startOffset="<em>int</em>"
+ android:repeatCount="<em>int</em>"
+ android:repeatMode=["repeat" | "reverse"]
+ android:valueType=["intType" | "floatType"]/&gt;
+
+ &lt;<a href="#animator-set-element">set</a>&gt;
+ ...
+ &lt;/set&gt;
+&lt;/set&gt;
+</pre>
+
+<p>The file must have a single root element: either
+<code>&lt;set&gt;</code>, <code>&lt;objectAnimator&gt;</code>, or <code>&lt;valueAnimator&gt;</code>. You can
+group animation elements together inside the <code>&lt;set&gt;</code> element, including other
+<code>&lt;set&gt;</code> elements.
+</p>
+</dd>
+
+<dt>elements:</dt>
+ <dd>
+ <dl class="tag-list">
+ <dt id="animator-set-element"><code>&lt;set&gt;</code></dt>
+ <dd>A container that holds other animation elements (<code>&lt;objectAnimator&gt;</code>,
+ <code>&lt;valueAnimator&gt;</code>, or other <code>&lt;set&gt;</code> elements). Represents
+ an {@link android.animation.AnimatorSet}.
+ <p>You can specify nested <code>&lt;set&gt;</code> tags to further
+ group animations together. Each <code>&lt;set&gt;</code> can define its own
+ <code>ordering</code> attribute.</p>
+
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt>
+ <code>android:ordering</code>
+ </dt>
+ <dd>
+ <em>Keyword</em>. Specifies the play ordering of animations in this set.
+ <table>
+ <tr><th>Value</th><th>Description</th></tr>
+ <tr><td><code>sequentially</code></td><td>Play animations in this set sequentially</td></tr>
+ <tr><td><code>together</code> (default)</td><td>Play animations in this set at the same time.</td></tr>
+ </table>
+ </dd>
+ </dl>
+ </dd>
+
+ <dt id="obj-animator-element"><code>&lt;objectAnimator&gt;</code></dt>
+ <dd>Animates a specific property of an object over a specific amount of time. Represents
+ an {@link android.animation.ObjectAnimator}.</p>
+
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt>
+ <code>android:propertyName</code>
+ </dt>
+ <dd>
+ <em>String</em>. <strong>Required</strong>. The object's property to animate, referenced by its name. For example you can specify
+ <code>"alpha"</code> or <code>"backgroundColor"</code> for a View object.
+ The <code>objectAnimator</code> element does not expose a <code>target</code>
+ attribute, however, so you cannot set the object to animate in the XML declaration. You have to
+ inflate your animation XML resource by calling {@link android.animation.AnimatorInflater#loadAnimator
+ loadAnimator()} and call {@link android.animation.ObjectAnimator#setTarget setTarget()} to set
+ the target object that contains this property.
+ </dd>
+
+ <dt>
+ <code>android:valueTo</code>
+ </dt>
+ <dd>
+ <em>float, int, or color</em>. <strong>Required</strong>. The value where the animated property ends. Colors are represented
+ as six digit hexadecimal numbers (for example, #333333).
+ </dd>
+
+ <dt>
+ <code>android:valueFrom</code>
+ </dt>
+ <dd>
+ <em>float, int, or color</em>. The value where the animated property starts. If not
+ specified, the animation starts at the value obtained by the property's get method. Colors are represented
+ as six digit hexadecimal numbers (for example, #333333).
+ </dd>
+
+ <dt>
+ <code>android:duration</code>
+ </dt>
+ <dd>
+ <em>int</em>. The time in milliseconds of the animation. 300 milliseconds is the default.
+ </dd>
+
+ <dt>
+ <code>android:startOffset</code>
+ </dt>
+ <dd>
+ <em>int</em>. The amount of milliseconds the animation delays after
+ {@link android.animation.ObjectAnimator#start start()} is called.
+ </dd>
+
+ <dt>
+ <code>android:repeatCount</code>
+ </dt>
+ <dd>
+ <em>int</em>. How many times to repeat an animation. Set to <code>"-1"</code> to infinitely
+ repeat or to a positive integer. For example, a value of <code>"1"</code> means that the animation
+ is repeated once after the initial run of the animation, so the animation plays a total
+ of two times. The default value is <code>"0"</code>, which means no repetition.
+
+ </dd>
+
+ <dt>
+ <code>android:repeatMode</code>
+ </dt>
+ <dd>
+ <em>int</em>. How an animation behaves when it reaches the end of the animation. <code>android:repeatCount</code>
+ must be set to a positive integer or <code>"-1"</code> for this attribute to have an effect. Set to <code>"reverse"</code>
+ to have the animation reverse direction with each iteration or <code>"repeat"</code> to have the animation
+ loop from the beginning each time.
+ </dd>
+
+ <dt>
+ <code>android:valueType</code>
+ </dt>
+ <dd>
+ <em>Keyword</em>. Do not specify this attribute if the value is a color. The animation framework automatically handles color
+ values
+ <table>
+ <tr><th>Value</th><th>Description</th></tr>
+ <tr><td><code>intType</code></td><td>Specifies that the animated values are integers</td></tr>
+ <tr><td><code>floatType</code> (default)</td><td>Specifies that the animated values are floats</td></tr>
+ </table>
+ </dd>
+
+ </dl>
+ </dd>
+
+<dt id="val-animator-element"><code>&lt;animator&gt;</code></dt>
+ <dd>Animates a over a specified amount of time.
+ Represents a {@link android.animation.ValueAnimator}.
+
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt>
+ <code>android:valueTo</code>
+ </dt>
+ <dd>
+ <em>float, int, or color</em>. <strong>Required</strong>. The value where the animation ends. Colors are represented
+ as six digit hexadecimal numbers (for example, #333333).
+ </dd>
+
+ <dt>
+ <code>android:valueFrom</code>
+ </dt>
+ <dd>
+ <em>float, int, or color</em>. <strong>Required</strong>. The value where the animation starts. Colors are represented
+ as six digit hexadecimal numbers (for example, #333333).
+ </dd>
+
+ <dt>
+ <code>android:duration</code>
+ </dt>
+ <dd>
+ <em>int</em>. The time in milliseconds of the animation. 300ms is the default.
+ </dd>
+
+ <dt>
+ <code>android:startOffset</code>
+ </dt>
+ <dd>
+ <em>int</em>. The amount of milliseconds the animation delays after
+ {@link android.animation.ValueAnimator#start start()} is called.
+ </dd>
+
+ <dt>
+ <code>android:repeatCount</code>
+ </dt>
+ <dd>
+ <em>int</em>. How many times to repeat an animation. Set to <code>"-1"</code> to infinitely
+ repeat or to a positive integer. For example, a value of <code>"1"</code> means that the animation
+ is repeated once after the initial run of the animation, so the animation plays a total
+ of two times. The default value is <code>"0"</code>, which means no repetition.
+ </dd>
+
+ <dt>
+ <code>android:repeatMode</code>
+ </dt>
+ <dd>
+ <em>int</em>. How an animation behaves when it reaches the end of the animation. <code>android:repeatCount</code>
+ must be set to a positive integer or <code>"-1"</code> for this attribute to have an effect. Set to <code>"reverse"</code>
+ to have the animation reverse direction with each iteration or <code>"repeat"</code> to have the animation
+ loop from the beginning each time.
+ </dd>
+
+ <dt>
+ <code>android:valueType</code>
+ </dt>
+ <dd>
+ <em>Keyword</em>. Do not specify this attribute if the value is a color. The animation framework automatically handles color
+ values.
+ <table>
+ <tr><th>Value</th><th>Description</th></tr>
+ <tr><td><code>intType</code></td><td>Specifies that the animated values are integers</td></tr>
+ <tr><td><code>floatType</code> (default)</td><td>Specifies that the animated values are floats</td></tr>
+ </table>
+ </dd>
+
+ </dl>
+ </dd>
+ </dl>
+
+</dd> <!-- end elements and attributes -->
+
+<dt>example:</dt>
+<dd>
+ <pp>XML file saved at <code>res/animator/property_animator.xml</code>:</p>
+<pre>
+&lt;set android:ordering="sequentially"&gt;
+ &lt;set&gt;
+ &lt;objectAnimator
+ android:propertyName="x"
+ android:duration="500"
+ android:valueTo="400"
+ android:valueType="intType"/&gt;
+ &lt;objectAnimator
+ android:propertyName="y"
+ android:duration="500"
+ android:valueTo="300"
+ android:valueType="intType"/&gt;
+ &lt;/set&gt;
+ &lt;objectAnimator
+ android:propertyName="alpha"
+ android:duration="500"
+ android:valueTo="1f"/&gt;
+&lt;/set&gt;
+</pre>
+ <p>In order to run this animation, you must inflate the XML resources in your code to an {@link
+ android.animation.AnimatorSet} object, and then set the target objects for all of the animations
+ before starting the animation set. Calling {@link android.animation.AnimatorSet#setTarget
+ setTarget()} sets a single target object for all children of the {@link
+ android.animation.AnimatorSet} as a convenience. The following code shows how to do this:</p>
+
+<pre>
+AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
+ R.anim.property_animator);
+set.setTarget(myObject);
+set.start();
+</pre>
+
+
+</dd> <!-- end example -->
+
+<dt>see also:</dt>
+<dd>
+<ul>
+ <li><a href="{@docRoot}guide/topics/graphics/animation.html">Property Animation</a></li>
+ <li><a href="http://zoso:8080/resources/samples/ApiDemos/src/com/example/android/apis/animation/index.html">API Demos</a> for examples
+ on how to use the property animation system.</li>
+</ul>
+</dd>
+
+</dl>
+
+<h2 id="View">View Animation</h2>
+The view animation framework supports both tween and frame by frame animations, which can both be declared
+in XML. The following sections describe how to use both methods.
+
+<h3 id="Tween">Tween animation</h3>
<p>An animation defined in XML that performs transitions such as rotating,
fading, moving, and stretching on a graphic.
@@ -254,18 +574,14 @@ image.{@link android.view.View#startAnimation(Animation) startAnimation}(hypersp
<dt>see also:</dt>
<dd>
<ul>
- <li><a href="{@docRoot}guide/topics/graphics/2d-graphics.html#tween-animation">2D
+ <li><a href="{@docRoot}guide/topics/graphics/view-animation.html#tween-animation">2D
Graphics: Tween Animation</a></li>
</ul>
</dd>
</dl>
-
-
-
-
-<h3 id="Interpolators">Interpolators</h3>
+<h4 id="Interpolators">Interpolators</h4>
<p>An interpolator is an animation modifier defined in XML that affects the rate of change in an
animation. This allows your existing animation effects to be accelerated, decelerated, repeated,
@@ -456,22 +772,7 @@ sinusoidal pattern.
</dl>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<h2 id="Frame">Frame Animation</h2>
+<h3 id="Frame">Frame animation</h3>
<p>An animation defined in XML that shows a sequence of images in order (like a film).
</p>
@@ -562,7 +863,11 @@ rocketAnimation.{@link android.graphics.drawable.AnimationDrawable#start()};
</dl>
</dd> <!-- end example -->
+<dt>see also:</dt>
+<dd>
+<ul>
+ <li><a href="{@docRoot}guide/topics/graphics/view-animation.html#frame-animation">2D
+Graphics: Frame Animation</a></li>
+</ul>
+</dd>
</dl>
-
-
-
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index 59f2e731dba5..a996ccc08d76 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -333,6 +333,86 @@ your application for other languages.</p>
indicates the current locale.</p>
</td>
</tr>
+ <tr id="SmallestScreenWidthQualifier">
+ <td>Smallest screen width</td>
+ <td>Examples:<br/>
+ <code>sw320dp</code><br/>
+ <code>sw600dp</code><br/>
+ <code>sw720dp</code><br/>
+ etc.
+ </td>
+ <td>
+ <p>Specifies a minimum "smallest screen width," in "dp" units, at which the resource
+ should be used. This configuration value represents the base screen size
+ of the device, regardless of the orientation of the display. It is based
+ on the smallest width the application will have in which to perform its
+ UI layout (in dp units) regardless of the orientation of the screen. The
+ value here takes into account screen decorations so if the device has some
+ persistent UI elements on the left or right edge of the display it must
+ present a value here that is smaller than the real screen size, accounting
+ for these UI elements reducing the application's available space.</p>
+ <p>Some values you may use here for common screen sizes:</p>
+ <ul>
+ <li>240x320 ldpi (QVGA phone): 320
+ <li>320x480 mdpi (phone): 320
+ <li>480x800 hdpi (high density phone): 320
+ <li>480x800 mdpi (tablet/phone): 480
+ <li>600x1024 mdpi (7" tablet): 600
+ <li>720x1280 mdpi (10" tablet): 720
+ </ul>
+ <p><em>Added in API Level 13.</em></p>
+ <p>Also see the {@link android.content.res.Configuration#smallestScreenWidthDp}
+ configuration field, which holds the current smallest screen width.</p>
+ </td>
+ </tr>
+ <tr id="ScreenWidthQualifier">
+ <td>Screen width</td>
+ <td>Examples:<br/>
+ <code>w720dp</code><br/>
+ <code>w1024dp</code><br/>
+ etc.
+ </td>
+ <td>
+ <p>Specifies a minimum screen width, in "dp" units, at which the resource
+ should be used. This configuration value will change when the orientation
+ changes between landscape and portrait to match the current actual width.
+ When multiple screen width configurations are available, the closest to
+ the current screen width will be used. The
+ value here takes into account screen decorations so if the device has some
+ persistent UI elements on the left or right edge of the display it must
+ present a value here that is smaller than the real screen size, accounting
+ for these UI elements reducing the application's available space.</p>
+ <p><em>Added in API Level 13.</em></p>
+ <p>Also see the {@link android.content.res.Configuration#screenWidthDp}
+ configuration field, which holds the current screen width.</p>
+ </td>
+ </tr>
+ <tr id="ScreenHeightQualifier">
+ <td>Screen height</td>
+ <td>Examples:<br/>
+ <code>h720dp</code><br/>
+ <code>h1024dp</code><br/>
+ etc.
+ </td>
+ <td>
+ <p>Specifies a minimum screen height, in "dp" units, at which the resource
+ should be used. This configuration value will change when the orientation
+ changes between landscape and portrait to match the current actual height.
+ When multiple screen height configurations are available, the closest to
+ the current screen height will be used. The
+ value here takes into account screen decorations so if the device has some
+ persistent UI elements on the left or right edge of the display it must
+ present a value here that is smaller than the real screen size, accounting
+ for these UI elements reducing the application's available space. Screen
+ decorations that are not fixed (such as a phone status bar that can be
+ hidden when full screen) are <em>not</em> accounted for here, nor are
+ window decorations like title bar, so applications must be prepared to
+ deal with a somewhat smaller space than they specify.
+ <p><em>Added in API Level 13.</em></p>
+ <p>Also see the {@link android.content.res.Configuration#screenHeightDp}
+ configuration field, which holds the current screen width.</p>
+ </td>
+ </tr>
<tr id="ScreenSizeQualifier">
<td>Screen size</td>
<td>
@@ -392,46 +472,6 @@ is not related to the screen orientation.</p>
which indicates whether the screen is long.</p>
</td>
</tr>
- <tr id="ScreenWidthQualifier">
- <td>Screen width</td>
- <td>Examples:<br/>
- <code>w720dp</code><br/>
- <code>w1024dp</code><br/>
- etc.
- </td>
- <td>
- <p>Specifies a minimum screen width, in "dp" units, at which the resource
- should be used. This configuration value will change when the orientation
- changes between landscape and portrait to match the current actual width.
- When multiple screen width configurations are available, the closest to
- the current screen width will be used. The value specified here is
- approximate; screen decorations like a status bar or system bar may cause
- the actual space available in your UI to be slightly smaller.
- <p><em>Added in API Level 13.</em></p>
- <p>Also see the {@link android.content.res.Configuration#screenWidthDp}
- configuration field, which holds the current screen width.</p>
- </td>
- </tr>
- <tr id="ScreenHeightQualifier">
- <td>Screen height</td>
- <td>Examples:<br/>
- <code>h720dp</code><br/>
- <code>h1024dp</code><br/>
- etc.
- </td>
- <td>
- <p>Specifies a minimum screen height, in "dp" units, at which the resource
- should be used. This configuration value will change when the orientation
- changes between landscape and portrait to match the current actual height.
- When multiple screen height configurations are available, the closest to
- the current screen height will be used. The value specified here is
- approximate; screen decorations like a status bar or system bar may cause
- the actual space available in your UI to be slightly smaller.
- <p><em>Added in API Level 13.</em></p>
- <p>Also see the {@link android.content.res.Configuration#screenHeightDp}
- configuration field, which holds the current screen width.</p>
- </td>
- </tr>
<tr id="OrientationQualifier">
<td>Screen orientation</td>
<td>
diff --git a/docs/html/guide/topics/usb/adk.jd b/docs/html/guide/topics/usb/adk.jd
index 8aaa65c9fd0b..6f23a17460b5 100644
--- a/docs/html/guide/topics/usb/adk.jd
+++ b/docs/html/guide/topics/usb/adk.jd
@@ -55,9 +55,7 @@ page.title=Android Open Accessory Development Kit
</ol>
</li>
</ol>
-
-
<h2>See also</h2>
<ol>
@@ -68,6 +66,12 @@ page.title=Android Open Accessory Development Kit
<h2>Where to buy</h2>
<ol>
+ <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">
+ Modern Device</a></li>
+
+ <li><a href="http://www.seeedstudio.com/depot/seeeduino-adk-main-board-p-846.html">
+ Seeed Studio</a></li>
+
<li><a href=
"http://www.rt-net.jp/shop/index.php?main_page=product_info&cPath=3_4&products_id=1">
RT Corp</a></li>
@@ -78,6 +82,7 @@ page.title=Android Open Accessory Development Kit
<li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">
DIY Drones</a></li>
+
</ol>
</div>
</div>
@@ -105,13 +110,25 @@ page.title=Android Open Accessory Development Kit
development boards:</p>
<ul>
+ <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">Modern
+ Device</a> provides an Arduino-compatible board that supports the ADK firmware.</li>
+
+ <li><a href="http://www.seeedstudio.com/depot/seeeduino-adk-main-board-p-846.html">
+ Seeed Studio</a> provides an Arduino-compatible board that supports the ADK firmware.</li>
+
<li><a href="http://www.rt-net.jp/shop/index.php?main_page=product_info&cPath=3_4&products_id=1">
RT Corp</a> provides an Arduino-compatible board based on the Android ADK board design.</li>
+
<li><a href="http://www.microchip.com/android">Microchip</a> provides a A PIC based USB
microcontroller board.</li>
+
<li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">DIY
Drones</a> provides an Arduino-compatible board geared towards RC (radio controlled) and UAV
(unmanned aerial vehicle) enthusiasts.</li>
+<<<<<<< HEAD
+=======
+
+>>>>>>> c38ed22... doc change: add link to seeedstudio board
</ul>
<p>We expect more hardware distributers to create a variety of kits, so please stay tuned for
@@ -122,7 +139,7 @@ page.title=Android Open Accessory Development Kit
accessory that is based on the <a href="http://www.arduino.cc/">Arduino open source electronics
prototyping platform</a>, the accessory's hardware design files, code that implements the
accessory's firmware, and the Android application that interacts with the accessory. The hardware
- design files and firmware code are contained in the <a href=
+ design files and firmware code are contained in the <a href=ctive
"https://dl-ssl.google.com/android/adk/adk_release_0512.zip">ADK package download</a>.</p>
<p>The main hardware and software components of the ADK include:</p>
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 5b90551385ed..d02c13d1bc2b 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -175,7 +175,8 @@ class="new">new!</span></li>
<span style="display:none" class="zh-TW"></span>
</h2>
<ul>
- <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r5b</a>
+ <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r5c <span
+ class="new">new!</span></a>
</li>
<li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li>
</ul>
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
index d430f727236a..07b3b47ee931 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
@@ -53,11 +53,11 @@ extern "C" void destroy(IDrmEngine* plugIn) {
}
FwdLockEngine::FwdLockEngine() {
- LOGD("FwdLockEngine Construction");
+ LOGV("FwdLockEngine Construction");
}
FwdLockEngine::~FwdLockEngine() {
- LOGD("FwdLockEngine Destruction");
+ LOGV("FwdLockEngine Destruction");
convertSessionMap.destroyMap();
decodeSessionMap.destroyMap();
@@ -91,7 +91,7 @@ int FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) {
DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) {
DrmConstraints* drmConstraints = NULL;
- LOGD("FwdLockEngine::onGetConstraints");
+ LOGV("FwdLockEngine::onGetConstraints");
if (NULL != path &&
(RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) {
@@ -105,7 +105,7 @@ DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* pat
DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
DrmMetadata* drmMetadata = NULL;
- LOGD("FwdLockEngine::onGetMetadata");
+ LOGV("FwdLockEngine::onGetMetadata");
if (NULL != path) {
// Returns empty metadata to show no error condition.
@@ -116,11 +116,11 @@ DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
}
android::status_t FwdLockEngine::onInitialize(int uniqueId) {
- LOGD("FwdLockEngine::onInitialize");
+ LOGV("FwdLockEngine::onInitialize");
if (FwdLockGlue_InitializeKeyEncryption()) {
- LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
+ LOGV("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
} else {
LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:"
"errno = %d", errno);
@@ -132,13 +132,13 @@ android::status_t FwdLockEngine::onInitialize(int uniqueId) {
android::status_t
FwdLockEngine::onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
// Not used
- LOGD("FwdLockEngine::onSetOnInfoListener");
+ LOGV("FwdLockEngine::onSetOnInfoListener");
return DRM_NO_ERROR;
}
android::status_t FwdLockEngine::onTerminate(int uniqueId) {
- LOGD("FwdLockEngine::onTerminate");
+ LOGV("FwdLockEngine::onTerminate");
return DRM_NO_ERROR;
}
@@ -146,7 +146,7 @@ android::status_t FwdLockEngine::onTerminate(int uniqueId) {
DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
DrmSupportInfo* pSupportInfo = new DrmSupportInfo();
- LOGD("FwdLockEngine::onGetSupportInfo");
+ LOGV("FwdLockEngine::onGetSupportInfo");
// fill all Forward Lock mimetypes and extensions
if (NULL != pSupportInfo) {
@@ -182,7 +182,7 @@ DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int uniqueId, const DrmInfo* drmI
drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8(""));
- LOGD("FwdLockEngine::onProcessDrmInfo");
+ LOGV("FwdLockEngine::onProcessDrmInfo");
return drmInfoStatus;
}
@@ -193,7 +193,7 @@ status_t FwdLockEngine::onSaveRights(
const String8& rightsPath,
const String8& contentPath) {
// No rights to save. Return
- LOGD("FwdLockEngine::onSaveRights");
+ LOGV("FwdLockEngine::onSaveRights");
return DRM_ERROR_UNKNOWN;
}
@@ -201,7 +201,7 @@ DrmInfo* FwdLockEngine::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drm
DrmInfo* drmInfo = NULL;
// Nothing to be done for Forward Lock file
- LOGD("FwdLockEngine::onAcquireDrmInfo");
+ LOGV("FwdLockEngine::onAcquireDrmInfo");
return drmInfo;
}
@@ -211,7 +211,7 @@ int FwdLockEngine::onCheckRightsStatus(int uniqueId,
int action) {
int result = RightsStatus::RIGHTS_INVALID;
- LOGD("FwdLockEngine::onCheckRightsStatus");
+ LOGV("FwdLockEngine::onCheckRightsStatus");
// Only Transfer action is not allowed for forward Lock files.
if (onCanHandle(uniqueId, path)) {
@@ -241,7 +241,7 @@ status_t FwdLockEngine::onConsumeRights(int uniqueId,
int action,
bool reserve) {
// No rights consumption
- LOGD("FwdLockEngine::onConsumeRights");
+ LOGV("FwdLockEngine::onConsumeRights");
return DRM_NO_ERROR;
}
@@ -249,14 +249,14 @@ bool FwdLockEngine::onValidateAction(int uniqueId,
const String8& path,
int action,
const ActionDescription& description) {
- LOGD("FwdLockEngine::onValidateAction");
+ LOGV("FwdLockEngine::onValidateAction");
// For the forwardlock engine checkRights and ValidateAction are the same.
return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
}
String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path) {
- LOGD("FwdLockEngine::onGetOriginalMimeType");
+ LOGV("FwdLockEngine::onGetOriginalMimeType");
String8 mimeString = String8("");
int fileDesc = FwdLockFile_open(path.string());
@@ -280,7 +280,7 @@ int FwdLockEngine::onGetDrmObjectType(int uniqueId,
const String8& mimeType) {
String8 mimeStr = String8(mimeType);
- LOGD("FwdLockEngine::onGetDrmObjectType");
+ LOGV("FwdLockEngine::onGetDrmObjectType");
mimeStr.toLower();
@@ -301,13 +301,13 @@ int FwdLockEngine::onGetDrmObjectType(int uniqueId,
status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
// No Rights to remove
- LOGD("FwdLockEngine::onRemoveRights");
+ LOGV("FwdLockEngine::onRemoveRights");
return DRM_NO_ERROR;
}
status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
// No rights to remove
- LOGD("FwdLockEngine::onRemoveAllRights");
+ LOGV("FwdLockEngine::onRemoveAllRights");
return DRM_NO_ERROR;
}
@@ -319,14 +319,14 @@ status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decrypt
int playbackStatus, int position) {
#endif
// Not used
- LOGD("FwdLockEngine::onSetPlaybackStatus");
+ LOGV("FwdLockEngine::onSetPlaybackStatus");
return DRM_NO_ERROR;
}
status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
int convertId) {
status_t result = DRM_ERROR_UNKNOWN;
- LOGD("FwdLockEngine::onOpenConvertSession");
+ LOGV("FwdLockEngine::onOpenConvertSession");
if (!convertSessionMap.isCreated(convertId)) {
ConvertSession *newSession = new ConvertSession();
if (FwdLockConv_Status_OK ==
@@ -383,7 +383,7 @@ DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId,
DrmBuffer *convResult = new DrmBuffer(NULL, 0);
int offset = -1;
- LOGD("FwdLockEngine::onCloseConvertSession");
+ LOGV("FwdLockEngine::onCloseConvertSession");
if (convertSessionMap.isCreated(convertId)) {
ConvertSession *convSession = convertSessionMap.getValue(convertId);
@@ -424,7 +424,7 @@ status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
status_t result = DRM_ERROR_CANNOT_HANDLE;
int fileDesc = -1;
- LOGD("FwdLockEngine::onOpenDecryptSession");
+ LOGV("FwdLockEngine::onOpenDecryptSession");
if ((-1 < fd) &&
(NULL != decryptHandle) &&
@@ -455,12 +455,15 @@ status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
} else {
LOGD("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
FwdLockFile_detach(fileDesc);
- ::close(fileDesc);
delete decodeSession;
}
}
- LOGD("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
+ if (DRM_NO_ERROR != result && -1 < fileDesc) {
+ ::close(fileDesc);
+ }
+
+ LOGV("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
return result;
}
@@ -497,7 +500,7 @@ status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
DecryptHandle* decryptHandle) {
status_t result = DRM_ERROR_UNKNOWN;
- LOGD("FwdLockEngine::onCloseDecryptSession");
+ LOGV("FwdLockEngine::onCloseDecryptSession");
if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
@@ -509,7 +512,7 @@ status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
}
}
- LOGD("FwdLockEngine::onCloseDecryptSession Exit");
+ LOGV("FwdLockEngine::onCloseDecryptSession Exit");
return result;
}
@@ -517,13 +520,13 @@ status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId,
DecryptHandle* decryptHandle,
int decryptUnitId,
const DrmBuffer* headerInfo) {
- LOGD("FwdLockEngine::onInitializeDecryptUnit");
+ LOGV("FwdLockEngine::onInitializeDecryptUnit");
return DRM_ERROR_UNKNOWN;
}
status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
- LOGD("FwdLockEngine::onDecrypt");
+ LOGV("FwdLockEngine::onDecrypt");
return DRM_ERROR_UNKNOWN;
}
@@ -532,14 +535,14 @@ status_t FwdLockEngine::onDecrypt(int uniqueId,
int decryptUnitId,
const DrmBuffer* encBuffer,
DrmBuffer** decBuffer) {
- LOGD("FwdLockEngine::onDecrypt");
+ LOGV("FwdLockEngine::onDecrypt");
return DRM_ERROR_UNKNOWN;
}
status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
DecryptHandle* decryptHandle,
int decryptUnitId) {
- LOGD("FwdLockEngine::onFinalizeDecryptUnit");
+ LOGV("FwdLockEngine::onFinalizeDecryptUnit");
return DRM_ERROR_UNKNOWN;
}
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 311f02439ff0..a4734fffd361 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -30,6 +30,7 @@ import android.graphics.BitmapShader;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
+import android.view.View;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -386,8 +387,9 @@ public class BitmapDrawable extends Drawable {
Shader shader = state.mPaint.getShader();
if (shader == null) {
if (mApplyGravity) {
+ final int layoutDirection = getResolvedLayoutDirectionSelf();
Gravity.apply(state.mGravity, mBitmapWidth, mBitmapHeight,
- getBounds(), mDstRect, isLayoutRtlSelf());
+ getBounds(), mDstRect, layoutDirection);
mApplyGravity = false;
}
canvas.drawBitmap(bitmap, null, mDstRect, state.mPaint);
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index 83020aaa7d37..29edc0407b7f 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -24,6 +24,7 @@ import android.content.res.TypedArray;
import android.graphics.*;
import android.view.Gravity;
import android.util.AttributeSet;
+import android.view.View;
import java.io.IOException;
@@ -209,7 +210,8 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
if ((mClipState.mOrientation & VERTICAL) != 0) {
h -= (h - ih) * (10000 - level) / 10000;
}
- Gravity.apply(mClipState.mGravity, w, h, bounds, r, isLayoutRtlSelf());
+ final int layoutDirection = getResolvedLayoutDirectionSelf();
+ Gravity.apply(mClipState.mGravity, w, h, bounds, r, layoutDirection);
if (w > 0 && h > 0) {
canvas.save();
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 8994efc6a3ab..72d233a3b35f 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -36,6 +36,7 @@ import android.util.DisplayMetrics;
import android.util.StateSet;
import android.util.TypedValue;
import android.util.Xml;
+import android.view.View;
import java.io.IOException;
import java.io.InputStream;
@@ -292,11 +293,11 @@ public abstract class Drawable {
*/
public static interface Callback2 extends Callback {
/**
- * A Drawable can call this to know whether the <var>who</var> is in RTL layout direction.
+ * A Drawable can call this to get the resolved layout direction of the <var>who</var>.
*
- * @param who The drawable being unscheduled.
+ * @param who The drawable being queried.
*/
- public boolean isLayoutRtl(Drawable who);
+ public int getResolvedLayoutDirection(Drawable who);
}
/**
@@ -376,15 +377,15 @@ public abstract class Drawable {
}
/**
- * Use the current {@link android.graphics.drawable.Drawable.Callback2} implementation to know
- * if this Drawable is having a layout in RTL direction.
+ * Use the current {@link android.graphics.drawable.Drawable.Callback2} implementation to get
+ * the resolved layout direction of this Drawable.
*/
- public boolean isLayoutRtlSelf() {
+ public int getResolvedLayoutDirectionSelf() {
final Callback callback = getCallback();
if (callback == null || !(callback instanceof Callback2)) {
- return false;
+ return View.LAYOUT_DIRECTION_LTR;
}
- return ((Callback2) callback).isLayoutRtl(this);
+ return ((Callback2) callback).getResolvedLayoutDirection(this);
}
/**
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index cbe1f2d6a14f..5fd5a1685c6b 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -24,6 +24,7 @@ import android.content.res.TypedArray;
import android.graphics.*;
import android.view.Gravity;
import android.util.AttributeSet;
+import android.view.View;
import java.io.IOException;
@@ -221,7 +222,8 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0;
h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000);
}
- Gravity.apply(mScaleState.mGravity, w, h, bounds, r, isLayoutRtlSelf());
+ final int layoutDirection = getResolvedLayoutDirectionSelf();
+ Gravity.apply(mScaleState.mGravity, w, h, bounds, r, layoutDirection);
if (w > 0 && h > 0) {
mScaleState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 3c8aba36563a..a63abb9f9bc7 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -588,13 +588,29 @@ public class Allocation extends BaseObj {
*
* @param off The offset of the first element to be copied.
* @param count The number of elements to be copied.
- * @param d the source data array
+ * @param d the source data array.
*/
public void copy1DRangeFrom(int off, int count, float[] d) {
validateIsFloat32();
copy1DRangeFromUnchecked(off, count, d);
}
+ /**
+ * Copy part of an allocation from another allocation.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param data the source data allocation.
+ * @param dataOff off The offset of the first element in data to
+ * be copied.
+ */
+ public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
+ mRS.nAllocationData2D(getID(), off, 0,
+ 0, Type.CubemapFace.POSITVE_X.mID,
+ count, 1, data.getID(), dataOff, 0,
+ 0, Type.CubemapFace.POSITVE_X.mID);
+ }
+
private void validate2DRange(int xoff, int yoff, int w, int h) {
if (xoff < 0 || yoff < 0) {
throw new RSIllegalArgumentException("Offset cannot be negative.");
@@ -609,9 +625,8 @@ public class Allocation extends BaseObj {
}
/**
- * Copy a rectanglular region from the array into the
- * allocation. The incoming array is assumed to be tightly
- * packed.
+ * Copy a rectangular region from the array into the allocation.
+ * The incoming array is assumed to be tightly packed.
*
* @param xoff X offset of the region to update
* @param yoff Y offset of the region to update
@@ -644,6 +659,28 @@ public class Allocation extends BaseObj {
}
/**
+ * Copy a rectangular region into the allocation from another
+ * allocation.
+ *
+ * @param xoff X offset of the region to update.
+ * @param yoff Y offset of the region to update.
+ * @param w Width of the incoming region to update.
+ * @param h Height of the incoming region to update.
+ * @param data source allocation.
+ * @param dataXoff X offset in data of the region to update.
+ * @param dataYoff Y offset in data of the region to update.
+ */
+ public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
+ Allocation data, int dataXoff, int dataYoff) {
+ mRS.validate();
+ validate2DRange(xoff, yoff, w, h);
+ mRS.nAllocationData2D(getID(), xoff, yoff,
+ 0, Type.CubemapFace.POSITVE_X.mID,
+ w, h, data.getID(), dataXoff, dataYoff,
+ 0, Type.CubemapFace.POSITVE_X.mID);
+ }
+
+ /**
* Copy a bitmap into an allocation. The height and width of
* the update will use the height and width of the incoming
* bitmap.
diff --git a/graphics/java/android/renderscript/AllocationAdapter.java b/graphics/java/android/renderscript/AllocationAdapter.java
index f2fedea3a530..07a1f5ddc423 100644
--- a/graphics/java/android/renderscript/AllocationAdapter.java
+++ b/graphics/java/android/renderscript/AllocationAdapter.java
@@ -33,7 +33,7 @@ public class AllocationAdapter extends Allocation {
private Allocation mAlloc;
private int mSelectedLOD = 0;
- private Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITVE_X;;
+ private Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITVE_X;
AllocationAdapter(int id, RenderScript rs, Allocation alloc) {
super(id, rs, null, alloc.mUsage);
@@ -163,15 +163,54 @@ public class AllocationAdapter extends Allocation {
mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
}
+ /**
+ * Copy part of an allocation from another allocation.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param data the source data allocation.
+ * @param dataOff off The offset of the first element in data to
+ * be copied.
+ */
+ public void subData1D(int off, int count, AllocationAdapter data, int dataOff) {
+ mRS.nAllocationData2D(getID(), off, 0,
+ mSelectedLOD, mSelectedFace.mID,
+ count, 1, data.getID(), dataOff, 0,
+ data.mSelectedLOD, data.mSelectedFace.mID);
+ }
+
public void subData2D(int xoff, int yoff, int w, int h, int[] d) {
mRS.validate();
- mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h, d, d.length * 4);
+ mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+ w, h, d, d.length * 4);
}
public void subData2D(int xoff, int yoff, int w, int h, float[] d) {
mRS.validate();
- mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h, d, d.length * 4);
+ mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+ w, h, d, d.length * 4);
+ }
+
+ /**
+ * Copy a rectangular region into the allocation from another
+ * allocation.
+ *
+ * @param xoff X offset of the region to update.
+ * @param yoff Y offset of the region to update.
+ * @param w Width of the incoming region to update.
+ * @param h Height of the incoming region to update.
+ * @param data source allocation.
+ * @param dataXoff X offset in data of the region to update.
+ * @param dataYoff Y offset in data of the region to update.
+ */
+ public void subData2D(int xoff, int yoff, int w, int h,
+ AllocationAdapter data, int dataXoff, int dataYoff) {
+ mRS.validate();
+ mRS.nAllocationData2D(getID(), xoff, yoff,
+ mSelectedLOD, mSelectedFace.mID,
+ w, h, data.getID(), dataXoff, dataYoff,
+ data.mSelectedLOD, data.mSelectedFace.mID);
}
public void readData(int[] d) {
@@ -185,12 +224,15 @@ public class AllocationAdapter extends Allocation {
}
public void setLOD(int lod) {
+ mSelectedLOD = lod;
}
public void setFace(Type.CubemapFace cf) {
+ mSelectedFace = cf;
}
public void setY(int y) {
+ mSelectedDimY = y;
}
public void setZ(int z) {
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 17f0fa649527..2110e37582ae 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -295,6 +295,26 @@ public class RenderScript {
rsnAllocationElementData1D(mContext, id, xoff, mip, compIdx, d, sizeBytes);
}
+ native void rsnAllocationData2D(int con,
+ int dstAlloc, int dstXoff, int dstYoff,
+ int dstMip, int dstFace,
+ int width, int height,
+ int srcAlloc, int srcXoff, int srcYoff,
+ int srcMip, int srcFace);
+ synchronized void nAllocationData2D(int dstAlloc, int dstXoff, int dstYoff,
+ int dstMip, int dstFace,
+ int width, int height,
+ int srcAlloc, int srcXoff, int srcYoff,
+ int srcMip, int srcFace) {
+ validate();
+ rsnAllocationData2D(mContext,
+ dstAlloc, dstXoff, dstYoff,
+ dstMip, dstFace,
+ width, height,
+ srcAlloc, srcXoff, srcYoff,
+ srcMip, srcFace);
+ }
+
native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes);
synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes) {
validate();
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 60b39b01162a..7e53cc4df237 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -468,7 +468,7 @@ nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint alloc
bitmap.lockPixels();
const void* ptr = bitmap.getPixels();
rsAllocation2DData(con, (RsAllocation)alloc, 0, 0,
- 0, RS_ALLOCATION_CUBMAP_FACE_POSITVE_X,
+ 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
w, h, ptr, bitmap.getSize());
bitmap.unlockPixels();
}
@@ -589,6 +589,30 @@ nAllocationData2D_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint
}
static void
+nAllocationData2D_alloc(JNIEnv *_env, jobject _this, RsContext con,
+ jint dstAlloc, jint dstXoff, jint dstYoff,
+ jint dstMip, jint dstFace,
+ jint width, jint height,
+ jint srcAlloc, jint srcXoff, jint srcYoff,
+ jint srcMip, jint srcFace)
+{
+ LOG_API("nAllocation2DData_s, con(%p), dstAlloc(%p), dstXoff, dstYoff,"
+ " dstMip(%i), dstFace(%i), width(%i), height(%i),"
+ " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i), srcFace(%i)",
+ con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace,
+ width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
+
+ rsAllocationCopy2DRange(con,
+ (RsAllocation)dstAlloc,
+ dstXoff, dstYoff,
+ dstMip, dstFace,
+ width, height,
+ (RsAllocation)srcAlloc,
+ srcXoff, srcYoff,
+ srcMip, srcFace);
+}
+
+static void
nAllocationRead_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jintArray data)
{
jint len = _env->GetArrayLength(data);
@@ -1217,6 +1241,7 @@ static JNINativeMethod methods[] = {
{"rsnAllocationData2D", "(IIIIIIII[SI)V", (void*)nAllocationData2D_s },
{"rsnAllocationData2D", "(IIIIIIII[BI)V", (void*)nAllocationData2D_b },
{"rsnAllocationData2D", "(IIIIIIII[FI)V", (void*)nAllocationData2D_f },
+{"rsnAllocationData2D", "(IIIIIIIIIIIII)V", (void*)nAllocationData2D_alloc },
{"rsnAllocationRead", "(II[I)V", (void*)nAllocationRead_i },
{"rsnAllocationRead", "(II[S)V", (void*)nAllocationRead_s },
{"rsnAllocationRead", "(II[B)V", (void*)nAllocationRead_b },
diff --git a/include/android_runtime/android_graphics_ParcelSurfaceTexture.h b/include/android_runtime/android_graphics_ParcelSurfaceTexture.h
index 22f1c12a5106..b94ac9b532be 100644
--- a/include/android_runtime/android_graphics_ParcelSurfaceTexture.h
+++ b/include/android_runtime/android_graphics_ParcelSurfaceTexture.h
@@ -23,10 +23,15 @@
namespace android {
+class ISurfaceTexture;
+
extern sp<ANativeWindow> android_ParcelSurfaceTexture_getNativeWindow(
JNIEnv* env, jobject thiz);
extern bool android_ParcelSurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz);
+/* Gets the underlying ISurfaceTexture from a ParcelSurfaceTexture Java object. */
+extern sp<ISurfaceTexture> ParcelSurfaceTexture_getISurfaceTexture(JNIEnv* env, jobject thiz);
+
} // namespace android
#endif // _ANDROID_GRAPHICS_PARCELSURFACETEXTURE_H
diff --git a/include/android_runtime/android_graphics_SurfaceTexture.h b/include/android_runtime/android_graphics_SurfaceTexture.h
index acf1ca82b0a6..badf22c4a03f 100644
--- a/include/android_runtime/android_graphics_SurfaceTexture.h
+++ b/include/android_runtime/android_graphics_SurfaceTexture.h
@@ -23,10 +23,14 @@
namespace android {
+class SurfaceTexture;
+
extern sp<ANativeWindow> android_SurfaceTexture_getNativeWindow(
JNIEnv* env, jobject thiz);
extern bool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz);
+/* Gets the underlying SurfaceTexture from a SurfaceTexture Java object. */
+extern sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz);
} // namespace android
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 2b314621abab..9294df674358 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -188,6 +188,11 @@ private:
status_t setBufferCountServerLocked(int bufferCount);
+ // computeCurrentTransformMatrix computes the transform matrix for the
+ // current texture. It uses mCurrentTransform and the current GraphicBuffer
+ // to compute this matrix and stores it in mCurrentTransformMatrix.
+ void computeCurrentTransformMatrix();
+
enum { INVALID_BUFFER_SLOT = -1 };
struct BufferSlot {
@@ -288,9 +293,9 @@ private:
// by calling setBufferCount or setBufferCountServer
int mBufferCount;
- // mRequestedBufferCount is the number of buffer slots requested by the
- // client. The default is zero, which means the client doesn't care how
- // many buffers there is.
+ // mClientBufferCount is the number of buffer slots requested by the client.
+ // The default is zero, which means the client doesn't care how many buffers
+ // there is.
int mClientBufferCount;
// mServerBufferCount buffer count requested by the server-side
@@ -322,6 +327,11 @@ private:
// gets set to mLastQueuedTransform each time updateTexImage is called.
uint32_t mCurrentTransform;
+ // mCurrentTransformMatrix is the transform matrix for the current texture.
+ // It gets computed by computeTransformMatrix each time updateTexImage is
+ // called.
+ float mCurrentTransformMatrix[16];
+
// mCurrentTimestamp is the timestamp for the current texture. It
// gets set to mLastQueuedTimestamp each time updateTexImage is called.
int64_t mCurrentTimestamp;
@@ -362,6 +372,7 @@ private:
// variables of SurfaceTexture objects. It must be locked whenever the
// member variables are accessed.
mutable Mutex mMutex;
+
};
// ----------------------------------------------------------------------------
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 68cd188358e9..89213b7086e4 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -22,7 +22,7 @@
#include <media/IAudioFlinger.h>
#include <system/audio.h>
-#include <hardware/audio_policy.h>
+#include <system/audio_policy.h>
/* XXX: Should be include by all the users instead */
#include <media/AudioParameter.h>
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 09b2bfea32e7..0fc8dbf127f9 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -26,7 +26,7 @@
#include <binder/IInterface.h>
#include <media/AudioSystem.h>
-#include <hardware/audio_policy.h>
+#include <system/audio_policy.h>
namespace android {
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 4044c5d61a1d..deade5ec5238 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -55,6 +55,7 @@ enum {
kKeyIsSyncFrame = 'sync', // int32_t (bool)
kKeyIsCodecConfig = 'conf', // int32_t (bool)
kKeyTime = 'time', // int64_t (usecs)
+ kKeyDecodingTime = 'decT', // int64_t (decoding timestamp in usecs)
kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp)
kKeyTargetTime = 'tarT', // int64_t (usecs)
kKeyDriftTime = 'dftT', // int64_t (usecs)
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 70daafaad52f..589cefda2038 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -202,6 +202,10 @@ private:
bool mOnlySubmitOneBufferAtOneTime;
bool mEnableGrallocUsageProtected;
+ // Used to record the decoding time for an output picture from
+ // a video encoder.
+ List<int64_t> mDecodingTimeList;
+
OMXCodec(const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
bool isEncoder, const char *mime, const char *componentName,
const sp<MediaSource> &source,
@@ -317,6 +321,8 @@ private:
status_t applyRotation();
+ int64_t retrieveDecodingTimeUs(bool isCodecSpecific);
+
OMXCodec(const OMXCodec &);
OMXCodec &operator=(const OMXCodec &);
};
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index 717f8370cb98..0da03d1343c7 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -20,355 +20,12 @@
#include <stdint.h>
#include <sys/types.h>
-#include <cutils/compiler.h>
-
#include <utils/Debug.h>
-#include <utils/threads.h>
-#include <utils/String8.h>
-
-#include <ui/Rect.h>
namespace android {
// ---------------------------------------------------------------------------
-/*
- * These classes manage a stack of buffers in shared memory.
- *
- * SharedClient: represents a client with several stacks
- * SharedBufferStack: represents a stack of buffers
- * SharedBufferClient: manipulates the SharedBufferStack from the client side
- * SharedBufferServer: manipulates the SharedBufferStack from the server side
- *
- * Buffers can be dequeued until there are none available, they can be locked
- * unless they are in use by the server, which is only the case for the last
- * dequeue-able buffer. When these various conditions are not met, the caller
- * waits until the condition is met.
- *
- */
-
-// ----------------------------------------------------------------------------
-
-class Region;
-class SharedBufferStack;
-class SharedClient;
-
-// ----------------------------------------------------------------------------
-
-class SharedBufferStack
-{
- friend class SharedClient;
- friend class SharedBufferBase;
- friend class SharedBufferClient;
- friend class SharedBufferServer;
-
-public:
- // When changing these values, the COMPILE_TIME_ASSERT at the end of this
- // file need to be updated.
- static const unsigned int NUM_LAYERS_MAX = 31;
- static const unsigned int NUM_BUFFER_MAX = 32;
- static const unsigned int NUM_BUFFER_MIN = 2;
- static const unsigned int NUM_DISPLAY_MAX = 4;
-
- struct Statistics { // 4 longs
- typedef int32_t usecs_t;
- usecs_t totalTime;
- usecs_t reserved[3];
- };
-
- struct SmallRect {
- uint16_t l, t, r, b;
- };
-
- struct FlatRegion { // 52 bytes = 4 * (1 + 2*N)
- static const unsigned int NUM_RECT_MAX = 5;
- uint32_t count;
- SmallRect rects[NUM_RECT_MAX];
- };
-
- struct BufferData {
- FlatRegion dirtyRegion;
- SmallRect crop;
- uint8_t transform;
- uint8_t reserved[3];
- };
-
- SharedBufferStack();
- void init(int32_t identity);
- status_t setDirtyRegion(int buffer, const Region& reg);
- status_t setCrop(int buffer, const Rect& reg);
- status_t setTransform(int buffer, uint8_t transform);
- Region getDirtyRegion(int buffer) const;
- Rect getCrop(int buffer) const;
- uint32_t getTransform(int buffer) const;
-
- // these attributes are part of the conditions/updates
- volatile int32_t head; // server's current front buffer
- volatile int32_t available; // number of dequeue-able buffers
- volatile int32_t queued; // number of buffers waiting for post
- volatile int32_t reserved1;
- volatile status_t status; // surface's status code
-
- // not part of the conditions
- volatile int32_t reallocMask;
- volatile int8_t index[NUM_BUFFER_MAX];
-
- int32_t identity; // surface's identity (const)
- int32_t token; // surface's token (for debugging)
- Statistics stats;
- int8_t headBuf; // last retired buffer
- uint8_t reservedBytes[3];
- int32_t reserved;
- BufferData buffers[NUM_BUFFER_MAX]; // 1024 bytes
-};
-
-// ----------------------------------------------------------------------------
-
-// 64 KB max
-class SharedClient
-{
-public:
- SharedClient();
- ~SharedClient();
- status_t validate(size_t token) const;
-
-private:
- friend class SharedBufferBase;
- friend class SharedBufferClient;
- friend class SharedBufferServer;
-
- // FIXME: this should be replaced by a lock-less primitive
- Mutex lock;
- Condition cv;
- SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ];
-};
-
-// ============================================================================
-
-class SharedBufferBase
-{
-public:
- SharedBufferBase(SharedClient* sharedClient, int surface,
- int32_t identity);
- ~SharedBufferBase();
- status_t getStatus() const;
- int32_t getIdentity() const;
- String8 dump(char const* prefix) const;
-
-protected:
- SharedClient* const mSharedClient;
- SharedBufferStack* const mSharedStack;
- const int mIdentity;
-
- friend struct Update;
- friend struct QueueUpdate;
-
- struct ConditionBase {
- SharedBufferStack& stack;
- inline ConditionBase(SharedBufferBase* sbc)
- : stack(*sbc->mSharedStack) { }
- virtual ~ConditionBase() { };
- virtual bool operator()() const = 0;
- virtual const char* name() const = 0;
- };
- status_t waitForCondition(const ConditionBase& condition);
-
- struct UpdateBase {
- SharedBufferStack& stack;
- inline UpdateBase(SharedBufferBase* sbb)
- : stack(*sbb->mSharedStack) { }
- };
- template <typename T>
- status_t updateCondition(T update);
-};
-
-template <typename T>
-status_t SharedBufferBase::updateCondition(T update) {
- SharedClient& client( *mSharedClient );
- Mutex::Autolock _l(client.lock);
- ssize_t result = update();
- client.cv.broadcast();
- return result;
-}
-
-// ----------------------------------------------------------------------------
-
-class SharedBufferClient : public SharedBufferBase
-{
-public:
- SharedBufferClient(SharedClient* sharedClient, int surface, int num,
- int32_t identity);
-
- ssize_t dequeue();
- status_t undoDequeue(int buf);
-
- status_t lock(int buf);
- status_t cancel(int buf);
- status_t queue(int buf);
- bool needNewBuffer(int buffer) const;
- status_t setDirtyRegion(int buffer, const Region& reg);
- status_t setCrop(int buffer, const Rect& reg);
- status_t setTransform(int buffer, uint32_t transform);
-
- class SetBufferCountCallback {
- friend class SharedBufferClient;
- virtual status_t operator()(int bufferCount) const = 0;
- protected:
- virtual ~SetBufferCountCallback() { }
- };
- status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc);
-
-private:
- friend struct Condition;
- friend struct DequeueCondition;
- friend struct LockCondition;
-
- struct QueueUpdate : public UpdateBase {
- inline QueueUpdate(SharedBufferBase* sbb);
- inline ssize_t operator()();
- };
-
- struct DequeueUpdate : public UpdateBase {
- inline DequeueUpdate(SharedBufferBase* sbb);
- inline ssize_t operator()();
- };
-
- struct CancelUpdate : public UpdateBase {
- int tail, buf;
- inline CancelUpdate(SharedBufferBase* sbb, int tail, int buf);
- inline ssize_t operator()();
- };
-
- // --
-
- struct DequeueCondition : public ConditionBase {
- inline DequeueCondition(SharedBufferClient* sbc);
- inline bool operator()() const;
- inline const char* name() const { return "DequeueCondition"; }
- };
-
- struct LockCondition : public ConditionBase {
- int buf;
- inline LockCondition(SharedBufferClient* sbc, int buf);
- inline bool operator()() const;
- inline const char* name() const { return "LockCondition"; }
- };
-
- int32_t computeTail() const;
-
- mutable RWLock mLock;
- int mNumBuffers;
-
- int32_t tail;
- int32_t queued_head;
- // statistics...
- nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX];
-};
-
-// ----------------------------------------------------------------------------
-
-class SharedBufferServer
- : public SharedBufferBase,
- public LightRefBase<SharedBufferServer>
-{
-public:
- SharedBufferServer(SharedClient* sharedClient, int surface, int num,
- int32_t identity);
-
- ssize_t retireAndLock();
- void setStatus(status_t status);
- status_t reallocateAll();
- status_t reallocateAllExcept(int buffer);
- int32_t getQueuedCount() const;
- Region getDirtyRegion(int buffer) const;
- Rect getCrop(int buffer) const;
- uint32_t getTransform(int buffer) const;
-
- status_t resize(int newNumBuffers);
- status_t grow(int newNumBuffers);
- status_t shrink(int newNumBuffers);
-
- SharedBufferStack::Statistics getStats() const;
-
-
-private:
- friend class LightRefBase<SharedBufferServer>;
- ~SharedBufferServer();
-
- /*
- * BufferList is basically a fixed-capacity sorted-vector of
- * unsigned 5-bits ints using a 32-bits int as storage.
- * it has efficient iterators to find items in the list and not in the list.
- */
- class BufferList {
- size_t mCapacity;
- uint32_t mList;
- public:
- BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX)
- : mCapacity(c), mList(0) { }
- status_t add(int value);
- status_t remove(int value);
- uint32_t getMask() const { return mList; }
-
- class const_iterator {
- friend class BufferList;
- uint32_t mask, curr;
- const_iterator(uint32_t mask) :
- mask(mask), curr(__builtin_clz(mask)) {
- }
- public:
- inline bool operator == (const const_iterator& rhs) const {
- return mask == rhs.mask;
- }
- inline bool operator != (const const_iterator& rhs) const {
- return mask != rhs.mask;
- }
- inline int operator *() const { return curr; }
- inline const const_iterator& operator ++() {
- mask &= ~(1<<(31-curr));
- curr = __builtin_clz(mask);
- return *this;
- }
- };
-
- inline const_iterator begin() const {
- return const_iterator(mList);
- }
- inline const_iterator end() const {
- return const_iterator(0);
- }
- inline const_iterator free_begin() const {
- uint32_t mask = (1 << (32-mCapacity)) - 1;
- return const_iterator( ~(mList | mask) );
- }
- };
-
- // this protects mNumBuffers and mBufferList
- mutable RWLock mLock;
- int mNumBuffers;
- BufferList mBufferList;
-
- struct BuffersAvailableCondition : public ConditionBase {
- int mNumBuffers;
- inline BuffersAvailableCondition(SharedBufferServer* sbs,
- int numBuffers);
- inline bool operator()() const;
- inline const char* name() const { return "BuffersAvailableCondition"; }
- };
-
- struct RetireUpdate : public UpdateBase {
- const int numBuffers;
- inline RetireUpdate(SharedBufferBase* sbb, int numBuffers);
- inline ssize_t operator()();
- };
-
- struct StatusUpdate : public UpdateBase {
- const status_t status;
- inline StatusUpdate(SharedBufferBase* sbb, status_t status);
- inline ssize_t operator()();
- };
-};
-
-// ===========================================================================
+#define NUM_DISPLAY_MAX 4
struct display_cblk_t
{
@@ -389,12 +46,11 @@ struct surface_flinger_cblk_t // 4KB max
uint8_t connected;
uint8_t reserved[3];
uint32_t pad[7];
- display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX];
+ display_cblk_t displays[NUM_DISPLAY_MAX];
};
// ---------------------------------------------------------------------------
-COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 65536)
COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
// ---------------------------------------------------------------------------
diff --git a/include/surfaceflinger/IGraphicBufferAlloc.h b/include/surfaceflinger/IGraphicBufferAlloc.h
index 01e4bd9ff052..e1b6b577b58f 100644
--- a/include/surfaceflinger/IGraphicBufferAlloc.h
+++ b/include/surfaceflinger/IGraphicBufferAlloc.h
@@ -27,6 +27,8 @@
namespace android {
// ----------------------------------------------------------------------------
+class GraphicBuffer;
+
class IGraphicBufferAlloc : public IInterface
{
public:
diff --git a/include/surfaceflinger/ISurface.h b/include/surfaceflinger/ISurface.h
index cd0ee400e120..5fdf234e5fac 100644
--- a/include/surfaceflinger/ISurface.h
+++ b/include/surfaceflinger/ISurface.h
@@ -27,42 +27,23 @@
#include <ui/PixelFormat.h>
-#include <hardware/hardware.h>
-#include <hardware/gralloc.h>
-
namespace android {
typedef int32_t SurfaceID;
-class GraphicBuffer;
+class ISurfaceTexture;
class ISurface : public IInterface
{
protected:
enum {
- RESERVED0 = IBinder::FIRST_CALL_TRANSACTION,
- RESERVED1,
- RESERVED2,
- REQUEST_BUFFER,
- SET_BUFFER_COUNT,
+ GET_SURFACE_TEXTURE = IBinder::FIRST_CALL_TRANSACTION,
};
public:
DECLARE_META_INTERFACE(Surface);
- /*
- * requests a new buffer for the given index. If w, h, or format are
- * null the buffer is created with the parameters assigned to the
- * surface it is bound to. Otherwise the buffer's parameters are
- * set to those specified.
- */
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
-
- /*
- * sets the number of buffers dequeuable for this surface.
- */
- virtual status_t setBufferCount(int bufferCount) = 0;
+ virtual sp<ISurfaceTexture> getSurfaceTexture() const = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index dea1b101e6ac..03fd01b31850 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -33,6 +33,8 @@
namespace android {
// ----------------------------------------------------------------------------
+class IMemoryHeap;
+
class ISurfaceComposer : public IInterface
{
public:
@@ -95,10 +97,6 @@ public:
*/
virtual sp<ISurfaceComposerClient> createConnection() = 0;
- /* create a client connection with surface flinger
- */
- virtual sp<ISurfaceComposerClient> createClientConnection() = 0;
-
/* create a graphic buffer allocator
*/
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
@@ -134,11 +132,6 @@ public:
virtual status_t turnElectronBeamOff(int32_t mode) = 0;
virtual status_t turnElectronBeamOn(int32_t mode) = 0;
- /* Signal surfaceflinger that there might be some work to do
- * This is an ASYNCHRONOUS call.
- */
- virtual void signal() const = 0;
-
/* verify that an ISurface was created by SurfaceFlinger.
*/
virtual bool authenticateSurface(const sp<ISurface>& surface) const = 0;
@@ -154,7 +147,6 @@ public:
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
CREATE_CONNECTION,
- CREATE_CLIENT_CONNECTION,
CREATE_GRAPHIC_BUFFER_ALLOC,
GET_CBLK,
OPEN_GLOBAL_TRANSACTION,
@@ -162,7 +154,6 @@ public:
SET_ORIENTATION,
FREEZE_DISPLAY,
UNFREEZE_DISPLAY,
- SIGNAL,
CAPTURE_SCREEN,
TURN_ELECTRON_BEAM_OFF,
TURN_ELECTRON_BEAM_ON,
diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h
index 46b1bb7e9fe1..2e75a0e4cfd9 100644
--- a/include/surfaceflinger/ISurfaceComposerClient.h
+++ b/include/surfaceflinger/ISurfaceComposerClient.h
@@ -33,9 +33,6 @@ namespace android {
// ----------------------------------------------------------------------------
-class IMemoryHeap;
-
-typedef int32_t ClientID;
typedef int32_t DisplayID;
// ----------------------------------------------------------------------------
@@ -57,9 +54,6 @@ public:
status_t writeToParcel(Parcel* parcel) const;
};
- virtual sp<IMemoryHeap> getControlBlock() const = 0;
- virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const = 0;
-
/*
* Requires ACCESS_SURFACE_FLINGER permission
*/
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index ab30f45dd541..8845dc9e1cb0 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -43,9 +43,7 @@ class IOMX;
class Rect;
class Surface;
class SurfaceComposerClient;
-class SharedClient;
-class SharedBufferClient;
-class SurfaceClient;
+class SurfaceTextureClient;
// ---------------------------------------------------------------------------
@@ -162,9 +160,6 @@ public:
status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
status_t unlockAndPost();
- // setSwapRectangle() is intended to be used by GL ES clients
- void setSwapRectangle(const Rect& r);
-
sp<IBinder> asBinder() const;
private:
@@ -209,6 +204,7 @@ private:
static int query(const ANativeWindow* window, int what, int* value);
static int perform(ANativeWindow* window, int operation, ...);
+ int setSwapInterval(int interval);
int dequeueBuffer(ANativeWindowBuffer** buffer);
int lockBuffer(ANativeWindowBuffer* buffer);
int queueBuffer(ANativeWindowBuffer* buffer);
@@ -216,83 +212,23 @@ private:
int query(int what, int* value) const;
int perform(int operation, va_list args);
- void dispatch_setUsage(va_list args);
- int dispatch_connect(va_list args);
- int dispatch_disconnect(va_list args);
- int dispatch_crop(va_list args);
- int dispatch_set_buffer_count(va_list args);
- int dispatch_set_buffers_geometry(va_list args);
- int dispatch_set_buffers_transform(va_list args);
- int dispatch_set_buffers_timestamp(va_list args);
-
- void setUsage(uint32_t reqUsage);
- int connect(int api);
- int disconnect(int api);
- int crop(Rect const* rect);
- int setBufferCount(int bufferCount);
- int setBuffersGeometry(int w, int h, int format);
- int setBuffersTransform(int transform);
- int setBuffersTimestamp(int64_t timestamp);
-
/*
* private stuff...
*/
void init();
status_t validate(bool inCancelBuffer = false) const;
- // When the buffer pool is a fixed size we want to make sure SurfaceFlinger
- // won't stall clients, so we require an extra buffer.
- enum { MIN_UNDEQUEUED_BUFFERS = 2 };
-
- inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
- inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
-
- status_t getBufferLocked(int index,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
- int getBufferIndex(const sp<GraphicBuffer>& buffer) const;
-
int getConnectedApi() const;
- bool needNewBuffer(int bufIdx,
- uint32_t *pWidth, uint32_t *pHeight,
- uint32_t *pFormat, uint32_t *pUsage) const;
-
static void cleanCachedSurfacesLocked();
- class BufferInfo {
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mFormat;
- uint32_t mUsage;
- mutable uint32_t mDirty;
- enum {
- GEOMETRY = 0x01
- };
- public:
- BufferInfo();
- void set(uint32_t w, uint32_t h, uint32_t format);
- void set(uint32_t usage);
- void get(uint32_t *pWidth, uint32_t *pHeight,
- uint32_t *pFormat, uint32_t *pUsage) const;
- bool validateBuffer(const sp<GraphicBuffer>& buffer) const;
- };
-
// constants
- GraphicBufferMapper& mBufferMapper;
- SurfaceClient& mClient;
- SharedBufferClient* mSharedBufferClient;
status_t mInitCheck;
sp<ISurface> mSurface;
+ sp<SurfaceTextureClient> mSurfaceTextureClient;
uint32_t mIdentity;
PixelFormat mFormat;
uint32_t mFlags;
-
- // protected by mSurfaceLock
- Rect mSwapRectangle;
- int mConnected;
- Rect mNextBufferCrop;
- uint32_t mNextBufferTransform;
- BufferInfo mBufferInfo;
// protected by mSurfaceLock. These are also used from lock/unlock
// but in that case, they must be called form the same thread.
@@ -304,9 +240,6 @@ private:
mutable Region mOldDirtyRegion;
bool mReserved;
- // only used from dequeueBuffer()
- Vector< sp<GraphicBuffer> > mBuffers;
-
// query() must be called from dequeueBuffer() thread
uint32_t mWidth;
uint32_t mHeight;
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index c61a5bff2a12..140b9f860bfd 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -36,10 +36,10 @@ namespace android {
// ---------------------------------------------------------------------------
-class Region;
-class SharedClient;
-class ISurfaceComposer;
class DisplayInfo;
+class IMemoryHeap;
+class ISurfaceComposer;
+class Region;
class surface_flinger_cblk_t;
// ---------------------------------------------------------------------------
diff --git a/include/utils/BlobCache.h b/include/utils/BlobCache.h
new file mode 100644
index 000000000000..8f76d72c18a3
--- /dev/null
+++ b/include/utils/BlobCache.h
@@ -0,0 +1,181 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_BLOB_CACHE_H
+#define ANDROID_BLOB_CACHE_H
+
+#include <stddef.h>
+
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/threads.h>
+
+namespace android {
+
+// A BlobCache is an in-memory cache for binary key/value pairs. All the public
+// methods are thread-safe.
+//
+// The cache contents can be serialized to a file and reloaded in a subsequent
+// execution of the program. This serialization is non-portable and should only
+// be loaded by the device that generated it.
+class BlobCache : public RefBase {
+public:
+
+ // Create an empty blob cache. The blob cache will cache key/value pairs
+ // with key and value sizes less than or equal to maxKeySize and
+ // maxValueSize, respectively. The total combined size of ALL cache entries
+ // (key sizes plus value sizes) will not exceed maxTotalSize.
+ BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize);
+
+ // set inserts a new binary value into the cache and associates it with the
+ // given binary key. If the key or value are too large for the cache then
+ // the cache remains unchanged. This includes the case where a different
+ // value was previously associated with the given key - the old value will
+ // remain in the cache. If the given key and value are small enough to be
+ // put in the cache (based on the maxKeySize, maxValueSize, and maxTotalSize
+ // values specified to the BlobCache constructor), then the key/value pair
+ // will be in the cache after set returns. Note, however, that a subsequent
+ // call to set may evict old key/value pairs from the cache.
+ //
+ // Preconditions:
+ // key != NULL
+ // 0 < keySize
+ // value != NULL
+ // 0 < valueSize
+ void set(const void* key, size_t keySize, const void* value,
+ size_t valueSize);
+
+ // The get function retrieves from the cache the binary value associated
+ // with a given binary key. If the key is present in the cache then the
+ // length of the binary value associated with that key is returned. If the
+ // value argument is non-NULL and the size of the cached value is less than
+ // valueSize bytes then the cached value is copied into the buffer pointed
+ // to by the value argument. If the key is not present in the cache then 0
+ // is returned and the buffer pointed to by the value argument is not
+ // modified.
+ //
+ // Note that when calling get multiple times with the same key, the later
+ // calls may fail, returning 0, even if earlier calls succeeded. The return
+ // value must be checked for each call.
+ //
+ // Preconditions:
+ // key != NULL
+ // 0 < keySize
+ // 0 <= valueSize
+ size_t get(const void* key, size_t keySize, void* value, size_t valueSize);
+
+private:
+ // Copying is disallowed.
+ BlobCache(const BlobCache&);
+ void operator=(const BlobCache&);
+
+ // clean evicts a randomly chosen set of entries from the cache such that
+ // the total size of all remaining entries is less than mMaxTotalSize/2.
+ void clean();
+
+ // isCleanable returns true if the cache is full enough for the clean method
+ // to have some effect, and false otherwise.
+ bool isCleanable() const;
+
+ // A Blob is an immutable sized unstructured data blob.
+ class Blob : public RefBase {
+ public:
+ Blob(const void* data, size_t size, bool copyData);
+ ~Blob();
+
+ bool operator<(const Blob& rhs) const;
+
+ const void* getData() const;
+ size_t getSize() const;
+
+ private:
+ // Copying is not allowed.
+ Blob(const Blob&);
+ void operator=(const Blob&);
+
+ // mData points to the buffer containing the blob data.
+ const void* mData;
+
+ // mSize is the size of the blob data in bytes.
+ size_t mSize;
+
+ // mOwnsData indicates whether or not this Blob object should free the
+ // memory pointed to by mData when the Blob gets destructed.
+ bool mOwnsData;
+ };
+
+ // A CacheEntry is a single key/value pair in the cache.
+ class CacheEntry {
+ public:
+ CacheEntry();
+ CacheEntry(const sp<Blob>& key, const sp<Blob>& value);
+ CacheEntry(const CacheEntry& ce);
+
+ bool operator<(const CacheEntry& rhs) const;
+ const CacheEntry& operator=(const CacheEntry&);
+
+ sp<Blob> getKey() const;
+ sp<Blob> getValue() const;
+
+ void setValue(const sp<Blob>& value);
+
+ private:
+
+ // mKey is the key that identifies the cache entry.
+ sp<Blob> mKey;
+
+ // mValue is the cached data associated with the key.
+ sp<Blob> mValue;
+ };
+
+ // mMaxKeySize is the maximum key size that will be cached. Calls to
+ // BlobCache::set with a keySize parameter larger than mMaxKeySize will
+ // simply not add the key/value pair to the cache.
+ const size_t mMaxKeySize;
+
+ // mMaxValueSize is the maximum value size that will be cached. Calls to
+ // BlobCache::set with a valueSize parameter larger than mMaxValueSize will
+ // simply not add the key/value pair to the cache.
+ const size_t mMaxValueSize;
+
+ // mMaxTotalSize is the maximum size that all cache entries can occupy. This
+ // includes space for both keys and values. When a call to BlobCache::set
+ // would otherwise cause this limit to be exceeded, either the key/value
+ // pair passed to BlobCache::set will not be cached or other cache entries
+ // will be evicted from the cache to make room for the new entry.
+ const size_t mMaxTotalSize;
+
+ // mTotalSize is the total combined size of all keys and values currently in
+ // the cache.
+ size_t mTotalSize;
+
+ // mRandState is the pseudo-random number generator state. It is passed to
+ // nrand48 to generate random numbers when needed. It must be protected by
+ // mMutex.
+ unsigned short mRandState[3];
+
+ // mCacheEntries stores all the cache entries that are resident in memory.
+ // Cache entries are added to it by the 'set' method.
+ SortedVector<CacheEntry> mCacheEntries;
+
+ // mMutex is used to synchronize access to all member variables. It must be
+ // locked any time the member variables are written or read.
+ Mutex mMutex;
+};
+
+}
+
+#endif // ANDROID_BLOB_CACHE_H
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index 412622596c85..ca170827f1b2 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -116,16 +116,23 @@ public:
typedef RefBase basetype;
-protected:
- RefBase();
- virtual ~RefBase();
+ // used to override the RefBase destruction.
+ class Destroyer {
+ friend class RefBase;
+ friend class weakref_type;
+ public:
+ virtual ~Destroyer();
+ private:
+ virtual void destroy(RefBase const* base) = 0;
+ };
- // called when the last reference goes away. this is responsible for
- // calling the destructor. The default implementation just does
- // "delete this;".
// Make sure to never acquire a strong reference from this function. The
// same restrictions than for destructors apply.
- virtual void destroy() const;
+ void setDestroyer(Destroyer* destroyer);
+
+protected:
+ RefBase();
+ virtual ~RefBase();
//! Flags for extendObjectLifetime()
enum {
diff --git a/include/utils/threads.h b/include/utils/threads.h
index 41e5766a04f9..0bd69cf37796 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -526,6 +526,7 @@ private:
Thread& operator=(const Thread&);
static int _threadLoop(void* user);
const bool mCanCallJava;
+ // always hold mLock when reading or writing
thread_id_t mThread;
mutable Mutex mLock;
Condition mThreadExitedCondition;
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index b5737ffff18f..4070eba736ae 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -16,7 +16,6 @@ LOCAL_SRC_FILES:= \
ISurfaceComposerClient.cpp \
IGraphicBufferAlloc.cpp \
LayerState.cpp \
- SharedBufferStack.cpp \
Surface.cpp \
SurfaceComposerClient.cpp \
diff --git a/libs/gui/ISurface.cpp b/libs/gui/ISurface.cpp
index 23b90af31143..96155d7458b1 100644
--- a/libs/gui/ISurface.cpp
+++ b/libs/gui/ISurface.cpp
@@ -22,9 +22,7 @@
#include <binder/Parcel.h>
-#include <ui/GraphicBuffer.h>
-
-#include <surfaceflinger/Surface.h>
+#include <gui/ISurfaceTexture.h>
#include <surfaceflinger/ISurface.h>
namespace android {
@@ -39,30 +37,11 @@ public:
{
}
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
- {
+ virtual sp<ISurfaceTexture> getSurfaceTexture() const {
Parcel data, reply;
data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
- data.writeInt32(bufferIdx);
- data.writeInt32(w);
- data.writeInt32(h);
- data.writeInt32(format);
- data.writeInt32(usage);
- remote()->transact(REQUEST_BUFFER, data, &reply);
- sp<GraphicBuffer> buffer = new GraphicBuffer();
- reply.read(*buffer);
- return buffer;
- }
-
- virtual status_t setBufferCount(int bufferCount)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
- data.writeInt32(bufferCount);
- remote()->transact(SET_BUFFER_COUNT, data, &reply);
- status_t err = reply.readInt32();
- return err;
+ remote()->transact(GET_SURFACE_TEXTURE, data, &reply);
+ return interface_cast<ISurfaceTexture>(reply.readStrongBinder());
}
};
@@ -74,23 +53,9 @@ status_t BnSurface::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
- case REQUEST_BUFFER: {
- CHECK_INTERFACE(ISurface, data, reply);
- int bufferIdx = data.readInt32();
- uint32_t w = data.readInt32();
- uint32_t h = data.readInt32();
- uint32_t format = data.readInt32();
- uint32_t usage = data.readInt32();
- sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, w, h, format, usage));
- if (buffer == NULL)
- return BAD_VALUE;
- return reply->write(*buffer);
- }
- case SET_BUFFER_COUNT: {
+ case GET_SURFACE_TEXTURE: {
CHECK_INTERFACE(ISurface, data, reply);
- int bufferCount = data.readInt32();
- status_t err = setBufferCount(bufferCount);
- reply->writeInt32(err);
+ reply->writeStrongBinder( getSurfaceTexture()->asBinder() );
return NO_ERROR;
}
default:
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 8951c3f0453a..40450a3d0750 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -57,15 +57,6 @@ public:
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}
- virtual sp<ISurfaceComposerClient> createClientConnection()
- {
- uint32_t n;
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::CREATE_CLIENT_CONNECTION, data, &reply);
- return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
- }
-
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
{
uint32_t n;
@@ -174,13 +165,6 @@ public:
return reply.readInt32();
}
- virtual void signal() const
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY);
- }
-
virtual bool authenticateSurface(const sp<ISurface>& surface) const
{
Parcel data, reply;
@@ -229,11 +213,6 @@ status_t BnSurfaceComposer::onTransact(
sp<IBinder> b = createConnection()->asBinder();
reply->writeStrongBinder(b);
} break;
- case CREATE_CLIENT_CONNECTION: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> b = createClientConnection()->asBinder();
- reply->writeStrongBinder(b);
- } break;
case CREATE_GRAPHIC_BUFFER_ALLOC: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
@@ -270,10 +249,6 @@ status_t BnSurfaceComposer::onTransact(
CHECK_INTERFACE(ISurfaceComposer, data, reply);
bootFinished();
} break;
- case SIGNAL: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- signal();
- } break;
case GET_CBLK: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> b = getCblk()->asBinder();
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index ea38e08a555f..8d8339258860 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -50,9 +50,7 @@
namespace android {
enum {
- GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
- GET_TOKEN,
- CREATE_SURFACE,
+ CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
DESTROY_SURFACE,
SET_STATE
};
@@ -65,23 +63,6 @@ public:
{
}
- virtual sp<IMemoryHeap> getControlBlock() const
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
- remote()->transact(GET_CBLK, data, &reply);
- return interface_cast<IMemoryHeap>(reply.readStrongBinder());
- }
-
- virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
- data.writeStrongBinder(sur->asBinder());
- remote()->transact(GET_TOKEN, data, &reply);
- return reply.readInt32();
- }
-
virtual sp<ISurface> createSurface( surface_data_t* params,
const String8& name,
DisplayID display,
@@ -131,41 +112,6 @@ IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClie
status_t BnSurfaceComposerClient::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
- // codes that don't require permission check
-
- switch(code) {
- case GET_CBLK: {
- CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
- sp<IMemoryHeap> ctl(getControlBlock());
- reply->writeStrongBinder(ctl->asBinder());
- return NO_ERROR;
- } break;
- case GET_TOKEN: {
- CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
- sp<ISurface> sur = interface_cast<ISurface>(data.readStrongBinder());
- ssize_t token = getTokenForSurface(sur);
- reply->writeInt32(token);
- return NO_ERROR;
- } break;
- }
-
- // these must be checked
-
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- const int self_pid = getpid();
- if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
- // we're called from a different process, do the real check
- if (!checkCallingPermission(
- String16("android.permission.ACCESS_SURFACE_FLINGER")))
- {
- LOGE("Permission Denial: "
- "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- }
-
switch(code) {
case CREATE_SURFACE: {
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
diff --git a/libs/gui/SharedBufferStack.cpp b/libs/gui/SharedBufferStack.cpp
deleted file mode 100644
index 7505d530e0c5..000000000000
--- a/libs/gui/SharedBufferStack.cpp
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#define LOG_TAG "SharedBufferStack"
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Debug.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
-
-#include <private/surfaceflinger/SharedBufferStack.h>
-
-#include <ui/Rect.h>
-#include <ui/Region.h>
-
-#define DEBUG_ATOMICS 0
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-SharedClient::SharedClient()
- : lock(Mutex::SHARED), cv(Condition::SHARED)
-{
-}
-
-SharedClient::~SharedClient() {
-}
-
-
-// these functions are used by the clients
-status_t SharedClient::validate(size_t i) const {
- if (uint32_t(i) >= uint32_t(SharedBufferStack::NUM_LAYERS_MAX))
- return BAD_INDEX;
- return surfaces[i].status;
-}
-
-// ----------------------------------------------------------------------------
-
-
-SharedBufferStack::SharedBufferStack()
-{
-}
-
-void SharedBufferStack::init(int32_t i)
-{
- status = NO_ERROR;
- identity = i;
-}
-
-status_t SharedBufferStack::setCrop(int buffer, const Rect& crop)
-{
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return BAD_INDEX;
-
- buffers[buffer].crop.l = uint16_t(crop.left);
- buffers[buffer].crop.t = uint16_t(crop.top);
- buffers[buffer].crop.r = uint16_t(crop.right);
- buffers[buffer].crop.b = uint16_t(crop.bottom);
- return NO_ERROR;
-}
-
-status_t SharedBufferStack::setTransform(int buffer, uint8_t transform)
-{
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return BAD_INDEX;
- buffers[buffer].transform = transform;
- return NO_ERROR;
-}
-
-status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
-{
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return BAD_INDEX;
-
- FlatRegion& reg(buffers[buffer].dirtyRegion);
- if (dirty.isEmpty()) {
- reg.count = 0;
- return NO_ERROR;
- }
-
- size_t count;
- Rect const* r = dirty.getArray(&count);
- if (count > FlatRegion::NUM_RECT_MAX) {
- const Rect bounds(dirty.getBounds());
- reg.count = 1;
- reg.rects[0].l = uint16_t(bounds.left);
- reg.rects[0].t = uint16_t(bounds.top);
- reg.rects[0].r = uint16_t(bounds.right);
- reg.rects[0].b = uint16_t(bounds.bottom);
- } else {
- reg.count = count;
- for (size_t i=0 ; i<count ; i++) {
- reg.rects[i].l = uint16_t(r[i].left);
- reg.rects[i].t = uint16_t(r[i].top);
- reg.rects[i].r = uint16_t(r[i].right);
- reg.rects[i].b = uint16_t(r[i].bottom);
- }
- }
- return NO_ERROR;
-}
-
-Region SharedBufferStack::getDirtyRegion(int buffer) const
-{
- Region res;
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return res;
-
- const FlatRegion& reg(buffers[buffer].dirtyRegion);
- if (reg.count > FlatRegion::NUM_RECT_MAX)
- return res;
-
- if (reg.count == 1) {
- const Rect r(
- reg.rects[0].l,
- reg.rects[0].t,
- reg.rects[0].r,
- reg.rects[0].b);
- res.set(r);
- } else {
- for (size_t i=0 ; i<reg.count ; i++) {
- const Rect r(
- reg.rects[i].l,
- reg.rects[i].t,
- reg.rects[i].r,
- reg.rects[i].b);
- res.orSelf(r);
- }
- }
- return res;
-}
-
-Rect SharedBufferStack::getCrop(int buffer) const
-{
- Rect res(-1, -1);
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return res;
- res.left = buffers[buffer].crop.l;
- res.top = buffers[buffer].crop.t;
- res.right = buffers[buffer].crop.r;
- res.bottom = buffers[buffer].crop.b;
- return res;
-}
-
-uint32_t SharedBufferStack::getTransform(int buffer) const
-{
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return 0;
- return buffers[buffer].transform;
-}
-
-
-// ----------------------------------------------------------------------------
-
-SharedBufferBase::SharedBufferBase(SharedClient* sharedClient,
- int surface, int32_t identity)
- : mSharedClient(sharedClient),
- mSharedStack(sharedClient->surfaces + surface),
- mIdentity(identity)
-{
-}
-
-SharedBufferBase::~SharedBufferBase()
-{
-}
-
-status_t SharedBufferBase::getStatus() const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.status;
-}
-
-int32_t SharedBufferBase::getIdentity() const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.identity;
-}
-
-String8 SharedBufferBase::dump(char const* prefix) const
-{
- const size_t SIZE = 1024;
- char buffer[SIZE];
- String8 result;
- SharedBufferStack& stack( *mSharedStack );
- snprintf(buffer, SIZE,
- "%s[ head=%2d, available=%2d, queued=%2d ] "
- "reallocMask=%08x, identity=%d, status=%d",
- prefix, stack.head, stack.available, stack.queued,
- stack.reallocMask, stack.identity, stack.status);
- result.append(buffer);
- result.append("\n");
- return result;
-}
-
-status_t SharedBufferBase::waitForCondition(const ConditionBase& condition)
-{
- const SharedBufferStack& stack( *mSharedStack );
- SharedClient& client( *mSharedClient );
- const nsecs_t TIMEOUT = s2ns(1);
- const int identity = mIdentity;
-
- Mutex::Autolock _l(client.lock);
- while ((condition()==false) &&
- (stack.identity == identity) &&
- (stack.status == NO_ERROR))
- {
- status_t err = client.cv.waitRelative(client.lock, TIMEOUT);
- // handle errors and timeouts
- if (CC_UNLIKELY(err != NO_ERROR)) {
- if (err == TIMED_OUT) {
- if (condition()) {
- LOGE("waitForCondition(%s) timed out (identity=%d), "
- "but condition is true! We recovered but it "
- "shouldn't happen." , condition.name(), stack.identity);
- break;
- } else {
- LOGW("waitForCondition(%s) timed out "
- "(identity=%d, status=%d). "
- "CPU may be pegged. trying again.", condition.name(),
- stack.identity, stack.status);
- }
- } else {
- LOGE("waitForCondition(%s) error (%s) ",
- condition.name(), strerror(-err));
- return err;
- }
- }
- }
- return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status;
-}
-// ============================================================================
-// conditions and updates
-// ============================================================================
-
-SharedBufferClient::DequeueCondition::DequeueCondition(
- SharedBufferClient* sbc) : ConditionBase(sbc) {
-}
-bool SharedBufferClient::DequeueCondition::operator()() const {
- return stack.available > 0;
-}
-
-SharedBufferClient::LockCondition::LockCondition(
- SharedBufferClient* sbc, int buf) : ConditionBase(sbc), buf(buf) {
-}
-bool SharedBufferClient::LockCondition::operator()() const {
- // NOTE: if stack.head is messed up, we could crash the client
- // or cause some drawing artifacts. This is okay, as long as it is
- // limited to the client.
- return (buf != stack.index[stack.head]);
-}
-
-SharedBufferServer::BuffersAvailableCondition::BuffersAvailableCondition(
- SharedBufferServer* sbs, int numBuffers) : ConditionBase(sbs),
- mNumBuffers(numBuffers) {
-}
-bool SharedBufferServer::BuffersAvailableCondition::operator()() const {
- return stack.available == mNumBuffers;
-}
-
-// ----------------------------------------------------------------------------
-
-SharedBufferClient::QueueUpdate::QueueUpdate(SharedBufferBase* sbb)
- : UpdateBase(sbb) {
-}
-ssize_t SharedBufferClient::QueueUpdate::operator()() {
- android_atomic_inc(&stack.queued);
- return NO_ERROR;
-}
-
-SharedBufferClient::DequeueUpdate::DequeueUpdate(SharedBufferBase* sbb)
- : UpdateBase(sbb) {
-}
-ssize_t SharedBufferClient::DequeueUpdate::operator()() {
- if (android_atomic_dec(&stack.available) == 0) {
- LOGW("dequeue probably called from multiple threads!");
- }
- return NO_ERROR;
-}
-
-SharedBufferClient::CancelUpdate::CancelUpdate(SharedBufferBase* sbb,
- int tail, int buf)
- : UpdateBase(sbb), tail(tail), buf(buf) {
-}
-ssize_t SharedBufferClient::CancelUpdate::operator()() {
- stack.index[tail] = buf;
- android_atomic_inc(&stack.available);
- return NO_ERROR;
-}
-
-SharedBufferServer::RetireUpdate::RetireUpdate(
- SharedBufferBase* sbb, int numBuffers)
- : UpdateBase(sbb), numBuffers(numBuffers) {
-}
-ssize_t SharedBufferServer::RetireUpdate::operator()() {
- int32_t head = stack.head;
- if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
- return BAD_VALUE;
-
- // Decrement the number of queued buffers
- int32_t queued;
- do {
- queued = stack.queued;
- if (queued == 0) {
- return NOT_ENOUGH_DATA;
- }
- } while (android_atomic_cmpxchg(queued, queued-1, &stack.queued));
-
- // lock the buffer before advancing head, which automatically unlocks
- // the buffer we preventively locked upon entering this function
-
- head = (head + 1) % numBuffers;
- const int8_t headBuf = stack.index[head];
- stack.headBuf = headBuf;
-
- // head is only modified here, so we don't need to use cmpxchg
- android_atomic_write(head, &stack.head);
-
- // now that head has moved, we can increment the number of available buffers
- android_atomic_inc(&stack.available);
- return head;
-}
-
-SharedBufferServer::StatusUpdate::StatusUpdate(
- SharedBufferBase* sbb, status_t status)
- : UpdateBase(sbb), status(status) {
-}
-
-ssize_t SharedBufferServer::StatusUpdate::operator()() {
- android_atomic_write(status, &stack.status);
- return NO_ERROR;
-}
-
-// ============================================================================
-
-SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,
- int surface, int num, int32_t identity)
- : SharedBufferBase(sharedClient, surface, identity),
- mNumBuffers(num), tail(0)
-{
- SharedBufferStack& stack( *mSharedStack );
- tail = computeTail();
- queued_head = stack.head;
-}
-
-int32_t SharedBufferClient::computeTail() const
-{
- SharedBufferStack& stack( *mSharedStack );
- return (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers;
-}
-
-ssize_t SharedBufferClient::dequeue()
-{
- SharedBufferStack& stack( *mSharedStack );
-
- RWLock::AutoRLock _rd(mLock);
-
- const nsecs_t dequeueTime = systemTime(SYSTEM_TIME_THREAD);
-
- //LOGD("[%d] about to dequeue a buffer",
- // mSharedStack->identity);
- DequeueCondition condition(this);
- status_t err = waitForCondition(condition);
- if (err != NO_ERROR)
- return ssize_t(err);
-
- DequeueUpdate update(this);
- updateCondition( update );
-
- int dequeued = stack.index[tail];
- tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1);
- LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail++=%d, %s",
- dequeued, tail, dump("").string());
-
- mDequeueTime[dequeued] = dequeueTime;
-
- return dequeued;
-}
-
-status_t SharedBufferClient::undoDequeue(int buf)
-{
- return cancel(buf);
-}
-
-status_t SharedBufferClient::cancel(int buf)
-{
- RWLock::AutoRLock _rd(mLock);
-
- // calculate the new position of the tail index (essentially tail--)
- int localTail = (tail + mNumBuffers - 1) % mNumBuffers;
- CancelUpdate update(this, localTail, buf);
- status_t err = updateCondition( update );
- if (err == NO_ERROR) {
- tail = localTail;
- }
- return err;
-}
-
-status_t SharedBufferClient::lock(int buf)
-{
- RWLock::AutoRLock _rd(mLock);
-
- SharedBufferStack& stack( *mSharedStack );
- LockCondition condition(this, buf);
- status_t err = waitForCondition(condition);
- return err;
-}
-
-status_t SharedBufferClient::queue(int buf)
-{
- RWLock::AutoRLock _rd(mLock);
-
- SharedBufferStack& stack( *mSharedStack );
-
- queued_head = (queued_head + 1) % mNumBuffers;
- stack.index[queued_head] = buf;
-
- QueueUpdate update(this);
- status_t err = updateCondition( update );
- LOGD_IF(DEBUG_ATOMICS, "queued=%d, %s", buf, dump("").string());
-
- const nsecs_t now = systemTime(SYSTEM_TIME_THREAD);
- stack.stats.totalTime = ns2us(now - mDequeueTime[buf]);
-
- return err;
-}
-
-bool SharedBufferClient::needNewBuffer(int buf) const
-{
- SharedBufferStack& stack( *mSharedStack );
- const uint32_t mask = 1<<(31-buf);
- return (android_atomic_and(~mask, &stack.reallocMask) & mask) != 0;
-}
-
-status_t SharedBufferClient::setCrop(int buf, const Rect& crop)
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.setCrop(buf, crop);
-}
-
-status_t SharedBufferClient::setTransform(int buf, uint32_t transform)
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.setTransform(buf, uint8_t(transform));
-}
-
-status_t SharedBufferClient::setDirtyRegion(int buf, const Region& reg)
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.setDirtyRegion(buf, reg);
-}
-
-status_t SharedBufferClient::setBufferCount(
- int bufferCount, const SetBufferCountCallback& ipc)
-{
- SharedBufferStack& stack( *mSharedStack );
- if (uint32_t(bufferCount) >= SharedBufferStack::NUM_BUFFER_MAX)
- return BAD_VALUE;
-
- if (uint32_t(bufferCount) < SharedBufferStack::NUM_BUFFER_MIN)
- return BAD_VALUE;
-
- RWLock::AutoWLock _wr(mLock);
-
- status_t err = ipc(bufferCount);
- if (err == NO_ERROR) {
- mNumBuffers = bufferCount;
- queued_head = (stack.head + stack.queued) % mNumBuffers;
- tail = computeTail();
- }
- return err;
-}
-
-// ----------------------------------------------------------------------------
-
-SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
- int surface, int num, int32_t identity)
- : SharedBufferBase(sharedClient, surface, identity),
- mNumBuffers(num)
-{
- mSharedStack->init(identity);
- mSharedStack->token = surface;
- mSharedStack->head = num-1;
- mSharedStack->available = num;
- mSharedStack->queued = 0;
- mSharedStack->reallocMask = 0;
- memset(mSharedStack->buffers, 0, sizeof(mSharedStack->buffers));
- for (int i=0 ; i<num ; i++) {
- mBufferList.add(i);
- mSharedStack->index[i] = i;
- }
-}
-
-SharedBufferServer::~SharedBufferServer()
-{
-}
-
-ssize_t SharedBufferServer::retireAndLock()
-{
- RWLock::AutoRLock _l(mLock);
-
- RetireUpdate update(this, mNumBuffers);
- ssize_t buf = updateCondition( update );
- if (buf >= 0) {
- if (uint32_t(buf) >= SharedBufferStack::NUM_BUFFER_MAX)
- return BAD_VALUE;
- SharedBufferStack& stack( *mSharedStack );
- buf = stack.index[buf];
- LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s",
- int(buf), dump("").string());
- }
- return buf;
-}
-
-void SharedBufferServer::setStatus(status_t status)
-{
- if (status < NO_ERROR) {
- StatusUpdate update(this, status);
- updateCondition( update );
- }
-}
-
-status_t SharedBufferServer::reallocateAll()
-{
- RWLock::AutoRLock _l(mLock);
-
- SharedBufferStack& stack( *mSharedStack );
- uint32_t mask = mBufferList.getMask();
- android_atomic_or(mask, &stack.reallocMask);
- return NO_ERROR;
-}
-
-status_t SharedBufferServer::reallocateAllExcept(int buffer)
-{
- RWLock::AutoRLock _l(mLock);
-
- SharedBufferStack& stack( *mSharedStack );
- BufferList temp(mBufferList);
- temp.remove(buffer);
- uint32_t mask = temp.getMask();
- android_atomic_or(mask, &stack.reallocMask);
- return NO_ERROR;
-}
-
-int32_t SharedBufferServer::getQueuedCount() const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.queued;
-}
-
-Region SharedBufferServer::getDirtyRegion(int buf) const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.getDirtyRegion(buf);
-}
-
-Rect SharedBufferServer::getCrop(int buf) const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.getCrop(buf);
-}
-
-uint32_t SharedBufferServer::getTransform(int buf) const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.getTransform(buf);
-}
-
-/*
- * NOTE: this is not thread-safe on the server-side, meaning
- * 'head' cannot move during this operation. The client-side
- * can safely operate an usual.
- *
- */
-status_t SharedBufferServer::resize(int newNumBuffers)
-{
- if ((unsigned int)(newNumBuffers) < SharedBufferStack::NUM_BUFFER_MIN ||
- (unsigned int)(newNumBuffers) > SharedBufferStack::NUM_BUFFER_MAX) {
- return BAD_VALUE;
- }
-
- RWLock::AutoWLock _l(mLock);
-
- if (newNumBuffers < mNumBuffers) {
- return shrink(newNumBuffers);
- } else {
- return grow(newNumBuffers);
- }
-}
-
-status_t SharedBufferServer::grow(int newNumBuffers)
-{
- SharedBufferStack& stack( *mSharedStack );
- const int numBuffers = mNumBuffers;
- const int extra = newNumBuffers - numBuffers;
-
- // read the head, make sure it's valid
- int32_t head = stack.head;
- if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
- return BAD_VALUE;
-
- int base = numBuffers;
- int32_t avail = stack.available;
- int tail = head - avail + 1;
-
- if (tail >= 0) {
- int8_t* const index = const_cast<int8_t*>(stack.index);
- const int nb = numBuffers - head;
- memmove(&index[head + extra], &index[head], nb);
- base = head;
- // move head 'extra' ahead, this doesn't impact stack.index[head];
- stack.head = head + extra;
- }
- stack.available += extra;
-
- // fill the new free space with unused buffers
- BufferList::const_iterator curr(mBufferList.free_begin());
- for (int i=0 ; i<extra ; i++) {
- stack.index[base+i] = *curr;
- mBufferList.add(*curr);
- ++curr;
- }
-
- mNumBuffers = newNumBuffers;
- return NO_ERROR;
-}
-
-status_t SharedBufferServer::shrink(int newNumBuffers)
-{
- SharedBufferStack& stack( *mSharedStack );
-
- // Shrinking is only supported if there are no buffers currently dequeued.
- int32_t avail = stack.available;
- int32_t queued = stack.queued;
- if (avail + queued != mNumBuffers) {
- return INVALID_OPERATION;
- }
-
- // Wait for any queued buffers to be displayed.
- BuffersAvailableCondition condition(this, mNumBuffers);
- status_t err = waitForCondition(condition);
- if (err < 0) {
- return err;
- }
-
- // Reset head to index 0 and make it refer to buffer 0. The same renaming
- // (head -> 0) is done in the BufferManager.
- int32_t head = stack.head;
- int8_t* index = const_cast<int8_t*>(stack.index);
- for (int8_t i = 0; i < newNumBuffers; i++) {
- index[i] = i;
- }
- stack.head = 0;
- stack.headBuf = 0;
-
- // Free the buffers from the end of the list that are no longer needed.
- for (int i = newNumBuffers; i < mNumBuffers; i++) {
- mBufferList.remove(i);
- }
-
- // Tell the client to reallocate all the buffers.
- reallocateAll();
-
- mNumBuffers = newNumBuffers;
- stack.available = newNumBuffers;
-
- return NO_ERROR;
-}
-
-SharedBufferStack::Statistics SharedBufferServer::getStats() const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.stats;
-}
-
-// ---------------------------------------------------------------------------
-status_t SharedBufferServer::BufferList::add(int value)
-{
- if (uint32_t(value) >= mCapacity)
- return BAD_VALUE;
- uint32_t mask = 1<<(31-value);
- if (mList & mask)
- return ALREADY_EXISTS;
- mList |= mask;
- return NO_ERROR;
-}
-
-status_t SharedBufferServer::BufferList::remove(int value)
-{
- if (uint32_t(value) >= mCapacity)
- return BAD_VALUE;
- uint32_t mask = 1<<(31-value);
- if (!(mList & mask))
- return NAME_NOT_FOUND;
- mList &= ~mask;
- return NO_ERROR;
-}
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 0c5767b8c2e9..4d1d923a4262 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -21,13 +21,15 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <utils/Errors.h>
-#include <utils/threads.h>
#include <utils/CallStack.h>
+#include <utils/Errors.h>
#include <utils/Log.h>
+#include <utils/threads.h>
-#include <binder/IPCThreadState.h>
#include <binder/IMemory.h>
+#include <binder/IPCThreadState.h>
+
+#include <gui/SurfaceTextureClient.h>
#include <ui/DisplayInfo.h>
#include <ui/GraphicBuffer.h>
@@ -35,12 +37,11 @@
#include <ui/GraphicLog.h>
#include <ui/Rect.h>
-#include <surfaceflinger/Surface.h>
#include <surfaceflinger/ISurface.h>
#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/Surface.h>
#include <surfaceflinger/SurfaceComposerClient.h>
-#include <private/surfaceflinger/SharedBufferStack.h>
#include <private/surfaceflinger/LayerState.h>
namespace android {
@@ -273,58 +274,10 @@ sp<Surface> SurfaceControl::getSurface() const
// Surface
// ============================================================================
-class SurfaceClient : public Singleton<SurfaceClient>
-{
- // all these attributes are constants
- sp<ISurfaceComposer> mComposerService;
- sp<ISurfaceComposerClient> mClient;
- status_t mStatus;
- SharedClient* mControl;
- sp<IMemoryHeap> mControlMemory;
-
- SurfaceClient()
- : Singleton<SurfaceClient>(), mStatus(NO_INIT)
- {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- mComposerService = sf;
- mClient = sf->createClientConnection();
- if (mClient != NULL) {
- mControlMemory = mClient->getControlBlock();
- if (mControlMemory != NULL) {
- mControl = static_cast<SharedClient *>(
- mControlMemory->getBase());
- if (mControl) {
- mStatus = NO_ERROR;
- }
- }
- }
- }
- friend class Singleton<SurfaceClient>;
-public:
- status_t initCheck() const {
- return mStatus;
- }
- SharedClient* getSharedClient() const {
- return mControl;
- }
- ssize_t getTokenForSurface(const sp<ISurface>& sur) const {
- // TODO: we could cache a few tokens here to avoid an IPC
- return mClient->getTokenForSurface(sur);
- }
- void signalServer() const {
- mComposerService->signal();
- }
-};
-
-ANDROID_SINGLETON_STATIC_INSTANCE(SurfaceClient);
-
// ---------------------------------------------------------------------------
Surface::Surface(const sp<SurfaceControl>& surface)
- : mBufferMapper(GraphicBufferMapper::get()),
- mClient(SurfaceClient::getInstance()),
- mSharedBufferClient(NULL),
- mInitCheck(NO_INIT),
+ : mInitCheck(NO_INIT),
mSurface(surface->mSurface),
mIdentity(surface->mIdentity),
mFormat(surface->mFormat), mFlags(surface->mFlags),
@@ -334,10 +287,7 @@ Surface::Surface(const sp<SurfaceControl>& surface)
}
Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref)
- : mBufferMapper(GraphicBufferMapper::get()),
- mClient(SurfaceClient::getInstance()),
- mSharedBufferClient(NULL),
- mInitCheck(NO_INIT)
+ : mInitCheck(NO_INIT)
{
mSurface = interface_cast<ISurface>(ref);
mIdentity = parcel.readInt32();
@@ -382,7 +332,6 @@ status_t Surface::writeToParcel(
}
-
Mutex Surface::sCachedSurfacesLock;
DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces;
@@ -422,32 +371,29 @@ void Surface::init()
ANativeWindow::query = query;
ANativeWindow::perform = perform;
- DisplayInfo dinfo;
- SurfaceComposerClient::getDisplayInfo(0, &dinfo);
- const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
- const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
- // FIXME: set real values here
- const_cast<int&>(ANativeWindow::minSwapInterval) = 1;
- const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
- const_cast<uint32_t&>(ANativeWindow::flags) = 0;
-
- mNextBufferTransform = 0;
- mConnected = 0;
- mSwapRectangle.makeInvalid();
- mNextBufferCrop = Rect(0,0);
- // two buffers by default
- mBuffers.setCapacity(2);
- mBuffers.insertAt(0, 2);
-
- if (mSurface != 0 && mClient.initCheck() == NO_ERROR) {
- int32_t token = mClient.getTokenForSurface(mSurface);
- if (token >= 0) {
- mSharedBufferClient = new SharedBufferClient(
- mClient.getSharedClient(), token, 2, mIdentity);
- mInitCheck = mClient.getSharedClient()->validate(token);
- } else {
- LOGW("Not initializing the shared buffer client because token = %d",
- token);
+ if (mSurface != NULL) {
+ sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture());
+ LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface");
+ if (surfaceTexture != NULL) {
+ mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture);
+ mSurfaceTextureClient->setUsage(GraphicBuffer::USAGE_HW_RENDER);
+ }
+
+ DisplayInfo dinfo;
+ SurfaceComposerClient::getDisplayInfo(0, &dinfo);
+ const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
+ const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
+
+ const_cast<int&>(ANativeWindow::minSwapInterval) =
+ mSurfaceTextureClient->minSwapInterval;
+
+ const_cast<int&>(ANativeWindow::maxSwapInterval) =
+ mSurfaceTextureClient->maxSwapInterval;
+
+ const_cast<uint32_t&>(ANativeWindow::flags) = 0;
+
+ if (mSurfaceTextureClient != 0) {
+ mInitCheck = NO_ERROR;
}
}
}
@@ -456,9 +402,8 @@ Surface::~Surface()
{
// clear all references and trigger an IPC now, to make sure things
// happen without delay, since these resources are quite heavy.
- mBuffers.clear();
+ mSurfaceTextureClient.clear();
mSurface.clear();
- delete mSharedBufferClient;
IPCThreadState::self()->flushCommands();
}
@@ -473,32 +418,6 @@ status_t Surface::validate(bool inCancelBuffer) const
LOGE("invalid token (identity=%u)", mIdentity);
return mInitCheck;
}
-
- // verify the identity of this surface
- uint32_t identity = mSharedBufferClient->getIdentity();
- if (mIdentity != identity) {
- LOGE("[Surface] using an invalid surface, "
- "identity=%u should be %d",
- mIdentity, identity);
- CallStack stack;
- stack.update();
- stack.dump("Surface");
- return BAD_INDEX;
- }
-
- // check the surface didn't become invalid
- status_t err = mSharedBufferClient->getStatus();
- if (err != NO_ERROR) {
- if (!inCancelBuffer) {
- LOGE("surface (identity=%u) is invalid, err=%d (%s)",
- mIdentity, err, strerror(-err));
- CallStack stack;
- stack.update();
- stack.dump("Surface");
- }
- return err;
- }
-
return NO_ERROR;
}
@@ -509,7 +428,8 @@ sp<IBinder> Surface::asBinder() const {
// ----------------------------------------------------------------------------
int Surface::setSwapInterval(ANativeWindow* window, int interval) {
- return 0;
+ Surface* self = getSelf(window);
+ return self->setSwapInterval(interval);
}
int Surface::dequeueBuffer(ANativeWindow* window,
@@ -554,383 +474,52 @@ int Surface::perform(ANativeWindow* window,
// ----------------------------------------------------------------------------
-bool Surface::needNewBuffer(int bufIdx,
- uint32_t *pWidth, uint32_t *pHeight,
- uint32_t *pFormat, uint32_t *pUsage) const
-{
- Mutex::Autolock _l(mSurfaceLock);
-
- // Always call needNewBuffer(), since it clears the needed buffers flags
- bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx);
- bool validBuffer = mBufferInfo.validateBuffer(mBuffers[bufIdx]);
- bool newNeewBuffer = needNewBuffer || !validBuffer;
- if (newNeewBuffer) {
- mBufferInfo.get(pWidth, pHeight, pFormat, pUsage);
- }
- return newNeewBuffer;
+int Surface::setSwapInterval(int interval) {
+ return mSurfaceTextureClient->setSwapInterval(interval);
}
-int Surface::dequeueBuffer(ANativeWindowBuffer** buffer)
-{
- status_t err = validate();
- if (err != NO_ERROR)
- return err;
-
- GraphicLog& logger(GraphicLog::getInstance());
- logger.log(GraphicLog::SF_APP_DEQUEUE_BEFORE, mIdentity, -1);
-
- ssize_t bufIdx = mSharedBufferClient->dequeue();
-
- logger.log(GraphicLog::SF_APP_DEQUEUE_AFTER, mIdentity, bufIdx);
-
- if (bufIdx < 0) {
- LOGE("error dequeuing a buffer (%s)", strerror(bufIdx));
- return bufIdx;
- }
-
- // grow the buffer array if needed
- const size_t size = mBuffers.size();
- const size_t needed = bufIdx+1;
- if (size < needed) {
- mBuffers.insertAt(size, needed-size);
- }
-
- uint32_t w, h, format, usage;
- if (needNewBuffer(bufIdx, &w, &h, &format, &usage)) {
- err = getBufferLocked(bufIdx, w, h, format, usage);
- LOGE_IF(err, "getBufferLocked(%ld, %u, %u, %u, %08x) failed (%s)",
- bufIdx, w, h, format, usage, strerror(-err));
- if (err == NO_ERROR) {
- // reset the width/height with the what we get from the buffer
- const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
- mWidth = uint32_t(backBuffer->width);
- mHeight = uint32_t(backBuffer->height);
- }
- }
-
- // if we still don't have a buffer here, we probably ran out of memory
- const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
- if (!err && backBuffer==0) {
- err = NO_MEMORY;
- }
-
+int Surface::dequeueBuffer(ANativeWindowBuffer** buffer) {
+ status_t err = mSurfaceTextureClient->dequeueBuffer(buffer);
if (err == NO_ERROR) {
- mDirtyRegion.set(backBuffer->width, backBuffer->height);
- *buffer = backBuffer.get();
- } else {
- mSharedBufferClient->undoDequeue(bufIdx);
+ mDirtyRegion.set(buffer[0]->width, buffer[0]->height);
}
-
return err;
}
-int Surface::cancelBuffer(ANativeWindowBuffer* buffer)
-{
- status_t err = validate(true);
- switch (err) {
- case NO_ERROR:
- // no error, common case
- break;
- case BAD_INDEX:
- // legitimate errors here
- return err;
- default:
- // other errors happen because the surface is now invalid,
- // for instance because it has been destroyed. In this case,
- // we just fail silently (canceling a buffer is not technically
- // an error at this point)
- return NO_ERROR;
- }
-
- int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
-
- err = mSharedBufferClient->cancel(bufIdx);
-
- LOGE_IF(err, "error canceling buffer %d (%s)", bufIdx, strerror(-err));
- return err;
+int Surface::cancelBuffer(ANativeWindowBuffer* buffer) {
+ return mSurfaceTextureClient->cancelBuffer(buffer);
}
-
-int Surface::lockBuffer(ANativeWindowBuffer* buffer)
-{
- status_t err = validate();
- if (err != NO_ERROR)
- return err;
-
- int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
-
- GraphicLog& logger(GraphicLog::getInstance());
- logger.log(GraphicLog::SF_APP_LOCK_BEFORE, mIdentity, bufIdx);
-
- err = mSharedBufferClient->lock(bufIdx);
-
- logger.log(GraphicLog::SF_APP_LOCK_AFTER, mIdentity, bufIdx);
-
- LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err));
- return err;
+int Surface::lockBuffer(ANativeWindowBuffer* buffer) {
+ return mSurfaceTextureClient->lockBuffer(buffer);
}
-int Surface::queueBuffer(ANativeWindowBuffer* buffer)
-{
- status_t err = validate();
- if (err != NO_ERROR)
- return err;
-
- if (mSwapRectangle.isValid()) {
- mDirtyRegion.set(mSwapRectangle);
- }
-
- int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
-
- GraphicLog::getInstance().log(GraphicLog::SF_APP_QUEUE, mIdentity, bufIdx);
-
- mSharedBufferClient->setTransform(bufIdx, mNextBufferTransform);
- mSharedBufferClient->setCrop(bufIdx, mNextBufferCrop);
- mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion);
- err = mSharedBufferClient->queue(bufIdx);
- LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err));
-
- if (err == NO_ERROR) {
- // TODO: can we avoid this IPC if we know there is one pending?
- mClient.signalServer();
- }
- return err;
+int Surface::queueBuffer(ANativeWindowBuffer* buffer) {
+ return mSurfaceTextureClient->queueBuffer(buffer);
}
-int Surface::query(int what, int* value) const
-{
+int Surface::query(int what, int* value) const {
switch (what) {
- case NATIVE_WINDOW_WIDTH:
- *value = int(mWidth);
- return NO_ERROR;
- case NATIVE_WINDOW_HEIGHT:
- *value = int(mHeight);
- return NO_ERROR;
- case NATIVE_WINDOW_FORMAT:
- *value = int(mFormat);
+ case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
+ // TODO: this is not needed anymore
+ *value = 1;
return NO_ERROR;
- case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
- *value = MIN_UNDEQUEUED_BUFFERS;
- return NO_ERROR;
- case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- *value = sf->authenticateSurface(mSurface) ? 1 : 0;
- return NO_ERROR;
- }
case NATIVE_WINDOW_CONCRETE_TYPE:
+ // TODO: this is not needed anymore
*value = NATIVE_WINDOW_SURFACE;
return NO_ERROR;
}
- return BAD_VALUE;
-}
-
-int Surface::perform(int operation, va_list args)
-{
- status_t err = validate();
- if (err != NO_ERROR)
- return err;
-
- int res = NO_ERROR;
- switch (operation) {
- case NATIVE_WINDOW_SET_USAGE:
- dispatch_setUsage( args );
- break;
- case NATIVE_WINDOW_CONNECT:
- res = dispatch_connect( args );
- break;
- case NATIVE_WINDOW_DISCONNECT:
- res = dispatch_disconnect( args );
- break;
- case NATIVE_WINDOW_SET_CROP:
- res = dispatch_crop( args );
- break;
- case NATIVE_WINDOW_SET_BUFFER_COUNT:
- res = dispatch_set_buffer_count( args );
- break;
- case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
- res = dispatch_set_buffers_geometry( args );
- break;
- case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
- res = dispatch_set_buffers_transform( args );
- break;
- case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
- res = dispatch_set_buffers_timestamp( args );
- break;
- default:
- res = NAME_NOT_FOUND;
- break;
- }
- return res;
-}
-
-void Surface::dispatch_setUsage(va_list args) {
- int usage = va_arg(args, int);
- setUsage( usage );
-}
-int Surface::dispatch_connect(va_list args) {
- int api = va_arg(args, int);
- return connect( api );
-}
-int Surface::dispatch_disconnect(va_list args) {
- int api = va_arg(args, int);
- return disconnect( api );
-}
-int Surface::dispatch_crop(va_list args) {
- android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
- return crop( reinterpret_cast<Rect const*>(rect) );
-}
-int Surface::dispatch_set_buffer_count(va_list args) {
- size_t bufferCount = va_arg(args, size_t);
- return setBufferCount(bufferCount);
-}
-int Surface::dispatch_set_buffers_geometry(va_list args) {
- int w = va_arg(args, int);
- int h = va_arg(args, int);
- int f = va_arg(args, int);
- return setBuffersGeometry(w, h, f);
-}
-
-int Surface::dispatch_set_buffers_transform(va_list args) {
- int transform = va_arg(args, int);
- return setBuffersTransform(transform);
-}
-
-int Surface::dispatch_set_buffers_timestamp(va_list args) {
- int64_t timestamp = va_arg(args, int64_t);
- return setBuffersTimestamp(timestamp);
-}
-
-void Surface::setUsage(uint32_t reqUsage)
-{
- Mutex::Autolock _l(mSurfaceLock);
- mBufferInfo.set(reqUsage);
-}
-
-int Surface::connect(int api)
-{
- Mutex::Autolock _l(mSurfaceLock);
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- if (mConnected) {
- err = -EINVAL;
- } else {
- mConnected = api;
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-int Surface::disconnect(int api)
-{
- Mutex::Autolock _l(mSurfaceLock);
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- if (mConnected == api) {
- mConnected = 0;
- } else {
- err = -EINVAL;
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-int Surface::crop(Rect const* rect)
-{
- Mutex::Autolock _l(mSurfaceLock);
- // TODO: validate rect size
-
- if (rect == NULL || rect->isEmpty()) {
- mNextBufferCrop = Rect(0,0);
- } else {
- mNextBufferCrop = *rect;
- }
-
- return NO_ERROR;
+ return mSurfaceTextureClient->query(what, value);
}
-int Surface::setBufferCount(int bufferCount)
-{
- sp<ISurface> s(mSurface);
- if (s == 0) return NO_INIT;
-
- class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback {
- sp<ISurface> surface;
- virtual status_t operator()(int bufferCount) const {
- return surface->setBufferCount(bufferCount);
- }
- public:
- SetBufferCountIPC(const sp<ISurface>& surface) : surface(surface) { }
- } ipc(s);
-
- status_t err = mSharedBufferClient->setBufferCount(bufferCount, ipc);
- LOGE_IF(err, "ISurface::setBufferCount(%d) returned %s",
- bufferCount, strerror(-err));
-
- if (err == NO_ERROR) {
- // Clear out any references to the old buffers.
- mBuffers.clear();
- }
-
- return err;
-}
-
-int Surface::setBuffersGeometry(int w, int h, int format)
-{
- if (w<0 || h<0 || format<0)
- return BAD_VALUE;
-
- if ((w && !h) || (!w && h))
- return BAD_VALUE;
-
- Mutex::Autolock _l(mSurfaceLock);
- if (mConnected == NATIVE_WINDOW_API_EGL) {
- return INVALID_OPERATION;
- }
-
- mBufferInfo.set(w, h, format);
- if (format != 0) {
- // we update the format of the surface as reported by query().
- // this is to allow applications to change the format of a surface's
- // buffer, and have it reflected in EGL; which is needed for
- // EGLConfig validation.
- mFormat = format;
- }
-
- mNextBufferCrop = Rect(0,0);
-
- return NO_ERROR;
-}
-
-int Surface::setBuffersTransform(int transform)
-{
- Mutex::Autolock _l(mSurfaceLock);
- mNextBufferTransform = transform;
- return NO_ERROR;
-}
-
-int Surface::setBuffersTimestamp(int64_t timestamp)
-{
- // Surface doesn't really have anything meaningful to do with timestamps
- // so they'll just be dropped here.
- return NO_ERROR;
+int Surface::perform(int operation, va_list args) {
+ return mSurfaceTextureClient->perform(operation, args);
}
// ----------------------------------------------------------------------------
-int Surface::getConnectedApi() const
-{
- Mutex::Autolock _l(mSurfaceLock);
- return mConnected;
+int Surface::getConnectedApi() const {
+ return mSurfaceTextureClient->getConnectedApi();
}
// ----------------------------------------------------------------------------
@@ -967,16 +556,17 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
}
// we're intending to do software rendering from this point
- setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+ mSurfaceTextureClient->setUsage(
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
ANativeWindowBuffer* out;
- status_t err = dequeueBuffer(&out);
+ status_t err = mSurfaceTextureClient->dequeueBuffer(&out);
LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
if (err == NO_ERROR) {
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
- err = lockBuffer(backBuffer.get());
- LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)",
- getBufferIndex(backBuffer), strerror(-err));
+ err = mSurfaceTextureClient->lockBuffer(backBuffer.get());
+ LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)",
+ backBuffer->handle, strerror(-err));
if (err == NO_ERROR) {
const Rect bounds(backBuffer->width, backBuffer->height);
const Region boundsRegion(bounds);
@@ -1043,110 +633,14 @@ status_t Surface::unlockAndPost()
status_t err = mLockedBuffer->unlock();
LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
- err = queueBuffer(mLockedBuffer.get());
- LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)",
- getBufferIndex(mLockedBuffer), strerror(-err));
+ err = mSurfaceTextureClient->queueBuffer(mLockedBuffer.get());
+ LOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
+ mLockedBuffer->handle, strerror(-err));
mPostedBuffer = mLockedBuffer;
mLockedBuffer = 0;
return err;
}
-void Surface::setSwapRectangle(const Rect& r) {
- Mutex::Autolock _l(mSurfaceLock);
- mSwapRectangle = r;
-}
-
-int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const
-{
- int idx = buffer->getIndex();
- if (idx < 0) {
- // The buffer doesn't have an index set. See if the handle the same as
- // one of the buffers for which we do know the index. This can happen
- // e.g. if GraphicBuffer is used to wrap an ANativeWindowBuffer that
- // was dequeued from an ANativeWindow.
- for (size_t i = 0; i < mBuffers.size(); i++) {
- if (mBuffers[i] != 0 && buffer->handle == mBuffers[i]->handle) {
- idx = mBuffers[i]->getIndex();
- break;
- }
- }
- }
- return idx;
-}
-
-status_t Surface::getBufferLocked(int index,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
-{
- sp<ISurface> s(mSurface);
- if (s == 0) return NO_INIT;
-
- status_t err = NO_MEMORY;
-
- // free the current buffer
- sp<GraphicBuffer>& currentBuffer(mBuffers.editItemAt(index));
- if (currentBuffer != 0) {
- currentBuffer.clear();
- }
-
- sp<GraphicBuffer> buffer = s->requestBuffer(index, w, h, format, usage);
- LOGE_IF(buffer==0,
- "ISurface::getBuffer(%d, %08x) returned NULL",
- index, usage);
- if (buffer != 0) { // this should always happen by construction
- LOGE_IF(buffer->handle == NULL,
- "Surface (identity=%d) requestBuffer(%d, %u, %u, %u, %08x) "
- "returned a buffer with a null handle",
- mIdentity, index, w, h, format, usage);
- err = mSharedBufferClient->getStatus();
- LOGE_IF(err, "Surface (identity=%d) state = %d", mIdentity, err);
- if (!err && buffer->handle != NULL) {
- currentBuffer = buffer;
- currentBuffer->setIndex(index);
- } else {
- err = err<0 ? err : status_t(NO_MEMORY);
- }
- }
- return err;
-}
-
-// ----------------------------------------------------------------------------
-Surface::BufferInfo::BufferInfo()
- : mWidth(0), mHeight(0), mFormat(0),
- mUsage(GRALLOC_USAGE_HW_RENDER), mDirty(0)
-{
-}
-
-void Surface::BufferInfo::set(uint32_t w, uint32_t h, uint32_t format) {
- if ((mWidth != w) || (mHeight != h) || (mFormat != format)) {
- mWidth = w;
- mHeight = h;
- mFormat = format;
- mDirty |= GEOMETRY;
- }
-}
-
-void Surface::BufferInfo::set(uint32_t usage) {
- mUsage = usage;
-}
-
-void Surface::BufferInfo::get(uint32_t *pWidth, uint32_t *pHeight,
- uint32_t *pFormat, uint32_t *pUsage) const {
- *pWidth = mWidth;
- *pHeight = mHeight;
- *pFormat = mFormat;
- *pUsage = mUsage;
-}
-
-bool Surface::BufferInfo::validateBuffer(const sp<GraphicBuffer>& buffer) const {
- // make sure we AT LEAST have the usage flags we want
- if (mDirty || buffer==0 ||
- ((buffer->usage & mUsage) != mUsage)) {
- mDirty = 0;
- return false;
- }
- return true;
-}
-
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index a1ff2c1e2f5d..1678711aaf42 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -20,19 +20,20 @@
#include <sys/types.h>
#include <utils/Errors.h>
-#include <utils/threads.h>
-#include <utils/SortedVector.h>
#include <utils/Log.h>
#include <utils/Singleton.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
+#include <utils/threads.h>
-#include <binder/IServiceManager.h>
#include <binder/IMemory.h>
+#include <binder/IServiceManager.h>
#include <ui/DisplayInfo.h>
+#include <surfaceflinger/ISurface.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/ISurfaceComposerClient.h>
-#include <surfaceflinger/ISurface.h>
#include <surfaceflinger/SurfaceComposerClient.h>
#include <private/surfaceflinger/LayerState.h>
@@ -217,7 +218,7 @@ void SurfaceComposerClient::dispose()
status_t SurfaceComposerClient::getDisplayInfo(
DisplayID dpy, DisplayInfo* info)
{
- if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
return BAD_VALUE;
volatile surface_flinger_cblk_t const * cblk = get_cblk();
@@ -235,7 +236,7 @@ status_t SurfaceComposerClient::getDisplayInfo(
ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
{
- if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
return BAD_VALUE;
volatile surface_flinger_cblk_t const * cblk = get_cblk();
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
@@ -244,7 +245,7 @@ ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
{
- if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
return BAD_VALUE;
volatile surface_flinger_cblk_t const * cblk = get_cblk();
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
@@ -253,7 +254,7 @@ ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy)
{
- if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
return BAD_VALUE;
volatile surface_flinger_cblk_t const * cblk = get_cblk();
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index ee97dcfa9c63..3cecdb401ab1 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -96,6 +96,7 @@ SurfaceTexture::SurfaceTexture(GLuint tex) :
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
mNextCrop.makeInvalid();
+ memcpy(mCurrentTransformMatrix, mtxIdentity, sizeof(mCurrentTransformMatrix));
}
SurfaceTexture::~SurfaceTexture() {
@@ -270,7 +271,7 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
if (state == BufferSlot::DEQUEUED) {
dequeuedCount++;
}
- if (state == BufferSlot::FREE || i == mCurrentTexture) {
+ if (state == BufferSlot::FREE /*|| i == mCurrentTexture*/) {
foundSync = i;
if (i != mCurrentTexture) {
found = i;
@@ -547,6 +548,7 @@ status_t SurfaceTexture::updateTexImage() {
mCurrentCrop = mSlots[buf].mCrop;
mCurrentTransform = mSlots[buf].mTransform;
mCurrentTimestamp = mSlots[buf].mTimestamp;
+ computeCurrentTransformMatrix();
mDequeueCondition.signal();
} else {
// We always bind the texture even if we don't update its contents.
@@ -596,8 +598,12 @@ GLenum SurfaceTexture::getCurrentTextureTarget() const {
}
void SurfaceTexture::getTransformMatrix(float mtx[16]) {
- LOGV("SurfaceTexture::getTransformMatrix");
Mutex::Autolock lock(mMutex);
+ memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
+}
+
+void SurfaceTexture::computeCurrentTransformMatrix() {
+ LOGV("SurfaceTexture::computeCurrentTransformMatrix");
float xform[16];
for (int i = 0; i < 16; i++) {
@@ -684,7 +690,7 @@ void SurfaceTexture::getTransformMatrix(float mtx[16]) {
// coordinate of 0, so SurfaceTexture must behave the same way. We don't
// want to expose this to applications, however, so we must add an
// additional vertical flip to the transform after all the other transforms.
- mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
+ mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
}
nsecs_t SurfaceTexture::getTimestamp() {
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index c20fcf27ccae..22b085227068 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -181,6 +181,12 @@ int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
int SurfaceTextureClient::query(int what, int* value) const {
LOGV("SurfaceTextureClient::query");
switch (what) {
+ case NATIVE_WINDOW_FORMAT:
+ if (mReqFormat) {
+ *value = mReqFormat;
+ return NO_ERROR;
+ }
+ break;
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
// TODO: this is not needed anymore
*value = 0;
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 2f704c89b822..a4c5b36288b7 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -32,6 +32,7 @@ protected:
virtual void SetUp() {
mST = new SurfaceTexture(123);
mSTC = new SurfaceTextureClient(mST);
+ mANW = mSTC;
// We need a valid GL context so we can test updateTexImage()
// This initializes EGL and create a dummy GL context with a
@@ -69,6 +70,8 @@ protected:
virtual void TearDown() {
mST.clear();
mSTC.clear();
+ mANW.clear();
+
eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mEglDisplay, mEglContext);
eglDestroySurface(mEglDisplay, mEglSurface);
@@ -86,6 +89,8 @@ protected:
sp<SurfaceTexture> mST;
sp<SurfaceTextureClient> mSTC;
+ sp<ANativeWindow> mANW;
+
EGLDisplay mEglDisplay;
EGLSurface mEglSurface;
EGLContext mEglContext;
@@ -97,31 +102,26 @@ TEST_F(SurfaceTextureClientTest, GetISurfaceTextureIsNotNull) {
}
TEST_F(SurfaceTextureClientTest, QueuesToWindowCompositorIsFalse) {
- sp<ANativeWindow> anw(mSTC);
int result = -123;
- int err = anw->query(anw.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
+ int err = mANW->query(mANW.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
&result);
EXPECT_EQ(NO_ERROR, err);
EXPECT_EQ(0, result);
}
TEST_F(SurfaceTextureClientTest, ConcreteTypeIsSurfaceTextureClient) {
- sp<ANativeWindow> anw(mSTC);
int result = -123;
- int err = anw->query(anw.get(), NATIVE_WINDOW_CONCRETE_TYPE, &result);
+ int err = mANW->query(mANW.get(), NATIVE_WINDOW_CONCRETE_TYPE, &result);
EXPECT_EQ(NO_ERROR, err);
EXPECT_EQ(NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT, result);
}
TEST_F(SurfaceTextureClientTest, ANativeWindowLockFails) {
- sp<ANativeWindow> anw(mSTC);
ANativeWindow_Buffer buf;
- ASSERT_EQ(BAD_VALUE, ANativeWindow_lock(anw.get(), &buf, NULL));
+ ASSERT_EQ(BAD_VALUE, ANativeWindow_lock(mANW.get(), &buf, NULL));
}
TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) {
- sp<ANativeWindow> anw(mSTC);
-
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
ASSERT_NE(EGL_NO_DISPLAY, dpy);
@@ -147,7 +147,7 @@ TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) {
&numConfigs));
ASSERT_EQ(EGL_SUCCESS, eglGetError());
- EGLSurface eglSurface = eglCreateWindowSurface(dpy, myConfig, anw.get(),
+ EGLSurface eglSurface = eglCreateWindowSurface(dpy, myConfig, mANW.get(),
NULL);
EXPECT_NE(EGL_NO_SURFACE, eglSurface);
EXPECT_EQ(EGL_SUCCESS, eglGetError());
@@ -156,269 +156,246 @@ TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceSucceeds) {
}
TEST_F(SurfaceTextureClientTest, BufferGeometryInvalidSizesFail) {
- sp<ANativeWindow> anw(mSTC);
-
- EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), -1, 0, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 0, -1, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, -1));
- EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), -1, -1, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 0, 8, 0));
- EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 8, 0, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), -1, 0, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, -1, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, -1));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), -1, -1, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 0, 8, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(mANW.get(), 8, 0, 0));
}
TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) {
- sp<ANativeWindow> anw(mSTC);
ANativeWindowBuffer* buf;
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
EXPECT_EQ(1, buf->width);
EXPECT_EQ(1, buf->height);
EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
}
TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) {
- sp<ANativeWindow> anw(mSTC);
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, PIXEL_FORMAT_RGB_565));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, PIXEL_FORMAT_RGB_565));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
EXPECT_EQ(16, buf->width);
EXPECT_EQ(8, buf->height);
EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
}
TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) {
- sp<ANativeWindow> anw(mSTC);
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, PIXEL_FORMAT_RGB_565));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
EXPECT_EQ(1, buf->width);
EXPECT_EQ(1, buf->height);
EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
}
TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) {
- sp<ANativeWindow> anw(mSTC);
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
EXPECT_EQ(16, buf->width);
EXPECT_EQ(8, buf->height);
EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
}
TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) {
- sp<ANativeWindow> anw(mSTC);
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
EXPECT_EQ(16, buf->width);
EXPECT_EQ(8, buf->height);
EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
- EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, 0));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, 0));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
EXPECT_EQ(1, buf->width);
EXPECT_EQ(1, buf->height);
EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
}
TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) {
- sp<ANativeWindow> anw(mSTC);
ANativeWindowBuffer* buf;
- EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, PIXEL_FORMAT_RGB_565));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
EXPECT_EQ(1, buf->width);
EXPECT_EQ(1, buf->height);
EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
- EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
EXPECT_EQ(16, buf->width);
EXPECT_EQ(8, buf->height);
EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
}
TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSize) {
- sp<ANativeWindow> anw(mSTC);
sp<SurfaceTexture> st(mST);
ANativeWindowBuffer* buf;
EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
EXPECT_EQ(16, buf->width);
EXPECT_EQ(8, buf->height);
EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
}
TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeAfterDequeue) {
- sp<ANativeWindow> anw(mSTC);
- sp<SurfaceTexture> st(mST);
ANativeWindowBuffer* buf[2];
- ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
EXPECT_NE(buf[0], buf[1]);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
- EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0]));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1]));
+ EXPECT_EQ(OK, mST->setDefaultBufferSize(16, 8));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
EXPECT_NE(buf[0], buf[1]);
EXPECT_EQ(16, buf[0]->width);
EXPECT_EQ(16, buf[1]->width);
EXPECT_EQ(8, buf[0]->height);
EXPECT_EQ(8, buf[1]->height);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0]));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1]));
}
TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) {
- sp<ANativeWindow> anw(mSTC);
- sp<SurfaceTexture> st(mST);
ANativeWindowBuffer* buf[2];
- ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
- EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
+ EXPECT_EQ(OK, mST->setDefaultBufferSize(16, 8));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
EXPECT_NE(buf[0], buf[1]);
EXPECT_EQ(16, buf[0]->width);
EXPECT_EQ(16, buf[1]->width);
EXPECT_EQ(8, buf[0]->height);
EXPECT_EQ(8, buf[1]->height);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
- EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 12, 24, 0));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0]));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1]));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 12, 24, 0));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
EXPECT_NE(buf[0], buf[1]);
EXPECT_EQ(12, buf[0]->width);
EXPECT_EQ(12, buf[1]->width);
EXPECT_EQ(24, buf[0]->height);
EXPECT_EQ(24, buf[1]->height);
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0]));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1]));
}
TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
- sp<ANativeWindow> anw(mSTC);
- sp<SurfaceTexture> st(mST);
android_native_buffer_t* buf[3];
- ASSERT_EQ(OK, st->setSynchronousMode(false));
- ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+ ASSERT_EQ(OK, mST->setSynchronousMode(false));
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(OK, st->updateTexImage());
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(OK, mST->updateTexImage());
- ASSERT_EQ(OK, st->setSynchronousMode(true));
- ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+ ASSERT_EQ(OK, mST->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(OK, st->updateTexImage());
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(OK, mST->updateTexImage());
}
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) {
- sp<ANativeWindow> anw(mSTC);
- sp<SurfaceTexture> st(mST);
android_native_buffer_t* buf[3];
- ASSERT_EQ(OK, st->setSynchronousMode(true));
- ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+ ASSERT_EQ(OK, mST->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
EXPECT_NE(buf[0], buf[1]);
EXPECT_NE(buf[1], buf[2]);
EXPECT_NE(buf[2], buf[0]);
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]);
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]);
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2]));
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]);
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]);
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]);
}
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) {
- sp<ANativeWindow> anw(mSTC);
- sp<SurfaceTexture> st(mST);
android_native_buffer_t* buf[3];
- ASSERT_EQ(OK, st->setSynchronousMode(true));
- ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+ ASSERT_EQ(OK, mST->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
EXPECT_NE(buf[0], buf[1]);
EXPECT_NE(buf[1], buf[2]);
EXPECT_NE(buf[2], buf[0]);
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]);
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]);
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]);
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]);
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2]));
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]);
}
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) {
- sp<ANativeWindow> anw(mSTC);
- sp<SurfaceTexture> st(mST);
android_native_buffer_t* buf[3];
- ASSERT_EQ(OK, st->setSynchronousMode(true));
- ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+ ASSERT_EQ(OK, mST->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]);
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]);
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
EXPECT_NE(buf[0], buf[1]);
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]);
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
EXPECT_NE(buf[1], buf[2]);
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]);
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2]));
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]);
}
// XXX: We currently have no hardware that properly handles dequeuing the
// buffer that is currently bound to the texture.
TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) {
- sp<ANativeWindow> anw(mSTC);
- sp<SurfaceTexture> st(mST);
android_native_buffer_t* buf[3];
android_native_buffer_t* firstBuf;
- ASSERT_EQ(OK, st->setSynchronousMode(true));
- ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &firstBuf));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), firstBuf));
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(st->getCurrentBuffer().get(), firstBuf);
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+ ASSERT_EQ(OK, mST->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &firstBuf));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf));
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(mST->getCurrentBuffer().get(), firstBuf);
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2]));
EXPECT_NE(buf[0], buf[1]);
EXPECT_NE(buf[1], buf[2]);
EXPECT_NE(buf[2], buf[0]);
@@ -426,41 +403,36 @@ TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent)
}
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) {
- sp<ANativeWindow> anw(mSTC);
- sp<SurfaceTexture> st(mST);
android_native_buffer_t* buf[3];
- ASSERT_EQ(OK, st->setSynchronousMode(true));
- ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+ ASSERT_EQ(OK, mST->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
- // We should be able to dequeue all the buffers before we've queued any.
- EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
- EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+ // We should be able to dequeue all the buffers before we've queued mANWy.
+ EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+ EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[2]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
- EXPECT_EQ(OK, st->updateTexImage());
- EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]);
+ EXPECT_EQ(OK, mST->updateTexImage());
+ EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]);
- EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
+ EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
// Once we've queued a buffer, however we should not be able to dequeue more
// than (buffer-count - MIN_UNDEQUEUED_BUFFERS), which is 2 in this case.
- EXPECT_EQ(-EBUSY, anw->dequeueBuffer(anw.get(), &buf[1]));
+ EXPECT_EQ(-EBUSY, mANW->dequeueBuffer(mANW.get(), &buf[1]));
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
- ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[2]));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0]));
+ ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2]));
}
// XXX: This is not expected to pass until the synchronization hacks are removed
// from the SurfaceTexture class.
TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) {
- sp<ANativeWindow> anw(mSTC);
- sp<SurfaceTexture> st(mST);
-
class MyThread : public Thread {
- sp<SurfaceTexture> st;
+ sp<SurfaceTexture> mST;
EGLContext ctx;
EGLSurface sur;
EGLDisplay dpy;
@@ -470,14 +442,14 @@ TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) {
eglMakeCurrent(dpy, sur, sur, ctx);
usleep(20000);
Mutex::Autolock _l(mLock);
- st->updateTexImage();
+ mST->updateTexImage();
mBufferRetired = true;
eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
return false;
}
public:
- MyThread(const sp<SurfaceTexture>& st)
- : st(st), mBufferRetired(false) {
+ MyThread(const sp<SurfaceTexture>& mST)
+ : mST(mST), mBufferRetired(false) {
ctx = eglGetCurrentContext();
sur = eglGetCurrentSurface(EGL_DRAW);
dpy = eglGetCurrentDisplay();
@@ -493,25 +465,152 @@ TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) {
};
android_native_buffer_t* buf[3];
- ASSERT_EQ(OK, st->setSynchronousMode(true));
- ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3));
+ ASSERT_EQ(OK, mST->setSynchronousMode(true));
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
// dequeue/queue/update so we have a current buffer
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
- st->updateTexImage();
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+ mST->updateTexImage();
- MyThread* thread = new MyThread(st);
+ MyThread* thread = new MyThread(mST);
sp<Thread> threadBase(thread);
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
thread->run();
- ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2]));
- ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2]));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
+ //ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
+ //ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2]));
thread->bufferDequeued();
thread->requestExitAndWait();
}
+TEST_F(SurfaceTextureClientTest, GetTransformMatrixReturnsVerticalFlip) {
+ android_native_buffer_t* buf[3];
+ float mtx[16] = {};
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+ ASSERT_EQ(OK, mST->updateTexImage());
+ mST->getTransformMatrix(mtx);
+
+ EXPECT_EQ(1.f, mtx[0]);
+ EXPECT_EQ(0.f, mtx[1]);
+ EXPECT_EQ(0.f, mtx[2]);
+ EXPECT_EQ(0.f, mtx[3]);
+
+ EXPECT_EQ(0.f, mtx[4]);
+ EXPECT_EQ(-1.f, mtx[5]);
+ EXPECT_EQ(0.f, mtx[6]);
+ EXPECT_EQ(0.f, mtx[7]);
+
+ EXPECT_EQ(0.f, mtx[8]);
+ EXPECT_EQ(0.f, mtx[9]);
+ EXPECT_EQ(1.f, mtx[10]);
+ EXPECT_EQ(0.f, mtx[11]);
+
+ EXPECT_EQ(0.f, mtx[12]);
+ EXPECT_EQ(1.f, mtx[13]);
+ EXPECT_EQ(0.f, mtx[14]);
+ EXPECT_EQ(1.f, mtx[15]);
}
+
+TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffers) {
+ android_native_buffer_t* buf[3];
+ float mtx[16] = {};
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+ ASSERT_EQ(OK, mST->updateTexImage());
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers
+ mST->getTransformMatrix(mtx);
+
+ EXPECT_EQ(1.f, mtx[0]);
+ EXPECT_EQ(0.f, mtx[1]);
+ EXPECT_EQ(0.f, mtx[2]);
+ EXPECT_EQ(0.f, mtx[3]);
+
+ EXPECT_EQ(0.f, mtx[4]);
+ EXPECT_EQ(-1.f, mtx[5]);
+ EXPECT_EQ(0.f, mtx[6]);
+ EXPECT_EQ(0.f, mtx[7]);
+
+ EXPECT_EQ(0.f, mtx[8]);
+ EXPECT_EQ(0.f, mtx[9]);
+ EXPECT_EQ(1.f, mtx[10]);
+ EXPECT_EQ(0.f, mtx[11]);
+
+ EXPECT_EQ(0.f, mtx[12]);
+ EXPECT_EQ(1.f, mtx[13]);
+ EXPECT_EQ(0.f, mtx[14]);
+ EXPECT_EQ(1.f, mtx[15]);
+}
+
+TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffersWithCrop) {
+ android_native_buffer_t* buf[3];
+ float mtx[16] = {};
+ android_native_rect_t crop;
+ crop.left = 0;
+ crop.top = 0;
+ crop.right = 5;
+ crop.bottom = 5;
+
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
+ ASSERT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 8, 8, 0));
+ ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+ ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &crop));
+ ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+ ASSERT_EQ(OK, mST->updateTexImage());
+ ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers
+ mST->getTransformMatrix(mtx);
+
+ // This accounts for the 1 texel shrink for each edge that's included in the
+ // transform matrix to avoid texturing outside the crop region.
+ EXPECT_EQ(.5f, mtx[0]);
+ EXPECT_EQ(0.f, mtx[1]);
+ EXPECT_EQ(0.f, mtx[2]);
+ EXPECT_EQ(0.f, mtx[3]);
+
+ EXPECT_EQ(0.f, mtx[4]);
+ EXPECT_EQ(-.5f, mtx[5]);
+ EXPECT_EQ(0.f, mtx[6]);
+ EXPECT_EQ(0.f, mtx[7]);
+
+ EXPECT_EQ(0.f, mtx[8]);
+ EXPECT_EQ(0.f, mtx[9]);
+ EXPECT_EQ(1.f, mtx[10]);
+ EXPECT_EQ(0.f, mtx[11]);
+
+ EXPECT_EQ(0.f, mtx[12]);
+ EXPECT_EQ(.5f, mtx[13]);
+ EXPECT_EQ(0.f, mtx[14]);
+ EXPECT_EQ(1.f, mtx[15]);
+}
+
+// This test verifies that the buffer format can be queried immediately after
+// it is set.
+TEST_F(SurfaceTextureClientTest, DISABLED_QueryFormatAfterSettingWorks) {
+ sp<ANativeWindow> anw(mSTC);
+ int fmts[] = {
+ // RGBA_8888 should not come first, as it's the default
+ HAL_PIXEL_FORMAT_RGBX_8888,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ HAL_PIXEL_FORMAT_RGB_888,
+ HAL_PIXEL_FORMAT_RGB_565,
+ HAL_PIXEL_FORMAT_BGRA_8888,
+ HAL_PIXEL_FORMAT_RGBA_5551,
+ HAL_PIXEL_FORMAT_RGBA_4444,
+ HAL_PIXEL_FORMAT_YV12,
+ };
+
+ const int numFmts = (sizeof(fmts) / sizeof(fmts[0]));
+ for (int i = 0; i < numFmts; i++) {
+ int fmt = -1;
+ ASSERT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, fmts[i]));
+ ASSERT_EQ(OK, anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt));
+ EXPECT_EQ(fmts[i], fmt);
+ }
+}
+
+} // namespace android
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 8747ba5c7c53..50af3bbbacd0 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -14,11 +14,14 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+
#include <gtest/gtest.h>
#include <gui/SurfaceTexture.h>
#include <gui/SurfaceTextureClient.h>
#include <ui/GraphicBuffer.h>
#include <utils/String8.h>
+#include <utils/threads.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/Surface.h>
@@ -43,8 +46,6 @@ protected:
}
virtual void SetUp() {
- EGLBoolean returnValue;
-
mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
@@ -56,9 +57,8 @@ protected:
RecordProperty("EglVersionMajor", majorVersion);
RecordProperty("EglVersionMajor", minorVersion);
- EGLConfig myConfig = {0};
EGLint numConfigs = 0;
- EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig,
+ EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig,
1, &numConfigs));
ASSERT_EQ(EGL_SUCCESS, eglGetError());
@@ -85,12 +85,12 @@ protected:
ASSERT_TRUE(mSurfaceControl->isValid());
ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction());
- ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(30000));
+ ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction());
sp<ANativeWindow> window = mSurfaceControl->getSurface();
- mEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig,
+ mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
window.get(), NULL);
} else {
EGLint pbufferAttribs[] = {
@@ -98,13 +98,13 @@ protected:
EGL_HEIGHT, getSurfaceHeight(),
EGL_NONE };
- mEglSurface = eglCreatePbufferSurface(mEglDisplay, myConfig,
+ mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
pbufferAttribs);
}
ASSERT_EQ(EGL_SUCCESS, eglGetError());
ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
- mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT,
+ mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
getContextAttribs());
ASSERT_EQ(EGL_SUCCESS, eglGetError());
ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
@@ -270,8 +270,12 @@ protected:
*outPgm = program;
}
+ static int abs(int value) {
+ return value > 0 ? value : -value;
+ }
+
::testing::AssertionResult checkPixel(int x, int y, int r,
- int g, int b, int a) {
+ int g, int b, int a, int tolerance=2) {
GLubyte pixel[4];
String8 msg;
glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
@@ -285,22 +289,22 @@ protected:
return ::testing::AssertionFailure(
::testing::Message(msg.string()));
}
- if (r >= 0 && GLubyte(r) != pixel[0]) {
+ if (r >= 0 && abs(r - int(pixel[0])) > tolerance) {
msg += String8::format("r(%d isn't %d)", pixel[0], r);
}
- if (g >= 0 && GLubyte(g) != pixel[1]) {
+ if (g >= 0 && abs(g - int(pixel[1])) > tolerance) {
if (!msg.isEmpty()) {
msg += " ";
}
msg += String8::format("g(%d isn't %d)", pixel[1], g);
}
- if (b >= 0 && GLubyte(b) != pixel[2]) {
+ if (b >= 0 && abs(b - int(pixel[2])) > tolerance) {
if (!msg.isEmpty()) {
msg += " ";
}
msg += String8::format("b(%d isn't %d)", pixel[2], b);
}
- if (a >= 0 && GLubyte(a) != pixel[3]) {
+ if (a >= 0 && abs(a - int(pixel[3])) > tolerance) {
if (!msg.isEmpty()) {
msg += " ";
}
@@ -322,6 +326,7 @@ protected:
EGLDisplay mEglDisplay;
EGLSurface mEglSurface;
EGLContext mEglContext;
+ EGLConfig mGlConfig;
};
// XXX: Code above this point should live elsewhere
@@ -394,6 +399,18 @@ protected:
glBindTexture(GL_TEXTURE_EXTERNAL_OES, TEX_ID);
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ // XXX: These calls are not needed for GL_TEXTURE_EXTERNAL_OES as
+ // they're setting the defautls for that target, but when hacking things
+ // to use GL_TEXTURE_2D they are needed to achieve the same behavior.
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+
GLfloat texMatrix[16];
mST->getTransformMatrix(texMatrix);
glUniformMatrix4fv(mTexMatrixHandle, 1, GL_FALSE, texMatrix);
@@ -467,12 +484,26 @@ void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride,
}
}
+void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) {
+ const size_t PIXEL_SIZE = 4;
+ for (int x = 0; x < w; x++) {
+ for (int y = 0; y < h; y++) {
+ off_t offset = (y * stride + x) * PIXEL_SIZE;
+ for (int c = 0; c < 4; c++) {
+ int parityX = (x / (1 << (c+2))) & 1;
+ int parityY = (y / (1 << (c+2))) & 1;
+ buf[offset + c] = (parityX ^ parityY) ? 231 : 35;
+ }
+ }
+ }
+}
+
TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) {
- const int yuvTexWidth = 64;
- const int yuvTexHeight = 66;
+ const int texWidth = 64;
+ const int texHeight = 66;
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- yuvTexWidth, yuvTexHeight, HAL_PIXEL_FORMAT_YV12));
+ texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -486,7 +517,7 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) {
// Fill the buffer with the a checkerboard pattern
uint8_t* img = NULL;
buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
- fillYV12Buffer(img, yuvTexWidth, yuvTexHeight, buf->getStride());
+ fillYV12Buffer(img, texWidth, texHeight, buf->getStride());
buf->unlock();
ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
@@ -516,11 +547,11 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) {
// I just copied them from the npot test above and haven't bothered to figure
// out the correct values.
TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledYV12BufferPow2) {
- const int yuvTexWidth = 64;
- const int yuvTexHeight = 64;
+ const int texWidth = 64;
+ const int texHeight = 64;
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- yuvTexWidth, yuvTexHeight, HAL_PIXEL_FORMAT_YV12));
+ texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -534,7 +565,7 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledYV12BufferPow2) {
// Fill the buffer with the a checkerboard pattern
uint8_t* img = NULL;
buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
- fillYV12Buffer(img, yuvTexWidth, yuvTexHeight, buf->getStride());
+ fillYV12Buffer(img, texWidth, texHeight, buf->getStride());
buf->unlock();
ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
@@ -560,11 +591,11 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledYV12BufferPow2) {
}
TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
- const int yuvTexWidth = 64;
- const int yuvTexHeight = 66;
+ const int texWidth = 64;
+ const int texHeight = 66;
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- yuvTexWidth, yuvTexHeight, HAL_PIXEL_FORMAT_YV12));
+ texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -572,8 +603,8 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
{4, 6, 22, 36},
{0, 6, 22, 36},
{4, 0, 22, 36},
- {4, 6, yuvTexWidth, 36},
- {4, 6, 22, yuvTexHeight},
+ {4, 6, texWidth, 36},
+ {4, 6, 22, texHeight},
};
for (int i = 0; i < 5; i++) {
@@ -592,7 +623,7 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
uint8_t* img = NULL;
buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
- fillYV12BufferRect(img, yuvTexWidth, yuvTexHeight, buf->getStride(), crop);
+ fillYV12BufferRect(img, texWidth, texHeight, buf->getStride(), crop);
buf->unlock();
ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
@@ -618,4 +649,453 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
}
}
+// XXX: This test is disabled because there are currently no drivers that can
+// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
+TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) {
+ const int texWidth = 64;
+ const int texHeight = 66;
+
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+ texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
+ ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+ android_native_buffer_t* anb;
+ ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+ ASSERT_TRUE(anb != NULL);
+
+ sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
+
+ // Fill the buffer with the a checkerboard pattern
+ uint8_t* img = NULL;
+ buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+ fillRGBA8Buffer(img, texWidth, texHeight, buf->getStride());
+ buf->unlock();
+ ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+
+ mST->updateTexImage();
+
+ glClearColor(0.2, 0.2, 0.2, 0.2);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ drawTexture();
+
+ EXPECT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
+ EXPECT_TRUE(checkPixel(63, 0, 231, 231, 231, 231));
+ EXPECT_TRUE(checkPixel(63, 63, 231, 231, 231, 231));
+ EXPECT_TRUE(checkPixel( 0, 63, 35, 35, 35, 35));
+
+ EXPECT_TRUE(checkPixel(15, 10, 35, 231, 231, 231));
+ EXPECT_TRUE(checkPixel(24, 63, 35, 231, 231, 35));
+ EXPECT_TRUE(checkPixel(19, 40, 87, 179, 35, 35));
+ EXPECT_TRUE(checkPixel(38, 30, 231, 35, 35, 35));
+ EXPECT_TRUE(checkPixel(42, 54, 35, 35, 35, 231));
+ EXPECT_TRUE(checkPixel(37, 33, 35, 231, 231, 231));
+ EXPECT_TRUE(checkPixel(31, 8, 231, 35, 35, 231));
+ EXPECT_TRUE(checkPixel(36, 47, 231, 35, 231, 231));
+ EXPECT_TRUE(checkPixel(24, 63, 35, 231, 231, 35));
+ EXPECT_TRUE(checkPixel(48, 3, 231, 231, 35, 35));
+ EXPECT_TRUE(checkPixel(54, 50, 35, 231, 231, 231));
+ EXPECT_TRUE(checkPixel(24, 25, 191, 191, 231, 231));
+ EXPECT_TRUE(checkPixel(10, 9, 93, 93, 231, 231));
+ EXPECT_TRUE(checkPixel(29, 4, 35, 35, 35, 231));
+ EXPECT_TRUE(checkPixel(56, 31, 35, 231, 231, 35));
+ EXPECT_TRUE(checkPixel(58, 55, 35, 35, 231, 231));
+}
+
+// XXX: This test is disabled because there are currently no drivers that can
+// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
+TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferPow2) {
+ const int texWidth = 64;
+ const int texHeight = 64;
+
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+ texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
+ ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+ android_native_buffer_t* anb;
+ ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+ ASSERT_TRUE(anb != NULL);
+
+ sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
+
+ // Fill the buffer with the a checkerboard pattern
+ uint8_t* img = NULL;
+ buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+ fillRGBA8Buffer(img, texWidth, texHeight, buf->getStride());
+ buf->unlock();
+ ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+
+ mST->updateTexImage();
+
+ glClearColor(0.2, 0.2, 0.2, 0.2);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ drawTexture();
+
+ EXPECT_TRUE(checkPixel( 0, 0, 231, 231, 231, 231));
+ EXPECT_TRUE(checkPixel(63, 0, 35, 35, 35, 35));
+ EXPECT_TRUE(checkPixel(63, 63, 231, 231, 231, 231));
+ EXPECT_TRUE(checkPixel( 0, 63, 35, 35, 35, 35));
+
+ EXPECT_TRUE(checkPixel(12, 46, 231, 231, 231, 35));
+ EXPECT_TRUE(checkPixel(16, 1, 231, 231, 35, 231));
+ EXPECT_TRUE(checkPixel(21, 12, 231, 35, 35, 231));
+ EXPECT_TRUE(checkPixel(26, 51, 231, 35, 231, 35));
+ EXPECT_TRUE(checkPixel( 5, 32, 35, 231, 231, 35));
+ EXPECT_TRUE(checkPixel(13, 8, 35, 231, 231, 231));
+ EXPECT_TRUE(checkPixel(46, 3, 35, 35, 231, 35));
+ EXPECT_TRUE(checkPixel(30, 33, 35, 35, 35, 35));
+ EXPECT_TRUE(checkPixel( 6, 52, 231, 231, 35, 35));
+ EXPECT_TRUE(checkPixel(55, 33, 35, 231, 35, 231));
+ EXPECT_TRUE(checkPixel(16, 29, 35, 35, 231, 231));
+ EXPECT_TRUE(checkPixel( 1, 30, 35, 35, 35, 231));
+ EXPECT_TRUE(checkPixel(41, 37, 35, 35, 231, 231));
+ EXPECT_TRUE(checkPixel(46, 29, 231, 231, 35, 35));
+ EXPECT_TRUE(checkPixel(15, 25, 35, 231, 35, 231));
+ EXPECT_TRUE(checkPixel( 3, 52, 35, 231, 35, 35));
+}
+
+// XXX: This test is disabled because there are currently no drivers that can
+// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
+TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromGLFilledRGBABufferPow2) {
+ const int texWidth = 64;
+ const int texHeight = 64;
+
+ mST->setDefaultBufferSize(texWidth, texHeight);
+
+ // Do the producer side of things
+ EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
+ mANW.get(), NULL);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
+
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface,
+ mEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ glClearColor(0.6, 0.6, 0.6, 0.6);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(4, 4, 4, 4);
+ glClearColor(1.0, 0.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glScissor(24, 48, 4, 4);
+ glClearColor(0.0, 1.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glScissor(37, 17, 4, 4);
+ glClearColor(0.0, 0.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ eglSwapBuffers(mEglDisplay, stcEglSurface);
+
+ // Do the consumer side of things
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+ mEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ glDisable(GL_SCISSOR_TEST);
+
+ mST->updateTexImage();
+
+ glClearColor(0.2, 0.2, 0.2, 0.2);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ drawTexture();
+
+ EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
+
+ EXPECT_TRUE(checkPixel( 4, 7, 255, 0, 0, 255));
+ EXPECT_TRUE(checkPixel(25, 51, 0, 255, 0, 255));
+ EXPECT_TRUE(checkPixel(40, 19, 0, 0, 255, 255));
+ EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(13, 8, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(46, 3, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
+}
+
+/*
+ * This test is for testing GL -> GL texture streaming via SurfaceTexture. It
+ * contains functionality to create a producer thread that will perform GL
+ * rendering to an ANativeWindow that feeds frames to a SurfaceTexture.
+ * Additionally it supports interlocking the producer and consumer threads so
+ * that a specific sequence of calls can be deterministically created by the
+ * test.
+ *
+ * The intended usage is as follows:
+ *
+ * TEST_F(...) {
+ * class PT : public ProducerThread {
+ * virtual void render() {
+ * ...
+ * swapBuffers();
+ * }
+ * };
+ *
+ * runProducerThread(new PT());
+ *
+ * // The order of these calls will vary from test to test and may include
+ * // multiple frames and additional operations (e.g. GL rendering from the
+ * // texture).
+ * fc->waitForFrame();
+ * mST->updateTexImage();
+ * fc->finishFrame();
+ * }
+ *
+ */
+class SurfaceTextureGLToGLTest : public SurfaceTextureGLTest {
+protected:
+
+ // ProducerThread is an abstract base class to simplify the creation of
+ // OpenGL ES frame producer threads.
+ class ProducerThread : public Thread {
+ public:
+ virtual ~ProducerThread() {
+ }
+
+ void setEglObjects(EGLDisplay producerEglDisplay,
+ EGLSurface producerEglSurface,
+ EGLContext producerEglContext) {
+ mProducerEglDisplay = producerEglDisplay;
+ mProducerEglSurface = producerEglSurface;
+ mProducerEglContext = producerEglContext;
+ }
+
+ virtual bool threadLoop() {
+ eglMakeCurrent(mProducerEglDisplay, mProducerEglSurface,
+ mProducerEglSurface, mProducerEglContext);
+ render();
+ eglMakeCurrent(mProducerEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ return false;
+ }
+
+ protected:
+ virtual void render() = 0;
+
+ void swapBuffers() {
+ eglSwapBuffers(mProducerEglDisplay, mProducerEglSurface);
+ }
+
+ EGLDisplay mProducerEglDisplay;
+ EGLSurface mProducerEglSurface;
+ EGLContext mProducerEglContext;
+ };
+
+ // FrameCondition is a utility class for interlocking between the producer
+ // and consumer threads. The FrameCondition object should be created and
+ // destroyed in the consumer thread only. The consumer thread should set
+ // the FrameCondition as the FrameAvailableListener of the SurfaceTexture,
+ // and should call both waitForFrame and finishFrame once for each expected
+ // frame.
+ //
+ // This interlocking relies on the fact that onFrameAvailable gets called
+ // synchronously from SurfaceTexture::queueBuffer.
+ class FrameCondition : public SurfaceTexture::FrameAvailableListener {
+ public:
+ // waitForFrame waits for the next frame to arrive. This should be
+ // called from the consumer thread once for every frame expected by the
+ // test.
+ void waitForFrame() {
+ LOGV("+waitForFrame");
+ Mutex::Autolock lock(mMutex);
+ status_t result = mFrameAvailableCondition.wait(mMutex);
+ LOGV("-waitForFrame");
+ }
+
+ // Allow the producer to return from its swapBuffers call and continue
+ // on to produce the next frame. This should be called by the consumer
+ // thread once for every frame expected by the test.
+ void finishFrame() {
+ LOGV("+finishFrame");
+ Mutex::Autolock lock(mMutex);
+ mFrameFinishCondition.signal();
+ LOGV("-finishFrame");
+ }
+
+ // This should be called by SurfaceTexture on the producer thread.
+ virtual void onFrameAvailable() {
+ LOGV("+onFrameAvailable");
+ Mutex::Autolock lock(mMutex);
+ mFrameAvailableCondition.signal();
+ mFrameFinishCondition.wait(mMutex);
+ LOGV("-onFrameAvailable");
+ }
+
+ protected:
+ Mutex mMutex;
+ Condition mFrameAvailableCondition;
+ Condition mFrameFinishCondition;
+ };
+
+ SurfaceTextureGLToGLTest():
+ mProducerEglSurface(EGL_NO_SURFACE),
+ mProducerEglContext(EGL_NO_CONTEXT) {
+ }
+
+ virtual void SetUp() {
+ SurfaceTextureGLTest::SetUp();
+
+ EGLConfig myConfig = {0};
+ EGLint numConfigs = 0;
+ EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig,
+ 1, &numConfigs));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig,
+ mANW.get(), NULL);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface);
+
+ mProducerEglContext = eglCreateContext(mEglDisplay, myConfig,
+ EGL_NO_CONTEXT, getContextAttribs());
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext);
+
+ mFC = new FrameCondition();
+ mST->setFrameAvailableListener(mFC);
+ }
+
+ virtual void TearDown() {
+ if (mProducerThread != NULL) {
+ mProducerThread->requestExitAndWait();
+ }
+ if (mProducerEglContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(mEglDisplay, mProducerEglContext);
+ }
+ if (mProducerEglSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mEglDisplay, mProducerEglSurface);
+ }
+ mProducerThread.clear();
+ mFC.clear();
+ }
+
+ void runProducerThread(const sp<ProducerThread> producerThread) {
+ ASSERT_TRUE(mProducerThread == NULL);
+ mProducerThread = producerThread;
+ producerThread->setEglObjects(mEglDisplay, mProducerEglSurface,
+ mProducerEglContext);
+ producerThread->run();
+ }
+
+ EGLSurface mProducerEglSurface;
+ EGLContext mProducerEglContext;
+ sp<ProducerThread> mProducerThread;
+ sp<FrameCondition> mFC;
+};
+
+// XXX: This test is disabled because it causes hangs on some devices.
+TEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageBeforeFrameFinishedWorks) {
+ class PT : public ProducerThread {
+ virtual void render() {
+ glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ swapBuffers();
+ }
+ };
+
+ runProducerThread(new PT());
+
+ mFC->waitForFrame();
+ mST->updateTexImage();
+ mFC->finishFrame();
+
+ // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
+}
+
+// XXX: This test is disabled because it causes hangs on some devices.
+TEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageAfterFrameFinishedWorks) {
+ class PT : public ProducerThread {
+ virtual void render() {
+ glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ swapBuffers();
+ }
+ };
+
+ runProducerThread(new PT());
+
+ mFC->waitForFrame();
+ mFC->finishFrame();
+ mST->updateTexImage();
+
+ // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
+}
+
+// XXX: This test is disabled because it causes hangs on some devices.
+TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageBeforeFrameFinishedWorks) {
+ enum { NUM_ITERATIONS = 1024 };
+
+ class PT : public ProducerThread {
+ virtual void render() {
+ for (int i = 0; i < NUM_ITERATIONS; i++) {
+ glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ LOGV("+swapBuffers");
+ swapBuffers();
+ LOGV("-swapBuffers");
+ }
+ }
+ };
+
+ runProducerThread(new PT());
+
+ for (int i = 0; i < NUM_ITERATIONS; i++) {
+ mFC->waitForFrame();
+ LOGV("+updateTexImage");
+ mST->updateTexImage();
+ LOGV("-updateTexImage");
+ mFC->finishFrame();
+
+ // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
+ }
+}
+
+// XXX: This test is disabled because it causes hangs on some devices.
+TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageAfterFrameFinishedWorks) {
+ enum { NUM_ITERATIONS = 1024 };
+
+ class PT : public ProducerThread {
+ virtual void render() {
+ for (int i = 0; i < NUM_ITERATIONS; i++) {
+ glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ LOGV("+swapBuffers");
+ swapBuffers();
+ LOGV("-swapBuffers");
+ }
+ }
+ };
+
+ runProducerThread(new PT());
+
+ for (int i = 0; i < NUM_ITERATIONS; i++) {
+ mFC->waitForFrame();
+ mFC->finishFrame();
+ LOGV("+updateTexImage");
+ mST->updateTexImage();
+ LOGV("-updateTexImage");
+
+ // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
+ }
}
+
+} // namespace android
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index f316ba79a1ea..146e7894aa73 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -315,5 +315,95 @@ void LayerRenderer::destroyLayerDeferred(Layer* layer) {
}
}
+bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
+ Caches& caches = Caches::getInstance();
+ if (layer && layer->isTextureLayer && bitmap->width() <= caches.maxTextureSize &&
+ bitmap->height() <= caches.maxTextureSize) {
+
+ GLuint fbo = caches.fboCache.get();
+ if (!fbo) {
+ LOGW("Could not obtain an FBO");
+ return false;
+ }
+
+ GLuint texture;
+ GLuint previousFbo;
+
+ GLenum format;
+ GLenum type;
+
+ switch (bitmap->config()) {
+ case SkBitmap::kA8_Config:
+ format = GL_ALPHA;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ case SkBitmap::kRGB_565_Config:
+ format = GL_RGB;
+ type = GL_UNSIGNED_SHORT_5_6_5;
+ break;
+ case SkBitmap::kARGB_4444_Config:
+ format = GL_RGBA;
+ type = GL_UNSIGNED_SHORT_4_4_4_4;
+ break;
+ case SkBitmap::kARGB_8888_Config:
+ default:
+ format = GL_RGBA;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ }
+
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ glGenTextures(1, &texture);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texture);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, format, bitmap->width(), bitmap->height(),
+ 0, format, type, NULL);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, texture, 0);
+
+ glBindTexture(GL_TEXTURE_2D, layer->texture);
+
+ float alpha = layer->alpha;
+ SkXfermode::Mode mode = layer->mode;
+
+ layer->mode = SkXfermode::kSrc_Mode;
+ layer->alpha = 255;
+ layer->fbo = fbo;
+
+ LayerRenderer renderer(layer);
+ renderer.setViewport(bitmap->width(), bitmap->height());
+ renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
+ bitmap->width(), bitmap->height(), !layer->blend);
+
+ Rect bounds;
+ bounds.set(0.0f, 0.0f, bitmap->width(), bitmap->height());
+ renderer.drawTextureLayer(layer, bounds);
+
+ SkAutoLockPixels alp(*bitmap);
+ glReadPixels(0, 0, bitmap->width(), bitmap->height(), format, type, bitmap->getPixels());
+
+ glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+
+ layer->mode = mode;
+ layer->alpha = alpha;
+ layer->fbo = 0;
+ glDeleteTextures(1, &texture);
+ caches.fboCache.put(fbo);
+
+ return true;
+ }
+ return false;
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 59cab963ca0a..797dfc63e5bb 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -20,6 +20,8 @@
#include "OpenGLRenderer.h"
#include "Layer.h"
+#include <SkBitmap.h>
+
namespace android {
namespace uirenderer {
@@ -60,6 +62,7 @@ public:
GLenum renderTarget, float* transform);
static void destroyLayer(Layer* layer);
static void destroyLayerDeferred(Layer* layer);
+ static bool copyLayer(Layer* layer, SkBitmap* bitmap);
private:
void generateMesh();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 6c9c0eb54ecf..5343a059ec26 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -476,13 +476,8 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
}
- // Clear the framebuffer where the layer will draw
- glScissor(bounds.left, mSnapshot->height - bounds.bottom,
- bounds.getWidth(), bounds.getHeight());
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT);
-
- dirtyClip();
+ // Enqueue the buffer coordinates to clear the corresponding region later
+ mLayers.push(new Rect(bounds));
}
}
@@ -817,6 +812,58 @@ void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) {
#endif
}
+void OpenGLRenderer::clearLayerRegions() {
+ const size_t count = mLayers.size();
+ if (count == 0) return;
+
+ if (!mSnapshot->isIgnored()) {
+ // Doing several glScissor/glClear here can negatively impact
+ // GPUs with a tiler architecture, instead we draw quads with
+ // the Clear blending mode
+
+ // The list contains bounds that have already been clipped
+ // against their initial clip rect, and the current clip
+ // is likely different so we need to disable clipping here
+ glDisable(GL_SCISSOR_TEST);
+
+ Vertex mesh[count * 6];
+ Vertex* vertex = mesh;
+
+ for (uint32_t i = 0; i < count; i++) {
+ Rect* bounds = mLayers.itemAt(i);
+
+ Vertex::set(vertex++, bounds->left, bounds->bottom);
+ Vertex::set(vertex++, bounds->left, bounds->top);
+ Vertex::set(vertex++, bounds->right, bounds->top);
+ Vertex::set(vertex++, bounds->left, bounds->bottom);
+ Vertex::set(vertex++, bounds->right, bounds->top);
+ Vertex::set(vertex++, bounds->right, bounds->bottom);
+
+ delete bounds;
+ }
+
+ setupDraw(false);
+ setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
+ setupDrawBlending(true, SkXfermode::kClear_Mode);
+ setupDrawProgram();
+ setupDrawPureColorUniforms();
+ setupDrawModelViewTranslate(0.0f, 0.0f, 0.0f, 0.0f, true);
+
+ mCaches.unbindMeshBuffer();
+ glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
+ gVertexStride, &mesh[0].position[0]);
+ glDrawArrays(GL_TRIANGLES, 0, count * 6);
+
+ glEnable(GL_SCISSOR_TEST);
+ } else {
+ for (uint32_t i = 0; i < count; i++) {
+ delete mLayers.itemAt(i);
+ }
+ }
+
+ mLayers.clear();
+}
+
///////////////////////////////////////////////////////////////////////////////
// Transforms
///////////////////////////////////////////////////////////////////////////////
@@ -901,7 +948,8 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom,
// Drawing commands
///////////////////////////////////////////////////////////////////////////////
-void OpenGLRenderer::setupDraw() {
+void OpenGLRenderer::setupDraw(bool clear) {
+ if (clear) clearLayerRegions();
if (mDirtyClip) {
setScissorFromClip();
}
@@ -994,7 +1042,7 @@ void OpenGLRenderer::accountForClear(SkXfermode::Mode mode) {
if (mColorSet && mode == SkXfermode::kClear_Mode) {
mColorA = 1.0f;
mColorR = mColorG = mColorB = 0.0f;
- mSetShaderColor = mDescription.setAlpha8Color(mColorR, mColorG, mColorB, mColorA);
+ mSetShaderColor = mDescription.modulate = true;
}
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 549d6e9e888b..0a3d509058fc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -178,6 +178,14 @@ protected:
return 0;
}
+ /**
+ * Renders the specified layer as a textured quad.
+ *
+ * @param layer The layer to render
+ * @param rect The bounds of the layer
+ */
+ void drawTextureLayer(Layer* layer, const Rect& rect);
+
private:
/**
* Saves the current state of the renderer as a new snapshot.
@@ -249,7 +257,11 @@ private:
*/
void composeLayerRect(Layer* layer, const Rect& rect, bool swap = false);
- void drawTextureLayer(Layer* layer, const Rect& rect);
+ /**
+ * Clears all the regions corresponding to the current list of layers.
+ * This method MUST be invoked before any drawing operation.
+ */
+ void clearLayerRegions();
/**
* Mark the layer as dirty at the specified coordinates. The coordinates
@@ -280,11 +292,53 @@ private:
void drawColorRect(float left, float top, float right, float bottom,
int color, SkXfermode::Mode mode, bool ignoreTransform = false);
+ /**
+ * Draws the shape represented by the specified path texture.
+ * This method invokes drawPathTexture() but takes into account
+ * the extra left/top offset and the texture offset to correctly
+ * position the final shape.
+ *
+ * @param left The left coordinate of the shape to render
+ * @param top The top coordinate of the shape to render
+ * @param texture The texture reprsenting the shape
+ * @param paint The paint to draw the shape with
+ */
void drawShape(float left, float top, const PathTexture* texture, SkPaint* paint);
+
+ /**
+ * Renders the rect defined by the specified bounds as a shape.
+ * This will render the rect using a path texture, which is used to render
+ * rects with stroke effects.
+ *
+ * @param left The left coordinate of the rect to draw
+ * @param top The top coordinate of the rect to draw
+ * @param right The right coordinate of the rect to draw
+ * @param bottom The bottom coordinate of the rect to draw
+ * @param p The paint to draw the rect with
+ */
void drawRectAsShape(float left, float top, float right, float bottom, SkPaint* p);
+ /**
+ * Draws the specified texture as an alpha bitmap. Alpha bitmaps obey
+ * different compositing rules.
+ *
+ * @param texture The texture to draw with
+ * @param left The x coordinate of the bitmap
+ * @param top The y coordinate of the bitmap
+ * @param paint The paint to render with
+ */
void drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint);
+ /**
+ * Renders the rect defined by the specified bounds as an anti-aliased rect.
+ *
+ * @param left The left coordinate of the rect to draw
+ * @param top The top coordinate of the rect to draw
+ * @param right The right coordinate of the rect to draw
+ * @param bottom The bottom coordinate of the rect to draw
+ * @param color The color of the rect
+ * @param mode The blending mode to draw the rect
+ */
void drawAARect(float left, float top, float right, float bottom,
int color, SkXfermode::Mode mode);
@@ -359,6 +413,15 @@ private:
void drawTextDecorations(const char* text, int bytesCount, float length,
float x, float y, SkPaint* paint);
+ /**
+ * Draws a path texture. Path textures are alpha8 bitmaps that need special
+ * compositing to apply colors/filters/etc.
+ *
+ * @param texture The texture to render
+ * @param x The x coordinate where the texture will be drawn
+ * @param y The y coordinate where the texture will be drawn
+ * @param paint The paint to draw the texture with
+ */
void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
/**
@@ -434,7 +497,7 @@ private:
/**
* Invoked before any drawing operation. This sets required state.
*/
- void setupDraw();
+ void setupDraw(bool clear = true);
/**
* Various methods to setup OpenGL rendering.
*/
@@ -522,6 +585,9 @@ private:
// Various caches
Caches& mCaches;
+ // List of rectagnles to clear after saveLayer() is invoked
+ Vector<Rect*> mLayers;
+
// Indentity matrix
const mat4 mIdentity;
diff --git a/libs/rs/RenderScriptDefines.h b/libs/rs/RenderScriptDefines.h
index ee9645c37bcd..d092520feb81 100644
--- a/libs/rs/RenderScriptDefines.h
+++ b/libs/rs/RenderScriptDefines.h
@@ -110,12 +110,12 @@ enum RsAllocationMipmapControl {
};
enum RsAllocationCubemapFace {
- RS_ALLOCATION_CUBMAP_FACE_POSITVE_X = 0,
- RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_X = 1,
- RS_ALLOCATION_CUBMAP_FACE_POSITVE_Y = 2,
- RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Y = 3,
- RS_ALLOCATION_CUBMAP_FACE_POSITVE_Z = 4,
- RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Z = 5
+ RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X = 0,
+ RS_ALLOCATION_CUBEMAP_FACE_NEGATIVE_X = 1,
+ RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_Y = 2,
+ RS_ALLOCATION_CUBEMAP_FACE_NEGATIVE_Y = 3,
+ RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_Z = 4,
+ RS_ALLOCATION_CUBEMAP_FACE_NEGATIVE_Z = 5
};
enum RsDataType {
diff --git a/libs/rs/driver/rsdAllocation.cpp b/libs/rs/driver/rsdAllocation.cpp
index 2e13e9d0b5a0..8bfc1857d4bf 100644
--- a/libs/rs/driver/rsdAllocation.cpp
+++ b/libs/rs/driver/rsdAllocation.cpp
@@ -378,6 +378,32 @@ void rsdAllocationData3D(const Context *rsc, const Allocation *alloc,
}
+void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstLod, uint32_t count,
+ const android::renderscript::Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcLod){
+}
+
+void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
+ RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
+ const android::renderscript::Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
+ RsAllocationCubemapFace srcFace) {
+}
+
+void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
+ uint32_t dstLod, RsAllocationCubemapFace dstFace,
+ uint32_t w, uint32_t h, uint32_t d,
+ const android::renderscript::Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
+ uint32_t srcLod, RsAllocationCubemapFace srcFace) {
+}
+
void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc,
uint32_t x,
const void *data, uint32_t cIdx, uint32_t sizeBytes) {
diff --git a/libs/rs/driver/rsdAllocation.h b/libs/rs/driver/rsdAllocation.h
index d7385cee64cf..7555c4ab0711 100644
--- a/libs/rs/driver/rsdAllocation.h
+++ b/libs/rs/driver/rsdAllocation.h
@@ -80,6 +80,27 @@ void rsdAllocationData3D(const android::renderscript::Context *rsc,
uint32_t lod, RsAllocationCubemapFace face,
uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes);
+void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstLod, uint32_t count,
+ const android::renderscript::Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcLod);
+void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
+ RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
+ const android::renderscript::Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
+ RsAllocationCubemapFace srcFace);
+void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
+ uint32_t dstLod, RsAllocationCubemapFace dstFace,
+ uint32_t w, uint32_t h, uint32_t d,
+ const android::renderscript::Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
+ uint32_t srcLod, RsAllocationCubemapFace srcFace);
+
void rsdAllocationElementData1D(const android::renderscript::Context *rsc,
const android::renderscript::Allocation *alloc,
uint32_t x,
diff --git a/libs/rs/driver/rsdCore.cpp b/libs/rs/driver/rsdCore.cpp
index 01cc369a8e01..38f6895f26fd 100644
--- a/libs/rs/driver/rsdCore.cpp
+++ b/libs/rs/driver/rsdCore.cpp
@@ -74,6 +74,9 @@ static RsdHalFunctions FunctionTable = {
rsdAllocationData1D,
rsdAllocationData2D,
rsdAllocationData3D,
+ rsdAllocationData1D_alloc,
+ rsdAllocationData2D_alloc,
+ rsdAllocationData3D_alloc,
rsdAllocationElementData1D,
rsdAllocationElementData2D
},
diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp
index 9cbff9526b16..bd8b3c325dce 100644
--- a/libs/rs/driver/rsdRuntimeStubs.cpp
+++ b/libs/rs/driver/rsdRuntimeStubs.cpp
@@ -88,6 +88,26 @@ static void SC_AllocationSyncAll(Allocation *a) {
rsrAllocationSyncAll(rsc, sc, a, RS_ALLOCATION_USAGE_SCRIPT);
}
+static void SC_AllocationCopy1DRange(Allocation *dstAlloc,
+ uint32_t dstOff,
+ uint32_t dstMip,
+ uint32_t count,
+ Allocation *srcAlloc,
+ uint32_t srcOff, uint32_t srcMip) {
+ GET_TLS();
+}
+
+static void SC_AllocationCopy2DRange(Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff,
+ uint32_t dstMip, uint32_t dstFace,
+ uint32_t width, uint32_t height,
+ Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff,
+ uint32_t srcMip, uint32_t srcFace) {
+ GET_TLS();
+}
+
+
const Allocation * SC_getAllocation(const void *ptr) {
GET_TLS();
return rsrGetAllocation(rsc, sc, ptr);
@@ -566,8 +586,11 @@ static RsdSymbolTable gSyms[] = {
{ "_Z21rsAllocationMarkDirty13rs_allocation", (void *)&SC_AllocationSyncAll, true },
{ "_Z20rsgAllocationSyncAll13rs_allocation", (void *)&SC_AllocationSyncAll, false },
{ "_Z20rsgAllocationSyncAll13rs_allocationj", (void *)&SC_AllocationSyncAll2, false },
+ { "_Z20rsgAllocationSyncAll13rs_allocation24rs_allocation_usage_type", (void *)&SC_AllocationSyncAll2, false },
{ "_Z15rsGetAllocationPKv", (void *)&SC_GetAllocation, true },
+ { "_Z23rsAllocationCopy1DRange13rs_allocationjjjS_jj", (void *)&SC_AllocationCopy1DRange, false },
+ { "_Z23rsAllocationCopy2DRange13rs_allocationjjj26rs_allocation_cubemap_facejjS_jjjS0_", (void *)&SC_AllocationCopy2DRange, false },
// Messaging
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 87d764d2f006..963a6e78dc29 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -209,6 +209,21 @@ AllocationResize2D {
param uint32_t dimY
}
+AllocationCopy2DRange {
+ param RsAllocation dest
+ param uint32_t destXoff
+ param uint32_t destYoff
+ param uint32_t destMip
+ param uint32_t destFace
+ param uint32_t width
+ param uint32_t height
+ param RsAllocation src
+ param uint32_t srcXoff
+ param uint32_t srcYoff
+ param uint32_t srcMip
+ param uint32_t srcFace
+ }
+
SamplerCreate {
param RsSamplerValue magFilter
param RsSamplerValue minFilter
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index bff36603e9d9..f3e0c0a75291 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -532,6 +532,23 @@ RsAllocation rsi_AllocationCubeCreateFromBitmap(Context *rsc, RsType vtype,
return texAlloc;
}
+void rsi_AllocationCopy2DRange(Context *rsc,
+ RsAllocation dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff,
+ uint32_t dstMip, uint32_t dstFace,
+ uint32_t width, uint32_t height,
+ RsAllocation srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff,
+ uint32_t srcMip, uint32_t srcFace) {
+ Allocation *dst = static_cast<Allocation *>(dstAlloc);
+ Allocation *src= static_cast<Allocation *>(srcAlloc);
+ rsc->mHal.funcs.allocation.allocData2D(rsc, dst, dstXoff, dstYoff, dstMip,
+ (RsAllocationCubemapFace)dstFace,
+ width, height,
+ src, srcXoff, srcYoff,srcMip,
+ (RsAllocationCubemapFace)srcFace);
+}
+
}
}
diff --git a/libs/rs/rsRuntime.h b/libs/rs/rsRuntime.h
index 6d45285e6d9f..cb962a815dc3 100644
--- a/libs/rs/rsRuntime.h
+++ b/libs/rs/rsRuntime.h
@@ -85,6 +85,21 @@ void rsrMeshComputeBoundingBox(Context *, Script *, Mesh *,
void rsrColor(Context *, Script *, float r, float g, float b, float a);
void rsrFinish(Context *, Script *);
void rsrAllocationSyncAll(Context *, Script *, Allocation *);
+
+void rsrAllocationCopy1DRange(Context *, Allocation *dstAlloc,
+ uint32_t dstOff,
+ uint32_t dstMip,
+ uint32_t count,
+ Allocation *srcAlloc,
+ uint32_t srcOff, uint32_t srcMip);
+void rsrAllocationCopy2DRange(Context *, Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff,
+ uint32_t dstMip, uint32_t dstFace,
+ uint32_t width, uint32_t height,
+ Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff,
+ uint32_t srcMip, uint32_t srcFace);
+
void rsrClearColor(Context *, Script *, float r, float g, float b, float a);
void rsrClearDepth(Context *, Script *, float v);
uint32_t rsrGetWidth(Context *, Script *);
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 4ee0a3ec4e5e..ec15bc0233a5 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -164,6 +164,29 @@ void rsrAllocationSyncAll(Context *rsc, Script *sc, Allocation *a, RsAllocationU
a->syncAll(rsc, usage);
}
+void rsrAllocationCopy1DRange(Context *rsc, Allocation *dstAlloc,
+ uint32_t dstOff,
+ uint32_t dstMip,
+ uint32_t count,
+ Allocation *srcAlloc,
+ uint32_t srcOff, uint32_t srcMip) {
+ rsi_AllocationCopy2DRange(rsc, dstAlloc, dstOff, 0,
+ dstMip, 0, count, 1,
+ srcAlloc, srcOff, 0, srcMip, 0);
+}
+
+void rsrAllocationCopy2DRange(Context *rsc, Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff,
+ uint32_t dstMip, uint32_t dstFace,
+ uint32_t width, uint32_t height,
+ Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff,
+ uint32_t srcMip, uint32_t srcFace) {
+ rsi_AllocationCopy2DRange(rsc, dstAlloc, dstXoff, dstYoff,
+ dstMip, dstFace, width, height,
+ srcAlloc, srcXoff, srcYoff, srcMip, srcFace);
+}
+
const Allocation * rsrGetAllocation(Context *rsc, Script *s, const void *ptr) {
ScriptC *sc = (ScriptC *)s;
return sc->ptrToAllocation(ptr);
diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h
index 7bb09bbf5597..928dca5376ed 100644
--- a/libs/rs/rs_hal.h
+++ b/libs/rs/rs_hal.h
@@ -112,6 +112,27 @@ typedef struct {
uint32_t lod, RsAllocationCubemapFace face,
uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes);
+ // Allocation to allocation copies
+ void (*allocData1D)(const Context *rsc,
+ const Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstLod, uint32_t count,
+ const Allocation *srcAlloc, uint32_t srcXoff, uint32_t srcLod);
+ void (*allocData2D)(const Context *rsc,
+ const Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
+ RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
+ const Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
+ RsAllocationCubemapFace srcFace);
+ void (*allocData3D)(const Context *rsc,
+ const Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
+ uint32_t dstLod, RsAllocationCubemapFace dstFace,
+ uint32_t w, uint32_t h, uint32_t d,
+ const Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
+ uint32_t srcLod, RsAllocationCubemapFace srcFace);
+
void (*elementData1D)(const Context *rsc, const Allocation *alloc, uint32_t x,
const void *data, uint32_t elementOff, uint32_t sizeBytes);
void (*elementData2D)(const Context *rsc, const Allocation *alloc, uint32_t x, uint32_t y,
diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh
index d53bc952ded5..9a8a4e66a03d 100644
--- a/libs/rs/scriptc/rs_graphics.rsh
+++ b/libs/rs/scriptc/rs_graphics.rsh
@@ -144,6 +144,17 @@ extern void __attribute__((overloadable))
rsgAllocationSyncAll(rs_allocation alloc);
/**
+ * Sync the contents of an allocation from memory space
+ * specified by source.
+ *
+ * @param alloc
+ * @param source
+ */
+extern void __attribute__((overloadable))
+ rsgAllocationSyncAll(rs_allocation alloc,
+ rs_allocation_usage_type source);
+
+/**
* Low performance utility function for drawing a simple rectangle. Not
* intended for drawing large quantities of geometry.
*
diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh
index 6e3cfdb77529..584317e0476c 100644
--- a/libs/rs/scriptc/rs_math.rsh
+++ b/libs/rs/scriptc/rs_math.rsh
@@ -136,6 +136,58 @@ extern uint32_t __attribute__((overloadable))
extern uint32_t __attribute__((overloadable))
rsAllocationGetDimFaces(rs_allocation);
+/**
+ * Copy part of an allocation from another allocation.
+ *
+ * @param dstAlloc Allocation to copy data into.
+ * @param dstOff The offset of the first element to be copied in
+ * the destination allocation.
+ * @param dstMip Mip level in the destination allocation.
+ * @param count The number of elements to be copied.
+ * @param srcAlloc The source data allocation.
+ * @param srcOff The offset of the first element in data to be
+ * copied in the source allocation.
+ * @param srcMip Mip level in the source allocation.
+ */
+extern void __attribute__((overloadable))
+ rsAllocationCopy1DRange(rs_allocation dstAlloc,
+ uint32_t dstOff, uint32_t dstMip,
+ uint32_t count,
+ rs_allocation srcAlloc,
+ uint32_t srcOff, uint32_t srcMip);
+
+/**
+ * Copy a rectangular region into the allocation from another
+ * allocation.
+ *
+ * @param dstAlloc allocation to copy data into.
+ * @param dstXoff X offset of the region to update in the
+ * destination allocation.
+ * @param dstYoff Y offset of the region to update in the
+ * destination allocation.
+ * @param dstMip Mip level in the destination allocation.
+ * @param dstFace Cubemap face of the destination allocation,
+ * ignored for allocations that aren't cubemaps.
+ * @param width Width of the incoming region to update.
+ * @param height Height of the incoming region to update.
+ * @param srcAlloc The source data allocation.
+ * @param srcXoff X offset in data of the source allocation.
+ * @param srcYoff Y offset in data of the source allocation.
+ * @param srcMip Mip level in the source allocation.
+ * @param srcFace Cubemap face of the source allocation,
+ * ignored for allocations that aren't cubemaps.
+ */
+extern void __attribute__((overloadable))
+ rsAllocationCopy2DRange(rs_allocation dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff,
+ uint32_t dstMip,
+ rs_allocation_cubemap_face dstFace,
+ uint32_t width, uint32_t height,
+ rs_allocation srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff,
+ uint32_t srcMip,
+ rs_allocation_cubemap_face srcFace);
+
// Extract a single element from an allocation.
extern const void * __attribute__((overloadable))
rsGetElementAt(rs_allocation, uint32_t x);
diff --git a/libs/rs/scriptc/rs_types.rsh b/libs/rs/scriptc/rs_types.rsh
index d9f4b4b9b948..536d1f04da48 100644
--- a/libs/rs/scriptc/rs_types.rsh
+++ b/libs/rs/scriptc/rs_types.rsh
@@ -88,4 +88,21 @@ typedef float4 rs_quaternion;
#define RS_PACKED __attribute__((packed, aligned(4)))
+typedef enum {
+ RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X = 0,
+ RS_ALLOCATION_CUBEMAP_FACE_NEGATIVE_X = 1,
+ RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_Y = 2,
+ RS_ALLOCATION_CUBEMAP_FACE_NEGATIVE_Y = 3,
+ RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_Z = 4,
+ RS_ALLOCATION_CUBEMAP_FACE_NEGATIVE_Z = 5
+} rs_allocation_cubemap_face;
+
+typedef enum {
+ RS_ALLOCATION_USAGE_SCRIPT = 0x0001,
+ RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE = 0x0002,
+ RS_ALLOCATION_USAGE_GRAPHICS_VERTEX = 0x0004,
+ RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS = 0x0008,
+ RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET = 0x0010
+} rs_allocation_usage_type;
+
#endif
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index e8d40ba08352..093189c5c05a 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -21,6 +21,7 @@ commonSources:= \
Asset.cpp \
AssetDir.cpp \
AssetManager.cpp \
+ BlobCache.cpp \
BufferedTextOutput.cpp \
CallStack.cpp \
Debug.cpp \
diff --git a/libs/utils/BlobCache.cpp b/libs/utils/BlobCache.cpp
new file mode 100644
index 000000000000..1298fa733cb0
--- /dev/null
+++ b/libs/utils/BlobCache.cpp
@@ -0,0 +1,232 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#define LOG_TAG "BlobCache"
+//#define LOG_NDEBUG 0
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <utils/BlobCache.h>
+#include <utils/Log.h>
+
+namespace android {
+
+BlobCache::BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize):
+ mMaxKeySize(maxKeySize),
+ mMaxValueSize(maxValueSize),
+ mMaxTotalSize(maxTotalSize),
+ mTotalSize(0) {
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ mRandState[0] = (now >> 0) & 0xFFFF;
+ mRandState[1] = (now >> 16) & 0xFFFF;
+ mRandState[2] = (now >> 32) & 0xFFFF;
+ LOGV("initializing random seed using %lld", now);
+}
+
+void BlobCache::set(const void* key, size_t keySize, const void* value,
+ size_t valueSize) {
+ if (mMaxKeySize < keySize) {
+ LOGV("set: not caching because the key is too large: %d (limit: %d)",
+ keySize, mMaxKeySize);
+ return;
+ }
+ if (mMaxValueSize < valueSize) {
+ LOGV("set: not caching because the value is too large: %d (limit: %d)",
+ valueSize, mMaxValueSize);
+ return;
+ }
+ if (mMaxTotalSize < keySize + valueSize) {
+ LOGV("set: not caching because the combined key/value size is too "
+ "large: %d (limit: %d)", keySize + valueSize, mMaxTotalSize);
+ return;
+ }
+ if (keySize == 0) {
+ LOGW("set: not caching because keySize is 0");
+ return;
+ }
+ if (valueSize <= 0) {
+ LOGW("set: not caching because valueSize is 0");
+ return;
+ }
+
+ Mutex::Autolock lock(mMutex);
+ sp<Blob> dummyKey(new Blob(key, keySize, false));
+ CacheEntry dummyEntry(dummyKey, NULL);
+
+ while (true) {
+
+ ssize_t index = mCacheEntries.indexOf(dummyEntry);
+ if (index < 0) {
+ // Create a new cache entry.
+ sp<Blob> keyBlob(new Blob(key, keySize, true));
+ sp<Blob> valueBlob(new Blob(value, valueSize, true));
+ size_t newTotalSize = mTotalSize + keySize + valueSize;
+ if (mMaxTotalSize < newTotalSize) {
+ if (isCleanable()) {
+ // Clean the cache and try again.
+ clean();
+ continue;
+ } else {
+ LOGV("set: not caching new key/value pair because the "
+ "total cache size limit would be exceeded: %d "
+ "(limit: %d)",
+ keySize + valueSize, mMaxTotalSize);
+ break;
+ }
+ }
+ mCacheEntries.add(CacheEntry(keyBlob, valueBlob));
+ mTotalSize = newTotalSize;
+ LOGV("set: created new cache entry with %d byte key and %d byte value",
+ keySize, valueSize);
+ } else {
+ // Update the existing cache entry.
+ sp<Blob> valueBlob(new Blob(value, valueSize, true));
+ sp<Blob> oldValueBlob(mCacheEntries[index].getValue());
+ size_t newTotalSize = mTotalSize + valueSize - oldValueBlob->getSize();
+ if (mMaxTotalSize < newTotalSize) {
+ if (isCleanable()) {
+ // Clean the cache and try again.
+ clean();
+ continue;
+ } else {
+ LOGV("set: not caching new value because the total cache "
+ "size limit would be exceeded: %d (limit: %d)",
+ keySize + valueSize, mMaxTotalSize);
+ break;
+ }
+ }
+ mCacheEntries.editItemAt(index).setValue(valueBlob);
+ mTotalSize = newTotalSize;
+ LOGV("set: updated existing cache entry with %d byte key and %d byte "
+ "value", keySize, valueSize);
+ }
+ break;
+ }
+}
+
+size_t BlobCache::get(const void* key, size_t keySize, void* value,
+ size_t valueSize) {
+ if (mMaxKeySize < keySize) {
+ LOGV("get: not searching because the key is too large: %d (limit %d)",
+ keySize, mMaxKeySize);
+ return 0;
+ }
+ Mutex::Autolock lock(mMutex);
+ sp<Blob> dummyKey(new Blob(key, keySize, false));
+ CacheEntry dummyEntry(dummyKey, NULL);
+ ssize_t index = mCacheEntries.indexOf(dummyEntry);
+ if (index < 0) {
+ LOGV("get: no cache entry found for key of size %d", keySize);
+ return 0;
+ }
+
+ // The key was found. Return the value if the caller's buffer is large
+ // enough.
+ sp<Blob> valueBlob(mCacheEntries[index].getValue());
+ size_t valueBlobSize = valueBlob->getSize();
+ if (valueBlobSize <= valueSize) {
+ LOGV("get: copying %d bytes to caller's buffer", valueBlobSize);
+ memcpy(value, valueBlob->getData(), valueBlobSize);
+ } else {
+ LOGV("get: caller's buffer is too small for value: %d (needs %d)",
+ valueSize, valueBlobSize);
+ }
+ return valueBlobSize;
+}
+
+void BlobCache::clean() {
+ // Remove a random cache entry until the total cache size gets below half
+ // the maximum total cache size.
+ while (mTotalSize > mMaxTotalSize / 2) {
+ size_t i = size_t(nrand48(mRandState) % (mCacheEntries.size()));
+ const CacheEntry& entry(mCacheEntries[i]);
+ mTotalSize -= entry.getKey()->getSize() + entry.getValue()->getSize();
+ mCacheEntries.removeAt(i);
+ }
+}
+
+bool BlobCache::isCleanable() const {
+ return mTotalSize > mMaxTotalSize / 2;
+}
+
+BlobCache::Blob::Blob(const void* data, size_t size, bool copyData):
+ mData(copyData ? malloc(size) : data),
+ mSize(size),
+ mOwnsData(copyData) {
+ if (copyData) {
+ memcpy(const_cast<void*>(mData), data, size);
+ }
+}
+
+BlobCache::Blob::~Blob() {
+ if (mOwnsData) {
+ free(const_cast<void*>(mData));
+ }
+}
+
+bool BlobCache::Blob::operator<(const Blob& rhs) const {
+ if (mSize == rhs.mSize) {
+ return memcmp(mData, rhs.mData, mSize) < 0;
+ } else {
+ return mSize < rhs.mSize;
+ }
+}
+
+const void* BlobCache::Blob::getData() const {
+ return mData;
+}
+
+size_t BlobCache::Blob::getSize() const {
+ return mSize;
+}
+
+BlobCache::CacheEntry::CacheEntry() {
+}
+
+BlobCache::CacheEntry::CacheEntry(const sp<Blob>& key, const sp<Blob>& value):
+ mKey(key),
+ mValue(value) {
+}
+
+BlobCache::CacheEntry::CacheEntry(const CacheEntry& ce):
+ mKey(ce.mKey),
+ mValue(ce.mValue) {
+}
+
+bool BlobCache::CacheEntry::operator<(const CacheEntry& rhs) const {
+ return *mKey < *rhs.mKey;
+}
+
+const BlobCache::CacheEntry& BlobCache::CacheEntry::operator=(const CacheEntry& rhs) {
+ mKey = rhs.mKey;
+ mValue = rhs.mValue;
+ return *this;
+}
+
+sp<BlobCache::Blob> BlobCache::CacheEntry::getKey() const {
+ return mKey;
+}
+
+sp<BlobCache::Blob> BlobCache::CacheEntry::getValue() const {
+ return mValue;
+}
+
+void BlobCache::CacheEntry::setValue(const sp<Blob>& value) {
+ mValue = value;
+}
+
+} // namespace android
diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp
index 58e0811f21a0..8db2009587f7 100644
--- a/libs/utils/RefBase.cpp
+++ b/libs/utils/RefBase.cpp
@@ -49,6 +49,11 @@ namespace android {
// ---------------------------------------------------------------------------
+RefBase::Destroyer::~Destroyer() {
+}
+
+// ---------------------------------------------------------------------------
+
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
@@ -56,7 +61,7 @@ public:
volatile int32_t mWeak;
RefBase* const mBase;
volatile int32_t mFlags;
-
+ Destroyer* mDestroyer;
#if !DEBUG_REFS
@@ -65,6 +70,7 @@ public:
, mWeak(0)
, mBase(base)
, mFlags(0)
+ , mDestroyer(0)
{
}
@@ -345,10 +351,6 @@ void RefBase::incStrong(const void* id) const
const_cast<RefBase*>(this)->onFirstRef();
}
-void RefBase::destroy() const {
- delete this;
-}
-
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
@@ -361,7 +363,11 @@ void RefBase::decStrong(const void* id) const
if (c == 1) {
const_cast<RefBase*>(this)->onLastStrongRef(id);
if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
- destroy();
+ if (refs->mDestroyer) {
+ refs->mDestroyer->destroy(this);
+ } else {
+ delete this;
+ }
}
}
refs->decWeak(id);
@@ -394,7 +400,9 @@ int32_t RefBase::getStrongCount() const
return mRefs->mStrong;
}
-
+void RefBase::setDestroyer(RefBase::Destroyer* destroyer) {
+ mRefs->mDestroyer = destroyer;
+}
RefBase* RefBase::weakref_type::refBase() const
{
@@ -420,7 +428,11 @@ void RefBase::weakref_type::decWeak(const void* id)
if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
if (impl->mStrong == INITIAL_STRONG_VALUE) {
if (impl->mBase) {
- impl->mBase->destroy();
+ if (impl->mDestroyer) {
+ impl->mDestroyer->destroy(impl->mBase);
+ } else {
+ delete impl->mBase;
+ }
}
} else {
// LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
@@ -430,7 +442,11 @@ void RefBase::weakref_type::decWeak(const void* id)
impl->mBase->onLastWeakRef(id);
if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
if (impl->mBase) {
- impl->mBase->destroy();
+ if (impl->mDestroyer) {
+ impl->mDestroyer->destroy(impl->mBase);
+ } else {
+ delete impl->mBase;
+ }
}
}
}
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 8b5da0e58014..15bb1d22627c 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -168,6 +168,9 @@ int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
return 0;
}
+ // Note that *threadID is directly available to the parent only, as it is
+ // assigned after the child starts. Use memory barrier / lock if the child
+ // or other threads also need access.
if (threadId != NULL) {
*threadId = (android_thread_id_t)thread; // XXX: this is not portable
}
@@ -332,10 +335,17 @@ int androidSetThreadPriority(pid_t tid, int pri)
pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
if (gDoSchedulingGroup) {
+ // set_sched_policy does not support tid == 0
+ int policy_tid;
+ if (tid == 0) {
+ policy_tid = androidGetTid();
+ } else {
+ policy_tid = tid;
+ }
if (pri >= ANDROID_PRIORITY_BACKGROUND) {
- rc = set_sched_policy(tid, SP_BACKGROUND);
+ rc = set_sched_policy(policy_tid, SP_BACKGROUND);
} else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
- rc = set_sched_policy(tid, SP_FOREGROUND);
+ rc = set_sched_policy(policy_tid, SP_FOREGROUND);
}
}
@@ -718,7 +728,6 @@ status_t Thread::run(const char* name, int32_t priority, size_t stack)
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
}
- // The new thread wakes up at _threadLoop, but immediately blocks on mLock
if (res == false) {
mStatus = UNKNOWN_ERROR; // something happened!
@@ -742,11 +751,6 @@ int Thread::_threadLoop(void* user)
{
Thread* const self = static_cast<Thread*>(user);
- // force a memory barrier before reading any fields, in particular mHoldSelf
- {
- Mutex::Autolock _l(self->mLock);
- }
-
sp<Thread> strong(self->mHoldSelf);
wp<Thread> weak(strong);
self->mHoldSelf.clear();
@@ -816,6 +820,7 @@ void Thread::requestExit()
status_t Thread::requestExitAndWait()
{
+ Mutex::Autolock _l(mLock);
if (mThread == getThreadId()) {
LOGW(
"Thread (this=%p): don't call waitForExit() from this "
@@ -825,9 +830,8 @@ status_t Thread::requestExitAndWait()
return WOULD_BLOCK;
}
- requestExit();
+ mExitPending = true;
- Mutex::Autolock _l(mLock);
while (mRunning == true) {
mThreadExitedCondition.wait(mLock);
}
diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk
index 72d48769a589..87ad98eaad77 100644
--- a/libs/utils/tests/Android.mk
+++ b/libs/utils/tests/Android.mk
@@ -6,6 +6,7 @@ ifneq ($(TARGET_SIMULATOR),true)
# Build the unit tests.
test_src_files := \
+ BlobCache_test.cpp \
ObbFile_test.cpp \
Looper_test.cpp \
String8_test.cpp \
diff --git a/libs/utils/tests/BlobCache_test.cpp b/libs/utils/tests/BlobCache_test.cpp
new file mode 100644
index 000000000000..653ea5e91cde
--- /dev/null
+++ b/libs/utils/tests/BlobCache_test.cpp
@@ -0,0 +1,257 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <utils/BlobCache.h>
+
+namespace android {
+
+class BlobCacheTest : public ::testing::Test {
+protected:
+ enum {
+ MAX_KEY_SIZE = 6,
+ MAX_VALUE_SIZE = 8,
+ MAX_TOTAL_SIZE = 13,
+ };
+
+ virtual void SetUp() {
+ mBC = new BlobCache(MAX_KEY_SIZE, MAX_VALUE_SIZE, MAX_TOTAL_SIZE);
+ }
+
+ virtual void TearDown() {
+ mBC.clear();
+ }
+
+ sp<BlobCache> mBC;
+};
+
+TEST_F(BlobCacheTest, CacheSingleValueSucceeds) {
+ char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
+ ASSERT_EQ('e', buf[0]);
+ ASSERT_EQ('f', buf[1]);
+ ASSERT_EQ('g', buf[2]);
+ ASSERT_EQ('h', buf[3]);
+}
+
+TEST_F(BlobCacheTest, CacheTwoValuesSucceeds) {
+ char buf[2] = { 0xee, 0xee };
+ mBC->set("ab", 2, "cd", 2);
+ mBC->set("ef", 2, "gh", 2);
+ ASSERT_EQ(size_t(2), mBC->get("ab", 2, buf, 2));
+ ASSERT_EQ('c', buf[0]);
+ ASSERT_EQ('d', buf[1]);
+ ASSERT_EQ(size_t(2), mBC->get("ef", 2, buf, 2));
+ ASSERT_EQ('g', buf[0]);
+ ASSERT_EQ('h', buf[1]);
+}
+
+TEST_F(BlobCacheTest, GetOnlyWritesInsideBounds) {
+ char buf[6] = { 0xee, 0xee, 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf+1, 4));
+ ASSERT_EQ(0xee, buf[0]);
+ ASSERT_EQ('e', buf[1]);
+ ASSERT_EQ('f', buf[2]);
+ ASSERT_EQ('g', buf[3]);
+ ASSERT_EQ('h', buf[4]);
+ ASSERT_EQ(0xee, buf[5]);
+}
+
+TEST_F(BlobCacheTest, GetOnlyWritesIfBufferIsLargeEnough) {
+ char buf[3] = { 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 3));
+ ASSERT_EQ(0xee, buf[0]);
+ ASSERT_EQ(0xee, buf[1]);
+ ASSERT_EQ(0xee, buf[2]);
+}
+
+TEST_F(BlobCacheTest, GetDoesntAccessNullBuffer) {
+ mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, NULL, 0));
+}
+
+TEST_F(BlobCacheTest, MultipleSetsCacheLatestValue) {
+ char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+ mBC->set("abcd", 4, "ijkl", 4);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
+ ASSERT_EQ('i', buf[0]);
+ ASSERT_EQ('j', buf[1]);
+ ASSERT_EQ('k', buf[2]);
+ ASSERT_EQ('l', buf[3]);
+}
+
+TEST_F(BlobCacheTest, SecondSetKeepsFirstValueIfTooLarge) {
+ char buf[MAX_VALUE_SIZE+1] = { 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+ mBC->set("abcd", 4, buf, MAX_VALUE_SIZE+1);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
+ ASSERT_EQ('e', buf[0]);
+ ASSERT_EQ('f', buf[1]);
+ ASSERT_EQ('g', buf[2]);
+ ASSERT_EQ('h', buf[3]);
+}
+
+TEST_F(BlobCacheTest, DoesntCacheIfKeyIsTooBig) {
+ char key[MAX_KEY_SIZE+1];
+ char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ for (int i = 0; i < MAX_KEY_SIZE+1; i++) {
+ key[i] = 'a';
+ }
+ mBC->set(key, MAX_KEY_SIZE+1, "bbbb", 4);
+ ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE+1, buf, 4));
+ ASSERT_EQ(0xee, buf[0]);
+ ASSERT_EQ(0xee, buf[1]);
+ ASSERT_EQ(0xee, buf[2]);
+ ASSERT_EQ(0xee, buf[3]);
+}
+
+TEST_F(BlobCacheTest, DoesntCacheIfValueIsTooBig) {
+ char buf[MAX_VALUE_SIZE+1];
+ for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
+ buf[i] = 'b';
+ }
+ mBC->set("abcd", 4, buf, MAX_VALUE_SIZE+1);
+ for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
+ buf[i] = 0xee;
+ }
+ ASSERT_EQ(size_t(0), mBC->get("abcd", 4, buf, MAX_VALUE_SIZE+1));
+ for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
+ SCOPED_TRACE(i);
+ ASSERT_EQ(0xee, buf[i]);
+ }
+}
+
+TEST_F(BlobCacheTest, DoesntCacheIfKeyValuePairIsTooBig) {
+ // Check a testing assumptions
+ ASSERT_TRUE(MAX_TOTAL_SIZE < MAX_KEY_SIZE + MAX_VALUE_SIZE);
+ ASSERT_TRUE(MAX_KEY_SIZE < MAX_TOTAL_SIZE);
+
+ enum { bufSize = MAX_TOTAL_SIZE - MAX_KEY_SIZE + 1 };
+
+ char key[MAX_KEY_SIZE];
+ char buf[bufSize];
+ for (int i = 0; i < MAX_KEY_SIZE; i++) {
+ key[i] = 'a';
+ }
+ for (int i = 0; i < bufSize; i++) {
+ buf[i] = 'b';
+ }
+
+ mBC->set(key, MAX_KEY_SIZE, buf, MAX_VALUE_SIZE);
+ ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE, NULL, 0));
+}
+
+TEST_F(BlobCacheTest, CacheMaxKeySizeSucceeds) {
+ char key[MAX_KEY_SIZE];
+ char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ for (int i = 0; i < MAX_KEY_SIZE; i++) {
+ key[i] = 'a';
+ }
+ mBC->set(key, MAX_KEY_SIZE, "wxyz", 4);
+ ASSERT_EQ(size_t(4), mBC->get(key, MAX_KEY_SIZE, buf, 4));
+ ASSERT_EQ('w', buf[0]);
+ ASSERT_EQ('x', buf[1]);
+ ASSERT_EQ('y', buf[2]);
+ ASSERT_EQ('z', buf[3]);
+}
+
+TEST_F(BlobCacheTest, CacheMaxValueSizeSucceeds) {
+ char buf[MAX_VALUE_SIZE];
+ for (int i = 0; i < MAX_VALUE_SIZE; i++) {
+ buf[i] = 'b';
+ }
+ mBC->set("abcd", 4, buf, MAX_VALUE_SIZE);
+ for (int i = 0; i < MAX_VALUE_SIZE; i++) {
+ buf[i] = 0xee;
+ }
+ ASSERT_EQ(size_t(MAX_VALUE_SIZE), mBC->get("abcd", 4, buf,
+ MAX_VALUE_SIZE));
+ for (int i = 0; i < MAX_VALUE_SIZE; i++) {
+ SCOPED_TRACE(i);
+ ASSERT_EQ('b', buf[i]);
+ }
+}
+
+TEST_F(BlobCacheTest, CacheMaxKeyValuePairSizeSucceeds) {
+ // Check a testing assumption
+ ASSERT_TRUE(MAX_KEY_SIZE < MAX_TOTAL_SIZE);
+
+ enum { bufSize = MAX_TOTAL_SIZE - MAX_KEY_SIZE };
+
+ char key[MAX_KEY_SIZE];
+ char buf[bufSize];
+ for (int i = 0; i < MAX_KEY_SIZE; i++) {
+ key[i] = 'a';
+ }
+ for (int i = 0; i < bufSize; i++) {
+ buf[i] = 'b';
+ }
+
+ mBC->set(key, MAX_KEY_SIZE, buf, bufSize);
+ ASSERT_EQ(size_t(bufSize), mBC->get(key, MAX_KEY_SIZE, NULL, 0));
+}
+
+TEST_F(BlobCacheTest, CacheMinKeyAndValueSizeSucceeds) {
+ char buf[1] = { 0xee };
+ mBC->set("x", 1, "y", 1);
+ ASSERT_EQ(size_t(1), mBC->get("x", 1, buf, 1));
+ ASSERT_EQ('y', buf[0]);
+}
+
+TEST_F(BlobCacheTest, CacheSizeDoesntExceedTotalLimit) {
+ for (int i = 0; i < 256; i++) {
+ uint8_t k = i;
+ mBC->set(&k, 1, "x", 1);
+ }
+ int numCached = 0;
+ for (int i = 0; i < 256; i++) {
+ uint8_t k = i;
+ if (mBC->get(&k, 1, NULL, 0) == 1) {
+ numCached++;
+ }
+ }
+ ASSERT_GE(MAX_TOTAL_SIZE / 2, numCached);
+}
+
+TEST_F(BlobCacheTest, ExceedingTotalLimitHalvesCacheSize) {
+ // Fill up the entire cache with 1 char key/value pairs.
+ const int maxEntries = MAX_TOTAL_SIZE / 2;
+ for (int i = 0; i < maxEntries; i++) {
+ uint8_t k = i;
+ mBC->set(&k, 1, "x", 1);
+ }
+ // Insert one more entry, causing a cache overflow.
+ {
+ uint8_t k = maxEntries;
+ mBC->set(&k, 1, "x", 1);
+ }
+ // Count the number of entries in the cache.
+ int numCached = 0;
+ for (int i = 0; i < maxEntries+1; i++) {
+ uint8_t k = i;
+ if (mBC->get(&k, 1, NULL, 0) == 1) {
+ numCached++;
+ }
+ }
+ ASSERT_EQ(maxEntries/2 + 1, numCached);
+}
+
+} // namespace android
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 8f7dd6079e4a..255773067919 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -30,6 +30,7 @@ import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.graphics.Bitmap;
+import android.graphics.ParcelSurfaceTexture;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
@@ -51,6 +52,7 @@ import java.lang.ref.WeakReference;
* <li><a href="#StateDiagram">State Diagram</a>
* <li><a href="#Valid_and_Invalid_States">Valid and Invalid States</a>
* <li><a href="#Permissions">Permissions</a>
+ * <li><a href="#Callbacks">Register informational and error callbacks</a>
* </ol>
*
* <a name="StateDiagram"></a>
@@ -458,6 +460,25 @@ import java.lang.ref.WeakReference;
* android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
* element.
*
+ * <a name="Callbacks"></a>
+ * <h3>Callbacks</h3>
+ * <p>Applications may want to register for informational and error
+ * events in order to be informed of some internal state update and
+ * possible runtime errors during playback or streaming. Registration for
+ * these events is done by properly setting the appropriate listeners (via calls
+ * to
+ * {@link #setOnPreparedListener(OnPreparedListener)}setOnPreparedListener,
+ * {@link #setOnVideoSizeChangedListener(OnVideoSizeChangedListener)}setOnVideoSizeChangedListener,
+ * {@link #setOnSeekCompleteListener(OnSeekCompleteListener)}setOnSeekCompleteListener,
+ * {@link #setOnCompletionListener(OnCompletionListener)}setOnCompletionListener,
+ * {@link #setOnBufferingUpdateListener(OnBufferingUpdateListener)}setOnBufferingUpdateListener,
+ * {@link #setOnInfoListener(OnInfoListener)}setOnInfoListener,
+ * {@link #setOnErrorListener(OnErrorListener)}setOnErrorListener, etc).
+ * In order to receive the respective callback
+ * associated with these listeners, applications are required to create
+ * MediaPlayer objects on a thread with its own Looper running (main UI
+ * thread by default has a Looper running).
+ *
*/
public class MediaPlayer
{
@@ -509,7 +530,7 @@ public class MediaPlayer
private int mListenerContext; // accessed by native methods
private Surface mSurface; // accessed by native methods
private SurfaceHolder mSurfaceHolder;
- private SurfaceTexture mSurfaceTexture; // accessed by native methods
+ private ParcelSurfaceTexture mParcelSurfaceTexture; // accessed by native methods
private EventHandler mEventHandler;
private PowerManager.WakeLock mWakeLock = null;
private boolean mScreenOnWhilePlaying;
@@ -541,7 +562,7 @@ public class MediaPlayer
/*
* Update the MediaPlayer ISurface and ISurfaceTexture.
- * Call after updating mSurface and/or mSurfaceTexture.
+ * Call after updating mSurface and/or mParcelSurfaceTexture.
*/
private native void _setVideoSurfaceOrSurfaceTexture();
@@ -607,7 +628,7 @@ public class MediaPlayer
} else {
mSurface = null;
}
- mSurfaceTexture = null;
+ mParcelSurfaceTexture = null;
_setVideoSurfaceOrSurfaceTexture();
updateSurfaceScreenOn();
}
@@ -630,12 +651,32 @@ public class MediaPlayer
* program.
*/
public void setTexture(SurfaceTexture st) {
- if (mScreenOnWhilePlaying && st != null && mSurfaceTexture == null) {
+ ParcelSurfaceTexture pst = null;
+ if (st != null) {
+ pst = ParcelSurfaceTexture.fromSurfaceTexture(st);
+ }
+ setParcelSurfaceTexture(pst);
+ }
+
+ /**
+ * Sets the {@link ParcelSurfaceTexture} to be used as the sink for the video portion of
+ * the media. This is similar to {@link #setTexture(SurfaceTexture)}, but supports using
+ * a {@link ParcelSurfaceTexture} to transport the texture to be used via Binder. Setting
+ * a parceled surface texture will un-set any surface or surface texture that was previously
+ * set. See {@link #setTexture(SurfaceTexture)} for more details.
+ *
+ * @param pst The {@link ParcelSurfaceTexture} to be used as the sink for
+ * the video portion of the media.
+ *
+ * @hide Pending review by API council.
+ */
+ public void setParcelSurfaceTexture(ParcelSurfaceTexture pst) {
+ if (mScreenOnWhilePlaying && pst != null && mParcelSurfaceTexture == null) {
Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for SurfaceTexture");
}
mSurfaceHolder = null;
mSurface = null;
- mSurfaceTexture = st;
+ mParcelSurfaceTexture = pst;
_setVideoSurfaceOrSurfaceTexture();
updateSurfaceScreenOn();
}
@@ -962,7 +1003,7 @@ public class MediaPlayer
*/
public void setScreenOnWhilePlaying(boolean screenOn) {
if (mScreenOnWhilePlaying != screenOn) {
- if (screenOn && mSurfaceTexture != null) {
+ if (screenOn && mParcelSurfaceTexture != null) {
Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for SurfaceTexture");
}
mScreenOnWhilePlaying = screenOn;
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 1478a6dddf58..dd4511163c9e 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -51,6 +51,16 @@ import java.lang.ref.WeakReference;
* recorder.release(); // Now the object cannot be reused
* </pre>
*
+ * <p>Applications may want to register for informational and error
+ * events in order to be informed of some internal update and possible
+ * runtime errors during recording. Registration for such events is
+ * done by setting the appropriate listeners (via calls
+ * (to {@link #setOnInfoListener(OnInfoListener)}setOnInfoListener and/or
+ * {@link #setOnErrorListener(OnErrorListener)}setOnErrorListener).
+ * In order to receive the respective callback associated with these listeners,
+ * applications are required to create MediaRecorder objects on threads with a
+ * Looper running (the main UI thread by default already has a Looper running).
+ *
* <p>See the <a href="{@docRoot}guide/topics/media/index.html">Audio and Video</a>
* documentation for additional help with using MediaRecorder.
* <p>Note: Currently, MediaRecorder does not work on the emulator.
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index b03aa38be87c..5663683538cb 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -30,6 +30,7 @@
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/android_graphics_ParcelSurfaceTexture.h"
#include "utils/Errors.h" // for status_t
#include "utils/KeyedVector.h"
#include "utils/String8.h"
@@ -37,7 +38,6 @@
#include "android_util_Binder.h"
#include <binder/Parcel.h>
-#include <gui/SurfaceTexture.h>
#include <gui/ISurfaceTexture.h>
#include <surfaceflinger/Surface.h>
#include <binder/IPCThreadState.h>
@@ -52,11 +52,9 @@ using namespace android;
struct fields_t {
jfieldID context;
jfieldID surface;
- jfieldID surfaceTexture;
+ jfieldID parcelSurfaceTexture;
/* actually in android.view.Surface XXX */
jfieldID surface_native;
- // actually in android.graphics.SurfaceTexture
- jfieldID surfaceTexture_native;
jmethodID post_event;
};
@@ -130,13 +128,6 @@ static Surface* get_surface(JNIEnv* env, jobject clazz)
return (Surface*)env->GetIntField(clazz, fields.surface_native);
}
-sp<ISurfaceTexture> getSurfaceTexture(JNIEnv* env, jobject clazz)
-{
- sp<ISurfaceTexture> surfaceTexture(
- (ISurfaceTexture*)env->GetIntField(clazz, fields.surfaceTexture_native));
- return surfaceTexture;
-}
-
static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
{
Mutex::Autolock l(sLock);
@@ -257,8 +248,8 @@ static void setVideoSurfaceOrSurfaceTexture(
const sp<MediaPlayer>& mp, JNIEnv *env, jobject thiz, const char *prefix)
{
// The Java MediaPlayer class makes sure that at most one of mSurface and
- // mSurfaceTexture is non-null. But just in case, we give priority to
- // mSurface over mSurfaceTexture.
+ // mParcelSurfaceTexture is non-null. But just in case, we give priority to
+ // mSurface over mParcelSurfaceTexture.
jobject surface = env->GetObjectField(thiz, fields.surface);
if (surface != NULL) {
sp<Surface> native_surface(get_surface(env, surface));
@@ -266,10 +257,10 @@ static void setVideoSurfaceOrSurfaceTexture(
native_surface.get(), native_surface->getIdentity());
mp->setVideoSurface(native_surface);
} else {
- jobject surfaceTexture = env->GetObjectField(thiz, fields.surfaceTexture);
- if (surfaceTexture != NULL) {
+ jobject parcelSurfaceTexture = env->GetObjectField(thiz, fields.parcelSurfaceTexture);
+ if (parcelSurfaceTexture != NULL) {
sp<ISurfaceTexture> native_surfaceTexture(
- getSurfaceTexture(env, surfaceTexture));
+ ParcelSurfaceTexture_getISurfaceTexture(env, parcelSurfaceTexture));
LOGV("%s: texture=%p", prefix, native_surfaceTexture.get());
mp->setVideoSurfaceTexture(native_surfaceTexture);
}
@@ -610,23 +601,11 @@ android_media_MediaPlayer_native_init(JNIEnv *env)
return;
}
- fields.surfaceTexture = env->GetFieldID(clazz, "mSurfaceTexture",
- "Landroid/graphics/SurfaceTexture;");
- if (fields.surfaceTexture == NULL) {
- return;
- }
-
- jclass surfaceTexture = env->FindClass("android/graphics/SurfaceTexture");
- if (surfaceTexture == NULL) {
+ fields.parcelSurfaceTexture = env->GetFieldID(clazz, "mParcelSurfaceTexture",
+ "Landroid/graphics/ParcelSurfaceTexture;");
+ if (fields.parcelSurfaceTexture == NULL) {
return;
}
-
- fields.surfaceTexture_native = env->GetFieldID(surfaceTexture,
- ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I");
- if (fields.surfaceTexture_native == NULL) {
- return;
- }
-
}
static void
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 6b4391bac657..37fe1823b74c 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -40,7 +40,7 @@
#include <cutils/bitops.h>
#include <system/audio.h>
-#include <hardware/audio_policy.h>
+#include <system/audio_policy.h>
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 3689557bbf92..cc2257477071 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -486,7 +486,8 @@ bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) {
if (mForceRead) {
LOGV("dataCallbackTimestamp timelapse: forced read");
mForceRead = false;
- *timestampUs = mLastFrameTimestampUs;
+ *timestampUs =
+ mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
return false;
}
}
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index a953487eb4aa..28add18333c7 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -128,7 +128,6 @@ private:
size_t mNumStssTableEntries;
List<int32_t> mStssTableEntries;
- size_t mNumSttsTableEntries;
struct SttsTableEntry {
SttsTableEntry(uint32_t count, uint32_t duration)
@@ -137,8 +136,20 @@ private:
uint32_t sampleCount;
uint32_t sampleDuration; // time scale based
};
+ size_t mNumSttsTableEntries;
List<SttsTableEntry> mSttsTableEntries;
+ struct CttsTableEntry {
+ CttsTableEntry(uint32_t count, int32_t timescaledDur)
+ : sampleCount(count), sampleDuration(timescaledDur) {}
+
+ uint32_t sampleCount;
+ int32_t sampleDuration; // time scale based
+ };
+ bool mHasNegativeCttsDeltaDuration;
+ size_t mNumCttsTableEntries;
+ List<CttsTableEntry> mCttsTableEntries;
+
// Sequence parameter set or picture parameter set
struct AVCParamSet {
AVCParamSet(uint16_t length, const uint8_t *data)
@@ -219,6 +230,7 @@ private:
// Duration is time scale based
void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
+ void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
void sendTrackSummary(bool hasMultipleTracks);
// Write the boxes
@@ -227,6 +239,7 @@ private:
void writeStszBox();
void writeStssBox();
void writeSttsBox();
+ void writeCttsBox();
void writeD263Box();
void writePaspBox();
void writeAvccBox();
@@ -1147,6 +1160,7 @@ void MPEG4Writer::Track::updateTrackSizeEstimate() {
mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 + // stsc box size
mNumStssTableEntries * 4 + // stss box size
mNumSttsTableEntries * 8 + // stts box size
+ mNumCttsTableEntries * 8 + // ctts box size
stcoBoxSizeBytes + // stco box size
stszBoxSizeBytes; // stsz box size
}
@@ -1173,6 +1187,20 @@ void MPEG4Writer::Track::addOneSttsTableEntry(
++mNumSttsTableEntries;
}
+void MPEG4Writer::Track::addOneCttsTableEntry(
+ size_t sampleCount, int32_t duration) {
+
+ if (mIsAudio) {
+ return;
+ }
+ if (duration < 0 && !mHasNegativeCttsDeltaDuration) {
+ mHasNegativeCttsDeltaDuration = true;
+ }
+ CttsTableEntry cttsEntry(sampleCount, duration);
+ mCttsTableEntries.push_back(cttsEntry);
+ ++mNumCttsTableEntries;
+}
+
void MPEG4Writer::Track::addChunkOffset(off64_t offset) {
++mNumStcoTableEntries;
mChunkOffsets.push_back(offset);
@@ -1483,6 +1511,7 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
mNumStssTableEntries = 0;
mNumStscTableEntries = 0;
mNumSttsTableEntries = 0;
+ mNumCttsTableEntries = 0;
mMdatSizeBytes = 0;
mIsMediaTimeAdjustmentOn = false;
mPrevMediaTimeAdjustTimestampUs = 0;
@@ -1491,6 +1520,7 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
mTotalDriftTimeToAdjustUs = 0;
mPrevTotalAccumDriftTimeUs = 0;
mMaxChunkDurationUs = 0;
+ mHasNegativeCttsDeltaDuration = false;
pthread_create(&mThread, &attr, ThreadWrapper, this);
pthread_attr_destroy(&attr);
@@ -1932,21 +1962,26 @@ status_t MPEG4Writer::Track::threadEntry() {
int64_t chunkTimestampUs = 0;
int32_t nChunks = 0;
int32_t nZeroLengthFrames = 0;
- int64_t lastTimestampUs = 0; // Previous sample time stamp in ms
- int64_t lastDurationUs = 0; // Between the previous two samples in ms
- int64_t currDurationTicks = 0; // Timescale based ticks
- int64_t lastDurationTicks = 0; // Timescale based ticks
- int32_t sampleCount = 1; // Sample count in the current stts table entry
- uint32_t previousSampleSize = 0; // Size of the previous sample
+ int64_t lastTimestampUs = 0; // Previous sample time stamp
+ int64_t lastCttsTimeUs = 0; // Previous sample time stamp
+ int64_t lastDurationUs = 0; // Between the previous two samples
+ int64_t currDurationTicks = 0; // Timescale based ticks
+ int64_t lastDurationTicks = 0; // Timescale based ticks
+ int32_t sampleCount = 1; // Sample count in the current stts table entry
+ int64_t currCttsDurTicks = 0; // Timescale based ticks
+ int64_t lastCttsDurTicks = 0; // Timescale based ticks
+ int32_t cttsSampleCount = 1; // Sample count in the current ctts table entry
+ uint32_t previousSampleSize = 0; // Size of the previous sample
int64_t previousPausedDurationUs = 0;
- int64_t timestampUs;
+ int64_t timestampUs = 0;
+ int64_t cttsDeltaTimeUs = 0;
if (mIsAudio) {
prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
} else {
prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
}
- setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
+ androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
sp<MetaData> meta_data;
@@ -2063,7 +2098,6 @@ status_t MPEG4Writer::Track::threadEntry() {
*
*/
CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
- LOGV("%s timestampUs: %lld", mIsAudio? "Audio": "Video", timestampUs);
////////////////////////////////////////////////////////////////////////////////
if (mNumSamples == 0) {
@@ -2084,6 +2118,24 @@ status_t MPEG4Writer::Track::threadEntry() {
timestampUs -= previousPausedDurationUs;
CHECK(timestampUs >= 0);
+ if (!mIsAudio) {
+ /*
+ * Composition time: timestampUs
+ * Decoding time: decodingTimeUs
+ * Composition time delta = composition time - decoding time
+ *
+ * We save picture decoding time stamp delta in stts table entries,
+ * and composition time delta duration in ctts table entries.
+ */
+ int64_t decodingTimeUs;
+ CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
+ decodingTimeUs -= previousPausedDurationUs;
+ int64_t timeUs = decodingTimeUs;
+ cttsDeltaTimeUs = timestampUs - decodingTimeUs;
+ timestampUs = decodingTimeUs;
+ LOGV("decoding time: %lld and ctts delta time: %lld",
+ timestampUs, cttsDeltaTimeUs);
+ }
// Media time adjustment for real-time applications
if (mIsRealTimeRecording) {
@@ -2139,6 +2191,18 @@ status_t MPEG4Writer::Track::threadEntry() {
} else {
++sampleCount;
}
+
+ if (!mIsAudio) {
+ currCttsDurTicks =
+ ((cttsDeltaTimeUs * mTimeScale + 500000LL) / 1000000LL -
+ (lastCttsTimeUs * mTimeScale + 500000LL) / 1000000LL);
+ if (currCttsDurTicks != lastCttsDurTicks) {
+ addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
+ cttsSampleCount = 1;
+ } else {
+ ++cttsSampleCount;
+ }
+ }
}
if (mSamplesHaveSameSize) {
if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
@@ -2152,6 +2216,11 @@ status_t MPEG4Writer::Track::threadEntry() {
lastDurationTicks = currDurationTicks;
lastTimestampUs = timestampUs;
+ if (!mIsAudio) {
+ lastCttsDurTicks = currCttsDurTicks;
+ lastCttsTimeUs = cttsDeltaTimeUs;
+ }
+
if (isSync != 0) {
addOneStssTableEntry(mNumSamples);
}
@@ -2221,8 +2290,10 @@ status_t MPEG4Writer::Track::threadEntry() {
if (mNumSamples == 1) {
lastDurationUs = 0; // A single sample's duration
lastDurationTicks = 0;
+ lastCttsDurTicks = 0;
} else {
++sampleCount; // Count for the last sample
+ ++cttsSampleCount;
}
if (mNumSamples <= 2) {
@@ -2234,6 +2305,7 @@ status_t MPEG4Writer::Track::threadEntry() {
addOneSttsTableEntry(sampleCount, lastDurationTicks);
}
+ addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
mTrackDurationUs += lastDurationUs;
mReachedEOS = true;
@@ -2432,6 +2504,7 @@ void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
}
mOwner->endBox(); // stsd
writeSttsBox();
+ writeCttsBox();
if (!mIsAudio) {
writeStssBox();
}
@@ -2782,13 +2855,49 @@ void MPEG4Writer::Track::writeSttsBox() {
int32_t dur = (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL;
mOwner->writeInt32(dur + it->sampleDuration);
+ int64_t totalCount = 1;
while (++it != mSttsTableEntries.end()) {
mOwner->writeInt32(it->sampleCount);
mOwner->writeInt32(it->sampleDuration);
+ totalCount += it->sampleCount;
}
+ CHECK(totalCount == mNumSamples);
mOwner->endBox(); // stts
}
+void MPEG4Writer::Track::writeCttsBox() {
+ if (mIsAudio) { // ctts is not for audio
+ return;
+ }
+
+ // Do not write ctts box when there is no need to have it.
+ if ((mNumCttsTableEntries == 1 &&
+ mCttsTableEntries.begin()->sampleDuration == 0) ||
+ mNumCttsTableEntries == 0) {
+ return;
+ }
+
+ LOGV("ctts box has %d entries", mNumCttsTableEntries);
+
+ mOwner->beginBox("ctts");
+ if (mHasNegativeCttsDeltaDuration) {
+ mOwner->writeInt32(0x00010000); // version=1, flags=0
+ } else {
+ mOwner->writeInt32(0); // version=0, flags=0
+ }
+ mOwner->writeInt32(mNumCttsTableEntries);
+
+ int64_t totalCount = 0;
+ for (List<CttsTableEntry>::iterator it = mCttsTableEntries.begin();
+ it != mCttsTableEntries.end(); ++it) {
+ mOwner->writeInt32(it->sampleCount);
+ mOwner->writeInt32(it->sampleDuration);
+ totalCount += it->sampleCount;
+ }
+ CHECK(totalCount == mNumSamples);
+ mOwner->endBox(); // ctts
+}
+
void MPEG4Writer::Track::writeStssBox() {
mOwner->beginBox("stss");
mOwner->writeInt32(0); // version=0, flags=0
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 72d0d085e41d..c4fcc797cccb 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1981,6 +1981,20 @@ OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
return bufInfo;
}
+int64_t OMXCodec::retrieveDecodingTimeUs(bool isCodecSpecific) {
+ CHECK(mIsEncoder);
+ CHECK(!mDecodingTimeList.empty());
+ List<int64_t>::iterator it = mDecodingTimeList.begin();
+ int64_t timeUs = *it;
+
+ // If the output buffer is codec specific configuration,
+ // do not remove the decoding time from the list.
+ if (!isCodecSpecific) {
+ mDecodingTimeList.erase(it);
+ }
+ return timeUs;
+}
+
void OMXCodec::on_message(const omx_message &msg) {
if (mState == ERROR) {
LOGW("Dropping OMX message - we're in ERROR state.");
@@ -2128,14 +2142,21 @@ void OMXCodec::on_message(const omx_message &msg) {
if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
}
+ bool isCodecSpecific = false;
if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_CODECCONFIG) {
buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
+ isCodecSpecific = true;
}
if (isGraphicBuffer || mQuirks & kOutputBuffersAreUnreadable) {
buffer->meta_data()->setInt32(kKeyIsUnreadable, true);
}
+ if (mIsEncoder) {
+ int64_t decodingTimeUs = retrieveDecodingTimeUs(isCodecSpecific);
+ buffer->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
+ }
+
buffer->meta_data()->setPointer(
kKeyPlatformPrivate,
msg.u.extended_buffer_data.platform_private);
@@ -2938,6 +2959,9 @@ bool OMXCodec::drainInputBuffer(BufferInfo *info) {
int64_t lastBufferTimeUs;
CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
CHECK(lastBufferTimeUs >= 0);
+ if (mIsEncoder) {
+ mDecodingTimeList.push_back(lastBufferTimeUs);
+ }
if (offset == 0) {
timestampUs = lastBufferTimeUs;
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
index 5a453e96a499..a08eb7b371be 100644
--- a/media/libstagefright/TimedEventQueue.cpp
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -210,8 +210,7 @@ void *TimedEventQueue::ThreadWrapper(void *me) {
vm->AttachCurrentThread(&env, NULL);
#endif
- setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_FOREGROUND);
- set_sched_policy(androidGetTid(), SP_FOREGROUND);
+ androidSetThreadPriority(0, ANDROID_PRIORITY_FOREGROUND);
static_cast<TimedEventQueue *>(me)->threadEntry();
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 4b1c3a7ed12f..14968e880549 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -116,7 +116,7 @@ void *OMX::CallbackDispatcher::ThreadWrapper(void *me) {
}
void OMX::CallbackDispatcher::threadEntry() {
- setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
+ androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
prctl(PR_SET_NAME, (unsigned long)"OMXCallbackDisp", 0, 0, 0);
for (;;) {
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 2e2768f92bc0..b349030b524d 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -77,8 +77,6 @@
<!-- Default for Settings.System.VIBRATE_IN_SILENT -->
<bool name="def_vibrate_in_silent">true</bool>
- <bool name="def_use_ptp_interface">false</bool>
-
<!-- Default for Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION -->
<bool name="def_accessibility_script_injection">false</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 9cbf704c8511..47ab150627e8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1209,9 +1209,6 @@ public class DatabaseHelper extends SQLiteOpenHelper {
loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT,
R.bool.def_vibrate_in_silent);
- loadBooleanSetting(stmt, Settings.System.USE_PTP_INTERFACE,
- R.bool.def_use_ptp_interface);
-
// Set notification volume to follow ringer volume by default
loadBooleanSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME,
R.bool.def_notifications_use_ring_volume);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 3d15a1d18fc5..687de0750efd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -349,7 +349,8 @@ public class PhoneStatusBar extends StatusBar {
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
lp.setTitle("NavigationBar");
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 0178395be45f..08f9ebb0d8fd 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -587,7 +587,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen,
case SimMissing:
// text
mStatusView.setCarrierText(R.string.lockscreen_missing_sim_message_short);
- mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions);
+ mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions_long);
// layout
mScreenLocked.setVisibility(View.VISIBLE);
@@ -710,11 +710,17 @@ class LockScreen extends LinearLayout implements KeyguardScreen,
if (mEnergyWave != null) {
mEnergyWave.reset();
}
+ if (mMultiWaveView != null) {
+ mMultiWaveView.reset(false);
+ }
}
/** {@inheritDoc} */
public void onResume() {
resetStatusInfo(mUpdateMonitor);
+ if (mMultiWaveView != null) {
+ mMultiWaveView.ping();
+ }
}
/** {@inheritDoc} */
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d4a8ddb2f3da..44df5b552df0 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -44,7 +44,7 @@
#include <private/media/AudioEffectShared.h>
#include <system/audio.h>
-#include <hardware/audio_hal.h>
+#include <hardware/audio.h>
#include "AudioMixer.h"
#include "AudioFlinger.h"
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index f3371bffd6af..1fad9874fbaf 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -39,7 +39,7 @@
#include <binder/MemoryDealer.h>
#include <system/audio.h>
-#include <hardware/audio_hal.h>
+#include <hardware/audio.h>
#include "AudioBufferProvider.h"
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index dd91788633ba..47ca3a03c7dc 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -36,8 +36,8 @@
#include <hardware/hardware.h>
#include <system/audio.h>
+#include <system/audio_policy.h>
#include <hardware/audio_policy.h>
-#include <hardware/audio_policy_hal.h>
namespace android {
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index d9b5ada5671c..b8301209cd2a 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -23,8 +23,8 @@
#include <binder/BinderService.h>
#include <system/audio.h>
+#include <system/audio_policy.h>
#include <hardware/audio_policy.h>
-#include <hardware/audio_policy_hal.h>
namespace android {
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 29add52c8af2..6e803a441356 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -192,6 +192,7 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
outAxisInfo->maxValue = info.maximum;
outAxisInfo->flat = info.flat;
outAxisInfo->fuzz = info.fuzz;
+ outAxisInfo->resolution = info.resolution;
}
return OK;
}
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 558959b1a968..abe1318206ff 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -34,39 +34,6 @@
#include <linux/input.h>
-/* These constants are not defined in linux/input.h in the version of the kernel
- * headers currently provided with Bionic. */
-
-#define EVIOCGPROP(len) _IOC(_IOC_READ, 'E', 0x09, len)
-
-#define INPUT_PROP_POINTER 0x00
-#define INPUT_PROP_DIRECT 0x01
-#define INPUT_PROP_BUTTONPAD 0x02
-#define INPUT_PROP_SEMI_MT 0x03
-#define INPUT_PROP_MAX 0x1f
-#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
-
-#define ABS_MT_SLOT 0x2f
-#define ABS_MT_TOUCH_MAJOR 0x30
-#define ABS_MT_TOUCH_MINOR 0x31
-#define ABS_MT_WIDTH_MAJOR 0x32
-#define ABS_MT_WIDTH_MINOR 0x33
-#define ABS_MT_ORIENTATION 0x34
-#define ABS_MT_POSITION_X 0x35
-#define ABS_MT_POSITION_Y 0x36
-#define ABS_MT_TOOL_TYPE 0x37
-#define ABS_MT_BLOB_ID 0x38
-#define ABS_MT_TRACKING_ID 0x39
-#define ABS_MT_PRESSURE 0x3a
-#define ABS_MT_DISTANCE 0x3b
-
-#define MT_TOOL_FINGER 0
-#define MT_TOOL_PEN 1
-
-#define SYN_MT_REPORT 2
-#define SYN_DROPPED 3
-
-
/* Convenience constants. */
#define BTN_FIRST 0x100 // first button scancode
@@ -97,6 +64,7 @@ struct RawAbsoluteAxisInfo {
int32_t maxValue; // maximum value
int32_t flat; // center flat position, eg. flat == 8 means center is between -8 and 8
int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
+ int32_t resolution; // resolution in units per mm or radians per mm
inline void clear() {
valid = false;
@@ -104,6 +72,7 @@ struct RawAbsoluteAxisInfo {
maxValue = 0;
flat = 0;
fuzz = 0;
+ resolution = 0;
}
};
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index eff65c2c6965..28df3fb46594 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -1412,6 +1412,50 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
injectionResult = INPUT_EVENT_INJECTION_FAILED;
goto Failed;
}
+
+ // Check whether touches should slip outside of the current foreground window.
+ if (maskedAction == AMOTION_EVENT_ACTION_MOVE
+ && entry->pointerCount == 1
+ && mTempTouchState.isSlippery()) {
+ const MotionSample* sample = &entry->firstSample;
+ int32_t x = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
+ int32_t y = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
+
+ const InputWindow* oldTouchedWindow = mTempTouchState.getFirstForegroundWindow();
+ const InputWindow* newTouchedWindow = findTouchedWindowAtLocked(x, y);
+ if (oldTouchedWindow != newTouchedWindow && newTouchedWindow) {
+#if DEBUG_FOCUS
+ LOGD("Touch is slipping out of window %s into window %s.",
+ oldTouchedWindow->name.string(), newTouchedWindow->name.string());
+#endif
+ // Make a slippery exit from the old window.
+ mTempTouchState.addOrUpdateWindow(oldTouchedWindow,
+ InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
+
+ // Make a slippery entrance into the new window.
+ if (newTouchedWindow->supportsSplitTouch()) {
+ isSplit = true;
+ }
+
+ int32_t targetFlags = InputTarget::FLAG_FOREGROUND
+ | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER;
+ if (isSplit) {
+ targetFlags |= InputTarget::FLAG_SPLIT;
+ }
+ if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
+ targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+ }
+
+ BitSet32 pointerIds;
+ if (isSplit) {
+ pointerIds.markBit(entry->pointerProperties[0].id);
+ }
+ mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
+
+ // Split the batch here so we send exactly one sample.
+ *outSplitBatchAfterSample = &entry->firstSample;
+ }
+ }
}
if (newHoverWindow != mLastHoverWindow) {
@@ -1884,6 +1928,10 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
resumeWithAppendedMotionSample, InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
resumeWithAppendedMotionSample, InputTarget::FLAG_DISPATCH_AS_IS);
+ enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
+ resumeWithAppendedMotionSample, InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
+ enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
+ resumeWithAppendedMotionSample, InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
// If the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.isEmpty()) {
@@ -1985,6 +2033,10 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
action = AMOTION_EVENT_ACTION_HOVER_EXIT;
} else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
action = AMOTION_EVENT_ACTION_HOVER_ENTER;
+ } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
+ action = AMOTION_EVENT_ACTION_CANCEL;
+ } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
+ action = AMOTION_EVENT_ACTION_DOWN;
}
if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
@@ -4386,6 +4438,9 @@ void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
TouchedWindow& touchedWindow = windows.editItemAt(i);
if (touchedWindow.window == window) {
touchedWindow.targetFlags |= targetFlags;
+ if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
+ touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
+ }
touchedWindow.pointerIds.value |= pointerIds.value;
return;
}
@@ -4403,7 +4458,8 @@ void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
for (size_t i = 0 ; i < windows.size(); ) {
TouchedWindow& window = windows.editItemAt(i);
- if (window.targetFlags & InputTarget::FLAG_DISPATCH_AS_IS) {
+ if (window.targetFlags & (InputTarget::FLAG_DISPATCH_AS_IS
+ | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
i += 1;
@@ -4413,15 +4469,32 @@ void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
}
}
-const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() {
+const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() const {
for (size_t i = 0; i < windows.size(); i++) {
- if (windows[i].targetFlags & InputTarget::FLAG_FOREGROUND) {
- return windows[i].window;
+ const TouchedWindow& window = windows.itemAt(i);
+ if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
+ return window.window;
}
}
return NULL;
}
+bool InputDispatcher::TouchState::isSlippery() const {
+ // Must have exactly one foreground window.
+ bool haveSlipperyForegroundWindow = false;
+ for (size_t i = 0; i < windows.size(); i++) {
+ const TouchedWindow& window = windows.itemAt(i);
+ if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
+ if (haveSlipperyForegroundWindow
+ || !(window.window->layoutParamsFlags & InputWindow::FLAG_SLIPPERY)) {
+ return false;
+ }
+ haveSlipperyForegroundWindow = true;
+ }
+ }
+ return haveSlipperyForegroundWindow;
+}
+
// --- InputDispatcherThread ---
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 39d4aeb7fb4f..676d162daaac 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -121,11 +121,23 @@ struct InputTarget {
* The event is transmuted into ACTION_HOVER_ENTER. */
FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11,
+ /* This flag indicates that the event should be canceled.
+ * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
+ * outside of a window. */
+ FLAG_DISPATCH_AS_SLIPPERY_EXIT = 1 << 12,
+
+ /* This flag indicates that the event should be dispatched as an initial down.
+ * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
+ * into a new window. */
+ FLAG_DISPATCH_AS_SLIPPERY_ENTER = 1 << 13,
+
/* Mask for all dispatch modes. */
FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS
| FLAG_DISPATCH_AS_OUTSIDE
| FLAG_DISPATCH_AS_HOVER_ENTER
- | FLAG_DISPATCH_AS_HOVER_EXIT,
+ | FLAG_DISPATCH_AS_HOVER_EXIT
+ | FLAG_DISPATCH_AS_SLIPPERY_EXIT
+ | FLAG_DISPATCH_AS_SLIPPERY_ENTER,
};
// The input channel to be targeted.
@@ -950,9 +962,10 @@ private:
~TouchState();
void reset();
void copyFrom(const TouchState& other);
- void addOrUpdateWindow(const InputWindow* window, int32_t targetFlags, BitSet32 pointerIds);
+ void addOrUpdateWindow(const InputWindow* window,int32_t targetFlags, BitSet32 pointerIds);
void filterNonAsIsTouchWindows();
- const InputWindow* getFirstForegroundWindow();
+ const InputWindow* getFirstForegroundWindow() const;
+ bool isSlippery() const;
};
TouchState mTouchState;
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index fcc619857c0a..15bb300d3bae 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -1044,8 +1044,8 @@ void InputMapper::fadePointer() {
void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
const RawAbsoluteAxisInfo& axis, const char* name) {
if (axis.valid) {
- dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
- name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
+ dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
+ name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
} else {
dump.appendFormat(INDENT4 "%s: unknown range\n", name);
}
@@ -5656,9 +5656,10 @@ void JoystickInputMapper::dump(String8& dump) {
dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, "
"highScale=%0.5f, highOffset=%0.5f\n",
axis.scale, axis.offset, axis.highScale, axis.highOffset);
- dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
+ dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, "
+ "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
- axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
+ axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
}
}
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
index d7d819debed8..93c9b5f268b0 100644
--- a/services/input/InputWindow.h
+++ b/services/input/InputWindow.h
@@ -80,6 +80,10 @@ struct InputWindow {
FLAG_TURN_SCREEN_ON = 0x00200000,
FLAG_DISMISS_KEYGUARD = 0x00400000,
FLAG_SPLIT_TOUCH = 0x00800000,
+ FLAG_HARDWARE_ACCELERATED = 0x01000000,
+ FLAG_HARDWARE_ACCELERATED_SYSTEM = 0x02000000,
+ FLAG_SLIPPERY = 0x04000000,
+ FLAG_NEEDS_MENU_KEY = 0x08000000,
FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
FLAG_COMPATIBLE_WINDOW = 0x20000000,
FLAG_SYSTEM_ERROR = 0x40000000,
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index d04c9e7db145..acda86bc74fe 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -481,7 +481,7 @@ public:
}
void addAbsoluteAxis(int32_t deviceId, int axis,
- int32_t minValue, int32_t maxValue, int flat, int fuzz) {
+ int32_t minValue, int32_t maxValue, int flat, int fuzz, int resolution = 0) {
Device* device = getDevice(deviceId);
RawAbsoluteAxisInfo info;
@@ -490,6 +490,7 @@ public:
info.maxValue = maxValue;
info.flat = flat;
info.fuzz = fuzz;
+ info.resolution = resolution;
device->absoluteAxes.add(axis, info);
}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 367c8028687d..4ecdfed687c3 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -27,7 +27,6 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -37,7 +36,6 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.ContentObserver;
-import android.hardware.usb.UsbManager;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Binder;
@@ -47,7 +45,6 @@ import android.os.IBinder;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
-import android.os.SystemProperties;
import android.os.Vibrator;
import android.provider.Settings;
import android.telephony.TelephonyManager;
@@ -112,10 +109,6 @@ public class NotificationManagerService extends INotificationManager.Stub
// This is reset to false when the screen is turned on.
private boolean mPendingPulseNotification;
- // for adb connected notifications
- private boolean mAdbNotificationShown = false;
- private Notification mAdbNotification;
-
private final ArrayList<NotificationRecord> mNotificationList =
new ArrayList<NotificationRecord>();
@@ -330,12 +323,7 @@ public class NotificationManagerService extends INotificationManager.Stub
boolean queryRestart = false;
- if (action.equals(UsbManager.ACTION_USB_STATE)) {
- Bundle extras = intent.getExtras();
- boolean usbConnected = extras.getBoolean(UsbManager.USB_CONNECTED);
- boolean adbEnabled = extras.getBoolean(UsbManager.USB_FUNCTION_ADB);
- updateAdbNotification(usbConnected && adbEnabled);
- } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
+ if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
|| action.equals(Intent.ACTION_PACKAGE_RESTARTED)
|| (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART))
|| action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
@@ -436,7 +424,6 @@ public class NotificationManagerService extends INotificationManager.Stub
// register for various Intents
IntentFilter filter = new IntentFilter();
- filter.addAction(UsbManager.ACTION_USB_STATE);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
@@ -1116,67 +1103,6 @@ public class NotificationManagerService extends INotificationManager.Stub
return -1;
}
- // This is here instead of StatusBarPolicy because it is an important
- // security feature that we don't want people customizing the platform
- // to accidentally lose.
- private void updateAdbNotification(boolean adbEnabled) {
- if (adbEnabled) {
- if ("0".equals(SystemProperties.get("persist.adb.notify"))) {
- return;
- }
- if (!mAdbNotificationShown) {
- NotificationManager notificationManager = (NotificationManager) mContext
- .getSystemService(Context.NOTIFICATION_SERVICE);
- if (notificationManager != null) {
- Resources r = mContext.getResources();
- CharSequence title = r.getText(
- com.android.internal.R.string.adb_active_notification_title);
- CharSequence message = r.getText(
- com.android.internal.R.string.adb_active_notification_message);
-
- if (mAdbNotification == null) {
- mAdbNotification = new Notification();
- mAdbNotification.icon = com.android.internal.R.drawable.stat_sys_adb;
- mAdbNotification.when = 0;
- mAdbNotification.flags = Notification.FLAG_ONGOING_EVENT;
- mAdbNotification.tickerText = title;
- mAdbNotification.defaults = 0; // please be quiet
- mAdbNotification.sound = null;
- mAdbNotification.vibrate = null;
- }
-
- Intent intent = new Intent(
- Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- // Note: we are hard-coding the component because this is
- // an important security UI that we don't want anyone
- // intercepting.
- intent.setComponent(new ComponentName("com.android.settings",
- "com.android.settings.DevelopmentSettings"));
- PendingIntent pi = PendingIntent.getActivity(mContext, 0,
- intent, 0);
-
- mAdbNotification.setLatestEventInfo(mContext, title, message, pi);
-
- mAdbNotificationShown = true;
- notificationManager.notify(
- com.android.internal.R.string.adb_active_notification_title,
- mAdbNotification);
- }
- }
-
- } else if (mAdbNotificationShown) {
- NotificationManager notificationManager = (NotificationManager) mContext
- .getSystemService(Context.NOTIFICATION_SERVICE);
- if (notificationManager != null) {
- mAdbNotificationShown = false;
- notificationManager.cancel(
- com.android.internal.R.string.adb_active_notification_title);
- }
- }
- }
-
private void updateNotificationPulse() {
synchronized (mNotificationList) {
updateLightsLocked();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3484baf441c4..a8201399def0 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -26,7 +26,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.res.Configuration;
-import android.database.ContentObserver;
import android.media.AudioService;
import android.os.Looper;
import android.os.RemoteException;
@@ -66,19 +65,6 @@ class ServerThread extends Thread {
ContentResolver mContentResolver;
- private class AdbSettingsObserver extends ContentObserver {
- public AdbSettingsObserver() {
- super(null);
- }
- @Override
- public void onChange(boolean selfChange) {
- boolean enableAdb = (Settings.Secure.getInt(mContentResolver,
- Settings.Secure.ADB_ENABLED, 0) > 0);
- // setting this secure property will start or stop adbd
- SystemProperties.set("persist.service.adb.enable", enableAdb ? "1" : "0");
- }
- }
-
@Override
public void run() {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,
@@ -485,14 +471,6 @@ class ServerThread extends Thread {
}
}
- // make sure the ADB_ENABLED setting value matches the secure property value
- Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED,
- "1".equals(SystemProperties.get("persist.service.adb.enable")) ? 1 : 0);
-
- // register observer to listen for settings changes
- mContentResolver.registerContentObserver(Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED),
- false, new AdbSettingsObserver());
-
// Before things start rolling, be sure we have decided whether
// we are in safe mode.
final boolean safeMode = wm.detectSafeMode();
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 86671d6d19bb..ec59da6ed966 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -46,6 +46,7 @@ import android.text.TextUtils.SimpleStringSplitter;
import android.util.Slog;
import android.util.SparseArray;
import android.view.IWindow;
+import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
@@ -149,9 +150,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
synchronized (mLock) {
notifyEventListenerLocked(service, eventType);
- AccessibilityEvent oldEvent = service.mPendingEvents.get(eventType);
- service.mPendingEvents.remove(eventType);
- tryRecycleLocked(oldEvent);
}
}
};
@@ -319,17 +317,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
public boolean sendAccessibilityEvent(AccessibilityEvent event) {
synchronized (mLock) {
- mSecurityPolicy.updateRetrievalAllowingWindowAndEventSourceLocked(event);
- notifyAccessibilityServicesDelayedLocked(event, false);
- notifyAccessibilityServicesDelayedLocked(event, true);
- }
- // event not scheduled for dispatch => recycle
- if (mHandledFeedbackTypes == 0) {
- event.recycle();
- } else {
- mHandledFeedbackTypes = 0;
+ if (mSecurityPolicy.canDispatchAccessibilityEvent(event)) {
+ mSecurityPolicy.updateRetrievalAllowingWindowAndEventSourceLocked(event);
+ notifyAccessibilityServicesDelayedLocked(event, false);
+ notifyAccessibilityServicesDelayedLocked(event, true);
+ }
}
-
+ event.recycle();
+ mHandledFeedbackTypes = 0;
return (OWN_PROCESS_ID != Binder.getCallingPid());
}
@@ -517,46 +512,27 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private void notifyAccessibilityServiceDelayedLocked(Service service,
AccessibilityEvent event) {
synchronized (mLock) {
- int eventType = event.getEventType();
+ final int eventType = event.getEventType();
+ // Make a copy since during dispatch it is possible the event to
+ // be modified to remove its source if the receiving service does
+ // not have permission to access the window content.
+ AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
AccessibilityEvent oldEvent = service.mPendingEvents.get(eventType);
- service.mPendingEvents.put(eventType, event);
+ service.mPendingEvents.put(eventType, newEvent);
- int what = eventType | (service.mId << 16);
+ final int what = eventType | (service.mId << 16);
if (oldEvent != null) {
mHandler.removeMessages(what);
- tryRecycleLocked(oldEvent);
+ oldEvent.recycle();
}
Message message = mHandler.obtainMessage(what, service);
- message.arg1 = event.getEventType();
+ message.arg1 = eventType;
mHandler.sendMessageDelayed(message, service.mNotificationTimeout);
}
}
/**
- * Recycles an event if it can be safely recycled. The condition is that no
- * not notified service is interested in the event.
- *
- * @param event The event.
- */
- private void tryRecycleLocked(AccessibilityEvent event) {
- if (event == null) {
- return;
- }
- int eventType = event.getEventType();
- List<Service> services = mServices;
-
- // linear in the number of service which is not large
- for (int i = 0, count = services.size(); i < count; i++) {
- Service service = services.get(i);
- if (service.mPendingEvents.get(eventType) == event) {
- return;
- }
- }
- event.recycle();
- }
-
- /**
* Notifies a service for a scheduled event given the event type.
*
* @param service The service.
@@ -565,7 +541,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private void notifyEventListenerLocked(Service service, int eventType) {
IEventListener listener = service.mServiceInterface;
AccessibilityEvent event = service.mPendingEvents.get(eventType);
-
+ service.mPendingEvents.remove(eventType);
try {
if (mSecurityPolicy.canRetrieveWindowContent(service)) {
event.setConnection(service);
@@ -574,6 +550,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
event.setSealed(true);
listener.onAccessibilityEvent(event);
+ event.recycle();
if (DEBUG) {
Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
}
@@ -926,7 +903,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
- public AccessibilityNodeInfo findAccessibilityNodeInfoByViewId(int viewId) {
+ public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId) {
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this);
@@ -961,10 +938,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
return null;
}
- public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(String text) {
+ public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow(
+ String text) {
+ return findAccessibilityNodeInfosByViewText(text,
+ mSecurityPolicy.mRetrievalAlowingWindowId, View.NO_ID);
+ }
+
+ public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(String text,
+ int accessibilityWindowId, int accessibilityViewId) {
IAccessibilityInteractionConnection connection = null;
synchronized (mLock) {
- final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this);
+ final boolean permissionGranted =
+ mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId);
if (permissionGranted) {
connection = getConnectionToRetrievalAllowingWindowLocked();
}
@@ -978,7 +963,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final long identityToken = Binder.clearCallingIdentity();
try {
final int interactionId = mInteractionIdCounter.getAndIncrement();
- connection.findAccessibilityNodeInfosByViewText(text, interactionId, mCallback);
+ connection.findAccessibilityNodeInfosByViewText(text, accessibilityViewId,
+ interactionId, mCallback);
List<AccessibilityNodeInfo> infos =
mCallback.getFindAccessibilityNodeInfosResultAndClear(interactionId);
if (infos != null) {
@@ -1112,16 +1098,23 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
| AccessibilityEvent.TYPE_VIEW_CLICKED | AccessibilityEvent.TYPE_VIEW_FOCUSED
| AccessibilityEvent.TYPE_VIEW_HOVER_ENTER | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
| AccessibilityEvent.TYPE_VIEW_LONG_CLICKED | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
- | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+ | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_SELECTED
+ | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
private int mRetrievalAlowingWindowId;
+ private boolean canDispatchAccessibilityEvent(AccessibilityEvent event) {
+ // Send window changed event only for the retrieval allowing window.
+ return (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
+ || event.getWindowId() == mRetrievalAlowingWindowId);
+ }
+
public void updateRetrievalAllowingWindowAndEventSourceLocked(AccessibilityEvent event) {
- final int windowId = event.getSourceAccessibilityWindowId();
+ final int windowId = event.getWindowId();
final int eventType = event.getEventType();
if ((eventType & RETRIEVAL_ALLOWING_EVENT_TYPES) != 0) {
mRetrievalAlowingWindowId = windowId;
- } else {
+ } else {
event.setSource(null);
}
}
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index b754dbacf7c7..ab85b1464bc8 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -126,13 +126,15 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
// Unpack the config.
// TODO: move constants into VpnBuilder.
+ int mtu = config.getInt("mtu", -1);
String session = config.getString("session");
String addresses = config.getString("addresses");
String routes = config.getString("routes");
String dnsServers = config.getString("dnsServers");
- // Create interface and configure addresses and routes.
- ParcelFileDescriptor descriptor = nativeConfigure(addresses, routes);
+ // Create and configure the interface.
+ ParcelFileDescriptor descriptor =
+ ParcelFileDescriptor.adoptFd(nativeEstablish(mtu, addresses, routes));
// Replace the interface and abort if it fails.
try {
@@ -250,7 +252,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
}
}
- private native ParcelFileDescriptor nativeConfigure(String addresses, String routes);
+ private native int nativeEstablish(int mtu, String addresses, String routes);
private native String nativeGetName(int fd);
private native void nativeReset(String name);
private native int nativeCheck(String name);
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index e7d60638650a..99569a8449dd 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -385,10 +385,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private void ensureActiveMobilePolicyLocked() {
if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
final String subscriberId = getActiveSubscriberId();
- if (subscriberId == null) {
- if (LOGV) Slog.v(TAG, "no active mobile network, ignoring policy check");
- return;
- }
// examine to see if any policy is defined for active mobile
boolean mobileDefined = false;
@@ -412,6 +408,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mNetworkPolicy.add(new NetworkPolicy(
TEMPLATE_MOBILE_ALL, subscriberId, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED));
+ writePolicyLocked();
}
}
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index 95008e56acaf..ca8a184fdfa0 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -17,12 +17,17 @@
package com.android.server.usb;
import android.app.PendingIntent;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.net.Uri;
@@ -32,6 +37,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
import android.os.UEventObserver;
import android.provider.Settings;
import android.util.Log;
@@ -92,10 +98,81 @@ public class UsbDeviceManager {
private final ArrayList<String> mDefaultFunctions = new ArrayList<String>();
private final Context mContext;
+ ContentResolver mContentResolver;
private final Object mLock = new Object();
private final UsbSettingsManager mSettingsManager;
+ private NotificationManager mNotificationManager;
private final boolean mHasUsbAccessory;
+ // for adb connected notifications
+ private boolean mAdbNotificationShown = false;
+ private Notification mAdbNotification;
+ private boolean mAdbEnabled;
+
+ private class AdbSettingsObserver extends ContentObserver {
+ public AdbSettingsObserver() {
+ super(null);
+ }
+ @Override
+ public void onChange(boolean selfChange) {
+ mAdbEnabled = (Settings.Secure.getInt(mContentResolver,
+ Settings.Secure.ADB_ENABLED, 0) > 0);
+ // setting this secure property will start or stop adbd
+ SystemProperties.set("persist.service.adb.enable", mAdbEnabled ? "1" : "0");
+ updateAdbNotification();
+ }
+ }
+
+ private void updateAdbNotification() {
+ if (mNotificationManager == null) return;
+ boolean adbEnabled = mAdbEnabled && (mConnected == 1);
+ if (adbEnabled) {
+ if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
+
+ if (!mAdbNotificationShown) {
+ Resources r = mContext.getResources();
+ CharSequence title = r.getText(
+ com.android.internal.R.string.adb_active_notification_title);
+ CharSequence message = r.getText(
+ com.android.internal.R.string.adb_active_notification_message);
+
+ if (mAdbNotification == null) {
+ mAdbNotification = new Notification();
+ mAdbNotification.icon = com.android.internal.R.drawable.stat_sys_adb;
+ mAdbNotification.when = 0;
+ mAdbNotification.flags = Notification.FLAG_ONGOING_EVENT;
+ mAdbNotification.tickerText = title;
+ mAdbNotification.defaults = 0; // please be quiet
+ mAdbNotification.sound = null;
+ mAdbNotification.vibrate = null;
+ }
+
+ Intent intent = new Intent(
+ Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ // Note: we are hard-coding the component because this is
+ // an important security UI that we don't want anyone
+ // intercepting.
+ intent.setComponent(new ComponentName("com.android.settings",
+ "com.android.settings.DevelopmentSettings"));
+ PendingIntent pi = PendingIntent.getActivity(mContext, 0,
+ intent, 0);
+
+ mAdbNotification.setLatestEventInfo(mContext, title, message, pi);
+
+ mAdbNotificationShown = true;
+ mNotificationManager.notify(
+ com.android.internal.R.string.adb_active_notification_title,
+ mAdbNotification);
+ }
+ } else if (mAdbNotificationShown) {
+ mAdbNotificationShown = false;
+ mNotificationManager.cancel(
+ com.android.internal.R.string.adb_active_notification_title);
+ }
+ }
+
private final void readCurrentAccessoryLocked() {
if (mHasUsbAccessory) {
String[] strings = nativeGetAccessoryStrings();
@@ -191,6 +268,7 @@ public class UsbDeviceManager {
public UsbDeviceManager(Context context, UsbSettingsManager settingsManager) {
mContext = context;
+ mContentResolver = context.getContentResolver();
mSettingsManager = settingsManager;
PackageManager pm = mContext.getPackageManager();
mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
@@ -198,6 +276,16 @@ public class UsbDeviceManager {
synchronized (mLock) {
init(); // set initial status
+ // make sure the ADB_ENABLED setting value matches the secure property value
+ mAdbEnabled = "1".equals(SystemProperties.get("persist.service.adb.enable"));
+ Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED,
+ mAdbEnabled ? 1 : 0);
+
+ // register observer to listen for settings changes
+ mContentResolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED),
+ false, new AdbSettingsObserver());
+
// Watch for USB configuration changes
if (mConfiguration >= 0) {
mUEventObserver.startObserving(USB_CONNECTED_MATCH);
@@ -281,6 +369,9 @@ public class UsbDeviceManager {
public void systemReady() {
synchronized (mLock) {
+ mNotificationManager = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+
update(false);
if (mCurrentAccessory != null) {
Log.d(TAG, "accessoryAttached at systemReady");
@@ -335,6 +426,7 @@ public class UsbDeviceManager {
switch (msg.what) {
case MSG_UPDATE_STATE:
if (mConnected != mLastConnected || mConfiguration != mLastConfiguration) {
+ updateAdbNotification();
if (mConnected == 0) {
if (UsbManager.isFunctionEnabled(
UsbManager.USB_FUNCTION_ACCESSORY)) {
diff --git a/services/jni/com_android_server_connectivity_Vpn.cpp b/services/jni/com_android_server_connectivity_Vpn.cpp
index 374fd3b6d486..206df256b478 100644
--- a/services/jni/com_android_server_connectivity_Vpn.cpp
+++ b/services/jni/com_android_server_connectivity_Vpn.cpp
@@ -38,34 +38,20 @@
#include "jni.h"
#include "JNIHelp.h"
-#include "android_util_Binder.h"
namespace android
{
-static inline void init_sockaddr(sockaddr *sa) {
- ((sockaddr_in *)sa)->sin_family = AF_INET;
- ((sockaddr_in *)sa)->sin_port = 0;
-}
-
static inline in_addr_t *as_in_addr(sockaddr *sa) {
return &((sockaddr_in *)sa)->sin_addr.s_addr;
}
-static inline in_addr_t *as_in_addr(sockaddr_storage *ss) {
- return &((sockaddr_in *)ss)->sin_addr.s_addr;
-}
-
-static inline in6_addr *as_in6_addr(sockaddr_storage *ss) {
- return &((sockaddr_in6 *)&ss)->sin6_addr;
-}
-
//------------------------------------------------------------------------------
#define SYSTEM_ERROR -1
#define BAD_ARGUMENT -2
-static int create_interface(char *name, int *index)
+static int create_interface(int mtu, char *name, int *index)
{
int tun = open("/dev/tun", O_RDWR);
int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
@@ -74,7 +60,7 @@ static int create_interface(char *name, int *index)
memset(&ifr4, 0, sizeof(ifr4));
// Allocate interface.
- ifr4.ifr_flags = IFF_TUN;
+ ifr4.ifr_flags = IFF_TUN | IFF_NO_PI;
if (ioctl(tun, TUNSETIFF, &ifr4)) {
LOGE("Cannot allocate TUN: %s", strerror(errno));
goto error;
@@ -87,6 +73,13 @@ static int create_interface(char *name, int *index)
goto error;
}
+ // Set MTU if it is specified.
+ ifr4.ifr_mtu = mtu;
+ if (mtu > 0 && ioctl(inet4, SIOCSIFMTU, &ifr4)) {
+ LOGE("Cannot set MTU on %s: %s", ifr4.ifr_name, strerror(errno));
+ goto error;
+ }
+
// Get interface index.
if (ioctl(inet4, SIOGIFINDEX, &ifr4)) {
LOGE("Cannot get index of %s: %s", ifr4.ifr_name, strerror(errno));
@@ -112,7 +105,7 @@ static int set_addresses(const char *name, int index, const char *addresses)
ifreq ifr4;
memset(&ifr4, 0, sizeof(ifr4));
strcpy(ifr4.ifr_name, name);
- init_sockaddr(&ifr4.ifr_addr);
+ ifr4.ifr_addr.sa_family = AF_INET;
in6_ifreq ifr6;
memset(&ifr6, 0, sizeof(ifr6));
@@ -190,9 +183,8 @@ static int set_routes(const char *name, int index, const char *routes)
memset(&rt4, 0, sizeof(rt4));
rt4.rt_dev = (char *)name;
rt4.rt_flags = RTF_UP;
- init_sockaddr(&rt4.rt_dst);
- init_sockaddr(&rt4.rt_genmask);
- init_sockaddr(&rt4.rt_gateway);
+ rt4.rt_dst.sa_family = AF_INET;
+ rt4.rt_genmask.sa_family = AF_INET;
in6_rtmsg rt6;
memset(&rt6, 0, sizeof(rt6));
@@ -201,60 +193,50 @@ static int set_routes(const char *name, int index, const char *routes)
char address[65];
int prefix;
- char gateway[65];
int chars;
int count = 0;
- while (sscanf(routes, " %64[^/]/%d>%64[^ ] %n",
- address, &prefix, gateway, &chars) == 3) {
+ while (sscanf(routes, " %64[^/]/%d %n", address, &prefix, &chars) == 2) {
routes += chars;
if (strchr(address, ':')) {
// Add an IPv6 route.
- if (inet_pton(AF_INET6, gateway, &rt6.rtmsg_gateway) != 1 ||
- inet_pton(AF_INET6, address, &rt6.rtmsg_dst) != 1 ||
- prefix < 0 || prefix > 128) {
+ if (inet_pton(AF_INET6, address, &rt6.rtmsg_dst) != 1 ||
+ prefix < 1 || prefix > 128) {
count = BAD_ARGUMENT;
break;
}
rt6.rtmsg_dst_len = prefix;
- if (memcmp(&rt6.rtmsg_gateway, &in6addr_any, sizeof(in6addr_any))) {
- rt6.rtmsg_flags |= RTF_GATEWAY;
- }
- if (ioctl(inet6, SIOCADDRT, &rt6)) {
+ if (ioctl(inet6, SIOCADDRT, &rt6) && errno != EEXIST) {
count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
break;
}
} else {
// Add an IPv4 route.
- if (inet_pton(AF_INET, gateway, as_in_addr(&rt4.rt_gateway)) != 1 ||
- inet_pton(AF_INET, address, as_in_addr(&rt4.rt_dst)) != 1 ||
- prefix < 0 || prefix > 32) {
+ if (inet_pton(AF_INET, address, as_in_addr(&rt4.rt_dst)) != 1 ||
+ prefix < 1 || prefix > 32) {
count = BAD_ARGUMENT;
break;
}
in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0;
*as_in_addr(&rt4.rt_genmask) = htonl(mask);
- if (*as_in_addr(&rt4.rt_gateway)) {
- rt4.rt_flags |= RTF_GATEWAY;
- }
- if (ioctl(inet4, SIOCADDRT, &rt4)) {
+ if (ioctl(inet4, SIOCADDRT, &rt4) && errno != EEXIST) {
count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
break;
}
}
- LOGV("Route added on %s: %s/%d -> %s", name, address, prefix, gateway);
+ LOGV("Route added on %s: %s/%d", name, address, prefix);
++count;
}
if (count == BAD_ARGUMENT) {
- LOGE("Invalid route: %s/%d -> %s", address, prefix, gateway);
+ LOGE("Invalid route: %s/%d", address, prefix);
} else if (count == SYSTEM_ERROR) {
- LOGE("Cannot add route: %s/%d -> %s: %s",
- address, prefix, gateway, strerror(errno));
+ LOGE("Cannot add route: %s/%d: %s",
+ address, prefix, strerror(errno));
} else if (*routes) {
LOGE("Invalid route: %s", routes);
count = BAD_ARGUMENT;
@@ -299,10 +281,10 @@ static int check_interface(const char *name)
ifreq ifr4;
strncpy(ifr4.ifr_name, name, IFNAMSIZ);
+ ifr4.ifr_flags = 0;
if (ioctl(inet4, SIOCGIFFLAGS, &ifr4) && errno != ENODEV) {
LOGE("Cannot check %s: %s", name, strerror(errno));
- ifr4.ifr_flags = 0;
}
close(inet4);
return ifr4.ifr_flags;
@@ -328,15 +310,15 @@ static void throwException(JNIEnv *env, int error, const char *message)
}
}
-static jobject configure(JNIEnv *env, jobject thiz,
- jstring jAddresses, jstring jRoutes)
+static jint establish(JNIEnv *env, jobject thiz,
+ jint mtu, jstring jAddresses, jstring jRoutes)
{
char name[IFNAMSIZ];
int index;
- int tun = create_interface(name, &index);
+ int tun = create_interface(mtu, name, &index);
if (tun < 0) {
throwException(env, tun, "Cannot create interface");
- return NULL;
+ return -1;
}
LOGD("%s is created", name);
@@ -370,12 +352,12 @@ static jobject configure(JNIEnv *env, jobject thiz,
LOGD("Configured %d route(s) on %s", count, name);
}
- return newParcelFileDescriptor(env, jniCreateFileDescriptor(env, tun));
+ return tun;
error:
close(tun);
LOGD("%s is destroyed", name);
- return NULL;
+ return -1;
}
static jstring getName(JNIEnv *env, jobject thiz, jint fd)
@@ -434,7 +416,7 @@ static void protect(JNIEnv *env, jobject thiz, jint fd, jstring jName)
//------------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
- {"nativeConfigure", "(Ljava/lang/String;Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;", (void *)configure},
+ {"nativeEstablish", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)establish},
{"nativeGetName", "(I)Ljava/lang/String;", (void *)getName},
{"nativeReset", "(Ljava/lang/String;)V", (void *)reset},
{"nativeCheck", "(Ljava/lang/String;)I", (void *)check},
diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp
index b5f97e035485..d706af598320 100644
--- a/services/sensorservice/Fusion.cpp
+++ b/services/sensorservice/Fusion.cpp
@@ -24,10 +24,28 @@ namespace android {
// -----------------------------------------------------------------------
-static const float gyroSTDEV = 3.16e-4; // rad/s^3/2
+/*
+ * gyroVAR gives the measured variance of the gyro's output per
+ * Hz (or variance at 1 Hz). This is an "intrinsic" parameter of the gyro,
+ * which is independent of the sampling frequency.
+ *
+ * The variance of gyro's output at a given sampling period can be
+ * calculated as:
+ * variance(T) = gyroVAR / T
+ *
+ * The variance of the INTEGRATED OUTPUT at a given sampling period can be
+ * calculated as:
+ * variance_integrate_output(T) = gyroVAR * T
+ *
+ */
+static const float gyroVAR = 1e-7; // (rad/s)^2 / Hz
+static const float biasVAR = 1e-8; // (rad/s)^2 / s (guessed)
+
+/*
+ * Standard deviations of accelerometer and magnetometer
+ */
static const float accSTDEV = 0.05f; // m/s^2 (measured 0.08 / CDD 0.05)
static const float magSTDEV = 0.5f; // uT (measured 0.7 / CDD 0.5)
-static const float biasSTDEV = 3.16e-5; // rad/s^1/2 (guessed)
static const float FREE_FALL_THRESHOLD = 0.981f;
@@ -129,23 +147,34 @@ void Fusion::initFusion(const vec4_t& q, float dT)
x0 = q;
x1 = 0;
- // process noise covariance matrix
- // G = | -1 0 |
- // | 0 1 |
-
- const float v = gyroSTDEV;
- const float u = biasSTDEV;
- const float q00 = v*v*dT + 0.33333f*(dT*dT*dT)*u*u;
- const float q10 = 0.5f*(dT*dT) *u*u;
+ // process noise covariance matrix: G.Q.Gt, with
+ //
+ // G = | -1 0 | Q = | q00 q10 |
+ // | 0 1 | | q01 q11 |
+ //
+ // q00 = sv^2.dt + 1/3.su^2.dt^3
+ // q10 = q01 = 1/2.su^2.dt^2
+ // q11 = su^2.dt
+ //
+
+ // variance of integrated output at 1/dT Hz
+ // (random drift)
+ const float q00 = gyroVAR * dT;
+
+ // variance of drift rate ramp
+ const float q11 = biasVAR * dT;
+
+ const float u = q11 / dT;
+ const float q10 = 0.5f*u*dT*dT;
const float q01 = q10;
- const float q11 = u*u*dT;
- GQGt[0][0] = q00;
+
+ GQGt[0][0] = q00; // rad^2
GQGt[1][0] = -q10;
GQGt[0][1] = -q01;
- GQGt[1][1] = q11;
-
+ GQGt[1][1] = q11; // (rad/s)^2
// initial covariance: Var{ x(t0) }
+ // TODO: initialize P correctly
P = 0;
}
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 9daaad8ea18c..c618263717f4 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -2,18 +2,18 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- clz.cpp.arm \
- DisplayHardware/DisplayHardware.cpp \
+ Layer.cpp \
+ LayerBase.cpp \
+ LayerDim.cpp \
+ DisplayHardware/DisplayHardware.cpp \
DisplayHardware/DisplayHardwareBase.cpp \
- DisplayHardware/HWComposer.cpp \
- GLExtensions.cpp \
- Layer.cpp \
- LayerBase.cpp \
- LayerDim.cpp \
- MessageQueue.cpp \
- SurfaceFlinger.cpp \
- TextureManager.cpp \
- Transform.cpp
+ DisplayHardware/HWComposer.cpp \
+ GLExtensions.cpp \
+ MessageQueue.cpp \
+ SurfaceFlinger.cpp \
+ SurfaceTextureLayer.cpp \
+ Transform.cpp \
+
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8df2b9217d0c..2bab6a8fe18b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -18,8 +18,9 @@
#include <stdint.h>
#include <sys/types.h>
-#include <cutils/properties.h>
+#include <cutils/compiler.h>
#include <cutils/native_handle.h>
+#include <cutils/properties.h>
#include <utils/Errors.h>
#include <utils/Log.h>
@@ -31,12 +32,12 @@
#include <surfaceflinger/Surface.h>
#include "clz.h"
+#include "DisplayHardware/DisplayHardware.h"
+#include "DisplayHardware/HWComposer.h"
#include "GLExtensions.h"
#include "Layer.h"
#include "SurfaceFlinger.h"
-#include "DisplayHardware/DisplayHardware.h"
-#include "DisplayHardware/HWComposer.h"
-
+#include "SurfaceTextureLayer.h"
#define DEBUG_RESIZE 0
@@ -52,102 +53,83 @@ template <typename T> inline T min(T a, T b) {
Layer::Layer(SurfaceFlinger* flinger,
DisplayID display, const sp<Client>& client)
: LayerBaseClient(flinger, display, client),
+ mTextureName(-1U),
+ mQueuedFrames(0),
+ mCurrentTransform(0),
+ mCurrentOpacity(true),
mFormat(PIXEL_FORMAT_NONE),
mGLExtensions(GLExtensions::getInstance()),
- mNeedsBlending(true),
+ mOpaqueLayer(true),
mNeedsDithering(false),
mSecure(false),
mProtectedByApp(false),
- mTextureManager(),
- mBufferManager(mTextureManager),
- mWidth(0), mHeight(0),
- mNeedsScaling(false), mFixedSize(false)
-{
-}
-
-Layer::~Layer()
+ mFixedSize(false)
{
- // FIXME: must be called from the main UI thread
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
- mBufferManager.destroy(dpy);
-
- // we can use getUserClientUnsafe here because we know we're
- // single-threaded at that point.
- sp<UserClient> ourClient(mUserClientRef.getUserClientUnsafe());
- if (ourClient != 0) {
- ourClient->detachLayer(this);
- }
+ mCurrentCrop.makeInvalid();
+ glGenTextures(1, &mTextureName);
}
-void Layer::destroy() const {
- mFlinger->destroyLayer(this);
+void Layer::destroy(RefBase const* base) {
+ mFlinger->destroyLayer(static_cast<LayerBase const*>(base));
}
-status_t Layer::setToken(const sp<UserClient>& userClient,
- SharedClient* sharedClient, int32_t token)
+void Layer::onFirstRef()
{
- sp<SharedBufferServer> lcblk = new SharedBufferServer(
- sharedClient, token, mBufferManager.getDefaultBufferCount(),
- getIdentity());
-
-
- sp<UserClient> ourClient(mUserClientRef.getClient());
-
- /*
- * Here it is guaranteed that userClient != ourClient
- * (see UserClient::getTokenForSurface()).
- *
- * We release the token used by this surface in ourClient below.
- * This should be safe to do so now, since this layer won't be attached
- * to this client, it should be okay to reuse that id.
- *
- * If this causes problems, an other solution would be to keep a list
- * of all the {UserClient, token} ever used and release them when the
- * Layer is destroyed.
- *
- */
-
- if (ourClient != 0) {
- ourClient->detachLayer(this);
- }
-
- status_t err = mUserClientRef.setToken(userClient, lcblk, token);
- LOGE_IF(err != NO_ERROR,
- "ClientRef::setToken(%p, %p, %u) failed",
- userClient.get(), lcblk.get(), token);
-
- if (err == NO_ERROR) {
- // we need to free the buffers associated with this surface
- }
+ LayerBaseClient::onFirstRef();
+ setDestroyer(this);
- return err;
+ struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
+ FrameQueuedListener(Layer* layer) : mLayer(layer) { }
+ private:
+ wp<Layer> mLayer;
+ virtual void onFrameAvailable() {
+ sp<Layer> that(mLayer.promote());
+ if (that != 0) {
+ that->onFrameQueued();
+ }
+ }
+ };
+ mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);
+ mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
+ mSurfaceTexture->setSynchronousMode(true);
+ mSurfaceTexture->setBufferCountServer(2);
}
-int32_t Layer::getToken() const
+Layer::~Layer()
{
- return mUserClientRef.getToken();
+ glDeleteTextures(1, &mTextureName);
}
-sp<UserClient> Layer::getClient() const
-{
- return mUserClientRef.getClient();
+void Layer::onFrameQueued() {
+ if (android_atomic_or(1, &mQueuedFrames) == 0) {
+ mFlinger->signalEvent();
+ }
}
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list
void Layer::onRemoved()
{
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- if (lcblk) {
- // wake up the condition
- lcblk->setStatus(NO_INIT);
- }
}
-sp<LayerBaseClient::Surface> Layer::createSurface() const
+sp<ISurface> Layer::createSurface()
{
- sp<Surface> sur(new SurfaceLayer(mFlinger, const_cast<Layer *>(this)));
+ class BSurface : public BnSurface, public LayerCleaner {
+ wp<const Layer> mOwner;
+ virtual sp<ISurfaceTexture> getSurfaceTexture() const {
+ sp<ISurfaceTexture> res;
+ sp<const Layer> that( mOwner.promote() );
+ if (that != NULL) {
+ res = that->mSurfaceTexture;
+ }
+ return res;
+ }
+ public:
+ BSurface(const sp<SurfaceFlinger>& flinger,
+ const sp<Layer>& layer)
+ : LayerCleaner(flinger, layer), mOwner(layer) { }
+ };
+ sp<ISurface> sur(new BSurface(mFlinger, this));
return sur;
}
@@ -175,17 +157,14 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
const uint32_t hwFlags = hw.getFlags();
mFormat = format;
- mWidth = w;
- mHeight = h;
-
- mReqFormat = format;
- mReqWidth = w;
- mReqHeight = h;
mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
- mNeedsBlending = (info.h_alpha - info.l_alpha) > 0 &&
- (flags & ISurfaceComposer::eOpaque) == 0;
+ mOpaqueLayer = (flags & ISurfaceComposer::eOpaque);
+ mCurrentOpacity = getOpacityForFormat(format);
+
+ mSurfaceTexture->setDefaultBufferSize(w, h);
+ mSurfaceTexture->setDefaultBufferFormat(format);
// we use the red index
int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
@@ -216,10 +195,12 @@ void Layer::setGeometry(hwc_layer_t* hwcl)
return;
}
- Transform tr(Transform(mOrientation) * Transform(mBufferTransform));
+ // FIXME: shouldn't we take the state's transform into account here?
+
+ Transform tr(Transform(mOrientation) * Transform(mCurrentTransform));
hwcl->transform = tr.getOrientation();
- if (needsBlending()) {
+ if (!isOpaque()) {
hwcl->blending = mPremultipliedAlpha ?
HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
}
@@ -236,7 +217,7 @@ void Layer::setGeometry(hwc_layer_t* hwcl)
}
void Layer::setPerFrameData(hwc_layer_t* hwcl) {
- sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
+ const sp<GraphicBuffer>& buffer(mActiveBuffer);
if (buffer == NULL) {
// this can happen if the client never drew into this layer yet,
// or if we ran out of memory. In that case, don't let
@@ -247,11 +228,11 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) {
}
hwcl->handle = buffer->handle;
- if (!mBufferCrop.isEmpty()) {
- hwcl->sourceCrop.left = mBufferCrop.left;
- hwcl->sourceCrop.top = mBufferCrop.top;
- hwcl->sourceCrop.right = mBufferCrop.right;
- hwcl->sourceCrop.bottom = mBufferCrop.bottom;
+ if (isCropped()) {
+ hwcl->sourceCrop.left = mCurrentCrop.left;
+ hwcl->sourceCrop.top = mCurrentCrop.top;
+ hwcl->sourceCrop.right = mCurrentCrop.right;
+ hwcl->sourceCrop.bottom = mCurrentCrop.bottom;
} else {
hwcl->sourceCrop.left = 0;
hwcl->sourceCrop.top = 0;
@@ -260,51 +241,12 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) {
}
}
-void Layer::reloadTexture(const Region& dirty)
-{
- sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
- if (buffer == NULL) {
- // this situation can happen if we ran out of memory for instance.
- // not much we can do. continue to use whatever texture was bound
- // to this context.
- return;
- }
-
- if (mGLExtensions.haveDirectTexture()) {
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
- if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) {
- // not sure what we can do here...
- goto slowpath;
- }
- } else {
-slowpath:
- GGLSurface t;
- if (buffer->usage & GRALLOC_USAGE_SW_READ_MASK) {
- status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
- LOGE_IF(res, "error %d (%s) locking buffer %p",
- res, strerror(res), buffer.get());
- if (res == NO_ERROR) {
- mBufferManager.loadTexture(dirty, t);
- buffer->unlock();
- }
- } else {
- // we can't do anything
- }
- }
-}
-
-void Layer::drawForSreenShot() const
-{
- const bool currentFiltering = mNeedsFiltering;
- const_cast<Layer*>(this)->mNeedsFiltering = true;
- LayerBase::drawForSreenShot();
- const_cast<Layer*>(this)->mNeedsFiltering = currentFiltering;
+static inline uint16_t pack565(int r, int g, int b) {
+ return (r<<11)|(g<<5)|b;
}
-
void Layer::onDraw(const Region& clip) const
{
- Texture tex(mBufferManager.getActiveTexture());
- if (tex.name == -1LU) {
+ if (CC_UNLIKELY(mActiveBuffer == 0)) {
// the texture has not been created yet, this Layer has
// in fact never been drawn into. This happens frequently with
// SurfaceView because the WindowManager can't know when the client
@@ -330,7 +272,25 @@ void Layer::onDraw(const Region& clip) const
}
return;
}
- drawWithOpenGL(clip, tex);
+
+ GLenum target = mSurfaceTexture->getCurrentTextureTarget();
+ glBindTexture(target, mTextureName);
+ if (getFiltering() || needsFiltering() || isFixedSize() || isCropped()) {
+ // TODO: we could be more subtle with isFixedSize()
+ glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ } else {
+ glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+ glEnable(target);
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf(mTextureMatrix);
+ glMatrixMode(GL_MODELVIEW);
+
+ drawWithOpenGL(clip);
+
+ glDisable(target);
}
// As documented in libhardware header, formats in the range
@@ -340,186 +300,37 @@ void Layer::onDraw(const Region& clip) const
// hardware.h, instead of using hard-coded values here.
#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
-bool Layer::needsBlending(const sp<GraphicBuffer>& buffer) const
+bool Layer::getOpacityForFormat(uint32_t format)
{
- // If buffers where set with eOpaque flag, all buffers are known to
- // be opaque without having to check their actual format
- if (mNeedsBlending && buffer != NULL) {
- PixelFormat format = buffer->getPixelFormat();
-
- if (HARDWARE_IS_DEVICE_FORMAT(format)) {
- return false;
- }
-
- PixelFormatInfo info;
- status_t err = getPixelFormatInfo(format, &info);
- if (!err && info.h_alpha <= info.l_alpha) {
- return false;
- }
+ if (HARDWARE_IS_DEVICE_FORMAT(format)) {
+ return true;
}
-
- // Return opacity as determined from flags and format options
- // passed to setBuffers()
- return mNeedsBlending;
+ PixelFormatInfo info;
+ status_t err = getPixelFormatInfo(PixelFormat(format), &info);
+ // in case of error (unknown format), we assume no blending
+ return (err || info.h_alpha <= info.l_alpha);
}
-bool Layer::needsBlending() const
-{
- if (mBufferManager.hasActiveBuffer()) {
- return needsBlending(mBufferManager.getActiveBuffer());
- }
- return mNeedsBlending;
-}
-
-bool Layer::needsFiltering() const
+bool Layer::isOpaque() const
{
- if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
- // if our buffer is not the same size than ourselves,
- // we need filtering.
- Mutex::Autolock _l(mLock);
- if (mNeedsScaling)
- return true;
- }
- return LayerBase::needsFiltering();
+ // if we don't have a buffer yet, we're translucent regardless of the
+ // layer's opaque flag.
+ if (mActiveBuffer == 0)
+ return false;
+
+ // if the layer has the opaque flag, then we're always opaque,
+ // otherwise we use the current buffer's format.
+ return mOpaqueLayer || mCurrentOpacity;
}
bool Layer::isProtected() const
{
- sp<GraphicBuffer> activeBuffer(mBufferManager.getActiveBuffer());
+ const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
return (activeBuffer != 0) &&
(activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
}
-status_t Layer::setBufferCount(int bufferCount)
-{
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- if (!lcblk) {
- // oops, the client is already gone
- return DEAD_OBJECT;
- }
-
- // NOTE: lcblk->resize() is protected by an internal lock
- status_t err = lcblk->resize(bufferCount);
- if (err == NO_ERROR) {
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
- mBufferManager.resize(bufferCount, mFlinger, dpy);
- }
-
- return err;
-}
-
-sp<GraphicBuffer> Layer::requestBuffer(int index,
- uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat,
- uint32_t usage)
-{
- sp<GraphicBuffer> buffer;
-
- if (int32_t(reqWidth | reqHeight | reqFormat) < 0)
- return buffer;
-
- if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight))
- return buffer;
-
- // this ensures our client doesn't go away while we're accessing
- // the shared area.
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- if (!lcblk) {
- // oops, the client is already gone
- return buffer;
- }
-
- /*
- * This is called from the client's Surface::dequeue(). This can happen
- * at any time, especially while we're in the middle of using the
- * buffer 'index' as our front buffer.
- */
-
- status_t err = NO_ERROR;
- uint32_t w, h, f;
- { // scope for the lock
- Mutex::Autolock _l(mLock);
-
- // zero means default
- const bool fixedSize = reqWidth && reqHeight;
- if (!reqFormat) reqFormat = mFormat;
- if (!reqWidth) reqWidth = mWidth;
- if (!reqHeight) reqHeight = mHeight;
-
- w = reqWidth;
- h = reqHeight;
- f = reqFormat;
-
- if ((reqWidth != mReqWidth) || (reqHeight != mReqHeight) ||
- (reqFormat != mReqFormat)) {
- mReqWidth = reqWidth;
- mReqHeight = reqHeight;
- mReqFormat = reqFormat;
- mFixedSize = fixedSize;
- mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
-
- lcblk->reallocateAllExcept(index);
- }
- }
-
- // here we have to reallocate a new buffer because the buffer could be
- // used as the front buffer, or by a client in our process
- // (eg: status bar), and we can't release the handle under its feet.
- const uint32_t effectiveUsage = getEffectiveUsage(usage);
- buffer = new GraphicBuffer(w, h, f, effectiveUsage);
- err = buffer->initCheck();
-
- if (err || buffer->handle == 0) {
- GraphicBuffer::dumpAllocationsToSystemLog();
- LOGE_IF(err || buffer->handle == 0,
- "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
- this, index, w, h, strerror(-err));
- } else {
- LOGD_IF(DEBUG_RESIZE,
- "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
- this, index, w, h, buffer->handle);
- }
-
- if (err == NO_ERROR && buffer->handle != 0) {
- Mutex::Autolock _l(mLock);
- mBufferManager.attachBuffer(index, buffer);
- }
- return buffer;
-}
-
-uint32_t Layer::getEffectiveUsage(uint32_t usage) const
-{
- /*
- * buffers used for software rendering, but h/w composition
- * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
- *
- * buffers used for h/w rendering and h/w composition
- * are allocated with HW_RENDER | HW_TEXTURE
- *
- * buffers used with h/w rendering and either NPOT or no egl_image_ext
- * are allocated with SW_READ_RARELY | HW_RENDER
- *
- */
-
- if (mSecure) {
- // secure buffer, don't store it into the GPU
- usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
- GraphicBuffer::USAGE_SW_WRITE_OFTEN;
- } else {
- // it's allowed to modify the usage flags here, but generally
- // the requested flags should be honored.
- // request EGLImage for all buffers
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
- }
- if (mProtectedByApp) {
- // need a hardware-protected path to external video sink
- usage |= GraphicBuffer::USAGE_PROTECTED;
- }
- return usage;
-}
-
uint32_t Layer::doTransaction(uint32_t flags)
{
const Layer::State& front(drawingState());
@@ -531,10 +342,12 @@ uint32_t Layer::doTransaction(uint32_t flags)
if (sizeChanged) {
// the size changed, we need to ask our client to request a new buffer
LOGD_IF(DEBUG_RESIZE,
- "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
+ "resize (layer=%p), requested (%dx%d), drawing (%d,%d), "
+ "fixedSize=%d",
this,
int(temp.requested_w), int(temp.requested_h),
- int(front.requested_w), int(front.requested_h));
+ int(front.requested_w), int(front.requested_h),
+ isFixedSize());
if (!isFixedSize()) {
// we're being resized and there is a freeze display request,
@@ -557,17 +370,7 @@ uint32_t Layer::doTransaction(uint32_t flags)
// record the new size, form this point on, when the client request
// a buffer, it'll get the new size.
- setBufferSize(temp.requested_w, temp.requested_h);
-
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- if (lcblk) {
- // all buffers need reallocation
- lcblk->reallocateAll();
- }
- } else {
- // record the new size
- setBufferSize(temp.requested_w, temp.requested_h);
+ mSurfaceTexture->setDefaultBufferSize(temp.requested_w, temp.requested_h);
}
}
@@ -582,16 +385,19 @@ uint32_t Layer::doTransaction(uint32_t flags)
return LayerBase::doTransaction(flags);
}
-void Layer::setBufferSize(uint32_t w, uint32_t h) {
+bool Layer::isFixedSize() const {
Mutex::Autolock _l(mLock);
- mWidth = w;
- mHeight = h;
- mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
+ return mFixedSize;
}
-bool Layer::isFixedSize() const {
+void Layer::setFixedSize(bool fixedSize)
+{
Mutex::Autolock _l(mLock);
- return mFixedSize;
+ mFixedSize = fixedSize;
+}
+
+bool Layer::isCropped() const {
+ return !mCurrentCrop.isEmpty();
}
// ----------------------------------------------------------------------------
@@ -600,61 +406,48 @@ bool Layer::isFixedSize() const {
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- if (!lcblk) {
- // client died
- recomputeVisibleRegions = true;
- return;
- }
-
- ssize_t buf = lcblk->retireAndLock();
- if (buf == NOT_ENOUGH_DATA) {
- // NOTE: This is not an error, it simply means there is nothing to
- // retire. The buffer is locked because we will use it
- // for composition later in the loop
- return;
- }
-
- if (buf < NO_ERROR) {
- LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
- mPostedDirtyRegion.clear();
- return;
- }
-
- // we retired a buffer, which becomes the new front buffer
+ if (android_atomic_and(0, &mQueuedFrames)) {
+ if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
+ // something happened!
+ recomputeVisibleRegions = true;
+ return;
+ }
- const bool noActiveBuffer = !mBufferManager.hasActiveBuffer();
- const bool activeBlending =
- noActiveBuffer ? true : needsBlending(mBufferManager.getActiveBuffer());
+ // signal another event if we have more frames waiting
+ if (mSurfaceTexture->getQueuedCount()) {
+ if (android_atomic_or(1, &mQueuedFrames) == 0) {
+ mFlinger->signalEvent();
+ }
+ }
- if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
- LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
- mPostedDirtyRegion.clear();
- return;
- }
+ mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
+ mSurfaceTexture->getTransformMatrix(mTextureMatrix);
- if (noActiveBuffer) {
- // we didn't have an active buffer, we need to recompute
- // our visible region
- recomputeVisibleRegions = true;
- }
+ const Rect crop(mSurfaceTexture->getCurrentCrop());
+ const uint32_t transform(mSurfaceTexture->getCurrentTransform());
+ if ((crop != mCurrentCrop) || (transform != mCurrentTransform)) {
+ mCurrentCrop = crop;
+ mCurrentTransform = transform;
+ mFlinger->invalidateHwcGeometry();
+ }
- sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
- if (newFrontBuffer != NULL) {
- if (!noActiveBuffer && activeBlending != needsBlending(newFrontBuffer)) {
- // new buffer has different opacity than previous active buffer, need
- // to recompute visible regions accordingly
+ const bool opacity(getOpacityForFormat(mActiveBuffer->format));
+ if (opacity != mCurrentOpacity) {
+ mCurrentOpacity = opacity;
recomputeVisibleRegions = true;
}
- // get the dirty region
- // compute the posted region
- const Region dirty(lcblk->getDirtyRegion(buf));
- mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
+ const GLenum target(mSurfaceTexture->getCurrentTextureTarget());
+ glTexParameterx(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterx(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// update the layer size and release freeze-lock
const Layer::State& front(drawingState());
+
+ // FIXME: mPostedDirtyRegion = dirty & bounds
+ mPostedDirtyRegion.set(front.w, front.h);
+
+ sp<GraphicBuffer> newFrontBuffer(mActiveBuffer);
if ((newFrontBuffer->getWidth() == front.requested_w &&
newFrontBuffer->getHeight() == front.requested_h) ||
isFixedSize())
@@ -685,35 +478,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
// we now have the correct size, unfreeze the screen
mFreezeLock.clear();
}
-
- // get the crop region
- setBufferCrop( lcblk->getCrop(buf) );
-
- // get the transformation
- setBufferTransform( lcblk->getTransform(buf) );
-
- } else {
- // this should not happen unless we ran out of memory while
- // allocating the buffer. we're hoping that things will get back
- // to normal the next time the app tries to draw into this buffer.
- // meanwhile, pretend the screen didn't update.
- mPostedDirtyRegion.clear();
- }
-
- if (lcblk->getQueuedCount()) {
- // signal an event if we have more buffers waiting
- mFlinger->signalEvent();
}
-
- /* a buffer was posted, so we need to call reloadTexture(), which
- * will update our internal data structures (eg: EGLImageKHR or
- * texture names). we need to do this even if mPostedDirtyRegion is
- * empty -- it's orthogonal to the fact that a new buffer was posted,
- * for instance, a degenerate case could be that the user did an empty
- * update but repainted the buffer with appropriate content (after a
- * resize for instance).
- */
- reloadTexture( mPostedDirtyRegion );
}
void Layer::unlockPageFlip(
@@ -746,329 +511,36 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
{
LayerBaseClient::dump(result, buffer, SIZE);
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- uint32_t totalTime = 0;
- if (lcblk) {
- SharedBufferStack::Statistics stats = lcblk->getStats();
- totalTime= stats.totalTime;
- result.append( lcblk->dump(" ") );
- }
-
- sp<const GraphicBuffer> buf0(getBuffer(0));
- sp<const GraphicBuffer> buf1(getBuffer(1));
- uint32_t w0=0, h0=0, s0=0;
- uint32_t w1=0, h1=0, s1=0;
+ sp<const GraphicBuffer> buf0(mActiveBuffer);
+ uint32_t w0=0, h0=0, s0=0, f0=0;
if (buf0 != 0) {
w0 = buf0->getWidth();
h0 = buf0->getHeight();
s0 = buf0->getStride();
- }
- if (buf1 != 0) {
- w1 = buf1->getWidth();
- h1 = buf1->getHeight();
- s1 = buf1->getStride();
+ f0 = buf0->format;
}
snprintf(buffer, SIZE,
" "
- "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
- " freezeLock=%p, dq-q-time=%u us\n",
- mFormat, w0, h0, s0, w1, h1, s1,
- getFreezeLock().get(), totalTime);
+ "format=%2d, activeBuffer=[%3ux%3u:%3u,%3u],"
+ " freezeLock=%p, queued-frames=%d\n",
+ mFormat, w0, h0, s0,f0,
+ getFreezeLock().get(), mQueuedFrames);
result.append(buffer);
-}
-
-// ---------------------------------------------------------------------------
-
-Layer::ClientRef::ClientRef()
- : mControlBlock(0), mToken(-1) {
-}
-
-Layer::ClientRef::~ClientRef() {
-}
-int32_t Layer::ClientRef::getToken() const {
- Mutex::Autolock _l(mLock);
- return mToken;
-}
-
-sp<UserClient> Layer::ClientRef::getClient() const {
- Mutex::Autolock _l(mLock);
- return mUserClient.promote();
-}
-
-status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,
- const sp<SharedBufferServer>& sharedClient, int32_t token) {
- Mutex::Autolock _l(mLock);
-
- { // scope for strong mUserClient reference
- sp<UserClient> userClient(mUserClient.promote());
- if (userClient != 0 && mControlBlock != 0) {
- mControlBlock->setStatus(NO_INIT);
- }
+ if (mSurfaceTexture != 0) {
+ mSurfaceTexture->dump(result, " ", buffer, SIZE);
}
-
- mUserClient = uc;
- mToken = token;
- mControlBlock = sharedClient;
- return NO_ERROR;
-}
-
-sp<UserClient> Layer::ClientRef::getUserClientUnsafe() const {
- return mUserClient.promote();
-}
-
-// this class gives us access to SharedBufferServer safely
-// it makes sure the UserClient (and its associated shared memory)
-// won't go away while we're accessing it.
-Layer::ClientRef::Access::Access(const ClientRef& ref)
- : mControlBlock(0)
-{
- Mutex::Autolock _l(ref.mLock);
- mUserClientStrongRef = ref.mUserClient.promote();
- if (mUserClientStrongRef != 0)
- mControlBlock = ref.mControlBlock;
}
-Layer::ClientRef::Access::~Access()
-{
-}
-
-// ---------------------------------------------------------------------------
-
-Layer::BufferManager::BufferManager(TextureManager& tm)
- : mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
- mActiveBufferIndex(-1), mFailover(false)
-{
-}
-
-Layer::BufferManager::~BufferManager()
-{
-}
-
-status_t Layer::BufferManager::resize(size_t size,
- const sp<SurfaceFlinger>& flinger, EGLDisplay dpy)
-{
- Mutex::Autolock _l(mLock);
-
- if (size < mNumBuffers) {
- // If there is an active texture, move it into slot 0 if needed
- if (mActiveBufferIndex > 0) {
- BufferData activeBufferData = mBufferData[mActiveBufferIndex];
- mBufferData[mActiveBufferIndex] = mBufferData[0];
- mBufferData[0] = activeBufferData;
- mActiveBufferIndex = 0;
- }
-
- // Free the buffers that are no longer needed.
- for (size_t i = size; i < mNumBuffers; i++) {
- mBufferData[i].buffer = 0;
-
- // Create a message to destroy the textures on SurfaceFlinger's GL
- // thread.
- class MessageDestroyTexture : public MessageBase {
- Image mTexture;
- EGLDisplay mDpy;
- public:
- MessageDestroyTexture(const Image& texture, EGLDisplay dpy)
- : mTexture(texture), mDpy(dpy) { }
- virtual bool handler() {
- status_t err = Layer::BufferManager::destroyTexture(
- &mTexture, mDpy);
- LOGE_IF(err<0, "error destroying texture: %d (%s)",
- mTexture.name, strerror(-err));
- return true; // XXX: err == 0; ????
- }
- };
-
- MessageDestroyTexture *msg = new MessageDestroyTexture(
- mBufferData[i].texture, dpy);
-
- // Don't allow this texture to be cleaned up by
- // BufferManager::destroy.
- mBufferData[i].texture.name = -1U;
- mBufferData[i].texture.image = EGL_NO_IMAGE_KHR;
-
- // Post the message to the SurfaceFlinger object.
- flinger->postMessageAsync(msg);
- }
- }
-
- mNumBuffers = size;
- return NO_ERROR;
-}
-
-// only for debugging
-sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const {
- return mBufferData[index].buffer;
-}
-
-status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
- BufferData const * const buffers = mBufferData;
- Mutex::Autolock _l(mLock);
- mActiveBuffer = buffers[index].buffer;
- mActiveBufferIndex = index;
- return NO_ERROR;
-}
-
-size_t Layer::BufferManager::getActiveBufferIndex() const {
- return mActiveBufferIndex;
-}
-
-Texture Layer::BufferManager::getActiveTexture() const {
- Texture res;
- if (mFailover || mActiveBufferIndex<0) {
- res = mFailoverTexture;
- } else {
- static_cast<Image&>(res) = mBufferData[mActiveBufferIndex].texture;
- }
- return res;
-}
-
-sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
- return mActiveBuffer;
-}
-
-bool Layer::BufferManager::hasActiveBuffer() const {
- return mActiveBufferIndex >= 0;
-}
-
-sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
-{
- BufferData* const buffers = mBufferData;
- sp<GraphicBuffer> buffer;
- Mutex::Autolock _l(mLock);
- buffer = buffers[index].buffer;
- buffers[index].buffer = 0;
- return buffer;
-}
-
-status_t Layer::BufferManager::attachBuffer(size_t index,
- const sp<GraphicBuffer>& buffer)
-{
- BufferData* const buffers = mBufferData;
- Mutex::Autolock _l(mLock);
- buffers[index].buffer = buffer;
- buffers[index].texture.dirty = true;
- return NO_ERROR;
-}
-
-status_t Layer::BufferManager::destroy(EGLDisplay dpy)
-{
- BufferData* const buffers = mBufferData;
- size_t num;
- { // scope for the lock
- Mutex::Autolock _l(mLock);
- num = mNumBuffers;
- for (size_t i=0 ; i<num ; i++) {
- buffers[i].buffer = 0;
- }
- }
- for (size_t i=0 ; i<num ; i++) {
- destroyTexture(&buffers[i].texture, dpy);
- }
- destroyTexture(&mFailoverTexture, dpy);
- return NO_ERROR;
-}
-
-status_t Layer::BufferManager::initEglImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& buffer)
-{
- status_t err = NO_INIT;
- ssize_t index = mActiveBufferIndex;
- if (index >= 0) {
- if (!mFailover) {
- {
- // Without that lock, there is a chance of race condition
- // where while composing a specific index, requestBuf
- // with the same index can be executed and touch the same data
- // that is being used in initEglImage.
- // (e.g. dirty flag in texture)
- Mutex::Autolock _l(mLock);
- Image& texture(mBufferData[index].texture);
- err = mTextureManager.initEglImage(&texture, dpy, buffer);
- }
- // if EGLImage fails, we switch to regular texture mode, and we
- // free all resources associated with using EGLImages.
- if (err == NO_ERROR) {
- mFailover = false;
- destroyTexture(&mFailoverTexture, dpy);
- } else {
- mFailover = true;
- const size_t num = mNumBuffers;
- for (size_t i=0 ; i<num ; i++) {
- destroyTexture(&mBufferData[i].texture, dpy);
- }
- }
- } else {
- // we failed once, don't try again
- err = BAD_VALUE;
- }
- }
- return err;
-}
-
-status_t Layer::BufferManager::loadTexture(
- const Region& dirty, const GGLSurface& t)
-{
- return mTextureManager.loadTexture(&mFailoverTexture, dirty, t);
-}
-
-status_t Layer::BufferManager::destroyTexture(Image* tex, EGLDisplay dpy)
-{
- if (tex->name != -1U) {
- glDeleteTextures(1, &tex->name);
- tex->name = -1U;
- }
- if (tex->image != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(dpy, tex->image);
- tex->image = EGL_NO_IMAGE_KHR;
- }
- return NO_ERROR;
-}
-
-// ---------------------------------------------------------------------------
-
-Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
- const sp<Layer>& owner)
- : Surface(flinger, owner->getIdentity(), owner)
-{
-}
-
-Layer::SurfaceLayer::~SurfaceLayer()
-{
-}
-
-sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
-{
- sp<GraphicBuffer> buffer;
- sp<Layer> owner(getOwner());
- if (owner != 0) {
- /*
- * requestBuffer() cannot be called from the main thread
- * as it could cause a dead-lock, since it may have to wait
- * on conditions updated my the main thread.
- */
- buffer = owner->requestBuffer(index, w, h, format, usage);
- }
- return buffer;
-}
-
-status_t Layer::SurfaceLayer::setBufferCount(int bufferCount)
+uint32_t Layer::getEffectiveUsage(uint32_t usage) const
{
- status_t err = DEAD_OBJECT;
- sp<Layer> owner(getOwner());
- if (owner != 0) {
- /*
- * setBufferCount() cannot be called from the main thread
- * as it could cause a dead-lock, since it may have to wait
- * on conditions updated my the main thread.
- */
- err = owner->setBufferCount(bufferCount);
+ // TODO: should we do something special if mSecure is set?
+ if (mProtectedByApp) {
+ // need a hardware-protected path to external video sink
+ usage |= GraphicBuffer::USAGE_PROTECTED;
}
- return err;
+ return usage;
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 278d64e9738c..e3fc13ddeef6 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -20,9 +20,11 @@
#include <stdint.h>
#include <sys/types.h>
+#include <gui/SurfaceTexture.h>
+
+#include <pixelflinger/pixelflinger.h>
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
-#include <pixelflinger/pixelflinger.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -30,8 +32,8 @@
#include <GLES/glext.h>
#include "LayerBase.h"
+#include "SurfaceTextureLayer.h"
#include "Transform.h"
-#include "TextureManager.h"
namespace android {
@@ -40,11 +42,10 @@ namespace android {
class FreezeLock;
class Client;
class GLExtensions;
-class UserClient;
// ---------------------------------------------------------------------------
-class Layer : public LayerBaseClient
+class Layer : public LayerBaseClient, private RefBase::Destroyer
{
public:
Layer(SurfaceFlinger* flinger, DisplayID display,
@@ -58,164 +59,59 @@ public:
status_t setBuffers(uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags=0);
- // associate a UserClient to this Layer
- status_t setToken(const sp<UserClient>& uc, SharedClient* sc, int32_t idx);
- int32_t getToken() const;
- sp<UserClient> getClient() const;
-
// Set this Layer's buffers size
- void setBufferSize(uint32_t w, uint32_t h);
bool isFixedSize() const;
// LayerBase interface
virtual void setGeometry(hwc_layer_t* hwcl);
virtual void setPerFrameData(hwc_layer_t* hwcl);
- virtual void drawForSreenShot() const;
virtual void onDraw(const Region& clip) const;
virtual uint32_t doTransaction(uint32_t transactionFlags);
virtual void lockPageFlip(bool& recomputeVisibleRegions);
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
- virtual bool needsBlending(const sp<GraphicBuffer>& buffer) const;
- virtual bool needsBlending() const;
+ virtual bool isOpaque() const;
virtual bool needsDithering() const { return mNeedsDithering; }
- virtual bool needsFiltering() const;
virtual bool isSecure() const { return mSecure; }
virtual bool isProtected() const;
- virtual sp<Surface> createSurface() const;
virtual void onRemoved();
// only for debugging
- inline sp<GraphicBuffer> getBuffer(int i) const {
- return mBufferManager.getBuffer(i); }
- // only for debugging
- inline const sp<FreezeLock>& getFreezeLock() const {
- return mFreezeLock; }
+ inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; }
protected:
- virtual void destroy() const;
+ virtual void destroy(RefBase const* base);
+ virtual void onFirstRef();
virtual void dump(String8& result, char* scratch, size_t size) const;
private:
- void reloadTexture(const Region& dirty);
+ friend class SurfaceTextureLayer;
+ void onFrameQueued();
+ virtual sp<ISurface> createSurface();
uint32_t getEffectiveUsage(uint32_t usage) const;
- sp<GraphicBuffer> requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
- status_t setBufferCount(int bufferCount);
-
- // -----------------------------------------------------------------------
-
- class SurfaceLayer : public LayerBaseClient::Surface {
- public:
- SurfaceLayer(const sp<SurfaceFlinger>& flinger, const sp<Layer>& owner);
- ~SurfaceLayer();
- private:
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
- virtual status_t setBufferCount(int bufferCount);
- sp<Layer> getOwner() const {
- return static_cast<Layer*>(Surface::getOwner().get());
- }
- };
- friend class SurfaceLayer;
+ void setFixedSize(bool fixedSize);
+ bool isCropped() const;
+ static bool getOpacityForFormat(uint32_t format);
// -----------------------------------------------------------------------
- class ClientRef {
- ClientRef(const ClientRef& rhs);
- ClientRef& operator = (const ClientRef& rhs);
- mutable Mutex mLock;
- // binder thread, page-flip thread
- sp<SharedBufferServer> mControlBlock;
- wp<UserClient> mUserClient;
- int32_t mToken;
- public:
- ClientRef();
- ~ClientRef();
- int32_t getToken() const;
- sp<UserClient> getClient() const;
- status_t setToken(const sp<UserClient>& uc,
- const sp<SharedBufferServer>& sharedClient, int32_t token);
- sp<UserClient> getUserClientUnsafe() const;
- class Access {
- Access(const Access& rhs);
- Access& operator = (const Access& rhs);
- sp<UserClient> mUserClientStrongRef;
- sp<SharedBufferServer> mControlBlock;
- public:
- Access(const ClientRef& ref);
- ~Access();
- inline SharedBufferServer* get() const { return mControlBlock.get(); }
- };
- friend class Access;
- };
-
- // -----------------------------------------------------------------------
-
- class BufferManager {
- static const size_t NUM_BUFFERS = 2;
- struct BufferData {
- sp<GraphicBuffer> buffer;
- Image texture;
- };
- // this lock protect mBufferData[].buffer but since there
- // is very little contention, we have only one like for
- // the whole array, we also use it to protect mNumBuffers.
- mutable Mutex mLock;
- BufferData mBufferData[SharedBufferStack::NUM_BUFFER_MAX];
- size_t mNumBuffers;
- Texture mFailoverTexture;
- TextureManager& mTextureManager;
- ssize_t mActiveBufferIndex;
- sp<GraphicBuffer> mActiveBuffer;
- bool mFailover;
- static status_t destroyTexture(Image* tex, EGLDisplay dpy);
-
- public:
- static size_t getDefaultBufferCount() { return NUM_BUFFERS; }
- BufferManager(TextureManager& tm);
- ~BufferManager();
-
- // detach/attach buffer from/to given index
- sp<GraphicBuffer> detachBuffer(size_t index);
- status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer);
- // resize the number of active buffers
- status_t resize(size_t size, const sp<SurfaceFlinger>& flinger,
- EGLDisplay dpy);
-
- // ----------------------------------------------
- // must be called from GL thread
-
- // set/get active buffer index
- status_t setActiveBufferIndex(size_t index);
- size_t getActiveBufferIndex() const;
- // return the active buffer
- sp<GraphicBuffer> getActiveBuffer() const;
- // return wether we have an active buffer
- bool hasActiveBuffer() const;
- // return the active texture (or fail-over)
- Texture getActiveTexture() const;
- // frees resources associated with all buffers
- status_t destroy(EGLDisplay dpy);
- // load bitmap data into the active buffer
- status_t loadTexture(const Region& dirty, const GGLSurface& t);
- // make active buffer an EGLImage if needed
- status_t initEglImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& buffer);
-
- // ----------------------------------------------
- // only for debugging
- sp<GraphicBuffer> getBuffer(size_t index) const;
- };
-
- // -----------------------------------------------------------------------
+ // constants
+ sp<SurfaceTextureLayer> mSurfaceTexture;
+ GLuint mTextureName;
// thread-safe
- ClientRef mUserClientRef;
+ volatile int32_t mQueuedFrames;
+
+ // main thread
+ sp<GraphicBuffer> mActiveBuffer;
+ GLfloat mTextureMatrix[16];
+ Rect mCurrentCrop;
+ uint32_t mCurrentTransform;
+ bool mCurrentOpacity;
// constants
PixelFormat mFormat;
const GLExtensions& mGLExtensions;
- bool mNeedsBlending;
+ bool mOpaqueLayer;
bool mNeedsDithering;
// page-flip thread (currently main thread)
@@ -226,18 +122,8 @@ private:
// page-flip thread and transaction thread (currently main thread)
sp<FreezeLock> mFreezeLock;
- // see threading usage in declaration
- TextureManager mTextureManager;
- BufferManager mBufferManager;
-
// binder thread, transaction thread
mutable Mutex mLock;
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mReqWidth;
- uint32_t mReqHeight;
- uint32_t mReqFormat;
- bool mNeedsScaling;
bool mFixedSize;
};
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 022f25145297..bcd8c8332590 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -32,8 +32,6 @@
#include "LayerBase.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
-#include "TextureManager.h"
-
namespace android {
@@ -44,7 +42,7 @@ int32_t LayerBase::sSequence = 1;
LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
: dpy(display), contentDirty(false),
sequence(uint32_t(android_atomic_inc(&sSequence))),
- mFlinger(flinger),
+ mFlinger(flinger), mFiltering(false),
mNeedsFiltering(false),
mOrientation(0),
mLeft(0), mTop(0),
@@ -54,8 +52,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
{
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
mFlags = hw.getFlags();
- mBufferCrop.makeInvalid();
- mBufferTransform = 0;
}
LayerBase::~LayerBase()
@@ -310,6 +306,16 @@ void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
hwcl->handle = NULL;
}
+void LayerBase::setFiltering(bool filtering)
+{
+ mFiltering = filtering;
+}
+
+bool LayerBase::getFiltering() const
+{
+ return mFiltering;
+}
+
void LayerBase::draw(const Region& clip) const
{
// reset GL state
@@ -318,10 +324,12 @@ void LayerBase::draw(const Region& clip) const
onDraw(clip);
}
-void LayerBase::drawForSreenShot() const
+void LayerBase::drawForSreenShot()
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ setFiltering(true);
onDraw( Region(hw.bounds()) );
+ setFiltering(false);
}
void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
@@ -332,8 +340,12 @@ void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
const uint32_t fbHeight = hw.getHeight();
glColor4f(red,green,blue,alpha);
- TextureManager::deactivateTextures();
-
+#if defined(GL_OES_EGL_image_external)
+ if (GLExtensions::getInstance().haveTextureExternal()) {
+ glDisable(GL_TEXTURE_EXTERNAL_OES);
+ }
+#endif
+ glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glDisable(GL_DITHER);
@@ -354,24 +366,11 @@ void LayerBase::clearWithOpenGL(const Region& clip) const
clearWithOpenGL(clip,0,0,0,0);
}
-template <typename T>
-static inline
-void swap(T& a, T& b) {
- T t(a);
- a = b;
- b = t;
-}
-
-void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
+void LayerBase::drawWithOpenGL(const Region& clip) const
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const uint32_t fbHeight = hw.getHeight();
const State& s(drawingState());
-
- // bind our texture
- TextureManager::activateTexture(texture, needsFiltering());
- uint32_t width = texture.width;
- uint32_t height = texture.height;
GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
if (UNLIKELY(s.alpha < 0xFF)) {
@@ -387,7 +386,7 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
} else {
glColor4f(1, 1, 1, 1);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- if (needsBlending()) {
+ if (!isOpaque()) {
glEnable(GL_BLEND);
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
} else {
@@ -395,86 +394,20 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
}
}
- /*
- * compute texture coordinates
- * here, we handle NPOT, cropping and buffer transformations
- */
-
- GLfloat cl, ct, cr, cb;
- if (!mBufferCrop.isEmpty()) {
- // source is cropped
- const GLfloat us = (texture.NPOTAdjust ? texture.wScale : 1.0f) / width;
- const GLfloat vs = (texture.NPOTAdjust ? texture.hScale : 1.0f) / height;
- cl = mBufferCrop.left * us;
- ct = mBufferCrop.top * vs;
- cr = mBufferCrop.right * us;
- cb = mBufferCrop.bottom * vs;
- } else {
- cl = 0;
- ct = 0;
- cr = (texture.NPOTAdjust ? texture.wScale : 1.0f);
- cb = (texture.NPOTAdjust ? texture.hScale : 1.0f);
- }
-
- /*
- * For the buffer transformation, we apply the rotation last.
- * Since we're transforming the texture-coordinates, we need
- * to apply the inverse of the buffer transformation:
- * inverse( FLIP_V -> FLIP_H -> ROT_90 )
- * <=> inverse( ROT_90 * FLIP_H * FLIP_V )
- * = inverse(FLIP_V) * inverse(FLIP_H) * inverse(ROT_90)
- * = FLIP_V * FLIP_H * ROT_270
- * <=> ROT_270 -> FLIP_H -> FLIP_V
- *
- * The rotation is performed first, in the texture coordinate space.
- *
- */
-
struct TexCoords {
GLfloat u;
GLfloat v;
};
- enum {
- // name of the corners in the texture map
- LB = 0, // left-bottom
- LT = 1, // left-top
- RT = 2, // right-top
- RB = 3 // right-bottom
- };
-
- // vertices in screen space
- int vLT = LB;
- int vLB = LT;
- int vRB = RT;
- int vRT = RB;
-
- // the texture's source is rotated
- uint32_t transform = mBufferTransform;
- if (transform & HAL_TRANSFORM_ROT_90) {
- vLT = RB;
- vLB = LB;
- vRB = LT;
- vRT = RT;
- }
- if (transform & HAL_TRANSFORM_FLIP_V) {
- swap(vLT, vLB);
- swap(vRT, vRB);
- }
- if (transform & HAL_TRANSFORM_FLIP_H) {
- swap(vLT, vRT);
- swap(vLB, vRB);
- }
-
TexCoords texCoords[4];
- texCoords[vLT].u = cl;
- texCoords[vLT].v = ct;
- texCoords[vLB].u = cl;
- texCoords[vLB].v = cb;
- texCoords[vRB].u = cr;
- texCoords[vRB].v = cb;
- texCoords[vRT].u = cr;
- texCoords[vRT].v = ct;
+ texCoords[0].u = 0;
+ texCoords[0].v = 1;
+ texCoords[1].u = 0;
+ texCoords[1].v = 0;
+ texCoords[2].u = 1;
+ texCoords[2].v = 0;
+ texCoords[3].u = 1;
+ texCoords[3].v = 1;
if (needsDithering()) {
glEnable(GL_DITHER);
@@ -497,20 +430,6 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
-void LayerBase::setBufferCrop(const Rect& crop) {
- if (mBufferCrop != crop) {
- mBufferCrop = crop;
- mFlinger->invalidateHwcGeometry();
- }
-}
-
-void LayerBase::setBufferTransform(uint32_t transform) {
- if (mBufferTransform != transform) {
- mBufferTransform = transform;
- mFlinger->invalidateHwcGeometry();
- }
-}
-
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
{
const Layer::State& s(drawingState());
@@ -518,10 +437,10 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
"+ %s %p\n"
" "
"z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
- "needsBlending=%1d, needsDithering=%1d, invalidate=%1d, "
+ "isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
getTypeId(), this, s.z, tx(), ty(), s.w, s.h,
- needsBlending(), needsDithering(), contentDirty,
+ isOpaque(), needsDithering(), contentDirty,
s.alpha, s.flags,
s.transform[0][0], s.transform[0][1],
s.transform[1][0], s.transform[1][1]);
@@ -555,9 +474,22 @@ LayerBaseClient::~LayerBaseClient()
}
}
-sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
+sp<ISurface> LayerBaseClient::createSurface()
+{
+ class BSurface : public BnSurface, public LayerCleaner {
+ virtual sp<ISurfaceTexture> getSurfaceTexture() const { return 0; }
+ public:
+ BSurface(const sp<SurfaceFlinger>& flinger,
+ const sp<LayerBaseClient>& layer)
+ : LayerCleaner(flinger, layer) { }
+ };
+ sp<ISurface> sur(new BSurface(mFlinger, this));
+ return sur;
+}
+
+sp<ISurface> LayerBaseClient::getSurface()
{
- sp<Surface> s;
+ sp<ISurface> s;
Mutex::Autolock _l(mLock);
LOG_ALWAYS_FATAL_IF(mHasSurface,
@@ -573,12 +505,6 @@ wp<IBinder> LayerBaseClient::getSurfaceBinder() const {
return mClientSurfaceBinder;
}
-sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const
-{
- return new Surface(mFlinger, mIdentity,
- const_cast<LayerBaseClient *>(this));
-}
-
void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
{
LayerBase::dump(result, buffer, SIZE);
@@ -601,44 +527,14 @@ void LayerBaseClient::shortDump(String8& result, char* scratch, size_t size) con
// ---------------------------------------------------------------------------
-LayerBaseClient::Surface::Surface(
- const sp<SurfaceFlinger>& flinger,
- int identity,
- const sp<LayerBaseClient>& owner)
- : mFlinger(flinger), mIdentity(identity), mOwner(owner)
-{
+LayerBaseClient::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
+ const sp<LayerBaseClient>& layer)
+ : mFlinger(flinger), mLayer(layer) {
}
-LayerBaseClient::Surface::~Surface()
-{
- /*
- * This is a good place to clean-up all client resources
- */
-
+LayerBaseClient::LayerCleaner::~LayerCleaner() {
// destroy client resources
- mFlinger->destroySurface(mOwner);
-}
-
-sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
- sp<LayerBaseClient> owner(mOwner.promote());
- return owner;
-}
-
-status_t LayerBaseClient::Surface::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- return BnSurface::onTransact(code, data, reply, flags);
-}
-
-sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
-{
- return NULL;
-}
-
-status_t LayerBaseClient::Surface::setBufferCount(int bufferCount)
-{
- return INVALID_OPERATION;
+ mFlinger->destroySurface(mLayer);
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 6c49a19720d8..faf71ddbe0dd 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -29,7 +29,6 @@
#include <ui/Region.h>
#include <surfaceflinger/ISurfaceComposerClient.h>
-#include <private/surfaceflinger/SharedBufferStack.h>
#include <private/surfaceflinger/LayerState.h>
#include <pixelflinger/pixelflinger.h>
@@ -43,13 +42,12 @@ namespace android {
// ---------------------------------------------------------------------------
-class DisplayHardware;
class Client;
+class DisplayHardware;
class GraphicBuffer;
class GraphicPlane;
class LayerBaseClient;
class SurfaceFlinger;
-class Texture;
// ---------------------------------------------------------------------------
@@ -121,7 +119,7 @@ public:
* to perform the actual drawing.
*/
virtual void draw(const Region& clip) const;
- virtual void drawForSreenShot() const;
+ virtual void drawForSreenShot();
/**
* onDraw - draws the surface.
@@ -174,9 +172,9 @@ public:
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
/**
- * needsBlending - true if this surface needs blending
+ * isOpaque - true if this surface is opaque
*/
- virtual bool needsBlending() const { return false; }
+ virtual bool isOpaque() const { return true; }
/**
* needsDithering - true if this surface needs dithering
@@ -184,11 +182,9 @@ public:
virtual bool needsDithering() const { return false; }
/**
- * needsLinearFiltering - true if this surface needs filtering
+ * needsLinearFiltering - true if this surface's state requires filtering
*/
- virtual bool needsFiltering() const {
- return (!(mFlags & DisplayHardware::SLOW_CONFIG)) && mNeedsFiltering;
- }
+ virtual bool needsFiltering() const { return mNeedsFiltering; }
/**
* isSecure - true if this surface is secure, that is if it prevents
@@ -231,21 +227,25 @@ protected:
void clearWithOpenGL(const Region& clip, GLclampf r, GLclampf g,
GLclampf b, GLclampf alpha) const;
void clearWithOpenGL(const Region& clip) const;
- void drawWithOpenGL(const Region& clip, const Texture& texture) const;
-
- // these must be called from the post/drawing thread
- void setBufferCrop(const Rect& crop);
- void setBufferTransform(uint32_t transform);
+ void drawWithOpenGL(const Region& clip) const;
+
+ void setFiltering(bool filtering);
+ bool getFiltering() const;
sp<SurfaceFlinger> mFlinger;
uint32_t mFlags;
- // post/drawing thread
- Rect mBufferCrop;
- uint32_t mBufferTransform;
+private:
+ // accessed only in the main thread
+ // Whether filtering is forced on or not
+ bool mFiltering;
// cached during validateVisibility()
+ // Whether filtering is needed b/c of the drawingstate
bool mNeedsFiltering;
+
+protected:
+ // cached during validateVisibility()
int32_t mOrientation;
GLfloat mVertices[4][2];
Rect mTransformedBounds;
@@ -281,52 +281,38 @@ private:
class LayerBaseClient : public LayerBase
{
public:
- class Surface;
-
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client);
- virtual ~LayerBaseClient();
- sp<Surface> getSurface();
+ virtual ~LayerBaseClient();
+
+ sp<ISurface> getSurface();
wp<IBinder> getSurfaceBinder() const;
- virtual sp<Surface> createSurface() const;
+
virtual sp<LayerBaseClient> getLayerBaseClient() const {
return const_cast<LayerBaseClient*>(this); }
+
virtual const char* getTypeId() const { return "LayerBaseClient"; }
uint32_t getIdentity() const { return mIdentity; }
- class Surface : public BnSurface {
- public:
- int32_t getIdentity() const { return mIdentity; }
-
- protected:
- Surface(const sp<SurfaceFlinger>& flinger, int identity,
- const sp<LayerBaseClient>& owner);
- virtual ~Surface();
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags);
- sp<LayerBaseClient> getOwner() const;
-
- private:
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
- virtual status_t setBufferCount(int bufferCount);
-
- protected:
- friend class LayerBaseClient;
- sp<SurfaceFlinger> mFlinger;
- int32_t mIdentity;
- wp<LayerBaseClient> mOwner;
- };
-
- friend class Surface;
-
protected:
virtual void dump(String8& result, char* scratch, size_t size) const;
virtual void shortDump(String8& result, char* scratch, size_t size) const;
+ class LayerCleaner {
+ sp<SurfaceFlinger> mFlinger;
+ wp<LayerBaseClient> mLayer;
+ protected:
+ ~LayerCleaner();
+ public:
+ LayerCleaner(const sp<SurfaceFlinger>& flinger,
+ const sp<LayerBaseClient>& layer);
+ };
+
private:
+ virtual sp<ISurface> createSurface();
+
mutable Mutex mLock;
mutable bool mHasSurface;
wp<IBinder> mClientSurfaceBinder;
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index f79166d8acca..654817d61bbe 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -65,8 +65,6 @@ void LayerDim::onDraw(const Region& clip) const
glDisable(GL_TEXTURE_EXTERNAL_OES);
}
#endif
- glDisable(GL_TEXTURE_2D);
-
glVertexPointer(2, GL_FLOAT, 0, mVertices);
while (it != end) {
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index 75f9a8928287..8770e6d865c1 100644
--- a/services/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
@@ -37,7 +37,7 @@ public:
virtual ~LayerDim();
virtual void onDraw(const Region& clip) const;
- virtual bool needsBlending() const { return true; }
+ virtual bool isOpaque() const { return false; }
virtual bool isSecure() const { return false; }
virtual bool isProtectedByApp() const { return false; }
virtual bool isProtectedByDRM() const { return false; }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b7a51a4e58aa..97edfeef5057 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -53,6 +53,8 @@
#include "DisplayHardware/DisplayHardware.h"
#include "DisplayHardware/HWComposer.h"
+#include <private/surfaceflinger/SharedBufferStack.h>
+
/* ideally AID_GRAPHICS would be in a semi-public header
* or there would be a way to map a user/group name to its id
*/
@@ -133,17 +135,6 @@ sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
return bclient;
}
-sp<ISurfaceComposerClient> SurfaceFlinger::createClientConnection()
-{
- sp<ISurfaceComposerClient> bclient;
- sp<UserClient> client(new UserClient(this));
- status_t err = client->initCheck();
- if (err == NO_ERROR) {
- bclient = client;
- }
- return bclient;
-}
-
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
{
sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
@@ -322,11 +313,6 @@ void SurfaceFlinger::signalEvent() {
mEventQueue.invalidate();
}
-void SurfaceFlinger::signal() const {
- // this is the IPC call
- const_cast<SurfaceFlinger*>(this)->signalEvent();
-}
-
bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const {
Mutex::Autolock _l(mStateLock);
sp<IBinder> surfBinder(surface->asBinder());
@@ -658,7 +644,7 @@ void SurfaceFlinger::computeVisibleRegions(
// handle hidden surfaces by setting the visible region to empty
if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
- const bool translucent = layer->needsBlending();
+ const bool translucent = !layer->isOpaque();
const Rect bounds(layer->visibleBounds());
visibleRegion.set(bounds);
visibleRegion.andSelf(screenRegion);
@@ -921,7 +907,7 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
for (size_t i=0 ; i<count ; i++) {
if (cur[i].hints & HWC_HINT_CLEAR_FB) {
const sp<LayerBase>& layer(layers[i]);
- if (!(layer->needsBlending())) {
+ if (layer->isOpaque()) {
transparent.orSelf(layer->visibleRegionScreen);
}
}
@@ -979,8 +965,6 @@ void SurfaceFlinger::debugFlashRegions()
composeSurfaces(repaint);
}
- TextureManager::deactivateTextures();
-
glDisable(GL_BLEND);
glDisable(GL_DITHER);
glDisable(GL_SCISSOR_TEST);
@@ -1070,6 +1054,7 @@ void SurfaceFlinger::drawWormhole() const
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
@@ -1269,7 +1254,7 @@ sp<ISurface> SurfaceFlinger::createSurface(
uint32_t flags)
{
sp<LayerBaseClient> layer;
- sp<LayerBaseClient::Surface> surfaceHandle;
+ sp<ISurface> surfaceHandle;
if (int32_t(w|h) < 0) {
LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",
@@ -1300,13 +1285,13 @@ sp<ISurface> SurfaceFlinger::createSurface(
surfaceHandle = layer->getSurface();
if (surfaceHandle != 0) {
params->token = token;
- params->identity = surfaceHandle->getIdentity();
+ params->identity = layer->getIdentity();
params->width = w;
params->height = h;
params->format = format;
if (normalLayer != 0) {
Mutex::Autolock _l(mStateLock);
- mLayerMap.add(surfaceHandle->asBinder(), normalLayer);
+ mLayerMap.add(layer->getSurfaceBinder(), normalLayer);
}
}
@@ -1782,7 +1767,6 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
GLfloat vtx[8];
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
- glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tname);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -1900,6 +1884,7 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
glEnable(GL_SCISSOR_TEST);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDeleteTextures(1, &tname);
+ glDisable(GL_TEXTURE_2D);
return NO_ERROR;
}
@@ -1930,7 +1915,6 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
GLfloat vtx[8];
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
- glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tname);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -2044,6 +2028,7 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
glEnable(GL_SCISSOR_TEST);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDeleteTextures(1, &tname);
+ glDisable(GL_TEXTURE_2D);
return NO_ERROR;
}
@@ -2408,133 +2393,78 @@ sp<LayerBaseClient> Client::getLayerUser(int32_t i) const
return lbc;
}
-sp<IMemoryHeap> Client::getControlBlock() const {
- return 0;
-}
-ssize_t Client::getTokenForSurface(const sp<ISurface>& sur) const {
- return -1;
+
+status_t Client::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ // these must be checked
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ const int self_pid = getpid();
+ if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
+ // we're called from a different process, do the real check
+ if (!checkCallingPermission(
+ String16("android.permission.ACCESS_SURFACE_FLINGER")))
+ {
+ LOGE("Permission Denial: "
+ "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ }
+ }
+ return BnSurfaceComposerClient::onTransact(code, data, reply, flags);
}
+
+
sp<ISurface> Client::createSurface(
ISurfaceComposerClient::surface_data_t* params,
const String8& name,
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags)
{
- return mFlinger->createSurface(params, name, this,
- display, w, h, format, flags);
-}
-status_t Client::destroySurface(SurfaceID sid) {
- return mFlinger->removeSurface(this, sid);
-}
-status_t Client::setState(int32_t count, const layer_state_t* states) {
- return mFlinger->setClientState(this, count, states);
-}
-
-// ---------------------------------------------------------------------------
-
-UserClient::UserClient(const sp<SurfaceFlinger>& flinger)
- : ctrlblk(0), mBitmap(0), mFlinger(flinger)
-{
- const int pgsize = getpagesize();
- const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
-
- mCblkHeap = new MemoryHeapBase(cblksize, 0,
- "SurfaceFlinger Client control-block");
-
- ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
- if (ctrlblk) { // construct the shared structure in-place.
- new(ctrlblk) SharedClient;
- }
-}
-
-UserClient::~UserClient()
-{
- if (ctrlblk) {
- ctrlblk->~SharedClient(); // destroy our shared-structure.
- }
-
/*
- * When a UserClient dies, it's unclear what to do exactly.
- * We could go ahead and destroy all surfaces linked to that client
- * however, it wouldn't be fair to the main Client
- * (usually the the window-manager), which might want to re-target
- * the layer to another UserClient.
- * I think the best is to do nothing, or not much; in most cases the
- * WM itself will go ahead and clean things up when it detects a client of
- * his has died.
- * The remaining question is what to display? currently we keep
- * just keep the current buffer.
+ * createSurface must be called from the GL thread so that it can
+ * have access to the GL context.
*/
-}
-status_t UserClient::initCheck() const {
- return ctrlblk == 0 ? NO_INIT : NO_ERROR;
-}
-
-void UserClient::detachLayer(const Layer* layer)
-{
- int32_t name = layer->getToken();
- if (name >= 0) {
- int32_t mask = 1LU<<name;
- if ((android_atomic_and(~mask, &mBitmap) & mask) == 0) {
- LOGW("token %d wasn't marked as used %08x", name, int(mBitmap));
+ class MessageCreateSurface : public MessageBase {
+ sp<ISurface> result;
+ SurfaceFlinger* flinger;
+ ISurfaceComposerClient::surface_data_t* params;
+ Client* client;
+ const String8& name;
+ DisplayID display;
+ uint32_t w, h;
+ PixelFormat format;
+ uint32_t flags;
+ public:
+ MessageCreateSurface(SurfaceFlinger* flinger,
+ ISurfaceComposerClient::surface_data_t* params,
+ const String8& name, Client* client,
+ DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t flags)
+ : flinger(flinger), params(params), client(client), name(name),
+ display(display), w(w), h(h), format(format), flags(flags)
+ {
}
- }
-}
-
-sp<IMemoryHeap> UserClient::getControlBlock() const {
- return mCblkHeap;
-}
-
-ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const
-{
- int32_t name = NAME_NOT_FOUND;
- sp<Layer> layer(mFlinger->getLayer(sur));
- if (layer == 0) {
- return name;
- }
-
- // if this layer already has a token, just return it
- name = layer->getToken();
- if ((name >= 0) && (layer->getClient() == this)) {
- return name;
- }
-
- name = 0;
- do {
- int32_t mask = 1LU<<name;
- if ((android_atomic_or(mask, &mBitmap) & mask) == 0) {
- // we found and locked that name
- status_t err = layer->setToken(
- const_cast<UserClient*>(this), ctrlblk, name);
- if (err != NO_ERROR) {
- // free the name
- android_atomic_and(~mask, &mBitmap);
- name = err;
- }
- break;
+ sp<ISurface> getResult() const { return result; }
+ virtual bool handler() {
+ result = flinger->createSurface(params, name, client,
+ display, w, h, format, flags);
+ return true;
}
- if (++name >= int32_t(SharedBufferStack::NUM_LAYERS_MAX))
- name = NO_MEMORY;
- } while(name >= 0);
-
- //LOGD("getTokenForSurface(%p) => %d (client=%p, bitmap=%08lx)",
- // sur->asBinder().get(), name, this, mBitmap);
- return name;
-}
+ };
-sp<ISurface> UserClient::createSurface(
- ISurfaceComposerClient::surface_data_t* params,
- const String8& name,
- DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags) {
- return 0;
+ sp<MessageBase> msg = new MessageCreateSurface(mFlinger.get(),
+ params, name, this, display, w, h, format, flags);
+ mFlinger->postMessageSync(msg);
+ return static_cast<MessageCreateSurface*>( msg.get() )->getResult();
}
-status_t UserClient::destroySurface(SurfaceID sid) {
- return INVALID_OPERATION;
+status_t Client::destroySurface(SurfaceID sid) {
+ return mFlinger->removeSurface(this, sid);
}
-status_t UserClient::setState(int32_t count, const layer_state_t* states) {
- return INVALID_OPERATION;
+status_t Client::setState(int32_t count, const layer_state_t* states) {
+ return mFlinger->setClientState(this, count, states);
}
// ---------------------------------------------------------------------------
@@ -2547,11 +2477,11 @@ sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h
PixelFormat format, uint32_t usage) {
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
status_t err = graphicBuffer->initCheck();
- if (err != 0) {
- LOGE("createGraphicBuffer: init check failed: %d", err);
- return 0;
- } else if (graphicBuffer->handle == 0) {
- LOGE("createGraphicBuffer: unable to create GraphicBuffer");
+ if (err != 0 || graphicBuffer->handle == 0) {
+ GraphicBuffer::dumpAllocationsToSystemLog();
+ LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
+ "failed (%s), handle=%p",
+ w, h, strerror(-err), graphicBuffer->handle);
return 0;
}
return graphicBuffer;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 992861a0af93..af1ef04dc29e 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -50,6 +50,7 @@ class DisplayHardware;
class FreezeLock;
class Layer;
class LayerDim;
+struct surface_flinger_cblk_t;
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
@@ -72,14 +73,14 @@ public:
private:
// ISurfaceComposerClient interface
- virtual sp<IMemoryHeap> getControlBlock() const;
- virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const;
virtual sp<ISurface> createSurface(
surface_data_t* params, const String8& name,
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
uint32_t flags);
virtual status_t destroySurface(SurfaceID surfaceId);
virtual status_t setState(int32_t count, const layer_state_t* states);
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
// constant
sp<SurfaceFlinger> mFlinger;
@@ -92,40 +93,6 @@ private:
mutable Mutex mLock;
};
-class UserClient : public BnSurfaceComposerClient
-{
-public:
- // pointer to this client's control block
- SharedClient* ctrlblk;
-
-public:
- UserClient(const sp<SurfaceFlinger>& flinger);
- ~UserClient();
-
- status_t initCheck() const;
-
- // protected by SurfaceFlinger::mStateLock
- void detachLayer(const Layer* layer);
-
-private:
-
- // ISurfaceComposerClient interface
- virtual sp<IMemoryHeap> getControlBlock() const;
- virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const;
- virtual sp<ISurface> createSurface(
- surface_data_t* params, const String8& name,
- DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
- uint32_t flags);
- virtual status_t destroySurface(SurfaceID surfaceId);
- virtual status_t setState(int32_t count, const layer_state_t* states);
-
- // atomic-ops
- mutable volatile int32_t mBitmap;
-
- sp<IMemoryHeap> mCblkHeap;
- sp<SurfaceFlinger> mFlinger;
-};
-
class GraphicBufferAlloc : public BnGraphicBufferAlloc
{
public:
@@ -199,7 +166,6 @@ public:
// ISurfaceComposer interface
virtual sp<ISurfaceComposerClient> createConnection();
- virtual sp<ISurfaceComposerClient> createClientConnection();
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
virtual sp<IMemoryHeap> getCblk() const;
virtual void bootFinished();
@@ -208,7 +174,6 @@ public:
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags);
virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags);
virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags);
- virtual void signal() const;
virtual bool authenticateSurface(const sp<ISurface>& surface) const;
virtual status_t captureScreen(DisplayID dpy,
@@ -235,7 +200,6 @@ private:
friend class Client;
friend class LayerBase;
friend class LayerBaseClient;
- friend class LayerBaseClient::Surface;
friend class Layer;
friend class LayerDim;
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
new file mode 100644
index 000000000000..60fa96591061
--- /dev/null
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -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.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+
+#include "Layer.h"
+#include "SurfaceTextureLayer.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+
+SurfaceTextureLayer::SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer)
+ : SurfaceTexture(tex), mLayer(layer) {
+}
+
+SurfaceTextureLayer::~SurfaceTextureLayer() {
+}
+
+
+status_t SurfaceTextureLayer::setDefaultBufferSize(uint32_t w, uint32_t h)
+{
+ //LOGD("%s, w=%u, h=%u", __PRETTY_FUNCTION__, w, h);
+ return SurfaceTexture::setDefaultBufferSize(w, h);
+}
+
+status_t SurfaceTextureLayer::setDefaultBufferFormat(uint32_t format)
+{
+ mDefaultFormat = format;
+ return NO_ERROR;
+}
+
+status_t SurfaceTextureLayer::setBufferCount(int bufferCount) {
+ status_t res = SurfaceTexture::setBufferCount(bufferCount);
+ return res;
+}
+
+status_t SurfaceTextureLayer::dequeueBuffer(int *buf,
+ uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+
+ status_t res(NO_INIT);
+ sp<Layer> layer(mLayer.promote());
+ if (layer != NULL) {
+ if (format == 0)
+ format = mDefaultFormat;
+ uint32_t effectiveUsage = layer->getEffectiveUsage(usage);
+ //LOGD("%s, w=%u, h=%u, format=%u, usage=%08x, effectiveUsage=%08x",
+ // __PRETTY_FUNCTION__, w, h, format, usage, effectiveUsage);
+ res = SurfaceTexture::dequeueBuffer(buf, w, h, format, effectiveUsage);
+ if (res == NO_ERROR) {
+ layer->setFixedSize(w && h);
+ }
+ }
+ return res;
+}
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h
new file mode 100644
index 000000000000..7faff548fd34
--- /dev/null
+++ b/services/surfaceflinger/SurfaceTextureLayer.h
@@ -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.
+ */
+
+#ifndef ANDROID_SURFACE_TEXTURE_LAYER_H
+#define ANDROID_SURFACE_TEXTURE_LAYER_H
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <gui/SurfaceTexture.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Layer;
+
+class SurfaceTextureLayer : public SurfaceTexture
+{
+ wp<Layer> mLayer;
+ uint32_t mDefaultFormat;
+
+public:
+ SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer);
+ ~SurfaceTextureLayer();
+
+ status_t setDefaultBufferSize(uint32_t w, uint32_t h);
+ status_t setDefaultBufferFormat(uint32_t format);
+
+public:
+ virtual status_t setBufferCount(int bufferCount);
+
+protected:
+ virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
+ uint32_t format, uint32_t usage);
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SURFACE_TEXTURE_LAYER_H
diff --git a/services/surfaceflinger/clz.h b/services/surfaceflinger/clz.h
index 0ddf986bff9f..ca445553f9ac 100644
--- a/services/surfaceflinger/clz.h
+++ b/services/surfaceflinger/clz.h
@@ -20,18 +20,10 @@
namespace android {
-int clz_impl(int32_t x);
-
-int inline clz(int32_t x)
-{
-#if defined(__arm__) && !defined(__thumb__)
+int inline clz(int32_t x) {
return __builtin_clz(x);
-#else
- return clz_impl(x);
-#endif
}
-
}; // namespace android
#endif /* ANDROID_SURFACE_FLINGER_CLZ_H */
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 7abae09eae70..171b3714d527 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -1803,33 +1803,33 @@ public final class CallManager {
Call call;
StringBuilder b = new StringBuilder();
- b.append("########### Dump CallManager ############");
- b.append("\nCallManager state = " + getState());
+ b.append("CallManager {");
+ b.append("\nstate = " + getState());
call = getActiveFgCall();
- b.append("\n - Foreground: " + getActiveFgCallState());
+ b.append("\n- Foreground: " + getActiveFgCallState());
b.append(" from " + call.getPhone());
- b.append("\n Conn: ").append(getFgCallConnections());
+ b.append("\n Conn: ").append(getFgCallConnections());
call = getFirstActiveBgCall();
- b.append("\n - Background: " + call.getState());
+ b.append("\n- Background: " + call.getState());
b.append(" from " + call.getPhone());
- b.append("\n Conn: ").append(getBgCallConnections());
+ b.append("\n Conn: ").append(getBgCallConnections());
call = getFirstActiveRingingCall();
- b.append("\n - Ringing: " +call.getState());
+ b.append("\n- Ringing: " +call.getState());
b.append(" from " + call.getPhone());
for (Phone phone : getAllPhones()) {
if (phone != null) {
- b.append("\n Phone: " + phone + ", name = " + phone.getPhoneName()
+ b.append("\nPhone: " + phone + ", name = " + phone.getPhoneName()
+ ", state = " + phone.getState());
call = phone.getForegroundCall();
- b.append("\n - Foreground: ").append(call);
+ b.append("\n- Foreground: ").append(call);
call = phone.getBackgroundCall();
b.append(" Background: ").append(call);
call = phone.getRingingCall();
b.append(" Ringing: ").append(call);
}
}
- b.append("\n########## End Dump CallManager ##########");
+ b.append("\n}");
return b.toString();
}
}
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 014901deb12f..457fa7aac3c1 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -19,6 +19,7 @@ package com.android.internal.telephony;
import android.content.Context;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
+import android.location.CountryDetector;
import android.net.Uri;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
@@ -29,6 +30,13 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberOfflineGeocoder;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+
+import java.util.Locale;
+
/**
* Looks up caller information for the given phone number.
@@ -72,7 +80,8 @@ public class CallerInfo {
*/
public String name;
public String phoneNumber;
- public String nomalizedNumber;
+ public String normalizedNumber;
+ public String geoDescription;
public String cnapName;
public int numberPresentation;
@@ -131,7 +140,7 @@ public class CallerInfo {
info.isCachedPhotoCurrent = false;
info.contactExists = false;
- if (VDBG) Log.v(TAG, "construct callerInfo from cursor");
+ if (VDBG) Log.v(TAG, "getCallerInfo() based on cursor...");
if (cursor != null) {
if (cursor.moveToFirst()) {
@@ -156,7 +165,7 @@ public class CallerInfo {
// Look for the normalized number
columnIndex = cursor.getColumnIndex(PhoneLookup.NORMALIZED_NUMBER);
if (columnIndex != -1) {
- info.nomalizedNumber = cursor.getString(columnIndex);
+ info.normalizedNumber = cursor.getString(columnIndex);
}
// Look for the label/type combo
@@ -236,6 +245,8 @@ public class CallerInfo {
* with all relevant fields empty or null.
*/
public static CallerInfo getCallerInfo(Context context, String number) {
+ if (VDBG) Log.v(TAG, "getCallerInfo() based on number...");
+
if (TextUtils.isEmpty(number)) {
return null;
}
@@ -473,6 +484,66 @@ public class CallerInfo {
}
/**
+ * Updates this CallerInfo's geoDescription field, based on the raw
+ * phone number in the phoneNumber field.
+ *
+ * (Note that the various getCallerInfo() methods do *not* set the
+ * geoDescription automatically; you need to call this method
+ * explicitly to get it.)
+ *
+ * @param context the context used to look up the current locale / country
+ * @param fallbackNumber if this CallerInfo's phoneNumber field is empty,
+ * this specifies a fallback number to use instead.
+ */
+ public void updateGeoDescription(Context context, String fallbackNumber) {
+ String number = TextUtils.isEmpty(phoneNumber) ? fallbackNumber : phoneNumber;
+ geoDescription = getGeoDescription(context, number);
+ }
+
+ /**
+ * @return a geographical description string for the specified number.
+ * @see com.google.i18n.phonenumbers.PhoneNumberOfflineGeocoder
+ */
+ private static String getGeoDescription(Context context, String number) {
+ if (VDBG) Log.v(TAG, "getGeoDescription('" + number + "')...");
+
+ if (TextUtils.isEmpty(number)) {
+ return null;
+ }
+
+ PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+ PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();
+
+ String countryIso;
+ Locale locale = context.getResources().getConfiguration().locale;
+ CountryDetector detector = (CountryDetector) context.getSystemService(
+ Context.COUNTRY_DETECTOR);
+ if (detector != null) {
+ countryIso = detector.detectCountry().getCountryIso();
+ } else {
+ countryIso = locale.getCountry();
+ Log.w(TAG, "No CountryDetector; falling back to countryIso based on locale: "
+ + countryIso);
+ }
+
+ PhoneNumber pn = null;
+ try {
+ pn = util.parse(number, countryIso);
+ if (VDBG) Log.v(TAG, "- parsed number: " + pn);
+ } catch (NumberParseException e) {
+ Log.w(TAG, "getGeoDescription: NumberParseException for incoming number '" + number + "'");
+ }
+
+ if (pn != null) {
+ String description = geocoder.getDescriptionForNumber(pn, locale);
+ if (VDBG) Log.v(TAG, "- got description: '" + description + "'");
+ return description;
+ } else {
+ return null;
+ }
+ }
+
+ /**
* @return a string debug representation of this instance.
*/
public String toString() {
@@ -482,8 +553,11 @@ public class CallerInfo {
if (VERBOSE_DEBUG) {
return new StringBuilder(384)
+ .append(super.toString() + " { ")
.append("\nname: " + name)
.append("\nphoneNumber: " + phoneNumber)
+ .append("\nnormalizedNumber: " + normalizedNumber)
+ .append("\ngeoDescription: " + geoDescription)
.append("\ncnapName: " + cnapName)
.append("\nnumberPresentation: " + numberPresentation)
.append("\nnamePresentation: " + namePresentation)
@@ -502,10 +576,11 @@ public class CallerInfo {
.append("\nemergency: " + mIsEmergency)
.append("\nvoicemail " + mIsVoiceMail)
.append("\ncontactExists " + contactExists)
+ .append(" }")
.toString();
} else {
return new StringBuilder(128)
- .append("CallerInfo { ")
+ .append(super.toString() + " { ")
.append("name " + ((name == null) ? "null" : "non-null"))
.append(", phoneNumber " + ((phoneNumber == null) ? "null" : "non-null"))
.append(" }")
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index c47e076a6707..bbd4232652c9 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -34,9 +34,11 @@ import android.text.TextUtils;
import android.util.Log;
/**
- * ASYNCHRONOUS QUERY API
+ * Helper class to make it easier to run asynchronous caller-id lookup queries.
+ * @see CallerInfo
+ *
+ * {@hide}
*/
-
public class CallerInfoAsyncQuery {
private static final boolean DBG = false;
private static final String LOG_TAG = "CallerInfoAsyncQuery";
@@ -239,12 +241,31 @@ public class CallerInfoAsyncQuery {
+ mCallerInfo);
}
+ // Final step: look up the geocoded description.
+ //
+ // For now, do this only if we *don't* have a valid name (i.e. if
+ // no contacts matched the phone number of the incoming call),
+ // since that's the only case where the incoming-call UI cares
+ // about this field.
+ // (TODO: But if we ever want the UI to show the geoDescription
+ // even when we *do* match a contact, we'll need to either call
+ // updateGeoDescription() unconditionally here, or possibly add a
+ // new parameter to CallerInfoAsyncQuery.startQuery() to force
+ // the geoDescription field to be populated.)
+ if (TextUtils.isEmpty(mCallerInfo.name)) {
+ // Actually when no contacts match the incoming phone number,
+ // the CallerInfo object is totally blank here (i.e. no name
+ // *or* phoneNumber). So we need to pass in cw.number as
+ // a fallback number.
+ mCallerInfo.updateGeoDescription(mQueryContext, cw.number);
+ }
+
// Use the number entered by the user for display.
if (!TextUtils.isEmpty(cw.number)) {
CountryDetector detector = (CountryDetector) mQueryContext.getSystemService(
Context.COUNTRY_DETECTOR);
mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number,
- mCallerInfo.nomalizedNumber,
+ mCallerInfo.normalizedNumber,
detector.detectCountry().getCountryIso());
}
}
@@ -412,7 +433,7 @@ public class CallerInfoAsyncQuery {
* Method to create a new CallerInfoAsyncQueryHandler object, ensuring correct
* state of context and uri.
*/
- private void allocate (Context context, Uri contactRef) {
+ private void allocate(Context context, Uri contactRef) {
if ((context == null) || (contactRef == null)){
throw new QueryPoolException("Bad context or query uri.");
}
@@ -424,7 +445,7 @@ public class CallerInfoAsyncQuery {
/**
* Releases the relevant data.
*/
- private void release () {
+ private void release() {
mHandler.mQueryContext = null;
mHandler.mQueryUri = null;
mHandler.mCallerInfo = null;
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 2c26f62b9a16..977b412f15b3 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -145,8 +145,10 @@ public abstract class DataConnectionTracker extends Handler {
public static final String APN_TYPE_KEY = "apnType";
- /** Delay between APN attempts */
- protected static final int APN_DELAY_MILLIS = 5000;
+ /** Delay between APN attempts.
+ Note the property override mechanism is there just for testing purpose only. */
+ protected static final int APN_DELAY_MILLIS =
+ SystemProperties.getInt("persist.radio.apn_delay", 5000);
// responds to the setInternalDataEnabled call - used internally to turn off data
// for example during emergency calls
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index abd87b89b5ec..318cf3728f54 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -125,6 +125,8 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
}
}
+ // Not sure if this is needed in CDMALTE phone.
+ // mDataRoaming = regCodeIsRoaming(regState);
mLteSS.setRadioTechnology(type);
mLteSS.setState(regCodeToServiceState(regState));
} else {
@@ -210,12 +212,6 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
if (DBG) log("pollStateDone: oldSS=[" + ss + "] newSS=[" + newSS + "]");
- if (cm.getSimState().isSIMReady()) {
- // If CSIM is used, check roaming status according to SID/NID
- // on EFcdmahome record.
- newSS.setRoaming(!isInHomeSidNid(newSS.getSystemId(), newSS.getNetworkId()));
- }
-
boolean hasRegistered = ss.getState() != ServiceState.STATE_IN_SERVICE
&& newSS.getState() == ServiceState.STATE_IN_SERVICE;
@@ -468,33 +464,6 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
return provisioningState;
}
- /**
- * Check whether the specified SID and NID pair appears in the HOME SID/NID list
- * read from NV or SIM.
- *
- * @return true if provided sid/nid pair belongs to operator's home network.
- */
- private boolean isInHomeSidNid(int sid, int nid) {
- // if SID/NID is not available, do not declare roaming.
- if (isSidsAllZeros()) return true;
-
- // length of SID/NID shold be same
- if (mHomeSystemId.length != mHomeNetworkId.length) return true;
-
- if (sid == 0) return true;
-
- for (int i = 0; i < mHomeSystemId.length; i++) {
- // Use SID only if NID is a reserved value.
- // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2)
- if ((mHomeSystemId[i] == sid) &&
- ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) ||
- (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) {
- return true;
- }
- }
- return false;
- }
-
@Override
protected void log(String s) {
Log.d(LOG_TAG, "[CdmaLteSST] " + s);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
index 58ef747b42d0..73b5d97c8b97 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
@@ -17,6 +17,7 @@ package com.android.internal.telephony.cdma;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.IccCardApplication.AppType;
import com.android.internal.telephony.IccFileHandler;
import com.android.internal.telephony.IccUtils;
import com.android.internal.telephony.MccTable;
@@ -438,9 +439,14 @@ public final class CdmaLteUiccRecords extends SIMRecords {
@Override
public boolean isProvisioned() {
- // Look for MDN and MIN field to determine if the SIM is provisioned.
- if ((mMdn != null) && (mMin != null)) return true;
-
- return false;
+ // If UICC card has CSIM app, look for MDN and MIN field
+ // to determine if the SIM is provisioned. Otherwise,
+ // consider the SIM is provisioned. (for case of ordinal
+ // USIM only UICC.)
+ if (phone.mIccCard.isApplicationOnIcc(AppType.APPTYPE_CSIM) &&
+ ((mMdn == null) || (mMin == null))) {
+ return false;
+ }
+ return true;
}
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index e41985ea3978..5ebdd22e3c7e 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -130,8 +130,8 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
private String curPlmn = null;
protected String mMdn;
- protected int mHomeSystemId[] = null;
- protected int mHomeNetworkId[] = null;
+ private int mHomeSystemId[] = null;
+ private int mHomeNetworkId[] = null;
protected String mMin;
protected String mPrlVersion;
protected boolean mIsMinInfoReady = false;
@@ -1481,7 +1481,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
}
}
- protected boolean isSidsAllZeros() {
+ private boolean isSidsAllZeros() {
if (mHomeSystemId != null) {
for (int i=0; i < mHomeSystemId.length; i++) {
if (mHomeSystemId[i] != 0) {
diff --git a/tests/BiDiTests/res/layout/frame_layout_rtl.xml b/tests/BiDiTests/res/layout/frame_layout_rtl.xml
index 258d44a1874b..a84904c430fa 100644
--- a/tests/BiDiTests/res/layout/frame_layout_rtl.xml
+++ b/tests/BiDiTests/res/layout/frame_layout_rtl.xml
@@ -21,7 +21,7 @@
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layoutDirection="ltr"
+ android:layoutDirection="rtl"
android:background="#FF000000">
<FrameLayout
diff --git a/tests/GridLayoutTest/res/layout/grid3.xml b/tests/GridLayoutTest/res/layout/grid3.xml
index 31dc75abfb9c..5cdacf74faa5 100644
--- a/tests/GridLayoutTest/res/layout/grid3.xml
+++ b/tests/GridLayoutTest/res/layout/grid3.xml
@@ -19,14 +19,17 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
+
android:useDefaultMargins="true"
android:marginsIncludedInAlignment="false"
+
android:columnCount="4"
>
<TextView
android:text="Email account"
android:textSize="48dip"
+
android:layout_columnSpan="4"
android:layout_gravity="center_horizontal"
/>
@@ -34,12 +37,14 @@
<TextView
android:text="You can configure email in just a few steps:"
android:textSize="20dip"
+
android:layout_columnSpan="4"
android:layout_gravity="left"
/>
<TextView
android:text="Email address:"
+
android:layout_gravity="right"
/>
@@ -49,6 +54,7 @@
<TextView
android:text="Password:"
+
android:layout_column="0"
android:layout_gravity="right"
/>
@@ -58,14 +64,15 @@
/>
<Space
- android:layout_rowWeight="1"
- android:layout_columnWeight="1"
android:layout_row="4"
android:layout_column="2"
+ android:layout_rowWeight="1"
+ android:layout_columnWeight="1"
/>
<Button
android:text="Manual setup"
+
android:layout_row="5"
android:layout_column="3"
android:layout_gravity="fill_horizontal"
@@ -73,6 +80,7 @@
<Button
android:text="Next"
+
android:layout_column="3"
android:layout_gravity="fill_horizontal"
/>
diff --git a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
index 5e29cf1ac8da..32365d7f7050 100644
--- a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
+++ b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
@@ -20,11 +20,15 @@ import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
-
-import android.widget.*;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.GridLayout;
+import android.widget.Space;
+import android.widget.TextView;
import static android.text.InputType.TYPE_CLASS_TEXT;
-import static android.view.inputmethod.EditorInfo.*;
+import static android.view.inputmethod.EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
+import static android.view.inputmethod.EditorInfo.TYPE_TEXT_VARIATION_PASSWORD;
import static android.widget.GridLayout.*;
public class Activity2 extends Activity {
@@ -42,12 +46,12 @@ public class Activity2 extends Activity {
Group row6 = new Group(6, CENTER);
Group row7 = new Group(7, CENTER);
- Group col1a = new Group(1, 5, CENTER);
- Group col1b = new Group(1, 5, LEFT);
+ Group col1a = new Group(1, 4, CENTER);
+ Group col1b = new Group(1, 4, LEFT);
Group col1c = new Group(1, RIGHT);
- Group col2 = new Group(2, LEFT);
- Group col3 = new Group(3, FILL);
- Group col4 = new Group(4, FILL);
+ Group col2 = new Group(2, LEFT);
+ Group col3 = new Group(3, FILL);
+ Group col4 = new Group(4, FILL);
{
TextView v = new TextView(context);
@@ -55,20 +59,17 @@ public class Activity2 extends Activity {
v.setText("Email setup");
vg.addView(v, new LayoutParams(row1, col1a));
}
-
{
TextView v = new TextView(context);
v.setTextSize(20);
v.setText("You can configure email in just a few steps:");
vg.addView(v, new LayoutParams(row2, col1b));
}
-
{
TextView v = new TextView(context);
v.setText("Email address:");
vg.addView(v, new LayoutParams(row3, col1c));
}
-
{
EditText v = new EditText(context);
v.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
@@ -78,13 +79,11 @@ public class Activity2 extends Activity {
vg.addView(v, lp);
}
}
-
{
TextView v = new TextView(context);
v.setText("Password:");
vg.addView(v, new LayoutParams(row4, col1c));
}
-
{
TextView v = new EditText(context);
v.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD);
@@ -94,7 +93,6 @@ public class Activity2 extends Activity {
vg.addView(v, lp);
}
}
-
{
Space v = new Space(context);
{
@@ -104,13 +102,11 @@ public class Activity2 extends Activity {
vg.addView(v, lp);
}
}
-
{
Button v = new Button(context);
v.setText("Manual setup");
vg.addView(v, new LayoutParams(row6, col4));
}
-
{
Button v = new Button(context);
v.setText("Next");
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 01d30ebf5a15..3e7ca08f94ea 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -19,6 +19,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java
index b49db7c571f1..1c82e9bbdf9b 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java
@@ -20,7 +20,6 @@ import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
@@ -79,6 +78,9 @@ public class ClearActivity extends Activity {
}
canvas.restore();
canvas.drawText("OpenGLRenderer", 50.0f, 50.0f, mClearPaint);
+ mClearPaint.setColor(0xff000000);
+ canvas.drawRect(800.0f, 100.0f, 900.0f, 200.0f, mClearPaint);
+ mClearPaint.setColor(0x0000ff00);
}
canvas.restore();
}
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 8ac7590152b4..223b1fa4912c 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -343,6 +343,9 @@ enum {
REQUIRED_ATTR = 0x0101028e,
SCREEN_SIZE_ATTR = 0x010102ca,
SCREEN_DENSITY_ATTR = 0x010102cb,
+ REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
+ COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
+ LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
};
const char *getComponentName(String8 &pkgName, String8 &componentName) {
@@ -423,6 +426,24 @@ int doDump(Bundle* bundle)
return 1;
}
+ // Make a dummy config for retrieving resources... we need to supply
+ // non-default values for some configs so that we can retrieve resources
+ // in the app that don't have a default. The most important of these is
+ // the API version because key resources like icons will have an implicit
+ // version if they are using newer config types like density.
+ ResTable_config config;
+ config.language[0] = 'e';
+ config.language[1] = 'n';
+ config.country[0] = 'U';
+ config.country[1] = 'S';
+ config.orientation = ResTable_config::ORIENTATION_PORT;
+ config.density = ResTable_config::DENSITY_MEDIUM;
+ config.sdkVersion = 10000; // Very high.
+ config.screenWidthDp = 320;
+ config.screenHeightDp = 480;
+ config.smallestScreenWidthDp = 320;
+ assets.setConfiguration(config);
+
const ResTable& res = assets.getResources(false);
if (&res == NULL) {
fprintf(stderr, "ERROR: dump failed because no resource table was found\n");
@@ -542,6 +563,19 @@ int doDump(Bundle* bundle)
}
}
} else if (strcmp("badging", option) == 0) {
+ Vector<String8> locales;
+ res.getLocales(&locales);
+
+ Vector<ResTable_config> configs;
+ res.getConfigurations(&configs);
+ SortedVector<int> densities;
+ const size_t NC = configs.size();
+ for (size_t i=0; i<NC; i++) {
+ int dens = configs[i].density;
+ if (dens == 0) dens = 160;
+ densities.add(dens);
+ }
+
size_t len;
ResXMLTree::event_code_t code;
int depth = 0;
@@ -598,6 +632,8 @@ int doDump(Bundle* bundle)
bool specTouchscreenFeature = false; // touchscreen-related
bool specMultitouchFeature = false;
bool reqDistinctMultitouchFeature = false;
+ bool specScreenPortraitFeature = false;
+ bool specScreenLandscapeFeature = false;
// 2.2 also added some other features that apps can request, but that
// have no corresponding permission, so we cannot implement any
// back-compatibility heuristic for them. The below are thus unnecessary
@@ -614,6 +650,9 @@ int doDump(Bundle* bundle)
int largeScreen = 1;
int xlargeScreen = 1;
int anyDensity = 1;
+ int requiresSmallestWidthDp = 0;
+ int compatibleWidthLimitDp = 0;
+ int largestWidthLimitDp = 0;
String8 pkg;
String8 activityName;
String8 activityLabel;
@@ -628,10 +667,11 @@ int doDump(Bundle* bundle)
} else if (depth < 3) {
if (withinActivity && isMainActivity && isLauncherActivity) {
const char *aName = getComponentName(pkg, activityName);
+ printf("launchable-activity:");
if (aName != NULL) {
- printf("launchable activity name='%s'", aName);
+ printf(" name='%s' ", aName);
}
- printf("label='%s' icon='%s'\n",
+ printf(" label='%s' icon='%s'\n",
activityLabel.string(),
activityIcon.string());
}
@@ -696,23 +736,51 @@ int doDump(Bundle* bundle)
withinApplication = false;
if (tag == "application") {
withinApplication = true;
- String8 label = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
- if (error != "") {
- fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", error.string());
- goto bail;
+
+ String8 label;
+ const size_t NL = locales.size();
+ for (size_t i=0; i<NL; i++) {
+ const char* localeStr = locales[i].string();
+ assets.setLocale(localeStr != NULL ? localeStr : "");
+ String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
+ if (llabel != "") {
+ if (localeStr == NULL || strlen(localeStr) == 0) {
+ label = llabel;
+ printf("application-label:'%s'\n", llabel.string());
+ } else {
+ if (label == "") {
+ label = llabel;
+ }
+ printf("application-label-%s:'%s'\n", localeStr,
+ llabel.string());
+ }
+ }
}
- printf("application: label='%s' ", label.string());
+
+ ResTable_config tmpConfig = config;
+ const size_t ND = densities.size();
+ for (size_t i=0; i<ND; i++) {
+ tmpConfig.density = densities[i];
+ assets.setConfiguration(tmpConfig);
+ String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
+ if (icon != "") {
+ printf("application-icon-%d:'%s'\n", densities[i], icon.string());
+ }
+ }
+ assets.setConfiguration(config);
+
String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
goto bail;
}
- printf("icon='%s'\n", icon.string());
int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0);
if (error != "") {
fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string());
goto bail;
}
+ printf("application: label='%s' ", label.string());
+ printf("icon='%s'\n", icon.string());
if (testOnly != 0) {
printf("testOnly='%d'\n", testOnly);
}
@@ -792,6 +860,12 @@ int doDump(Bundle* bundle)
XLARGE_SCREEN_ATTR, NULL, 1);
anyDensity = getIntegerAttribute(tree,
ANY_DENSITY_ATTR, NULL, 1);
+ requiresSmallestWidthDp = getIntegerAttribute(tree,
+ REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0);
+ compatibleWidthLimitDp = getIntegerAttribute(tree,
+ COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0);
+ largestWidthLimitDp = getIntegerAttribute(tree,
+ LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0);
} else if (tag == "uses-feature") {
String8 name = getAttribute(tree, NAME_ATTR, &error);
@@ -837,6 +911,10 @@ int doDump(Bundle* bundle)
// these have no corresponding permission to check for,
// but should imply the foundational telephony permission
reqTelephonySubFeature = true;
+ } else if (name == "android.hardware.screen.portrait") {
+ specScreenPortraitFeature = true;
+ } else if (name == "android.hardware.screen.landscape") {
+ specScreenLandscapeFeature = true;
}
printf("uses-feature%s:'%s'\n",
req ? "" : "-not-required", name.string());
@@ -1103,6 +1181,15 @@ int doDump(Bundle* bundle)
printf("uses-feature:'android.hardware.touchscreen.multitouch'\n");
}
+ // Landscape/portrait-related compatibility logic
+ if (!specScreenLandscapeFeature && !specScreenPortraitFeature && (targetSdk < 13)) {
+ // If app has not specified whether it requires portrait or landscape
+ // and is targeting an API before Honeycomb MR2, then assume it requires
+ // both.
+ printf("uses-feature:'android.hardware.screen.portrait'\n");
+ printf("uses-feature:'android.hardware.screen.landscape'\n");
+ }
+
if (hasMainActivity) {
printf("main\n");
}
@@ -1128,6 +1215,34 @@ int doDump(Bundle* bundle)
printf("other-services\n");
}
+ // For modern apps, if screen size buckets haven't been specified
+ // but the new width ranges have, then infer the buckets from them.
+ if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0
+ && requiresSmallestWidthDp > 0) {
+ int compatWidth = compatibleWidthLimitDp;
+ if (compatWidth <= 0) compatWidth = requiresSmallestWidthDp;
+ if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) {
+ smallScreen = -1;
+ } else {
+ smallScreen = 0;
+ }
+ if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) {
+ normalScreen = -1;
+ } else {
+ normalScreen = 0;
+ }
+ if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) {
+ largeScreen = -1;
+ } else {
+ largeScreen = 0;
+ }
+ if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) {
+ xlargeScreen = -1;
+ } else {
+ xlargeScreen = 0;
+ }
+ }
+
// Determine default values for any unspecified screen sizes,
// based on the target SDK of the package. As of 4 (donut)
// the screen size support was introduced, so all default to
@@ -1146,7 +1261,8 @@ int doDump(Bundle* bundle)
xlargeScreen = targetSdk >= 9 ? -1 : 0;
}
if (anyDensity > 0) {
- anyDensity = targetSdk >= 4 ? -1 : 0;
+ anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
+ || compatibleWidthLimitDp > 0) ? -1 : 0;
}
printf("supports-screens:");
if (smallScreen != 0) printf(" 'small'");
@@ -1154,12 +1270,18 @@ int doDump(Bundle* bundle)
if (largeScreen != 0) printf(" 'large'");
if (xlargeScreen != 0) printf(" 'xlarge'");
printf("\n");
-
printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
+ if (requiresSmallestWidthDp > 0) {
+ printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp);
+ }
+ if (compatibleWidthLimitDp > 0) {
+ printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp);
+ }
+ if (largestWidthLimitDp > 0) {
+ printf("largest-width-limit:'%d'\n", largestWidthLimitDp);
+ }
printf("locales:");
- Vector<String8> locales;
- res.getLocales(&locales);
const size_t NL = locales.size();
for (size_t i=0; i<NL; i++) {
const char* localeStr = locales[i].string();
@@ -1170,16 +1292,6 @@ int doDump(Bundle* bundle)
}
printf("\n");
- Vector<ResTable_config> configs;
- res.getConfigurations(&configs);
- SortedVector<int> densities;
- const size_t NC = configs.size();
- for (size_t i=0; i<NC; i++) {
- int dens = configs[i].density;
- if (dens == 0) dens = 160;
- densities.add(dens);
- }
-
printf("densities:");
const size_t ND = densities.size();
for (size_t i=0; i<ND; i++) {
diff --git a/wifi/java/android/net/wifi/SupplicantState.java b/wifi/java/android/net/wifi/SupplicantState.java
index 91e685fde905..509b02ca82d8 100644
--- a/wifi/java/android/net/wifi/SupplicantState.java
+++ b/wifi/java/android/net/wifi/SupplicantState.java
@@ -216,6 +216,28 @@ public enum SupplicantState implements Parcelable {
}
}
+ static boolean isDriverActive(SupplicantState state) {
+ switch(state) {
+ case DISCONNECTED:
+ case DORMANT:
+ case INACTIVE:
+ case AUTHENTICATING:
+ case ASSOCIATING:
+ case ASSOCIATED:
+ case SCANNING:
+ case FOUR_WAY_HANDSHAKE:
+ case GROUP_HANDSHAKE:
+ case COMPLETED:
+ return true;
+ case INTERFACE_DISABLED:
+ case UNINITIALIZED:
+ case INVALID:
+ return false;
+ default:
+ throw new IllegalArgumentException("Unknown supplicant state");
+ }
+ }
+
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
return 0;
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 4a45825b1b0b..4ec4cfcd34d9 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -107,7 +107,7 @@ public class WifiMonitor {
* <pre>
* CTRL-EVENT-DRIVER-STATE state
* </pre>
- * <code>state</code> is either STARTED or STOPPED
+ * <code>state</code> can be HANGED
*/
private static final String driverStateEvent = "DRIVER-STATE";
/**
@@ -304,11 +304,7 @@ public class WifiMonitor {
if (state == null) {
return;
}
- if (state.equals("STOPPED")) {
- mWifiStateMachine.notifyDriverStopped();
- } else if (state.equals("STARTED")) {
- mWifiStateMachine.notifyDriverStarted();
- } else if (state.equals("HANGED")) {
+ if (state.equals("HANGED")) {
mWifiStateMachine.notifyDriverHung();
}
}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 6df37bbddc3a..3df3736f0497 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -212,22 +212,18 @@ public class WifiStateMachine extends StateMachine {
static final int SUP_CONNECTION_EVENT = BASE + 31;
/* Connection to supplicant lost */
static final int SUP_DISCONNECTION_EVENT = BASE + 32;
- /* Driver start completed */
- static final int DRIVER_START_EVENT = BASE + 33;
- /* Driver stop completed */
- static final int DRIVER_STOP_EVENT = BASE + 34;
- /* Network connection completed */
- static final int NETWORK_CONNECTION_EVENT = BASE + 36;
+ /* Network connection completed */
+ static final int NETWORK_CONNECTION_EVENT = BASE + 33;
/* Network disconnection completed */
- static final int NETWORK_DISCONNECTION_EVENT = BASE + 37;
+ static final int NETWORK_DISCONNECTION_EVENT = BASE + 34;
/* Scan results are available */
- static final int SCAN_RESULTS_EVENT = BASE + 38;
+ static final int SCAN_RESULTS_EVENT = BASE + 35;
/* Supplicate state changed */
- static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 39;
+ static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 36;
/* Password failure and EAP authentication failure */
- static final int AUTHENTICATION_FAILURE_EVENT = BASE + 40;
+ static final int AUTHENTICATION_FAILURE_EVENT = BASE + 37;
/* WPS overlap detected */
- static final int WPS_OVERLAP_EVENT = BASE + 41;
+ static final int WPS_OVERLAP_EVENT = BASE + 38;
/* Supplicant commands */
@@ -1421,6 +1417,35 @@ public class WifiStateMachine extends StateMachine {
return mNetworkInfo.getDetailedState();
}
+
+ private SupplicantState handleSupplicantStateChange(Message message) {
+ StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+ SupplicantState state = stateChangeResult.state;
+ // Supplicant state change
+ // [31-13] Reserved for future use
+ // [8 - 0] Supplicant state (as defined in SupplicantState.java)
+ // 50023 supplicant_state_changed (custom|1|5)
+ EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, state.ordinal());
+ mWifiInfo.setSupplicantState(state);
+ // Network id is only valid when we start connecting
+ if (SupplicantState.isConnecting(state)) {
+ mWifiInfo.setNetworkId(stateChangeResult.networkId);
+ } else {
+ mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
+ }
+
+ if (state == SupplicantState.ASSOCIATING) {
+ /* BSSID is valid only in ASSOCIATING state */
+ mWifiInfo.setBSSID(stateChangeResult.BSSID);
+ }
+ setNetworkDetailedState(WifiInfo.getDetailedStateOf(state));
+
+ mSupplicantStateTracker.sendMessage(Message.obtain(message));
+ mWpsStateMachine.sendMessage(Message.obtain(message));
+
+ return state;
+ }
+
/**
* Resets the Wi-Fi Connections by clearing any state, resetting any sockets
* using the interface, stopping DHCP & disabling interface
@@ -1674,14 +1699,6 @@ public class WifiStateMachine extends StateMachine {
sendMessage(SCAN_RESULTS_EVENT);
}
- void notifyDriverStarted() {
- sendMessage(DRIVER_START_EVENT);
- }
-
- void notifyDriverStopped() {
- sendMessage(DRIVER_STOP_EVENT);
- }
-
void notifyDriverHung() {
setWifiEnabled(false);
setWifiEnabled(true);
@@ -1737,8 +1754,6 @@ public class WifiStateMachine extends StateMachine {
case CMD_REASSOCIATE:
case SUP_CONNECTION_EVENT:
case SUP_DISCONNECTION_EVENT:
- case DRIVER_START_EVENT:
- case DRIVER_STOP_EVENT:
case NETWORK_CONNECTION_EVENT:
case NETWORK_DISCONNECTION_EVENT:
case SCAN_RESULTS_EVENT:
@@ -2284,13 +2299,19 @@ public class WifiStateMachine extends StateMachine {
public boolean processMessage(Message message) {
if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
switch(message.what) {
- case DRIVER_START_EVENT:
- transitionTo(mDriverStartedState);
+ case SUPPLICANT_STATE_CHANGE_EVENT:
+ SupplicantState state = handleSupplicantStateChange(message);
+ /* If suplicant is exiting out of INTERFACE_DISABLED state into
+ * a state that indicates driver has started, it is ready to
+ * receive driver commands
+ */
+ if (SupplicantState.isDriverActive(state)) {
+ transitionTo(mDriverStartedState);
+ }
break;
/* Queue driver commands & connection events */
case CMD_START_DRIVER:
case CMD_STOP_DRIVER:
- case SUPPLICANT_STATE_CHANGE_EVENT:
case NETWORK_CONNECTION_EVENT:
case NETWORK_DISCONNECTION_EVENT:
case AUTHENTICATION_FAILURE_EVENT:
@@ -2429,8 +2450,11 @@ public class WifiStateMachine extends StateMachine {
public boolean processMessage(Message message) {
if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
switch(message.what) {
- case DRIVER_STOP_EVENT:
- transitionTo(mDriverStoppedState);
+ case SUPPLICANT_STATE_CHANGE_EVENT:
+ SupplicantState state = handleSupplicantStateChange(message);
+ if (state == SupplicantState.INTERFACE_DISABLED) {
+ transitionTo(mDriverStoppedState);
+ }
break;
/* Queue driver commands */
case CMD_START_DRIVER:
@@ -2465,11 +2489,23 @@ public class WifiStateMachine extends StateMachine {
public boolean processMessage(Message message) {
if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
switch (message.what) {
- case CMD_START_DRIVER:
- mWakeLock.acquire();
- WifiNative.startDriverCommand();
- transitionTo(mDriverStartingState);
- mWakeLock.release();
+ case CMD_START_DRIVER:
+ mWakeLock.acquire();
+ WifiNative.startDriverCommand();
+ mWakeLock.release();
+ break;
+ case SUPPLICANT_STATE_CHANGE_EVENT:
+ SupplicantState state = handleSupplicantStateChange(message);
+ /* A driver start causes supplicant to first report an INTERFACE_DISABLED
+ * state before transitioning out of it for connection. Stay in
+ * DriverStoppedState until we get an INTERFACE_DISABLED state and transition
+ * to DriverStarting upon getting that
+ * TODO: Fix this when the supplicant can be made to just transition out of
+ * INTERFACE_DISABLED state when driver gets started
+ */
+ if (state == SupplicantState.INTERFACE_DISABLED) {
+ transitionTo(mDriverStartingState);
+ }
break;
default:
return NOT_HANDLED;
@@ -2535,29 +2571,8 @@ public class WifiStateMachine extends StateMachine {
sendErrorBroadcast(WifiManager.WPS_OVERLAP_ERROR);
break;
case SUPPLICANT_STATE_CHANGE_EVENT:
- stateChangeResult = (StateChangeResult) message.obj;
- SupplicantState state = stateChangeResult.state;
- // Supplicant state change
- // [31-13] Reserved for future use
- // [8 - 0] Supplicant state (as defined in SupplicantState.java)
- // 50023 supplicant_state_changed (custom|1|5)
- EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, state.ordinal());
- mWifiInfo.setSupplicantState(state);
- // Network id is only valid when we start connecting
- if (SupplicantState.isConnecting(state)) {
- mWifiInfo.setNetworkId(stateChangeResult.networkId);
- } else {
- mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
- }
-
- if (state == SupplicantState.ASSOCIATING) {
- /* BSSID is valid only in ASSOCIATING state */
- mWifiInfo.setBSSID(stateChangeResult.BSSID);
- }
-
- mSupplicantStateTracker.sendMessage(Message.obtain(message));
- mWpsStateMachine.sendMessage(Message.obtain(message));
- break;
+ handleSupplicantStateChange(message);
+ break;
/* Do a redundant disconnect without transition */
case CMD_DISCONNECT:
WifiNative.disconnectCommand();
@@ -2964,12 +2979,7 @@ public class WifiStateMachine extends StateMachine {
/* Ignore network disconnect */
case NETWORK_DISCONNECTION_EVENT:
break;
- case SUPPLICANT_STATE_CHANGE_EVENT:
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
- setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state));
- /* DriverStartedState does the rest of the handling */
- return NOT_HANDLED;
- case CMD_START_SCAN:
+ case CMD_START_SCAN:
/* Disable background scan temporarily during a regular scan */
if (mEnableBackgroundScan) {
WifiNative.enableBackgroundScanCommand(false);