summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt301
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java6
-rw-r--r--cmds/app_process/app_main.cpp20
-rw-r--r--cmds/bootanimation/Android.mk7
-rw-r--r--cmds/bugreport/Android.mk4
-rw-r--r--cmds/dumpstate/Android.mk4
-rw-r--r--cmds/installd/Android.mk4
-rw-r--r--cmds/installd/tests/Android.mk4
-rw-r--r--cmds/keystore/Android.mk4
-rw-r--r--cmds/rawbu/Android.mk4
-rw-r--r--cmds/runtime/Android.mk30
-rw-r--r--cmds/runtime/MODULE_LICENSE_APACHE20
-rw-r--r--cmds/runtime/NOTICE190
-rw-r--r--cmds/runtime/ServiceManager.cpp74
-rw-r--r--cmds/runtime/ServiceManager.h38
-rw-r--r--cmds/runtime/SignalHandler.cpp249
-rw-r--r--cmds/runtime/SignalHandler.h137
-rw-r--r--cmds/runtime/main_runtime.cpp515
-rw-r--r--cmds/screenshot/Android.mk4
-rw-r--r--cmds/servicemanager/Android.mk2
-rw-r--r--cmds/system_server/library/system_init.cpp31
-rw-r--r--core/java/android/animation/AnimatorSet.java148
-rwxr-xr-xcore/java/android/animation/ValueAnimator.java14
-rw-r--r--core/java/android/app/ActivityManager.java18
-rw-r--r--core/java/android/app/ActivityThread.java20
-rw-r--r--core/java/android/app/ContextImpl.java12
-rw-r--r--core/java/android/app/backup/BackupAgent.java11
-rw-r--r--core/java/android/bluetooth/BluetoothHealth.java75
-rw-r--r--core/java/android/bluetooth/BluetoothHealthAppConfiguration.java45
-rw-r--r--core/java/android/bluetooth/BluetoothHealthCallback.java42
-rw-r--r--core/java/android/bluetooth/BluetoothServerSocket.java10
-rw-r--r--core/java/android/bluetooth/IBluetooth.aidl4
-rw-r--r--core/java/android/net/NetworkStats.java180
-rw-r--r--core/java/android/net/NetworkStatsHistory.java138
-rw-r--r--core/java/android/net/NetworkUtils.java18
-rw-r--r--core/java/android/net/http/AndroidHttpClient.java2
-rw-r--r--core/java/android/os/Looper.java4
-rw-r--r--core/java/android/os/Process.java145
-rw-r--r--core/java/android/os/ServiceManager.java2
-rw-r--r--core/java/android/os/storage/StorageVolume.java29
-rw-r--r--core/java/android/pim/EventRecurrence.java892
-rw-r--r--core/java/android/pim/ICalendar.java660
-rw-r--r--core/java/android/pim/RecurrenceSet.java511
-rw-r--r--core/java/android/provider/CalendarContract.java115
-rw-r--r--core/java/android/provider/ContactsContract.java380
-rw-r--r--core/java/android/provider/Settings.java5
-rw-r--r--core/java/android/server/BluetoothHealthProfileHandler.java49
-rwxr-xr-x[-rw-r--r--]core/java/android/server/BluetoothService.java11
-rw-r--r--core/java/android/speech/tts/AudioPlaybackHandler.java31
-rw-r--r--core/java/android/speech/tts/SynthesisMessageParams.java5
-rw-r--r--core/java/android/text/style/SuggestionSpan.java16
-rw-r--r--core/java/android/util/NtpTrustedTime.java60
-rw-r--r--core/java/android/view/ActionProvider.java37
-rw-r--r--core/java/android/view/HardwareRenderer.java88
-rw-r--r--core/java/android/view/MenuInflater.java34
-rw-r--r--core/java/android/view/View.java9
-rw-r--r--core/java/android/view/ViewAncestor.java8
-rw-r--r--core/java/android/view/ViewGroup.java6
-rw-r--r--core/java/android/webkit/L10nUtils.java13
-rw-r--r--core/java/android/webkit/WebView.java55
-rw-r--r--core/java/android/webkit/ZoomManager.java7
-rw-r--r--core/java/android/widget/ActivityChooserModel.java63
-rw-r--r--core/java/android/widget/ActivityChooserView.java311
-rw-r--r--core/java/android/widget/CalendarView.java75
-rw-r--r--core/java/android/widget/DatePicker.java95
-rw-r--r--core/java/android/widget/ShareActionProvider.java105
-rw-r--r--core/java/android/widget/TextView.java580
-rw-r--r--core/java/android/widget/TimePicker.java28
-rwxr-xr-xcore/java/com/android/internal/os/PkgUsageStats.java22
-rw-r--r--core/java/com/android/internal/os/RuntimeInit.java13
-rw-r--r--core/java/com/android/internal/os/WrapperInit.java23
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java22
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java11
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuPresenter.java80
-rw-r--r--core/java/com/android/internal/view/menu/BaseMenuPresenter.java10
-rw-r--r--core/java/com/android/internal/view/menu/IconMenuPresenter.java54
-rw-r--r--core/java/com/android/internal/view/menu/ListMenuPresenter.java27
-rw-r--r--core/java/com/android/internal/view/menu/MenuBuilder.java67
-rw-r--r--core/java/com/android/internal/view/menu/MenuItemImpl.java10
-rw-r--r--core/java/com/android/internal/view/menu/MenuPopupHelper.java15
-rw-r--r--core/java/com/android/internal/view/menu/MenuPresenter.java21
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java15
-rw-r--r--core/java/com/android/server/NetworkManagementSocketTagger.java56
-rw-r--r--core/jni/Android.mk14
-rw-r--r--core/jni/android_net_NetUtils.cpp13
-rw-r--r--core/jni/android_net_TrafficStats.cpp49
-rw-r--r--core/jni/android_server_BluetoothService.cpp9
-rw-r--r--core/jni/android_util_Process.cpp24
-rw-r--r--core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.pngbin846 -> 796 bytes
-rw-r--r--core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.pngbin1007 -> 850 bytes
-rw-r--r--core/res/res/drawable-hdpi/dialog_full_holo_dark.9.pngbin1653 -> 1300 bytes
-rw-r--r--core/res/res/drawable-hdpi/dialog_full_holo_light.9.pngbin2039 -> 1216 bytes
-rw-r--r--core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.pngbin361 -> 270 bytes
-rw-r--r--core/res/res/drawable-hdpi/dialog_middle_holo_light.9.pngbin536 -> 280 bytes
-rw-r--r--core/res/res/drawable-hdpi/dialog_top_holo_dark.9.pngbin825 -> 761 bytes
-rw-r--r--core/res/res/drawable-hdpi/dialog_top_holo_light.9.pngbin837 -> 669 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_btn_back.pngbin1952 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_btn_next.pngbin2086 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.pngbin809 -> 921 bytes
-rw-r--r--core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.pngbin815 -> 1056 bytes
-rw-r--r--core/res/res/drawable-hdpi/toast_frame.9.pngbin1923 -> 1319 bytes
-rw-r--r--core/res/res/drawable-hdpi/toast_frame_holo.9.pngbin1923 -> 1319 bytes
-rw-r--r--core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.pngbin586 -> 550 bytes
-rw-r--r--core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.pngbin691 -> 584 bytes
-rw-r--r--core/res/res/drawable-mdpi/dialog_full_holo_dark.9.pngbin1103 -> 809 bytes
-rw-r--r--core/res/res/drawable-mdpi/dialog_full_holo_light.9.pngbin1294 -> 845 bytes
-rw-r--r--core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.pngbin295 -> 240 bytes
-rw-r--r--core/res/res/drawable-mdpi/dialog_middle_holo_light.9.pngbin370 -> 243 bytes
-rw-r--r--core/res/res/drawable-mdpi/dialog_top_holo_dark.9.pngbin578 -> 507 bytes
-rw-r--r--core/res/res/drawable-mdpi/dialog_top_holo_light.9.pngbin599 -> 504 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_btn_back.pngbin906 -> 0 bytes
-rwxr-xr-xcore/res/res/drawable-mdpi/ic_btn_next.pngbin779 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.pngbin576 -> 651 bytes
-rw-r--r--core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.pngbin555 -> 721 bytes
-rwxr-xr-xcore/res/res/drawable-mdpi/toast_frame.9.pngbin1100 -> 839 bytes
-rwxr-xr-xcore/res/res/drawable-mdpi/toast_frame_holo.9.pngbin1100 -> 839 bytes
-rw-r--r--core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.pngbin1493 -> 1123 bytes
-rw-r--r--core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.pngbin1502 -> 1194 bytes
-rw-r--r--core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.pngbin2800 -> 1895 bytes
-rw-r--r--core/res/res/drawable-xhdpi/dialog_full_holo_light.9.pngbin2821 -> 1835 bytes
-rw-r--r--core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.pngbin272 -> 306 bytes
-rw-r--r--core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.pngbin281 -> 308 bytes
-rw-r--r--core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.pngbin1506 -> 1079 bytes
-rw-r--r--core/res/res/drawable-xhdpi/dialog_top_holo_light.9.pngbin1496 -> 908 bytes
-rw-r--r--core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.pngbin0 -> 1361 bytes
-rw-r--r--core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.pngbin0 -> 1553 bytes
-rw-r--r--core/res/res/drawable-xhdpi/toast_frame.9.pngbin2883 -> 1956 bytes
-rw-r--r--core/res/res/drawable-xhdpi/toast_frame_holo.9.pngbin2883 -> 1956 bytes
-rw-r--r--core/res/res/layout-sw600dp/preference_list_content.xml5
-rw-r--r--core/res/res/layout-w600dp/preference_list_content_single.xml5
-rw-r--r--core/res/res/layout-xlarge/activity_list.xml17
-rw-r--r--core/res/res/layout/activity_chooser_list_footer.xml44
-rw-r--r--core/res/res/layout/activity_chooser_list_header.xml43
-rw-r--r--core/res/res/layout/activity_chooser_view.xml4
-rw-r--r--core/res/res/layout/activity_chooser_view_list_item.xml49
-rw-r--r--core/res/res/layout/alert_dialog_holo.xml19
-rw-r--r--core/res/res/layout/dialog_custom_title_holo.xml8
-rw-r--r--core/res/res/layout/dialog_title_holo.xml8
-rw-r--r--core/res/res/layout/dialog_title_icons_holo.xml6
-rw-r--r--core/res/res/layout/preference_list_content.xml5
-rw-r--r--core/res/res/layout/preference_list_content_single.xml5
-rw-r--r--core/res/res/layout/preference_list_fragment.xml7
-rwxr-xr-xcore/res/res/values/attrs.xml21
-rw-r--r--core/res/res/values/colors.xml31
-rwxr-xr-xcore/res/res/values/config.xml5
-rw-r--r--core/res/res/values/dimens.xml3
-rw-r--r--core/res/res/values/ids.xml5
-rw-r--r--core/res/res/values/public.xml20
-rwxr-xr-xcore/res/res/values/strings.xml57
-rw-r--r--core/res/res/values/styles.xml4
-rw-r--r--core/res/res/values/themes.xml18
-rw-r--r--core/tests/coretests/Android.mk2
-rw-r--r--core/tests/coretests/AndroidManifest.xml14
-rw-r--r--core/tests/coretests/res/layout/animator_basic.xml11
-rw-r--r--core/tests/coretests/res/layout/textview_test.xml27
-rw-r--r--core/tests/coretests/res/values/strings.xml2
-rw-r--r--core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java39
-rw-r--r--core/tests/coretests/src/android/animation/BasicAnimatorActivity.java29
-rw-r--r--core/tests/coretests/src/android/animation/EventsTest.java265
-rw-r--r--core/tests/coretests/src/android/animation/FutureWaiter.java40
-rw-r--r--core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java35
-rw-r--r--core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java29
-rw-r--r--core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java136
-rw-r--r--core/tests/coretests/src/android/net/NetworkStatsTest.java120
-rw-r--r--core/tests/coretests/src/android/pim/EventRecurrenceTest.java753
-rw-r--r--core/tests/coretests/src/android/pim/RecurrenceSetTest.java82
-rw-r--r--core/tests/coretests/src/android/widget/TextViewTest.java72
-rw-r--r--core/tests/coretests/src/android/widget/TextViewTestActivity.java30
-rw-r--r--docs/html/guide/developing/tools/adb.jd4
-rw-r--r--docs/html/guide/guide_toc.cs7
-rw-r--r--docs/html/index.jd19
-rw-r--r--docs/html/resources/dashboard/opengl.jd2
-rw-r--r--docs/html/sdk/eclipse-adt.jd2
-rw-r--r--docs/html/sdk/ndk/index.jd70
-rw-r--r--docs/html/sdk/ndk/overview.jd4
-rw-r--r--docs/html/sdk/sdk_toc.cs10
-rw-r--r--docs/html/sdk/tools-notes.jd2
-rw-r--r--drm/drmserver/Android.mk9
-rw-r--r--drm/jni/Android.mk9
-rw-r--r--drm/libdrmframework/Android.mk9
-rw-r--r--drm/libdrmframework/plugins/passthru/Android.mk10
-rw-r--r--graphics/java/android/graphics/Path.java28
-rw-r--r--graphics/java/android/renderscript/ScriptC.java2
-rw-r--r--graphics/jni/Android.mk9
-rw-r--r--include/binder/ProcessState.h4
-rw-r--r--include/gui/SurfaceTextureClient.h5
-rw-r--r--include/media/IStreamSource.h11
-rw-r--r--include/media/stagefright/CameraSource.h6
-rw-r--r--include/media/stagefright/MPEG4Writer.h4
-rw-r--r--include/media/stagefright/MetadataBufferType.h7
-rw-r--r--libs/binder/ProcessState.cpp51
-rw-r--r--libs/camera/Android.mk4
-rw-r--r--libs/gui/Android.mk4
-rw-r--r--libs/gui/SurfaceTextureClient.cpp43
-rw-r--r--libs/gui/tests/Android.mk4
-rw-r--r--libs/hwui/Caches.cpp1
-rw-r--r--libs/hwui/Properties.h2
-rw-r--r--libs/hwui/ShapeCache.h2
-rw-r--r--libs/rs/Android.mk7
-rw-r--r--libs/rs/driver/rsdBcc.cpp69
-rw-r--r--libs/rs/driver/rsdGL.cpp80
-rw-r--r--libs/rs/rsElement.cpp12
-rw-r--r--libs/storage/Android.mk4
-rw-r--r--libs/surfaceflinger_client/Android.mk4
-rw-r--r--libs/ui/Android.mk4
-rw-r--r--libs/ui/EGLUtils.cpp58
-rw-r--r--libs/ui/FramebufferNativeWindow.cpp1
-rw-r--r--libs/ui/tests/Android.mk4
-rw-r--r--libs/utils/Android.mk4
-rw-r--r--libs/utils/BackupHelpers.cpp16
-rw-r--r--libs/utils/VectorImpl.cpp4
-rw-r--r--libs/utils/tests/Android.mk4
-rw-r--r--media/java/android/media/MediaFile.java7
-rw-r--r--media/java/android/media/MediaScanner.java81
-rw-r--r--media/java/android/mtp/MtpPropertyGroup.java1
-rw-r--r--media/java/android/mtp/MtpServer.java30
-rw-r--r--media/java/android/mtp/MtpStorage.java11
-rw-r--r--media/jni/android_media_MediaScanner.cpp7
-rw-r--r--media/jni/android_mtp_MtpServer.cpp236
-rw-r--r--media/libeffects/factory/Android.mk8
-rw-r--r--media/libeffects/factory/EffectsFactory.c43
-rw-r--r--media/libeffects/lvm/wrapper/Android.mk14
-rw-r--r--media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp3
-rwxr-xr-xmedia/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp3
-rw-r--r--media/libeffects/testlibs/EffectEqualizer.cpp3
-rw-r--r--media/libeffects/testlibs/EffectReverb.c3
-rw-r--r--media/libeffects/visualizer/Android.mk11
-rw-r--r--media/libeffects/visualizer/EffectVisualizer.cpp3
-rw-r--r--media/libmedia/Android.mk10
-rw-r--r--media/libmedia/IStreamSource.cpp3
-rw-r--r--media/libmediaplayerservice/Android.mk11
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp59
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h1
-rw-r--r--media/libmediaplayerservice/nuplayer/StreamingSource.cpp13
-rw-r--r--media/libstagefright/Android.mk43
-rwxr-xr-x[-rw-r--r--]media/libstagefright/CameraSource.cpp29
-rwxr-xr-x[-rw-r--r--]media/libstagefright/MPEG4Writer.cpp40
-rwxr-xr-x[-rw-r--r--]media/libstagefright/OMXCodec.cpp133
-rw-r--r--media/libstagefright/ThreadedSource.cpp213
-rw-r--r--media/libstagefright/chromium_http/Android.mk2
-rw-r--r--media/libstagefright/codecs/aacdec/AACDecoder.cpp335
-rw-r--r--media/libstagefright/codecs/aacdec/Android.mk1
-rw-r--r--media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp208
-rw-r--r--media/libstagefright/codecs/amrnb/dec/Android.mk1
-rw-r--r--media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp225
-rw-r--r--media/libstagefright/codecs/amrwb/Android.mk1
-rw-r--r--media/libstagefright/codecs/avc/dec/AVCDecoder.cpp622
-rw-r--r--media/libstagefright/codecs/avc/dec/Android.mk1
-rw-r--r--media/libstagefright/codecs/g711/dec/Android.mk14
-rw-r--r--media/libstagefright/codecs/g711/dec/G711Decoder.cpp213
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/Android.mk1
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp304
-rw-r--r--media/libstagefright/codecs/mp3dec/Android.mk1
-rw-r--r--media/libstagefright/codecs/mp3dec/MP3Decoder.cpp226
-rw-r--r--media/libstagefright/codecs/on2/dec/Android.mk19
-rw-r--r--media/libstagefright/codecs/on2/dec/VPXDecoder.cpp277
-rw-r--r--media/libstagefright/codecs/vorbis/dec/Android.mk18
-rw-r--r--media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp275
-rw-r--r--media/libstagefright/include/ThreadedSource.h73
-rw-r--r--media/libstagefright/omx/Android.mk9
-rw-r--r--media/mtp/Android.mk4
-rw-r--r--media/mtp/MtpServer.cpp10
-rw-r--r--media/mtp/MtpStorage.cpp4
-rw-r--r--media/mtp/MtpStorage.h4
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java11
-rw-r--r--opengl/java/android/opengl/GLSurfaceView.java2
-rw-r--r--opengl/libagl/Android.mk14
-rw-r--r--opengl/libagl2/Android.mk14
-rw-r--r--opengl/libs/Android.mk46
-rw-r--r--opengl/libs/EGL/egl.cpp5
-rw-r--r--opengl/libs/EGL/eglApi.cpp7
-rw-r--r--opengl/libs/GLES2_dbg/Android.mk14
-rw-r--r--opengl/libs/GLES2_dbg/test/Android.mk4
-rw-r--r--opengl/specs/EGL_ANDROID_blob_cache.txt208
-rw-r--r--opengl/specs/EGL_ANDROID_recordable.txt113
-rw-r--r--opengl/specs/README12
-rw-r--r--opengl/tests/EGLTest/Android.mk37
-rw-r--r--opengl/tests/EGLTest/EGL_test.cpp129
-rw-r--r--opengl/tests/gl2_jni/Android.mk4
-rw-r--r--opengl/tests/gl_jni/Android.mk4
-rw-r--r--opengl/tests/gl_perfapp/Android.mk4
-rw-r--r--opengl/tests/gldual/Android.mk4
-rw-r--r--opengl/tests/testPauseResume/Android.mk4
-rw-r--r--opengl/tests/testViewport/Android.mk4
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java46
-rw-r--r--packages/SystemUI/res/layout-port/status_bar_recent_panel.xml14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/Constants.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java31
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java45
-rw-r--r--services/audioflinger/Android.mk15
-rw-r--r--services/audioflinger/AudioResamplerCubic.cpp4
-rw-r--r--services/camera/libcameraservice/CameraHardwareStub.h9
-rw-r--r--services/camera/tests/CameraServiceTest/CameraServiceTest.cpp10
-rw-r--r--services/input/Android.mk4
-rw-r--r--services/input/tests/Android.mk4
-rw-r--r--services/java/com/android/server/AppWidgetService.java2
-rw-r--r--services/java/com/android/server/BackupManagerService.java134
-rw-r--r--services/java/com/android/server/ConnectivityService.java6
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java5
-rw-r--r--services/java/com/android/server/MountService.java21
-rw-r--r--services/java/com/android/server/NetworkManagementService.java141
-rw-r--r--services/java/com/android/server/NetworkTimeUpdateService.java67
-rw-r--r--services/java/com/android/server/ThrottleService.java38
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java215
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java10
-rw-r--r--services/java/com/android/server/am/ProcessRecord.java1
-rw-r--r--services/java/com/android/server/am/UsageStatsService.java45
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java2
-rwxr-xr-xservices/java/com/android/server/location/GpsLocationProvider.java31
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java9
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java101
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java529
-rw-r--r--services/java/com/android/server/usb/UsbDeviceManager.java61
-rw-r--r--services/jni/Android.mk8
-rw-r--r--services/sensorservice/Android.mk7
-rw-r--r--services/surfaceflinger/Android.mk7
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.cpp45
-rw-r--r--services/surfaceflinger/Layer.cpp25
-rw-r--r--services/surfaceflinger/LayerBase.cpp7
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp48
-rw-r--r--services/surfaceflinger/Transform.cpp1
-rw-r--r--services/tests/servicestests/res/raw/net_dev_typical8
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java66
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java112
-rw-r--r--services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java2
-rw-r--r--telephony/java/com/android/internal/telephony/DataConnectionTracker.java66
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyProperties.java7
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java50
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java7
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java16
-rw-r--r--tests/BiDiTests/res/layout/textview_drawables_ltr.xml104
-rw-r--r--tests/BiDiTests/res/layout/textview_drawables_rtl.xml104
-rw-r--r--tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java3
-rw-r--r--tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesLtr.java45
-rw-r--r--tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesRtl.java45
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml9
-rw-r--r--tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_bg_holo_dark.9.pngbin0 -> 189 bytes
-rw-r--r--tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_primary_holo_dark.9.pngbin0 -> 506 bytes
-rw-r--r--tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_secondary_holo_dark.9.pngbin0 -> 204 bytes
-rw-r--r--tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_primary_holo.9.pngbin0 -> 177 bytes
-rw-r--r--tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_secondary_holo.9.pngbin0 -> 179 bytes
-rw-r--r--tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_dark.9.pngbin0 -> 185 bytes
-rw-r--r--tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_light.9.pngbin0 -> 170 bytes
-rw-r--r--tests/HwAccelerationTest/res/drawable/progress_vertical_holo_dark.xml32
-rw-r--r--tests/HwAccelerationTest/res/drawable/scrubber_progress_vertical_holo_dark.xml28
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/MoreNinePatchesActivity.java77
-rw-r--r--tests/RenderScriptTests/FBOTest/Android.mk4
-rw-r--r--tests/RenderScriptTests/ImageProcessing/Android.mk4
-rw-r--r--tests/RenderScriptTests/ModelViewer/Android.mk4
-rw-r--r--tests/RenderScriptTests/PerfTest/Android.mk4
-rw-r--r--tests/RenderScriptTests/tests/Android.mk4
-rw-r--r--tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.pngbin0 -> 1007 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.pngbin0 -> 852 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.pngbin0 -> 574 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.pngbin3900 -> 782 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.pngbin3991 -> 695 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.pngbin3140 -> 534 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.pngbin0 -> 1283 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.pngbin0 -> 1029 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.pngbin0 -> 644 bytes
-rw-r--r--tools/layoutlib/bridge/src/android/view/Display_Delegate.java101
-rw-r--r--tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java42
-rw-r--r--tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java49
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java30
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java191
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java60
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java455
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java78
-rw-r--r--tools/layoutlib/bridge/tests/.classpath1
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java3
-rw-r--r--voip/java/android/net/sip/SipAudioCall.java11
-rw-r--r--voip/java/com/android/server/sip/SipHelper.java32
-rw-r--r--voip/java/com/android/server/sip/SipSessionGroup.java120
378 files changed, 7817 insertions, 10492 deletions
diff --git a/api/current.txt b/api/current.txt
index d507940..86339f2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -312,10 +312,15 @@ package android {
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int color = 16843173; // 0x10101a5
+ field public static final int colorActivatedHighlight = 16843684; // 0x10103a4
field public static final int colorBackground = 16842801; // 0x1010031
field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
+ field public static final int colorFocusedHighlight = 16843683; // 0x10103a3
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
+ field public static final int colorLongPressedHighlight = 16843682; // 0x10103a2
+ field public static final int colorMultiSelectHighlight = 16843685; // 0x10103a5
+ field public static final int colorPressedHighlight = 16843681; // 0x10103a1
field public static final int columnCount = 16843638; // 0x1010376
field public static final int columnDelay = 16843215; // 0x10101cf
field public static final int columnOrderPreserved = 16843639; // 0x1010377
@@ -372,9 +377,11 @@ package android {
field public static final int drawSelectorOnTop = 16843004; // 0x10100fc
field public static final int drawable = 16843161; // 0x1010199
field public static final int drawableBottom = 16843118; // 0x101016e
+ field public static final int drawableEnd = 16843687; // 0x10103a7
field public static final int drawableLeft = 16843119; // 0x101016f
field public static final int drawablePadding = 16843121; // 0x1010171
field public static final int drawableRight = 16843120; // 0x1010170
+ field public static final int drawableStart = 16843686; // 0x10103a6
field public static final int drawableTop = 16843117; // 0x101016d
field public static final int drawingCacheQuality = 16842984; // 0x10100e8
field public static final int dropDownAnchor = 16843363; // 0x1010263
@@ -1121,6 +1128,16 @@ package android {
field public static final int background_light = 17170447; // 0x106000f
field public static final int black = 17170444; // 0x106000c
field public static final int darker_gray = 17170432; // 0x1060000
+ field public static final int holo_blue_bright = 17170459; // 0x106001b
+ field public static final int holo_blue_dark = 17170451; // 0x1060013
+ field public static final int holo_blue_light = 17170450; // 0x1060012
+ field public static final int holo_green_dark = 17170453; // 0x1060015
+ field public static final int holo_green_light = 17170452; // 0x1060014
+ field public static final int holo_orange_dark = 17170457; // 0x1060019
+ field public static final int holo_orange_light = 17170456; // 0x1060018
+ field public static final int holo_purple = 17170458; // 0x106001a
+ field public static final int holo_red_dark = 17170455; // 0x1060017
+ field public static final int holo_red_light = 17170454; // 0x1060016
field public static final int primary_text_dark = 17170433; // 0x1060001
field public static final int primary_text_dark_nodisable = 17170434; // 0x1060002
field public static final int primary_text_light = 17170435; // 0x1060003
@@ -14377,7 +14394,7 @@ package android.os {
method public static final void sendSignal(int, int);
method public static final void setThreadPriority(int, int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
method public static final void setThreadPriority(int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
- method public static final boolean supportsProcesses();
+ method public static final deprecated boolean supportsProcesses();
field public static final int BLUETOOTH_GID = 2000; // 0x7d0
field public static final int FIRST_APPLICATION_UID = 10000; // 0x2710
field public static final int LAST_APPLICATION_UID = 99999; // 0x1869f
@@ -14999,6 +15016,257 @@ package android.provider {
field public static final deprecated java.lang.String URL = "url";
}
+ public final class CalendarContract {
+ field public static final java.lang.String ACCOUNT_TYPE_LOCAL = "LOCAL";
+ field public static final java.lang.String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
+ field public static final java.lang.String AUTHORITY = "com.android.calendar";
+ field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String EXTRA_EVENT_BEGIN_TIME = "beginTime";
+ field public static final java.lang.String EXTRA_EVENT_END_TIME = "endTime";
+ }
+
+ public static final class CalendarContract.Attendees implements android.provider.BaseColumns android.provider.CalendarContract.AttendeesColumns android.provider.CalendarContract.EventsColumns {
+ method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+ field public static final android.net.Uri CONTENT_URI;
+ }
+
+ protected static abstract interface CalendarContract.AttendeesColumns {
+ field public static final java.lang.String ATTENDEE_EMAIL = "attendeeEmail";
+ field public static final java.lang.String ATTENDEE_NAME = "attendeeName";
+ field public static final java.lang.String ATTENDEE_RELATIONSHIP = "attendeeRelationship";
+ field public static final java.lang.String ATTENDEE_STATUS = "attendeeStatus";
+ field public static final int ATTENDEE_STATUS_ACCEPTED = 1; // 0x1
+ field public static final int ATTENDEE_STATUS_DECLINED = 2; // 0x2
+ field public static final int ATTENDEE_STATUS_INVITED = 3; // 0x3
+ field public static final int ATTENDEE_STATUS_NONE = 0; // 0x0
+ field public static final int ATTENDEE_STATUS_TENTATIVE = 4; // 0x4
+ field public static final java.lang.String ATTENDEE_TYPE = "attendeeType";
+ field public static final java.lang.String EVENT_ID = "event_id";
+ field public static final int RELATIONSHIP_ATTENDEE = 1; // 0x1
+ field public static final int RELATIONSHIP_NONE = 0; // 0x0
+ field public static final int RELATIONSHIP_ORGANIZER = 2; // 0x2
+ field public static final int RELATIONSHIP_PERFORMER = 3; // 0x3
+ field public static final int RELATIONSHIP_SPEAKER = 4; // 0x4
+ field public static final int TYPE_NONE = 0; // 0x0
+ field public static final int TYPE_OPTIONAL = 2; // 0x2
+ field public static final int TYPE_REQUIRED = 1; // 0x1
+ }
+
+ public static final class CalendarContract.CalendarAlerts implements android.provider.BaseColumns android.provider.CalendarContract.CalendarAlertsColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns {
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final android.net.Uri CONTENT_URI_BY_INSTANCE;
+ }
+
+ protected static abstract interface CalendarContract.CalendarAlertsColumns {
+ field public static final java.lang.String ALARM_TIME = "alarmTime";
+ field public static final java.lang.String BEGIN = "begin";
+ field public static final java.lang.String CREATION_TIME = "creationTime";
+ field public static final java.lang.String DEFAULT_SORT_ORDER = "begin ASC,title ASC";
+ field public static final java.lang.String END = "end";
+ field public static final java.lang.String EVENT_ID = "event_id";
+ field public static final java.lang.String MINUTES = "minutes";
+ field public static final java.lang.String NOTIFY_TIME = "notifyTime";
+ field public static final java.lang.String RECEIVED_TIME = "receivedTime";
+ field public static final java.lang.String STATE = "state";
+ field public static final int STATE_DISMISSED = 2; // 0x2
+ field public static final int STATE_FIRED = 1; // 0x1
+ field public static final int STATE_SCHEDULED = 0; // 0x0
+ }
+
+ public static final class CalendarContract.CalendarCache implements android.provider.CalendarContract.CalendarCacheColumns {
+ field public static final java.lang.String KEY_TIMEZONE_INSTANCES = "timezoneInstances";
+ field public static final java.lang.String KEY_TIMEZONE_INSTANCES_PREVIOUS = "timezoneInstancesPrevious";
+ field public static final java.lang.String KEY_TIMEZONE_TYPE = "timezoneType";
+ field public static final java.lang.String TIMEZONE_TYPE_AUTO = "auto";
+ field public static final java.lang.String TIMEZONE_TYPE_HOME = "home";
+ field public static final android.net.Uri URI;
+ }
+
+ protected static abstract interface CalendarContract.CalendarCacheColumns {
+ field public static final java.lang.String KEY = "key";
+ field public static final java.lang.String VALUE = "value";
+ }
+
+ protected static abstract interface CalendarContract.CalendarColumns {
+ field public static final java.lang.String ALLOWED_REMINDERS = "allowedReminders";
+ field public static final java.lang.String CALENDAR_ACCESS_LEVEL = "calendar_access_level";
+ field public static final java.lang.String CALENDAR_COLOR = "calendar_color";
+ field public static final java.lang.String CALENDAR_DISPLAY_NAME = "calendar_displayName";
+ field public static final java.lang.String CALENDAR_TIME_ZONE = "calendar_timezone";
+ field public static final int CAL_ACCESS_CONTRIBUTOR = 500; // 0x1f4
+ field public static final int CAL_ACCESS_EDITOR = 600; // 0x258
+ field public static final int CAL_ACCESS_FREEBUSY = 100; // 0x64
+ field public static final int CAL_ACCESS_NONE = 0; // 0x0
+ field public static final int CAL_ACCESS_OVERRIDE = 400; // 0x190
+ field public static final int CAL_ACCESS_OWNER = 700; // 0x2bc
+ field public static final int CAL_ACCESS_READ = 200; // 0xc8
+ field public static final int CAL_ACCESS_RESPOND = 300; // 0x12c
+ field public static final int CAL_ACCESS_ROOT = 800; // 0x320
+ field public static final java.lang.String CAN_MODIFY_TIME_ZONE = "canModifyTimeZone";
+ field public static final java.lang.String CAN_ORGANIZER_RESPOND = "canOrganizerRespond";
+ field public static final java.lang.String MAX_REMINDERS = "maxReminders";
+ field public static final java.lang.String OWNER_ACCOUNT = "ownerAccount";
+ field public static final java.lang.String SYNC_EVENTS = "sync_events";
+ field public static final java.lang.String VISIBLE = "visible";
+ }
+
+ public static final class CalendarContract.CalendarEntity implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.SyncColumns {
+ method public static android.content.EntityIterator newEntityIterator(android.database.Cursor);
+ field public static final android.net.Uri CONTENT_URI;
+ }
+
+ protected static abstract interface CalendarContract.CalendarSyncColumns {
+ field public static final java.lang.String CAL_SYNC1 = "cal_sync1";
+ field public static final java.lang.String CAL_SYNC10 = "cal_sync10";
+ field public static final java.lang.String CAL_SYNC2 = "cal_sync2";
+ field public static final java.lang.String CAL_SYNC3 = "cal_sync3";
+ field public static final java.lang.String CAL_SYNC4 = "cal_sync4";
+ field public static final java.lang.String CAL_SYNC5 = "cal_sync5";
+ field public static final java.lang.String CAL_SYNC6 = "cal_sync6";
+ field public static final java.lang.String CAL_SYNC7 = "cal_sync7";
+ field public static final java.lang.String CAL_SYNC8 = "cal_sync8";
+ field public static final java.lang.String CAL_SYNC9 = "cal_sync9";
+ }
+
+ public static final class CalendarContract.Calendars implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.SyncColumns {
+ field public static final java.lang.String CALENDAR_LOCATION = "calendar_location";
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String DEFAULT_SORT_ORDER = "displayName";
+ field public static final java.lang.String NAME = "name";
+ }
+
+ public static final class CalendarContract.EventDays implements android.provider.CalendarContract.EventDaysColumns {
+ method public static final android.database.Cursor query(android.content.ContentResolver, int, int, java.lang.String[]);
+ field public static final android.net.Uri CONTENT_URI;
+ }
+
+ protected static abstract interface CalendarContract.EventDaysColumns {
+ field public static final java.lang.String ENDDAY = "endDay";
+ field public static final java.lang.String STARTDAY = "startDay";
+ }
+
+ public static final class CalendarContract.Events implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.SyncColumns {
+ field public static final android.net.Uri CONTENT_EXCEPTION_URI;
+ field public static final android.net.Uri CONTENT_URI;
+ }
+
+ protected static abstract interface CalendarContract.EventsColumns {
+ field public static final int ACCESS_CONFIDENTIAL = 1; // 0x1
+ field public static final int ACCESS_DEFAULT = 0; // 0x0
+ field public static final java.lang.String ACCESS_LEVEL = "accessLevel";
+ field public static final int ACCESS_PRIVATE = 2; // 0x2
+ field public static final int ACCESS_PUBLIC = 3; // 0x3
+ field public static final java.lang.String ALL_DAY = "allDay";
+ field public static final java.lang.String AVAILABILITY = "availability";
+ field public static final int AVAILABILITY_BUSY = 0; // 0x0
+ field public static final int AVAILABILITY_FREE = 1; // 0x1
+ field public static final java.lang.String CALENDAR_ID = "calendar_id";
+ field public static final java.lang.String CAN_INVITE_OTHERS = "canInviteOthers";
+ field public static final java.lang.String DESCRIPTION = "description";
+ field public static final java.lang.String DTEND = "dtend";
+ field public static final java.lang.String DTSTART = "dtstart";
+ field public static final java.lang.String DURATION = "duration";
+ field public static final java.lang.String EVENT_COLOR = "eventColor";
+ field public static final java.lang.String EVENT_END_TIMEZONE = "eventEndTimezone";
+ field public static final java.lang.String EVENT_LOCATION = "eventLocation";
+ field public static final java.lang.String EVENT_TIMEZONE = "eventTimezone";
+ field public static final java.lang.String EXDATE = "exdate";
+ field public static final java.lang.String EXRULE = "exrule";
+ field public static final java.lang.String GUESTS_CAN_INVITE_OTHERS = "guestsCanInviteOthers";
+ field public static final java.lang.String GUESTS_CAN_MODIFY = "guestsCanModify";
+ field public static final java.lang.String GUESTS_CAN_SEE_GUESTS = "guestsCanSeeGuests";
+ field public static final java.lang.String HAS_ALARM = "hasAlarm";
+ field public static final java.lang.String HAS_ATTENDEE_DATA = "hasAttendeeData";
+ field public static final java.lang.String HAS_EXTENDED_PROPERTIES = "hasExtendedProperties";
+ field public static final java.lang.String LAST_DATE = "lastDate";
+ field public static final java.lang.String LAST_SYNCED = "lastSynced";
+ field public static final java.lang.String ORGANIZER = "organizer";
+ field public static final java.lang.String ORIGINAL_ALL_DAY = "originalAllDay";
+ field public static final java.lang.String ORIGINAL_ID = "original_id";
+ field public static final java.lang.String ORIGINAL_INSTANCE_TIME = "originalInstanceTime";
+ field public static final java.lang.String ORIGINAL_SYNC_ID = "original_sync_id";
+ field public static final java.lang.String RDATE = "rdate";
+ field public static final java.lang.String RRULE = "rrule";
+ field public static final java.lang.String SELF_ATTENDEE_STATUS = "selfAttendeeStatus";
+ field public static final java.lang.String STATUS = "eventStatus";
+ field public static final int STATUS_CANCELED = 2; // 0x2
+ field public static final int STATUS_CONFIRMED = 1; // 0x1
+ field public static final int STATUS_TENTATIVE = 0; // 0x0
+ field public static final java.lang.String SYNC_DATA1 = "sync_data1";
+ field public static final java.lang.String SYNC_DATA10 = "sync_data10";
+ field public static final java.lang.String SYNC_DATA2 = "sync_data2";
+ field public static final java.lang.String SYNC_DATA3 = "sync_data3";
+ field public static final java.lang.String SYNC_DATA4 = "sync_data4";
+ field public static final java.lang.String SYNC_DATA5 = "sync_data5";
+ field public static final java.lang.String SYNC_DATA6 = "sync_data6";
+ field public static final java.lang.String SYNC_DATA7 = "sync_data7";
+ field public static final java.lang.String SYNC_DATA8 = "sync_data8";
+ field public static final java.lang.String SYNC_DATA9 = "sync_data9";
+ field public static final java.lang.String TITLE = "title";
+ }
+
+ public static final class CalendarContract.EventsEntity implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.SyncColumns {
+ method public static android.content.EntityIterator newEntityIterator(android.database.Cursor, android.content.ContentResolver);
+ method public static android.content.EntityIterator newEntityIterator(android.database.Cursor, android.content.ContentProviderClient);
+ field public static final android.net.Uri CONTENT_URI;
+ }
+
+ public static final class CalendarContract.ExtendedProperties implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.ExtendedPropertiesColumns {
+ field public static final android.net.Uri CONTENT_URI;
+ }
+
+ protected static abstract interface CalendarContract.ExtendedPropertiesColumns {
+ field public static final java.lang.String EVENT_ID = "event_id";
+ field public static final java.lang.String NAME = "name";
+ field public static final java.lang.String VALUE = "value";
+ }
+
+ public static final class CalendarContract.Instances implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns {
+ method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long);
+ method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long, java.lang.String);
+ field public static final java.lang.String BEGIN = "begin";
+ field public static final android.net.Uri CONTENT_BY_DAY_URI;
+ field public static final android.net.Uri CONTENT_SEARCH_BY_DAY_URI;
+ field public static final android.net.Uri CONTENT_SEARCH_URI;
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String END = "end";
+ field public static final java.lang.String END_DAY = "endDay";
+ field public static final java.lang.String END_MINUTE = "endMinute";
+ field public static final java.lang.String EVENT_ID = "event_id";
+ field public static final java.lang.String START_DAY = "startDay";
+ field public static final java.lang.String START_MINUTE = "startMinute";
+ }
+
+ public static final class CalendarContract.Reminders implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.RemindersColumns {
+ method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+ field public static final android.net.Uri CONTENT_URI;
+ }
+
+ protected static abstract interface CalendarContract.RemindersColumns {
+ field public static final java.lang.String EVENT_ID = "event_id";
+ field public static final java.lang.String METHOD = "method";
+ field public static final int METHOD_ALERT = 1; // 0x1
+ field public static final int METHOD_DEFAULT = 0; // 0x0
+ field public static final int METHOD_EMAIL = 2; // 0x2
+ field public static final int METHOD_SMS = 3; // 0x3
+ field public static final java.lang.String MINUTES = "minutes";
+ field public static final int MINUTES_DEFAULT = -1; // 0xffffffff
+ }
+
+ protected static abstract interface CalendarContract.SyncColumns implements android.provider.CalendarContract.CalendarSyncColumns {
+ field public static final java.lang.String ACCOUNT_NAME = "account_name";
+ field public static final java.lang.String ACCOUNT_TYPE = "account_type";
+ field public static final java.lang.String CAN_PARTIALLY_UPDATE = "canPartiallyUpdate";
+ field public static final java.lang.String DELETED = "deleted";
+ field public static final java.lang.String DIRTY = "dirty";
+ field public static final java.lang.String _SYNC_ID = "_sync_id";
+ }
+
+ public static final class CalendarContract.SyncState implements android.provider.SyncStateContract.Columns {
+ field public static final android.net.Uri CONTENT_URI;
+ }
+
public class CallLog {
ctor public CallLog();
field public static final java.lang.String AUTHORITY = "call_log";
@@ -15482,6 +15750,7 @@ package android.provider {
public static final class ContactsContract.CommonDataKinds.Photo implements android.provider.ContactsContract.DataColumnsWithJoins {
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
field public static final java.lang.String PHOTO = "data15";
+ field public static final java.lang.String PHOTO_FILE_ID = "data14";
}
public static final class ContactsContract.CommonDataKinds.Relation implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
@@ -15621,7 +15890,9 @@ package android.provider {
public static final class ContactsContract.Contacts.Photo implements android.provider.BaseColumns android.provider.ContactsContract.DataColumnsWithJoins {
field public static final java.lang.String CONTENT_DIRECTORY = "photo";
+ field public static final java.lang.String DISPLAY_PHOTO = "display_photo";
field public static final java.lang.String PHOTO = "data15";
+ field public static final java.lang.String PHOTO_FILE_ID = "data14";
}
public static final class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns {
@@ -15634,6 +15905,7 @@ package android.provider {
field public static final java.lang.String IN_VISIBLE_GROUP = "in_visible_group";
field public static final java.lang.String IS_USER_PROFILE = "is_user_profile";
field public static final java.lang.String LOOKUP_KEY = "lookup";
+ field public static final java.lang.String PHOTO_FILE_ID = "photo_file_id";
field public static final java.lang.String PHOTO_ID = "photo_id";
field public static final java.lang.String PHOTO_THUMBNAIL_URI = "photo_thumb_uri";
field public static final java.lang.String PHOTO_URI = "photo_uri";
@@ -15722,6 +15994,13 @@ package android.provider {
field public static final int UNDEFINED = 0; // 0x0
}
+ public static final class ContactsContract.DisplayPhoto {
+ field public static final android.net.Uri CONTENT_MAX_DIMENSIONS_URI;
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String DISPLAY_MAX_DIM = "display_max_dim";
+ field public static final java.lang.String THUMBNAIL_MAX_DIM = "thumbnail_max_dim";
+ }
+
public static abstract interface ContactsContract.FullNameStyle {
field public static final int CHINESE = 3; // 0x3
field public static final int CJK = 2; // 0x2
@@ -15740,7 +16019,10 @@ package android.provider {
}
protected static abstract interface ContactsContract.GroupsColumns {
+ field public static final java.lang.String ACTION = "action";
+ field public static final java.lang.String ACTION_URI = "action_uri";
field public static final java.lang.String AUTO_ADD = "auto_add";
+ field public static final java.lang.String DATA_SET = "data_set";
field public static final java.lang.String DELETED = "deleted";
field public static final java.lang.String FAVORITES = "favorites";
field public static final java.lang.String GROUP_IS_READ_ONLY = "group_is_read_only";
@@ -15856,6 +16138,10 @@ package android.provider {
field public static final java.lang.String CONTENT_DIRECTORY = "data";
}
+ public static final class ContactsContract.RawContacts.DisplayPhoto {
+ field public static final java.lang.String CONTENT_DIRECTORY = "display_photo";
+ }
+
public static final class ContactsContract.RawContacts.Entity implements android.provider.BaseColumns android.provider.ContactsContract.DataColumns {
field public static final java.lang.String CONTENT_DIRECTORY = "entity";
field public static final java.lang.String DATA_ID = "data_id";
@@ -15868,6 +16154,7 @@ package android.provider {
protected static abstract interface ContactsContract.RawContactsColumns {
field public static final java.lang.String AGGREGATION_MODE = "aggregation_mode";
field public static final java.lang.String CONTACT_ID = "contact_id";
+ field public static final java.lang.String DATA_SET = "data_set";
field public static final java.lang.String DELETED = "deleted";
field public static final java.lang.String RAW_CONTACT_IS_READ_ONLY = "raw_contact_is_read_only";
field public static final java.lang.String RAW_CONTACT_IS_USER_PROFILE = "raw_contact_is_user_profile";
@@ -20636,8 +20923,10 @@ package android.view {
public abstract class ActionProvider {
ctor public ActionProvider(android.content.Context);
+ method public boolean hasSubMenu();
method public abstract android.view.View onCreateActionView();
- method public void onPerformDefaultAction(android.view.View);
+ method public boolean onPerformDefaultAction();
+ method public void onPrepareSubMenu(android.view.SubMenu);
}
public abstract interface ContextMenu implements android.view.Menu {
@@ -22474,7 +22763,7 @@ package android.view {
method public void requestDisallowInterceptTouchEvent(boolean);
method public boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
method public void requestTransparentRegion(android.view.View);
- method protected void resetLayoutDirectionResolution();
+ method protected void resetResolvedLayoutDirection();
method public void scheduleLayoutAnimation();
method public void setAddStatesFromChildren(boolean);
method public void setAlwaysDrawnWithCacheEnabled(boolean);
@@ -25810,7 +26099,7 @@ package android.widget {
ctor public ShareActionProvider(android.content.Context);
method public android.view.View onCreateActionView();
method public void setShareHistoryFileName(java.lang.String);
- method public void setShareIntent(android.view.View, android.content.Intent);
+ method public void setShareIntent(android.content.Intent);
field public static final java.lang.String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
}
@@ -26151,7 +26440,9 @@ package android.widget {
method protected void onTextChanged(java.lang.CharSequence, int, int, int);
method public boolean onTextContextMenuItem(int);
method public void removeTextChangedListener(android.text.TextWatcher);
- method protected void resetLayoutDirectionResolution();
+ method protected void resetResolvedDrawables();
+ method protected void resetResolvedLayoutDirection();
+ method protected void resolveDrawables();
method public void setAllCaps(boolean);
method public final void setAutoLinkMask(int);
method public void setCompoundDrawablePadding(int);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 479b70a..3fb1736 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -157,6 +157,11 @@ public class Am {
String value = nextArgRequired();
intent.putExtra(key, Integer.valueOf(value));
hasIntentInfo = true;
+ } else if (opt.equals("--eu")) {
+ String key = nextArgRequired();
+ String value = nextArgRequired();
+ intent.putExtra(key, Uri.parse(value));
+ hasIntentInfo = true;
} else if (opt.equals("--eia")) {
String key = nextArgRequired();
String value = nextArgRequired();
@@ -1119,6 +1124,7 @@ public class Am {
" [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
" [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
" [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
+ " [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]\n" +
" [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
" [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
" [-n <COMPONENT>] [-f <FLAGS>]\n" +
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 152a7cb..f2be29f 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -82,35 +82,27 @@ public:
virtual void onStarted()
{
sp<ProcessState> proc = ProcessState::self();
- if (proc->supportsProcesses()) {
- LOGV("App process: starting thread pool.\n");
- proc->startThreadPool();
- }
+ LOGV("App process: starting thread pool.\n");
+ proc->startThreadPool();
AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgC, mArgV);
- if (ProcessState::self()->supportsProcesses()) {
- IPCThreadState::self()->stopProcess();
- }
+ IPCThreadState::self()->stopProcess();
}
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
- if (proc->supportsProcesses()) {
- LOGV("App process: starting thread pool.\n");
- proc->startThreadPool();
- }
+ LOGV("App process: starting thread pool.\n");
+ proc->startThreadPool();
}
virtual void onExit(int code)
{
if (mClassName == NULL) {
// if zygote
- if (ProcessState::self()->supportsProcesses()) {
- IPCThreadState::self()->stopProcess();
- }
+ IPCThreadState::self()->stopProcess();
}
AndroidRuntime::onExit(code);
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index a00a212..7d39912 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -5,13 +5,6 @@ LOCAL_SRC_FILES:= \
bootanimation_main.cpp \
BootAnimation.cpp
-# need "-lrt" on Linux simulator to pick up clock_gettime
-ifeq ($(TARGET_SIMULATOR),true)
- ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt
- endif
-endif
-
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_SHARED_LIBRARIES := \
diff --git a/cmds/bugreport/Android.mk b/cmds/bugreport/Android.mk
index 631c219..f476f5e 100644
--- a/cmds/bugreport/Android.mk
+++ b/cmds/bugreport/Android.mk
@@ -1,5 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -10,5 +8,3 @@ LOCAL_MODULE:= bugreport
LOCAL_SHARED_LIBRARIES := libcutils
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 431a556..56f1324 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -1,5 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -14,5 +12,3 @@ LOCAL_MODULE := dumpstate
LOCAL_SHARED_LIBRARIES := libcutils
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index d7a9ef6..f277339 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -1,5 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH := $(call my-dir)
common_src_files := \
@@ -41,5 +39,3 @@ LOCAL_MODULE := installd
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
-
-endif # !simulator
diff --git a/cmds/installd/tests/Android.mk b/cmds/installd/tests/Android.mk
index e53378d..315acdb 100644
--- a/cmds/installd/tests/Android.mk
+++ b/cmds/installd/tests/Android.mk
@@ -2,8 +2,6 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-ifneq ($(TARGET_SIMULATOR),true)
-
# Build the unit tests.
test_src_files := \
installd_utils_test.cpp
@@ -38,5 +36,3 @@ $(foreach file,$(test_src_files), \
$(eval LOCAL_MODULE_TAGS := $(module_tags)) \
$(eval include $(BUILD_EXECUTABLE)) \
)
-
-endif
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
index 67dd9f8..5a9b979 100644
--- a/cmds/keystore/Android.mk
+++ b/cmds/keystore/Android.mk
@@ -14,8 +14,6 @@
# limitations under the License.
#
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -32,5 +30,3 @@ LOCAL_SHARED_LIBRARIES := libcutils libcrypto
LOCAL_MODULE:= keystore_cli
LOCAL_MODULE_TAGS := debug
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/cmds/rawbu/Android.mk b/cmds/rawbu/Android.mk
index c1be8a4..b580390 100644
--- a/cmds/rawbu/Android.mk
+++ b/cmds/rawbu/Android.mk
@@ -1,7 +1,5 @@
# Copyright 2009 The Android Open Source Project
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -15,5 +13,3 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := debug
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/cmds/runtime/Android.mk b/cmds/runtime/Android.mk
deleted file mode 100644
index 6a72d10..0000000
--- a/cmds/runtime/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-ifeq ($(TARGET_SIMULATOR),true)
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- ServiceManager.cpp \
- SignalHandler.cpp \
- main_runtime.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libutils \
- libbinder \
- libandroid_runtime \
- libcutils \
- libui \
- libsystem_server \
- libhardware_legacy
-
-LOCAL_C_INCLUDES := \
- $(JNI_H_INCLUDE)
-
-ifeq ($(TARGET_OS),linux)
- LOCAL_CFLAGS += -DXP_UNIX
-endif
-
-LOCAL_MODULE:= runtime
-
-include $(BUILD_EXECUTABLE)
-endif
diff --git a/cmds/runtime/MODULE_LICENSE_APACHE2 b/cmds/runtime/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/cmds/runtime/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/cmds/runtime/NOTICE b/cmds/runtime/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/cmds/runtime/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2005-2008, 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.
-
- 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.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/cmds/runtime/ServiceManager.cpp b/cmds/runtime/ServiceManager.cpp
deleted file mode 100644
index b2bef07..0000000
--- a/cmds/runtime/ServiceManager.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-
-#define LOG_TAG "ServiceManager"
-
-#include "ServiceManager.h"
-#include "SignalHandler.h"
-
-#include <utils/Debug.h>
-#include <utils/Log.h>
-#include <binder/Parcel.h>
-#include <utils/String8.h>
-#include <binder/ProcessState.h>
-
-#include <private/utils/Static.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-
-namespace android {
-
-BServiceManager::BServiceManager()
-{
-}
-
-sp<IBinder> BServiceManager::getService(const String16& name) const
-{
- AutoMutex _l(mLock);
- ssize_t i = mServices.indexOfKey(name);
- LOGV("ServiceManager: getService(%s) -> %d\n", String8(name).string(), i);
- if (i >= 0) return mServices.valueAt(i);
- return NULL;
-}
-
-sp<IBinder> BServiceManager::checkService(const String16& name) const
-{
- AutoMutex _l(mLock);
- ssize_t i = mServices.indexOfKey(name);
- LOGV("ServiceManager: getService(%s) -> %d\n", String8(name).string(), i);
- if (i >= 0) return mServices.valueAt(i);
- return NULL;
-}
-
-status_t BServiceManager::addService(const String16& name, const sp<IBinder>& service)
-{
- AutoMutex _l(mLock);
- LOGI("ServiceManager: addService(%s, %p)\n", String8(name).string(), service.get());
- const ssize_t res = mServices.add(name, service);
- if (res >= NO_ERROR) {
- mChanged.broadcast();
- return NO_ERROR;
- }
- return res;
-}
-
-Vector<String16> BServiceManager::listServices()
-{
- Vector<String16> res;
-
- AutoMutex _l(mLock);
- const size_t N = mServices.size();
- for (size_t i=0; i<N; i++) {
- res.add(mServices.keyAt(i));
- }
-
- return res;
-}
-
-}; // namespace android
diff --git a/cmds/runtime/ServiceManager.h b/cmds/runtime/ServiceManager.h
deleted file mode 100644
index 090ca6d..0000000
--- a/cmds/runtime/ServiceManager.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-#ifndef ANDROID_SERVICE_MANAGER_H
-#define ANDROID_SERVICE_MANAGER_H
-
-#include <binder/IServiceManager.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------
-
-class BServiceManager : public BnServiceManager
-{
-public:
- BServiceManager();
-
- virtual sp<IBinder> getService( const String16& name) const;
- virtual sp<IBinder> checkService( const String16& name) const;
- virtual status_t addService( const String16& name,
- const sp<IBinder>& service);
- virtual Vector<String16> listServices();
-
-
-private:
- mutable Mutex mLock;
- mutable Condition mChanged;
- sp<IPermissionController> mPermissionController;
- KeyedVector<String16, sp<IBinder> > mServices;
-};
-
-// ----------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_SERVICE_MANAGER_H
diff --git a/cmds/runtime/SignalHandler.cpp b/cmds/runtime/SignalHandler.cpp
deleted file mode 100644
index cccaabf..0000000
--- a/cmds/runtime/SignalHandler.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-
-#define LOG_TAG "SignalHandler"
-
-#include "SignalHandler.h"
-
-#include <utils/Atomic.h>
-#include <utils/Debug.h>
-#include <utils/Log.h>
-
-#include <errno.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-namespace android {
-
-class SignalHandler::ProcessThread : public Thread
-{
-public:
- ProcessThread(SignalHandler& sh)
- : Thread(false)
- , mOwner(sh)
- {
- }
-
- virtual bool threadLoop()
- {
- char buffer[32];
- read(mOwner.mAvailMsg[0], buffer, sizeof(buffer));
-
- LOGV("Signal command processing thread woke up!");
-
- if (mOwner.mLostCommands) {
- LOGE("Lost %d signals!", mOwner.mLostCommands);
- mOwner.mLostCommands = 0;
- }
-
- int cur;
- while ((cur=mOwner.mCommandBottom) != mOwner.mCommandTop) {
- if (mOwner.mCommands[cur].filled == 0) {
- LOGV("Command at %d is not yet filled", cur);
- break;
- }
-
- LOGV("Processing command at %d, top is %d",
- cur, mOwner.mCommandTop);
- processCommand(mOwner.mCommands[cur]);
- mOwner.mCommands[cur].filled = 0;
-
- int next = mOwner.mCommandBottom+1;
- if (next >= COMMAND_QUEUE_SIZE) {
- next = 0;
- }
-
- mOwner.mCommandBottom = next;
- }
-
- return true;
- }
-
- void processCommand(const CommandEntry& entry)
- {
- switch (entry.signum) {
- case SIGCHLD: {
- mOwner.mLock.lock();
- ssize_t i = mOwner.mChildHandlers.indexOfKey(entry.info.si_pid);
- ChildHandler ch;
- if (i >= 0) {
- ch = mOwner.mChildHandlers.valueAt(i);
- mOwner.mChildHandlers.removeItemsAt(i);
- }
- mOwner.mLock.unlock();
-
- LOGD("SIGCHLD: pid=%d, handle index=%d", entry.info.si_pid, i);
-
- if (i >= 0) {
- int res = waitpid(entry.info.si_pid, NULL, WNOHANG);
- LOGW_IF(res == 0,
- "Received SIGCHLD, but pid %d is not yet stopped",
- entry.info.si_pid);
- if (ch.handler) {
- ch.handler(entry.info.si_pid, ch.userData);
- }
- } else {
- LOGW("Unhandled SIGCHLD for pid %d", entry.info.si_pid);
- }
- } break;
- }
- }
-
- SignalHandler& mOwner;
-};
-
-
-Mutex SignalHandler::mInstanceLock;
-SignalHandler* SignalHandler::mInstance = NULL;
-
-status_t SignalHandler::setChildHandler(pid_t childPid,
- int tag,
- child_callback_t handler,
- void* userData)
-{
- SignalHandler* const self = getInstance();
-
- self->mLock.lock();
-
- // First make sure this child hasn't already exited.
- pid_t res = waitpid(childPid, NULL, WNOHANG);
- if (res != 0) {
- if (res < 0) {
- LOGW("setChildHandler waitpid of %d failed: %d (%s)",
- childPid, res, strerror(errno));
- } else {
- LOGW("setChildHandler waitpid of %d said %d already dead",
- childPid, res);
- }
-
- // Some kind of error... just handle the exit now.
- self->mLock.unlock();
-
- if (handler) {
- handler(childPid, userData);
- }
-
- // Return an error code -- 0 means it already exited.
- return (status_t)res;
- }
-
- ChildHandler entry;
- entry.childPid = childPid;
- entry.tag = tag;
- entry.handler = handler;
- entry.userData = userData;
-
- // Note: this replaces an existing entry for this pid, if there already
- // is one. This is the required behavior.
- LOGD("setChildHandler adding pid %d, tag %d, handler %p, data %p",
- childPid, tag, handler, userData);
- self->mChildHandlers.add(childPid, entry);
-
- self->mLock.unlock();
-
- return NO_ERROR;
-}
-
-void SignalHandler::killAllChildren(int tag)
-{
- SignalHandler* const self = getInstance();
-
- AutoMutex _l (self->mLock);
- const size_t N = self->mChildHandlers.size();
- for (size_t i=0; i<N; i++) {
- const ChildHandler& ch(self->mChildHandlers.valueAt(i));
- if (tag == 0 || ch.tag == tag) {
- const pid_t pid = ch.childPid;
- LOGI("Killing child %d (tag %d)\n", pid, ch.tag);
- kill(pid, SIGKILL);
- }
- }
-}
-
-SignalHandler::SignalHandler()
- : mCommandTop(0)
- , mCommandBottom(0)
- , mLostCommands(0)
-{
- memset(mCommands, 0, sizeof(mCommands));
-
- int res = pipe(mAvailMsg);
- LOGE_IF(res != 0, "Unable to create signal handler pipe: %s", strerror(errno));
-
- mProcessThread = new ProcessThread(*this);
- mProcessThread->run("SignalHandler", PRIORITY_HIGHEST);
-
- struct sigaction sa;
- memset(&sa, 0, sizeof(sa));
- sa.sa_sigaction = sigAction;
- sa.sa_flags = SA_NOCLDSTOP|SA_SIGINFO;
- sigaction(SIGCHLD, &sa, NULL);
-}
-
-SignalHandler::~SignalHandler()
-{
-}
-
-SignalHandler* SignalHandler::getInstance()
-{
- AutoMutex _l(mInstanceLock);
- if (mInstance == NULL) {
- mInstance = new SignalHandler();
- }
- return mInstance;
-}
-
-void SignalHandler::sigAction(int signum, siginfo_t* info, void*)
-{
- static const char wakeupMsg[1] = { 0xff };
-
- // If our signal handler is being called, then we know we have
- // already initialized the SignalHandler class and thus mInstance
- // is valid.
- SignalHandler* const self = mInstance;
-
- // XXX This is not safe!
- #if 0
- LOGV("Signal %d: signo=%d, errno=%d, code=%d, pid=%d\n",
- signum,
- info->si_signo, info->si_errno, info->si_code,
- info->si_pid);
- #endif
-
- int32_t oldTop, newTop;
-
- // Find the next command slot...
- do {
- oldTop = self->mCommandTop;
-
- newTop = oldTop + 1;
- if (newTop >= COMMAND_QUEUE_SIZE) {
- newTop = 0;
- }
-
- if (newTop == self->mCommandBottom) {
- // The buffer is filled up! Ouch!
- // XXX This is not safe!
- #if 0
- LOGE("Command buffer overflow! newTop=%d\n", newTop);
- #endif
- android_atomic_add(1, &self->mLostCommands);
- write(self->mAvailMsg[1], wakeupMsg, sizeof(wakeupMsg));
- return;
- }
- } while(android_atomic_cmpxchg(oldTop, newTop, &(self->mCommandTop)));
-
- // Fill in the command data...
- self->mCommands[oldTop].signum = signum;
- self->mCommands[oldTop].info = *info;
-
- // And now make this command available.
- self->mCommands[oldTop].filled = 1;
-
- // Wake up the processing thread.
- write(self->mAvailMsg[1], wakeupMsg, sizeof(wakeupMsg));
-}
-
-}; // namespace android
-
diff --git a/cmds/runtime/SignalHandler.h b/cmds/runtime/SignalHandler.h
deleted file mode 100644
index 7f4ef8e..0000000
--- a/cmds/runtime/SignalHandler.h
+++ /dev/null
@@ -1,137 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-#ifndef ANDROID_SIGNAL_HANDLER_H
-#define ANDROID_SIGNAL_HANDLER_H
-
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-
-#include <signal.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------
-
-enum {
- DEFAULT_PROCESS_TAG = 1
-};
-
-class SignalHandler
-{
-public:
- typedef void (*child_callback_t)(pid_t child, void* userData);
-
- /**
- * Set a handler for when a child process exits. By calling
- * this, a waitpid() will be done when the child exits to remove
- * it from the zombie state. You can also optionally specify a
- * handler to be called when the child exits.
- *
- * If there is already a handler for this child process, it is
- * replaced by this new handler. In this case the old handler's
- * function is not called.
- *
- * @param childPid Process ID of child to watch.
- * @param childTag User-defined tag for this child. Must be
- * greater than zero.
- * @param handler If non-NULL, this will be called when the
- * child exits. It may be called in either a
- * separate signal handling thread, or
- * immediately if the child has already exited.
- * @param userData Propageted as-is to handler.
- *
- * @return status_t NO_ERROR if all is well.
- */
- static status_t setChildHandler(pid_t childPid,
- int childTag = DEFAULT_PROCESS_TAG,
- child_callback_t handler = NULL,
- void* userData = NULL);
-
- /**
- * Kill all of the child processes for which we have a waiting
- * handler, whose tag is the given value. If tag is 0, all
- * children are killed.
- *
- * @param tag
- */
- static void killAllChildren(int tag = 0);
-
-private:
- SignalHandler();
- ~SignalHandler();
-
- static SignalHandler* getInstance();
-
- static void sigAction(int, siginfo_t*, void*);
-
- // --------------------------------------------------
- // Shared state... all of this is protected by mLock.
- // --------------------------------------------------
-
- mutable Mutex mLock;
-
- struct ChildHandler
- {
- pid_t childPid;
- int tag;
- child_callback_t handler;
- void* userData;
- };
- KeyedVector<pid_t, ChildHandler> mChildHandlers;
-
- // --------------------------------------------------
- // Commmand queue... data is inserted by the signal
- // handler using atomic ops, and retrieved by the
- // signal processing thread. Because these are touched
- // by the signal handler, no lock is used.
- // --------------------------------------------------
-
- enum {
- COMMAND_QUEUE_SIZE = 64
- };
- struct CommandEntry
- {
- int filled;
- int signum;
- siginfo_t info;
- };
-
- // The top of the queue. This is incremented atomically by the
- // signal handler before placing a command in the queue.
- volatile int32_t mCommandTop;
-
- // The bottom of the queue. Only modified by the processing
- // thread; the signal handler reads it only to determine if the
- // queue is full.
- int32_t mCommandBottom;
-
- // Incremented each time we receive a signal and don't have room
- // for it on the command queue.
- volatile int32_t mLostCommands;
-
- // The command processing thread.
- class ProcessThread;
- sp<Thread> mProcessThread;
-
- // Pipe used to tell command processing thread when new commands.
- // are available. The thread blocks on the read end, the signal
- // handler writes when it enqueues new commands.
- int mAvailMsg[2];
-
- // The commands.
- CommandEntry mCommands[COMMAND_QUEUE_SIZE];
-
- // --------------------------------------------------
- // Singleton.
- // --------------------------------------------------
-
- static Mutex mInstanceLock;
- static SignalHandler* mInstance;
-};
-
-// ----------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_SIGNAL_HANDLER_H
diff --git a/cmds/runtime/main_runtime.cpp b/cmds/runtime/main_runtime.cpp
deleted file mode 100644
index dbff095..0000000
--- a/cmds/runtime/main_runtime.cpp
+++ /dev/null
@@ -1,515 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-// Main entry point for runtime.
-//
-
-#include "ServiceManager.h"
-#include "SignalHandler.h"
-
-#include <utils/threads.h>
-#include <utils/Errors.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <utils/Log.h>
-#include <cutils/zygote.h>
-
-#include <cutils/properties.h>
-
-#include <private/utils/Static.h>
-
-#include <surfaceflinger/ISurfaceComposer.h>
-
-#include <android_runtime/AndroidRuntime.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <getopt.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <linux/capability.h>
-#include <linux/ioctl.h>
-#ifdef HAVE_ANDROID_OS
-# include <linux/android_alarm.h>
-#endif
-
-#undef LOG_TAG
-#define LOG_TAG "runtime"
-
-static const char* ZYGOTE_ARGV[] = {
- "--setuid=1000",
- "--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
- /* CAP_SYS_TTY_CONFIG & CAP_SYS_RESOURCE & CAP_NET_BROADCAST &
- * CAP_NET_ADMIN & CAP_NET_RAW & CAP_NET_BIND_SERVICE & CAP_KILL &
- * CAP_SYS_BOOT CAP_SYS_NICE
- */
- "--capabilities=96549920,96549920",
- "--runtime-init",
- "--nice-name=system_server",
- "com.android.server.SystemServer"
-};
-
-using namespace android;
-
-extern "C" status_t system_init();
-
-enum {
- SYSTEM_PROCESS_TAG = DEFAULT_PROCESS_TAG+1
-};
-
-extern Mutex gEventQMutex;
-extern Condition gEventQCondition;
-
-namespace android {
-
-extern void set_finish_init_func(void (*func)());
-
-
-/**
- * This class is used to kill this process (runtime) when the system_server dies.
- */
-class GrimReaper : public IBinder::DeathRecipient {
-public:
- GrimReaper() { }
-
- virtual void binderDied(const wp<IBinder>& who)
- {
- LOGI("Grim Reaper killing runtime...");
- kill(getpid(), SIGKILL);
- }
-};
-
-extern void QuickTests();
-
-/*
- * Print usage info.
- */
-static void usage(const char* argv0)
-{
- fprintf(stderr,
- "Usage: runtime [-g gamma] [-l logfile] [-n] [-s]\n"
- " [-j app-component] [-v app-verb] [-d app-data]\n"
- "\n"
- "-l: File to send log messages to\n"
- "-n: Don't print to stdout/stderr\n"
- "-s: Force single-process mode\n"
- "-j: Custom home app component name\n"
- "-v: Custom home app intent verb\n"
- "-d: Custom home app intent data\n"
- );
- exit(1);
-}
-
-// Selected application to run.
-static const char* gInitialApplication = NULL;
-static const char* gInitialVerb = NULL;
-static const char* gInitialData = NULL;
-
-static void writeStringToParcel(Parcel& parcel, const char* str)
-{
- if (str) {
- parcel.writeString16(String16(str));
- } else {
- parcel.writeString16(NULL, 0);
- }
-}
-
-/*
- * Starting point for program logic.
- *
- * Returns with an exit status code (0 on success, nonzero on error).
- */
-static int run(sp<ProcessState>& proc)
-{
- // Temporary hack to call startRunning() on the activity manager.
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> am;
- while ((am = sm->getService(String16("activity"))) == NULL) {
- LOGI("Waiting for activity manager...");
- }
- Parcel data, reply;
- // XXX Need to also supply a package name for this to work again.
- // IActivityManager::getInterfaceDescriptor() is the token for invoking on this interface;
- // hardcoding it here avoids having to link with the full Activity Manager library
- data.writeInterfaceToken(String16("android.app.IActivityManager"));
- writeStringToParcel(data, NULL);
- writeStringToParcel(data, gInitialApplication);
- writeStringToParcel(data, gInitialVerb);
- writeStringToParcel(data, gInitialData);
-LOGI("run() sending FIRST_CALL_TRANSACTION to activity manager");
- am->transact(IBinder::FIRST_CALL_TRANSACTION, data, &reply);
-
- if (proc->supportsProcesses()) {
- // Now we link to the Activity Manager waiting for it to die. If it does kill ourself.
- // initd will restart this process and bring the system back up.
- sp<GrimReaper> grim = new GrimReaper();
- am->linkToDeath(grim, grim.get(), 0);
-
- // Now join the thread pool. Note this is needed so that the message enqueued in the driver
- // for the linkToDeath gets processed.
- IPCThreadState::self()->joinThreadPool();
- } else {
- // Keep this thread running forever...
- while (1) {
- usleep(100000);
- }
- }
- return 1;
-}
-
-
-}; // namespace android
-
-
-/*
- * Post-system-process initialization.
- *
- * This function continues initialization after the system process
- * has been initialized. It needs to be separate because the system
- * initialization needs to care of starting the Android runtime if it is not
- * running in its own process, which doesn't return until the runtime is
- * being shut down. So it will call back to here from inside of Dalvik,
- * to allow us to continue booting up.
- */
-static void finish_system_init(sp<ProcessState>& proc)
-{
- // If we are running multiprocess, we now need to have the
- // thread pool started here. We don't do this in boot_init()
- // because when running single process we need to start the
- // thread pool after the Android runtime has been started (so
- // the pool uses Dalvik threads).
- if (proc->supportsProcesses()) {
- proc->startThreadPool();
- }
-}
-
-
-// This function can be used to enforce security to different
-// root contexts. For now, we just give every access.
-static bool contextChecker(
- const String16& name, const sp<IBinder>& caller, void* userData)
-{
- return true;
-}
-
-/*
- * Initialization of boot services.
- *
- * This is where we perform initialization of all of our low-level
- * boot services. Most importantly, here we become the context
- * manager and use that to publish the service manager that will provide
- * access to all other services.
- */
-static void boot_init()
-{
- LOGI("Entered boot_init()!\n");
-
- sp<ProcessState> proc(ProcessState::self());
- LOGD("ProcessState: %p\n", proc.get());
- proc->becomeContextManager(contextChecker, NULL);
-
- if (proc->supportsProcesses()) {
- LOGI("Binder driver opened. Multiprocess enabled.\n");
- } else {
- LOGI("Binder driver not found. Processes not supported.\n");
- }
-
- sp<BServiceManager> sm = new BServiceManager;
- proc->setContextObject(sm);
-}
-
-/*
- * Redirect stdin/stdout/stderr to /dev/null.
- */
-static void redirectStdFds(void)
-{
- int fd = open("/dev/null", O_RDWR, 0);
- if (fd < 0) {
- LOGW("Unable to open /dev/null: %s\n", strerror(errno));
- } else {
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- close(fd);
- }
-}
-
-static int hasDir(const char* dir)
-{
- struct stat s;
- int res = stat(dir, &s);
- if (res == 0) {
- return S_ISDIR(s.st_mode);
- }
- return 0;
-}
-
-static void validateTime()
-{
-#if HAVE_ANDROID_OS
- int fd;
- int res;
- time_t min_time = 1167652800; // jan 1 2007, type 'date -ud "1/1 12:00" +%s' to get value for current year
- struct timespec ts;
-
- fd = open("/dev/alarm", O_RDWR);
- if(fd < 0) {
- LOGW("Unable to open alarm driver: %s\n", strerror(errno));
- return;
- }
- res = ioctl(fd, ANDROID_ALARM_GET_TIME(ANDROID_ALARM_RTC_WAKEUP), &ts);
- if(res < 0) {
- LOGW("Unable to read rtc, %s\n", strerror(errno));
- }
- else if(ts.tv_sec >= min_time) {
- goto done;
- }
- LOGW("Invalid time detected, %ld set to %ld\n", ts.tv_sec, min_time);
- ts.tv_sec = min_time;
- ts.tv_nsec = 0;
- res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
- if(res < 0) {
- LOGW("Unable to set rtc to %ld: %s\n", ts.tv_sec, strerror(errno));
- }
-done:
- close(fd);
-#endif
-}
-
-#ifndef HAVE_ANDROID_OS
-class QuickRuntime : public AndroidRuntime
-{
-public:
- QuickRuntime() {}
-
- virtual void onStarted()
- {
- printf("QuickRuntime: onStarted\n");
- }
-};
-#endif
-
-static status_t start_process(const char* name);
-
-static void restart_me(pid_t child, void* userData)
-{
- start_process((const char*)userData);
-}
-
-static status_t start_process(const char* name)
-{
- String8 path(name);
- Vector<const char*> args;
- String8 leaf(path.getPathLeaf());
- String8 parentDir(path.getPathDir());
- args.insertAt(leaf.string(), 0);
- args.add(parentDir.string());
- args.add(NULL);
- pid_t child = fork();
- if (child < 0) {
- status_t err = errno;
- LOGE("*** fork of child %s failed: %s", leaf.string(), strerror(err));
- return -errno;
- } else if (child == 0) {
- LOGI("Executing: %s", path.string());
- execv(path.string(), const_cast<char**>(args.array()));
- int err = errno;
- LOGE("Exec failed: %s\n", strerror(err));
- _exit(err);
- } else {
- SignalHandler::setChildHandler(child, DEFAULT_PROCESS_TAG,
- restart_me, (void*)name);
- }
- return -errno;
-}
-
-/*
- * Application entry point.
- *
- * Parse arguments, set some values, and pass control off to Run().
- *
- * This is redefined to "SDL_main" on SDL simulator builds, and
- * "runtime_main" on wxWidgets builds.
- */
-extern "C"
-int main(int argc, char* const argv[])
-{
- bool singleProcess = false;
- const char* logFile = NULL;
- int ic;
- int result = 1;
- pid_t systemPid;
-
- sp<ProcessState> proc;
-
-#ifndef HAVE_ANDROID_OS
- /* Set stdout/stderr to unbuffered for MinGW/MSYS. */
- //setvbuf(stdout, NULL, _IONBF, 0);
- //setvbuf(stderr, NULL, _IONBF, 0);
-
- LOGI("commandline args:\n");
- for (int i = 0; i < argc; i++)
- LOGI(" %2d: '%s'\n", i, argv[i]);
-#endif
-
- while (1) {
- ic = getopt(argc, argv, "g:j:v:d:l:ns");
- if (ic < 0)
- break;
-
- switch (ic) {
- case 'g':
- break;
- case 'j':
- gInitialApplication = optarg;
- break;
- case 'v':
- gInitialVerb = optarg;
- break;
- case 'd':
- gInitialData = optarg;
- break;
- case 'l':
- logFile = optarg;
- break;
- case 'n':
- redirectStdFds();
- break;
- case 's':
- singleProcess = true;
- break;
- case '?':
- default:
- LOGE("runtime: unrecognized flag -%c\n", ic);
- usage(argv[0]);
- break;
- }
- }
- if (optind < argc) {
- LOGE("runtime: extra stuff: %s\n", argv[optind]);
- usage(argv[0]);
- }
-
- if (singleProcess) {
- ProcessState::setSingleProcess(true);
- }
-
- if (logFile != NULL) {
- android_logToFile(NULL, logFile);
- }
-
- /*
- * Set up ANDROID_* environment variables.
- *
- * TODO: the use of $ANDROID_PRODUCT_OUT will go away soon.
- */
- static const char* kSystemDir = "/system";
- static const char* kDataDir = "/data";
- static const char* kAppSubdir = "/app";
- const char* out = NULL;
-#ifndef HAVE_ANDROID_OS
- //out = getenv("ANDROID_PRODUCT_OUT");
-#endif
- if (out == NULL)
- out = "";
-
- char* systemDir = (char*) malloc(strlen(out) + strlen(kSystemDir) +1);
- char* dataDir = (char*) malloc(strlen(out) + strlen(kDataDir) +1);
-
- sprintf(systemDir, "%s%s", out, kSystemDir);
- sprintf(dataDir, "%s%s", out, kDataDir);
- setenv("ANDROID_ROOT", systemDir, 1);
- setenv("ANDROID_DATA", dataDir, 1);
-
- char* assetDir = (char*) malloc(strlen(systemDir) + strlen(kAppSubdir) +1);
- sprintf(assetDir, "%s%s", systemDir, kAppSubdir);
-
- LOGI("Startup: sys='%s' asset='%s' data='%s'\n",
- systemDir, assetDir, dataDir);
- free(systemDir);
- free(dataDir);
-
-#ifdef HAVE_ANDROID_OS
- /* set up a process group for easier killing on the device */
- setpgid(0, getpid());
-#endif
-
- // Change to asset dir. This is only necessary if we've changed to
- // a different directory, but there's little harm in doing it regardless.
- //
- // Expecting assets to live in the current dir is not a great idea,
- // because some of our code or one of our libraries could change the
- // directory out from under us. Preserve the behavior for now.
- if (chdir(assetDir) != 0) {
- LOGW("WARNING: could not change dir to '%s': %s\n",
- assetDir, strerror(errno));
- }
- free(assetDir);
-
-#if 0
- // Hack to keep libc from beating the filesystem to death. It's
- // hitting /etc/localtime frequently,
- //
- // This statement locks us into Pacific time. We could do better,
- // but there's not much point until we're sure that the library
- // can't be changed to do more along the lines of what we want.
-#ifndef XP_WIN
- setenv("TZ", "PST+8PDT,M4.1.0/2,M10.5.0/2", true);
-#endif
-#endif
-
- /* track our progress through the boot sequence */
- const int LOG_BOOT_PROGRESS_START = 3000;
- LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
- ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
-
- validateTime();
-
- proc = ProcessState::self();
-
- boot_init();
-
- /* If we are in multiprocess mode, have zygote spawn the system
- * server process and call system_init(). If we are running in
- * single process mode just call system_init() directly.
- */
- if (proc->supportsProcesses()) {
- // If stdio logging is on, system_server should not inherit our stdio
- // The dalvikvm instance will copy stdio to the log on its own
- char propBuf[PROPERTY_VALUE_MAX];
- bool logStdio = false;
- property_get("log.redirect-stdio", propBuf, "");
- logStdio = (strcmp(propBuf, "true") == 0);
-
- zygote_run_oneshot((int)(!logStdio),
- sizeof(ZYGOTE_ARGV) / sizeof(ZYGOTE_ARGV[0]),
- ZYGOTE_ARGV);
-
- //start_process("/system/bin/mediaserver");
-
- } else {
-#ifndef HAVE_ANDROID_OS
- QuickRuntime* runt = new QuickRuntime();
- runt->start("com/android/server/SystemServer",
- "" /* spontaneously fork system server from zygote */);
-#endif
- }
-
- //printf("+++ post-zygote\n");
-
- finish_system_init(proc);
- run(proc);
-
-bail:
- if (proc != NULL) {
- proc->setContextObject(NULL);
- }
-
- return 0;
-}
diff --git a/cmds/screenshot/Android.mk b/cmds/screenshot/Android.mk
index 99c7aeb..73a8e22 100644
--- a/cmds/screenshot/Android.mk
+++ b/cmds/screenshot/Android.mk
@@ -1,5 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -12,5 +10,3 @@ LOCAL_STATIC_LIBRARIES := libpng
LOCAL_C_INCLUDES += external/zlib
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/cmds/servicemanager/Android.mk b/cmds/servicemanager/Android.mk
index fe5929b..ea80c7d 100644
--- a/cmds/servicemanager/Android.mk
+++ b/cmds/servicemanager/Android.mk
@@ -1,4 +1,3 @@
-ifneq ($(TARGET_SIMULATOR),true)
LOCAL_PATH:= $(call my-dir)
#include $(CLEAR_VARS)
@@ -14,4 +13,3 @@ ifeq ($(BOARD_USE_LVMX),true)
LOCAL_CFLAGS += -DLVMX
endif
include $(BUILD_EXECUTABLE)
-endif
diff --git a/cmds/system_server/library/system_init.cpp b/cmds/system_server/library/system_init.cpp
index a19711e..59360d3 100644
--- a/cmds/system_server/library/system_init.cpp
+++ b/cmds/system_server/library/system_init.cpp
@@ -76,23 +76,6 @@ extern "C" status_t system_init()
SensorService::instantiate();
}
- // On the simulator, audioflinger et al don't get started the
- // same way as on the device, and we need to start them here
- if (!proc->supportsProcesses()) {
-
- // Start the AudioFlinger
- AudioFlinger::instantiate();
-
- // Start the media playback service
- MediaPlayerService::instantiate();
-
- // Start the camera service
- CameraService::instantiate();
-
- // Start the audio policy service
- AudioPolicyService::instantiate();
- }
-
// And now start the Android runtime. We have to do this bit
// of nastiness because the Android runtime initialization requires
// some of the core system services to already be started.
@@ -117,14 +100,10 @@ extern "C" status_t system_init()
}
env->CallStaticVoidMethod(clazz, methodId);
- // If running in our own process, just go into the thread
- // pool. Otherwise, call the initialization finished
- // func to let this process continue its initilization.
- if (proc->supportsProcesses()) {
- LOGI("System server: entering thread pool.\n");
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
- LOGI("System server: exiting thread pool.\n");
- }
+ LOGI("System server: entering thread pool.\n");
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+ LOGI("System server: exiting thread pool.\n");
+
return NO_ERROR;
}
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index d77dbdc..e6c2a0f 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -87,11 +87,13 @@ public final class AnimatorSet extends Animator {
private AnimatorSetListener mSetListener = null;
/**
- * Flag indicating that the AnimatorSet has been canceled (by calling cancel() or end()).
+ * Flag indicating that the AnimatorSet has been manually
+ * terminated (by calling cancel() or end()).
* This flag is used to avoid starting other animations when currently-playing
- * child animations of this AnimatorSet end.
+ * child animations of this AnimatorSet end. It also determines whether cancel/end
+ * notifications are sent out via the normal AnimatorSetListener mechanism.
*/
- boolean mCanceled = false;
+ boolean mTerminated = false;
// The amount of time in ms to delay starting the animation after start() is called
private long mStartDelay = 0;
@@ -271,30 +273,28 @@ public final class AnimatorSet extends Animator {
@SuppressWarnings("unchecked")
@Override
public void cancel() {
- mCanceled = true;
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- for (AnimatorListener listener : tmpListeners) {
- listener.onAnimationCancel(this);
- }
- }
- if (mDelayAnim != null && mDelayAnim.isRunning()) {
- // If we're currently in the startDelay period, just cancel that animator and
- // send out the end event to all listeners
- mDelayAnim.cancel();
+ mTerminated = true;
+ if (isRunning()) {
+ ArrayList<AnimatorListener> tmpListeners = null;
if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
+ tmpListeners = (ArrayList<AnimatorListener>) mListeners.clone();
for (AnimatorListener listener : tmpListeners) {
- listener.onAnimationEnd(this);
+ listener.onAnimationCancel(this);
}
}
- return;
- }
- if (mSortedNodes.size() > 0) {
- for (Node node : mSortedNodes) {
- node.animation.cancel();
+ if (mDelayAnim != null && mDelayAnim.isRunning()) {
+ // If we're currently in the startDelay period, just cancel that animator and
+ // send out the end event to all listeners
+ mDelayAnim.cancel();
+ } else if (mSortedNodes.size() > 0) {
+ for (Node node : mSortedNodes) {
+ node.animation.cancel();
+ }
+ }
+ if (tmpListeners != null) {
+ for (AnimatorListener listener : tmpListeners) {
+ listener.onAnimationEnd(this);
+ }
}
}
}
@@ -307,23 +307,32 @@ public final class AnimatorSet extends Animator {
*/
@Override
public void end() {
- mCanceled = true;
- if (mSortedNodes.size() != mNodes.size()) {
- // hasn't been started yet - sort the nodes now, then end them
- sortNodes();
- for (Node node : mSortedNodes) {
- if (mSetListener == null) {
- mSetListener = new AnimatorSetListener(this);
+ mTerminated = true;
+ if (isRunning()) {
+ if (mSortedNodes.size() != mNodes.size()) {
+ // hasn't been started yet - sort the nodes now, then end them
+ sortNodes();
+ for (Node node : mSortedNodes) {
+ if (mSetListener == null) {
+ mSetListener = new AnimatorSetListener(this);
+ }
+ node.animation.addListener(mSetListener);
}
- node.animation.addListener(mSetListener);
}
- }
- if (mDelayAnim != null) {
- mDelayAnim.cancel();
- }
- if (mSortedNodes.size() > 0) {
- for (Node node : mSortedNodes) {
- node.animation.end();
+ if (mDelayAnim != null) {
+ mDelayAnim.cancel();
+ }
+ if (mSortedNodes.size() > 0) {
+ for (Node node : mSortedNodes) {
+ node.animation.end();
+ }
+ }
+ if (mListeners != null) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ for (AnimatorListener listener : tmpListeners) {
+ listener.onAnimationEnd(this);
+ }
}
}
}
@@ -424,7 +433,7 @@ public final class AnimatorSet extends Animator {
@SuppressWarnings("unchecked")
@Override
public void start() {
- mCanceled = false;
+ mTerminated = false;
// First, sort the nodes (if necessary). This will ensure that sortedNodes
// contains the animation nodes in the correct order.
@@ -437,7 +446,8 @@ public final class AnimatorSet extends Animator {
ArrayList<AnimatorListener> oldListeners = node.animation.getListeners();
if (oldListeners != null && oldListeners.size() > 0) {
for (AnimatorListener listener : oldListeners) {
- if (listener instanceof DependencyListener) {
+ if (listener instanceof DependencyListener ||
+ listener instanceof AnimatorSetListener) {
node.animation.removeListener(listener);
}
}
@@ -522,7 +532,7 @@ public final class AnimatorSet extends Animator {
* and will populate any appropriate lists, when it is started.
*/
anim.mNeedsSort = true;
- anim.mCanceled = false;
+ anim.mTerminated = false;
anim.mPlayingSet = new ArrayList<Animator>();
anim.mNodeMap = new HashMap<Animator, Node>();
anim.mNodes = new ArrayList<Node>();
@@ -640,7 +650,7 @@ public final class AnimatorSet extends Animator {
* @param dependencyAnimation the animation that sent the event.
*/
private void startIfReady(Animator dependencyAnimation) {
- if (mAnimatorSet.mCanceled) {
+ if (mAnimatorSet.mTerminated) {
// if the parent AnimatorSet was canceled, then don't start any dependent anims
return;
}
@@ -676,11 +686,15 @@ public final class AnimatorSet extends Animator {
}
public void onAnimationCancel(Animator animation) {
- if (mPlayingSet.size() == 0) {
- if (mListeners != null) {
- int numListeners = mListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- mListeners.get(i).onAnimationCancel(mAnimatorSet);
+ if (!mTerminated) {
+ // Listeners are already notified of the AnimatorSet canceling in cancel().
+ // The logic below only kicks in when animations end normally
+ if (mPlayingSet.size() == 0) {
+ if (mListeners != null) {
+ int numListeners = mListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ mListeners.get(i).onAnimationCancel(mAnimatorSet);
+ }
}
}
}
@@ -692,24 +706,28 @@ public final class AnimatorSet extends Animator {
mPlayingSet.remove(animation);
Node animNode = mAnimatorSet.mNodeMap.get(animation);
animNode.done = true;
- ArrayList<Node> sortedNodes = mAnimatorSet.mSortedNodes;
- boolean allDone = true;
- int numSortedNodes = sortedNodes.size();
- for (int i = 0; i < numSortedNodes; ++i) {
- if (!sortedNodes.get(i).done) {
- allDone = false;
- break;
+ if (!mTerminated) {
+ // Listeners are already notified of the AnimatorSet ending in cancel() or
+ // end(); the logic below only kicks in when animations end normally
+ ArrayList<Node> sortedNodes = mAnimatorSet.mSortedNodes;
+ boolean allDone = true;
+ int numSortedNodes = sortedNodes.size();
+ for (int i = 0; i < numSortedNodes; ++i) {
+ if (!sortedNodes.get(i).done) {
+ allDone = false;
+ break;
+ }
}
- }
- if (allDone) {
- // If this was the last child animation to end, then notify listeners that this
- // AnimatorSet has ended
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationEnd(mAnimatorSet);
+ if (allDone) {
+ // If this was the last child animation to end, then notify listeners that this
+ // AnimatorSet has ended
+ if (mListeners != null) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ int numListeners = tmpListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ tmpListeners.get(i).onAnimationEnd(mAnimatorSet);
+ }
}
}
}
@@ -791,6 +809,8 @@ public final class AnimatorSet extends Animator {
}
}
}
+ // nodes are 'done' by default; they become un-done when started, and done
+ // again when ended
node.done = false;
}
}
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 1dcaa04..90d676e 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -933,17 +933,17 @@ public class ValueAnimator extends Animator {
@Override
public void cancel() {
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- for (AnimatorListener listener : tmpListeners) {
- listener.onAnimationCancel(this);
- }
- }
// Only cancel if the animation is actually running or has been started and is about
// to run
if (mPlayingState != STOPPED || sPendingAnimations.get().contains(this) ||
sDelayedAnims.get().contains(this)) {
+ if (mListeners != null) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ for (AnimatorListener listener : tmpListeners) {
+ listener.onAnimationCancel(this);
+ }
+ }
endAnimation();
}
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index a6658cc..d207a0a 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1471,6 +1471,24 @@ public class ActivityManager {
}
/**
+ * Returns the usage statistics of each installed package.
+ *
+ * @hide
+ */
+ public PkgUsageStats[] getAllPackageUsageStats() {
+ try {
+ IUsageStats usageStatsService = IUsageStats.Stub.asInterface(
+ ServiceManager.getService("usagestats"));
+ if (usageStatsService != null) {
+ return usageStatsService.getAllPkgUsageStats();
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Could not query usage stats", e);
+ }
+ return new PkgUsageStats[0];
+ }
+
+ /**
* @param userid the user's id. Zero indicates the default user
* @hide
*/
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index eee14fb..ee04729 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4093,11 +4093,6 @@ public final class ActivityThread {
});
}
- private final void detach()
- {
- sThreadLocal.set(null);
- }
-
public static final ActivityThread systemMain() {
HardwareRenderer.disable();
ActivityThread thread = new ActivityThread();
@@ -4105,10 +4100,9 @@ public final class ActivityThread {
return thread;
}
- public final void installSystemProviders(List providers) {
+ public final void installSystemProviders(List<ProviderInfo> providers) {
if (providers != null) {
- installContentProviders(mInitialApplication,
- (List<ProviderInfo>)providers);
+ installContentProviders(mInitialApplication, providers);
}
}
@@ -4147,14 +4141,6 @@ public final class ActivityThread {
Looper.loop();
- if (Process.supportsProcesses()) {
- throw new RuntimeException("Main thread loop unexpectedly exited");
- }
-
- thread.detach();
- String name = (thread.mInitialApplication != null)
- ? thread.mInitialApplication.getPackageName()
- : "<unknown>";
- Slog.i(TAG, "Main thread of " + name + " is now exiting");
+ throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 8749d3e..d2323e7 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1163,9 +1163,6 @@ class ContextImpl extends Context {
throw new IllegalArgumentException("permission is null");
}
- if (!Process.supportsProcesses()) {
- return PackageManager.PERMISSION_GRANTED;
- }
try {
return ActivityManagerNative.getDefault().checkPermission(
permission, pid, uid);
@@ -1180,9 +1177,6 @@ class ContextImpl extends Context {
throw new IllegalArgumentException("permission is null");
}
- if (!Process.supportsProcesses()) {
- return PackageManager.PERMISSION_GRANTED;
- }
int pid = Binder.getCallingPid();
if (pid != Process.myPid()) {
return checkPermission(permission, pid,
@@ -1263,9 +1257,6 @@ class ContextImpl extends Context {
@Override
public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
- if (!Process.supportsProcesses()) {
- return PackageManager.PERMISSION_GRANTED;
- }
try {
return ActivityManagerNative.getDefault().checkUriPermission(
uri, pid, uid, modeFlags);
@@ -1276,9 +1267,6 @@ class ContextImpl extends Context {
@Override
public int checkCallingUriPermission(Uri uri, int modeFlags) {
- if (!Process.supportsProcesses()) {
- return PackageManager.PERMISSION_GRANTED;
- }
int pid = Binder.getCallingPid();
if (pid != Process.myPid()) {
return checkUriPermission(uri, pid,
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index dce0a97..436fdf8 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -28,6 +28,7 @@ import android.os.RemoteException;
import android.util.Log;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
@@ -533,6 +534,16 @@ public abstract class BackupAgent extends ContextWrapper {
Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
throw ex;
} finally {
+ // Send the EOD marker indicating that there is no more data
+ // forthcoming from this agent.
+ try {
+ FileOutputStream out = new FileOutputStream(data.getFileDescriptor());
+ byte[] buf = new byte[4];
+ out.write(buf);
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to finalize backup stream!");
+ }
+
Binder.restoreCallingIdentity(ident);
try {
callbackBinder.opComplete(token);
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index 52efc07..0a01dcf 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -16,7 +16,6 @@
package android.bluetooth;
-import android.annotation.SdkConstant;
import android.content.Context;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -67,9 +66,6 @@ public final class BluetoothHealth implements BluetoothProfile {
*/
public static final int CHANNEL_TYPE_ANY = 12;
- private final ArrayList<BluetoothHealthAppConfiguration> mAppConfigs =
- new ArrayList<BluetoothHealthAppConfiguration>();
-
/**
* Register an application configuration that acts as a Health SINK.
* This is the configuration that will be used to communicate with health devices
@@ -86,7 +82,7 @@ public final class BluetoothHealth implements BluetoothProfile {
* @return If true, callback will be called.
*/
public boolean registerSinkAppConfiguration(String name, int dataType,
- IBluetoothHealthCallback callback) {
+ BluetoothHealthCallback callback) {
if (!isEnabled() || name == null) return false;
if (DBG) log("registerSinkApplication(" + name + ":" + dataType + ")");
@@ -111,18 +107,18 @@ public final class BluetoothHealth implements BluetoothProfile {
* @hide
*/
public boolean registerAppConfiguration(String name, int dataType, int role,
- int channelType, IBluetoothHealthCallback callback) {
+ int channelType, BluetoothHealthCallback callback) {
boolean result = false;
if (!isEnabled() || !checkAppParam(name, role, channelType, callback)) return result;
if (DBG) log("registerApplication(" + name + ":" + dataType + ")");
+ BluetoothHealthCallbackWrapper wrapper = new BluetoothHealthCallbackWrapper(callback);
BluetoothHealthAppConfiguration config =
- new BluetoothHealthAppConfiguration(name, dataType, role, channelType,
- callback);
+ new BluetoothHealthAppConfiguration(name, dataType, role, channelType);
if (mService != null) {
try {
- result = mService.registerAppConfiguration(config);
+ result = mService.registerAppConfiguration(config, wrapper);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -130,8 +126,6 @@ public final class BluetoothHealth implements BluetoothProfile {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
-
- if (result) mAppConfigs.add(config);
return result;
}
@@ -147,7 +141,7 @@ public final class BluetoothHealth implements BluetoothProfile {
*/
public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
boolean result = false;
- if (mService != null && isEnabled() && isValidAppConfig(config)) {
+ if (mService != null && isEnabled() && config != null) {
try {
result = mService.unregisterAppConfiguration(config);
} catch (RemoteException e) {
@@ -157,26 +151,26 @@ public final class BluetoothHealth implements BluetoothProfile {
Log.w(TAG, "Proxy not attached to service");
if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
}
- if (result) mAppConfigs.remove(config);
+
return result;
}
/**
* Connect to a health device which has the {@link #SOURCE_ROLE}.
- * This is an asynchrnous call. If this function returns true, the callback
+ * This is an asynchronous call. If this function returns true, the callback
* associated with the application configuration will be called.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param device The remote Bluetooth device.
- * @param config The application configuration which has been registed using
- * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) }
+ * @param config The application configuration which has been registered using
+ * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) }
* @return If true, the callback associated with the application config will be called.
*/
public boolean connectChannelToSource(BluetoothDevice device,
BluetoothHealthAppConfiguration config) {
if (mService != null && isEnabled() && isValidDevice(device) &&
- isValidAppConfig(config)) {
+ config != null) {
try {
return mService.connectChannelToSource(device, config);
} catch (RemoteException e) {
@@ -197,15 +191,15 @@ public final class BluetoothHealth implements BluetoothProfile {
*<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param device The remote Bluetooth device.
- * @param config The application configuration which has been registed using
- * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) }
+ * @param config The application configuration which has been registered using
+ * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) }
* @return If true, the callback associated with the application config will be called.
* @hide
*/
public boolean connectChannelToSink(BluetoothDevice device,
BluetoothHealthAppConfiguration config, int channelType) {
if (mService != null && isEnabled() && isValidDevice(device) &&
- isValidAppConfig(config)) {
+ config != null) {
try {
return mService.connectChannelToSink(device, config, channelType);
} catch (RemoteException e) {
@@ -226,8 +220,8 @@ public final class BluetoothHealth implements BluetoothProfile {
*<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param device The remote Bluetooth device.
- * @param config The application configuration which has been registed using
- * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) }
+ * @param config The application configuration which has been registered using
+ * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) }
* @param fd The file descriptor that was associated with the channel.
* @return If true, the callback associated with the application config will be called.
* @hide
@@ -235,7 +229,7 @@ public final class BluetoothHealth implements BluetoothProfile {
public boolean disconnectChannel(BluetoothDevice device,
BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
if (mService != null && isEnabled() && isValidDevice(device) &&
- isValidAppConfig(config)) {
+ config != null) {
try {
return mService.disconnectChannel(device, config, fd);
} catch (RemoteException e) {
@@ -262,7 +256,7 @@ public final class BluetoothHealth implements BluetoothProfile {
public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
BluetoothHealthAppConfiguration config) {
if (mService != null && isEnabled() && isValidDevice(device) &&
- isValidAppConfig(config)) {
+ config != null) {
try {
return mService.getMainChannelFd(device, config);
} catch (RemoteException e) {
@@ -290,6 +284,7 @@ public final class BluetoothHealth implements BluetoothProfile {
* {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
* {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
*/
+ @Override
public int getConnectionState(BluetoothDevice device) {
if (mService != null && isEnabled() && isValidDevice(device)) {
try {
@@ -317,6 +312,7 @@ public final class BluetoothHealth implements BluetoothProfile {
* local adapter.
* @return List of devices. The list will be empty on error.
*/
+ @Override
public List<BluetoothDevice> getConnectedDevices() {
if (mService != null && isEnabled()) {
try {
@@ -348,6 +344,7 @@ public final class BluetoothHealth implements BluetoothProfile {
* {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
* @return List of devices. The list will be empty on error.
*/
+ @Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (mService != null && isEnabled()) {
try {
@@ -361,6 +358,27 @@ public final class BluetoothHealth implements BluetoothProfile {
return new ArrayList<BluetoothDevice>();
}
+ private static class BluetoothHealthCallbackWrapper extends IBluetoothHealthCallback.Stub {
+ private BluetoothHealthCallback mCallback;
+
+ public BluetoothHealthCallbackWrapper(BluetoothHealthCallback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config,
+ int status) {
+ mCallback.onHealthAppConfigurationStatusChange(config, status);
+ }
+
+ @Override
+ public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
+ BluetoothDevice device, int prevState, int newState,
+ ParcelFileDescriptor fd) {
+ mCallback.onHealthChannelStateChange(config, device, prevState, newState, fd);
+ }
+ }
+
/** Health Channel Connection State - Disconnected */
public static final int STATE_CHANNEL_DISCONNECTED = 0;
/** Health Channel Connection State - Connecting */
@@ -379,7 +397,6 @@ public final class BluetoothHealth implements BluetoothProfile {
/** Health App Configuration un-registration failure */
public static final int APPLICATION_UNREGISTRATION_FAILURE = 3;
- private Context mContext;
private ServiceListener mServiceListener;
private IBluetooth mService;
BluetoothAdapter mAdapter;
@@ -420,14 +437,8 @@ public final class BluetoothHealth implements BluetoothProfile {
return false;
}
- private boolean isValidAppConfig(BluetoothHealthAppConfiguration config) {
- if (!mAppConfigs.isEmpty() && mAppConfigs.contains(config)) return true;
- log("Not a valid config: " + config);
- return false;
- }
-
private boolean checkAppParam(String name, int role, int channelType,
- IBluetoothHealthCallback callback) {
+ BluetoothHealthCallback callback) {
if (name == null || (role != SOURCE_ROLE && role != SINK_ROLE) ||
(channelType != CHANNEL_TYPE_RELIABLE &&
channelType != CHANNEL_TYPE_STREAMING &&
diff --git a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
index b87aea5..7020249 100644
--- a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
+++ b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
@@ -17,7 +17,6 @@
package android.bluetooth;
-import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -34,21 +33,18 @@ public final class BluetoothHealthAppConfiguration implements Parcelable {
private final int mDataType;
private final int mRole;
private final int mChannelType;
- private final IBluetoothHealthCallback mCallback;
/**
* Constructor to register the SINK role
*
* @param name Friendly name associated with the application configuration
* @param dataType Data Type of the remote Bluetooth Health device
- * @param callback Callback associated with the application configuration.
*/
- BluetoothHealthAppConfiguration(String name, int dataType, IBluetoothHealthCallback callback) {
+ BluetoothHealthAppConfiguration(String name, int dataType) {
mName = name;
mDataType = dataType;
mRole = BluetoothHealth.SINK_ROLE;
mChannelType = BluetoothHealth.CHANNEL_TYPE_ANY;
- mCallback = callback;
}
/**
@@ -56,17 +52,15 @@ public final class BluetoothHealthAppConfiguration implements Parcelable {
*
* @param name Friendly name associated with the application configuration
* @param dataType Data Type of the remote Bluetooth Health device
- * @param role {@link BluetoothHealth.SOURCE_ROLE} or
- * {@link BluetoothHealth.SINK_ROLE}
- * @param callback Callback associated with the application configuration.
+ * @param role {@link BluetoothHealth#SOURCE_ROLE} or
+ * {@link BluetoothHealth#SINK_ROLE}
*/
- BluetoothHealthAppConfiguration(String name, int dataType, int role, int channelType,
- IBluetoothHealthCallback callback) {
+ BluetoothHealthAppConfiguration(String name, int dataType, int role, int
+ channelType) {
mName = name;
mDataType = dataType;
mRole = role;
mChannelType = channelType;
- mCallback = callback;
}
@Override
@@ -77,8 +71,7 @@ public final class BluetoothHealthAppConfiguration implements Parcelable {
return mName.equals(config.getName()) &&
mDataType == config.getDataType() &&
mRole == config.getRole() &&
- mChannelType == config.getChannelType() &&
- mCallback.equals(config.getCallback());
+ mChannelType == config.getChannelType();
}
return false;
}
@@ -90,7 +83,6 @@ public final class BluetoothHealthAppConfiguration implements Parcelable {
result = 31 * result + mDataType;
result = 31 * result + mRole;
result = 31 * result + mChannelType;
- result = 31 * result + (mCallback != null ? mCallback.hashCode() : 0);
return result;
}
@@ -98,9 +90,10 @@ public final class BluetoothHealthAppConfiguration implements Parcelable {
public String toString() {
return "BluetoothHealthAppConfiguration [mName = " + mName +
",mDataType = " + mDataType + ", mRole = " + mRole + ",mChannelType = " +
- mChannelType + ",callback=" + mCallback +"]";
+ mChannelType + "]";
}
+ @Override
public int describeContents() {
return 0;
}
@@ -144,37 +137,31 @@ public final class BluetoothHealthAppConfiguration implements Parcelable {
return mChannelType;
}
- /**
- * Return the callback associated with this application configuration.
- *
- * @return IBluetoothHealthCallback
- */
- public IBluetoothHealthCallback getCallback() {
- return mCallback;
- }
-
public static final Parcelable.Creator<BluetoothHealthAppConfiguration> CREATOR =
new Parcelable.Creator<BluetoothHealthAppConfiguration>() {
+ @Override
public BluetoothHealthAppConfiguration createFromParcel(Parcel in) {
String name = in.readString();
int type = in.readInt();
int role = in.readInt();
int channelType = in.readInt();
- IBluetoothHealthCallback callback =
- IBluetoothHealthCallback.Stub.asInterface(in.readStrongBinder());
- return new BluetoothHealthAppConfiguration(name, type, role, channelType,
- callback);
+ return new BluetoothHealthAppConfiguration(name, type, role,
+ channelType);
}
+
+ @Override
public BluetoothHealthAppConfiguration[] newArray(int size) {
return new BluetoothHealthAppConfiguration[size];
}
};
+ @Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(mName);
out.writeInt(mDataType);
out.writeInt(mRole);
out.writeInt(mChannelType);
- out.writeStrongInterface(mCallback);
}
+
+
}
diff --git a/core/java/android/bluetooth/BluetoothHealthCallback.java b/core/java/android/bluetooth/BluetoothHealthCallback.java
new file mode 100644
index 0000000..0d11bb5
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHealthCallback.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.bluetooth;
+
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+/**
+ * This class is used for all the {@link BluetoothHealth} callbacks.
+ * @hide
+ */
+public abstract class BluetoothHealthCallback {
+
+ private static final String TAG = "BluetoothHealthCallback";
+
+ public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config,
+ int status) {
+ Log.d(TAG, "onHealthAppConfigurationStatusChange: " + config + " Status:" + status);
+ }
+
+ public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config,
+ BluetoothDevice device, int prevState, int newState,
+ ParcelFileDescriptor fd) {
+ Log.d(TAG, "onHealthChannelStateChange: " + config + " Device:" + device +
+ "PrevState:" + prevState + "NewState:" + newState + "FileDescriptor:" + fd);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 83e59e2..acce182 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -62,6 +62,7 @@ public final class BluetoothServerSocket implements Closeable {
/*package*/ final BluetoothSocket mSocket;
private Handler mHandler;
private int mMessage;
+ private final int mChannel;
/**
* Construct a socket for incoming connections.
@@ -74,6 +75,7 @@ public final class BluetoothServerSocket implements Closeable {
*/
/*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port)
throws IOException {
+ mChannel = port;
mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null);
}
@@ -125,4 +127,12 @@ public final class BluetoothServerSocket implements Closeable {
mHandler = handler;
mMessage = message;
}
+
+ /**
+ * Returns the channel on which this socket is bound.
+ * @hide
+ */
+ public int getChannel() {
+ return mChannel;
+ }
}
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 6ca6c2e..183772d 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.bluetooth.IBluetoothCallback;
+import android.bluetooth.IBluetoothHealthCallback;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHealthAppConfiguration;
import android.os.ParcelUuid;
@@ -102,7 +103,8 @@ interface IBluetooth
boolean disconnectPanDevice(in BluetoothDevice device);
// HDP profile APIs
- boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config);
+ boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config,
+ in IBluetoothHealthCallback callback);
boolean unregisterAppConfiguration(in BluetoothHealthAppConfiguration config);
boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config,
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 9d40c42..fbff7d8 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -47,13 +47,39 @@ public class NetworkStats implements Parcelable {
* {@link SystemClock#elapsedRealtime()} timestamp when this data was
* generated.
*/
- public final long elapsedRealtime;
- public int size;
- public String[] iface;
- public int[] uid;
- public int[] tag;
- public long[] rx;
- public long[] tx;
+ private final long elapsedRealtime;
+ private int size;
+ private String[] iface;
+ private int[] uid;
+ private int[] tag;
+ private long[] rxBytes;
+ private long[] rxPackets;
+ private long[] txBytes;
+ private long[] txPackets;
+
+ public static class Entry {
+ public String iface;
+ public int uid;
+ public int tag;
+ public long rxBytes;
+ public long rxPackets;
+ public long txBytes;
+ public long txPackets;
+
+ public Entry() {
+ }
+
+ public Entry(String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes,
+ long txPackets) {
+ this.iface = iface;
+ this.uid = uid;
+ this.tag = tag;
+ this.rxBytes = rxBytes;
+ this.rxPackets = rxPackets;
+ this.txBytes = txBytes;
+ this.txPackets = txPackets;
+ }
+ }
public NetworkStats(long elapsedRealtime, int initialSize) {
this.elapsedRealtime = elapsedRealtime;
@@ -61,8 +87,10 @@ public class NetworkStats implements Parcelable {
this.iface = new String[initialSize];
this.uid = new int[initialSize];
this.tag = new int[initialSize];
- this.rx = new long[initialSize];
- this.tx = new long[initialSize];
+ this.rxBytes = new long[initialSize];
+ this.rxPackets = new long[initialSize];
+ this.txBytes = new long[initialSize];
+ this.txPackets = new long[initialSize];
}
public NetworkStats(Parcel parcel) {
@@ -71,46 +99,93 @@ public class NetworkStats implements Parcelable {
iface = parcel.createStringArray();
uid = parcel.createIntArray();
tag = parcel.createIntArray();
- rx = parcel.createLongArray();
- tx = parcel.createLongArray();
+ rxBytes = parcel.createLongArray();
+ rxPackets = parcel.createLongArray();
+ txBytes = parcel.createLongArray();
+ txPackets = parcel.createLongArray();
+ }
+
+ public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
+ long txBytes, long txPackets) {
+ return addValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets));
}
/**
- * Add new stats entry with given values.
+ * Add new stats entry, copying from given {@link Entry}. The {@link Entry}
+ * object can be recycled across multiple calls.
*/
- public NetworkStats addEntry(String iface, int uid, int tag, long rx, long tx) {
+ public NetworkStats addValues(Entry entry) {
if (size >= this.iface.length) {
- final int newLength = Math.max(this.iface.length, 10) * 3 / 2;
- this.iface = Arrays.copyOf(this.iface, newLength);
- this.uid = Arrays.copyOf(this.uid, newLength);
- this.tag = Arrays.copyOf(this.tag, newLength);
- this.rx = Arrays.copyOf(this.rx, newLength);
- this.tx = Arrays.copyOf(this.tx, newLength);
+ final int newLength = Math.max(iface.length, 10) * 3 / 2;
+ iface = Arrays.copyOf(iface, newLength);
+ uid = Arrays.copyOf(uid, newLength);
+ tag = Arrays.copyOf(tag, newLength);
+ rxBytes = Arrays.copyOf(rxBytes, newLength);
+ rxPackets = Arrays.copyOf(rxPackets, newLength);
+ txBytes = Arrays.copyOf(txBytes, newLength);
+ txPackets = Arrays.copyOf(txPackets, newLength);
}
- this.iface[size] = iface;
- this.uid[size] = uid;
- this.tag[size] = tag;
- this.rx[size] = rx;
- this.tx[size] = tx;
+ iface[size] = entry.iface;
+ uid[size] = entry.uid;
+ tag[size] = entry.tag;
+ rxBytes[size] = entry.rxBytes;
+ rxPackets[size] = entry.rxPackets;
+ txBytes[size] = entry.txBytes;
+ txPackets[size] = entry.txPackets;
size++;
return this;
}
/**
+ * Return specific stats entry.
+ */
+ public Entry getValues(int i, Entry recycle) {
+ final Entry entry = recycle != null ? recycle : new Entry();
+ entry.iface = iface[i];
+ entry.uid = uid[i];
+ entry.tag = tag[i];
+ entry.rxBytes = rxBytes[i];
+ entry.rxPackets = rxPackets[i];
+ entry.txBytes = txBytes[i];
+ entry.txPackets = txPackets[i];
+ return entry;
+ }
+
+ public long getElapsedRealtime() {
+ return elapsedRealtime;
+ }
+
+ public int size() {
+ return size;
+ }
+
+ // @VisibleForTesting
+ public int internalSize() {
+ return iface.length;
+ }
+
+ public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
+ long txBytes, long txPackets) {
+ return combineValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets));
+ }
+
+ /**
* Combine given values with an existing row, or create a new row if
* {@link #findIndex(String, int, int)} is unable to find match. Can also be
* used to subtract values from existing rows.
*/
- public NetworkStats combineEntry(String iface, int uid, int tag, long rx, long tx) {
- final int i = findIndex(iface, uid, tag);
+ public NetworkStats combineValues(Entry entry) {
+ final int i = findIndex(entry.iface, entry.uid, entry.tag);
if (i == -1) {
// only create new entry when positive contribution
- addEntry(iface, uid, tag, rx, tx);
+ addValues(entry);
} else {
- this.rx[i] += rx;
- this.tx[i] += tx;
+ rxBytes[i] += entry.rxBytes;
+ rxPackets[i] += entry.rxPackets;
+ txBytes[i] += entry.txBytes;
+ txPackets[i] += entry.txPackets;
}
return this;
}
@@ -199,30 +274,41 @@ public class NetworkStats implements Parcelable {
}
// result will have our rows, and elapsed time between snapshots
+ final Entry entry = new Entry();
final NetworkStats result = new NetworkStats(deltaRealtime, size);
for (int i = 0; i < size; i++) {
- final String iface = this.iface[i];
- final int uid = this.uid[i];
- final int tag = this.tag[i];
+ entry.iface = iface[i];
+ entry.uid = uid[i];
+ entry.tag = tag[i];
// find remote row that matches, and subtract
- final int j = value.findIndex(iface, uid, tag);
+ final int j = value.findIndex(entry.iface, entry.uid, entry.tag);
if (j == -1) {
// newly appearing row, return entire value
- result.addEntry(iface, uid, tag, this.rx[i], this.tx[i]);
+ entry.rxBytes = rxBytes[i];
+ entry.rxPackets = rxPackets[i];
+ entry.txBytes = txBytes[i];
+ entry.txPackets = txPackets[i];
} else {
// existing row, subtract remote value
- long rx = this.rx[i] - value.rx[j];
- long tx = this.tx[i] - value.tx[j];
- if (enforceMonotonic && (rx < 0 || tx < 0)) {
+ entry.rxBytes = rxBytes[i] - value.rxBytes[j];
+ entry.rxPackets = rxPackets[i] - value.rxPackets[j];
+ entry.txBytes = txBytes[i] - value.txBytes[j];
+ entry.txPackets = txPackets[i] - value.txPackets[j];
+ if (enforceMonotonic
+ && (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0
+ || entry.txPackets < 0)) {
throw new IllegalArgumentException("found non-monotonic values");
}
if (clampNegative) {
- rx = Math.max(0, rx);
- tx = Math.max(0, tx);
+ entry.rxBytes = Math.max(0, entry.rxBytes);
+ entry.rxPackets = Math.max(0, entry.rxPackets);
+ entry.txBytes = Math.max(0, entry.txBytes);
+ entry.txPackets = Math.max(0, entry.txPackets);
}
- result.addEntry(iface, uid, tag, rx, tx);
}
+
+ result.addValues(entry);
}
return result;
@@ -235,13 +321,15 @@ public class NetworkStats implements Parcelable {
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix);
pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
- for (int i = 0; i < iface.length; i++) {
+ for (int i = 0; i < size; i++) {
pw.print(prefix);
pw.print(" iface="); pw.print(iface[i]);
pw.print(" uid="); pw.print(uid[i]);
pw.print(" tag="); pw.print(tag[i]);
- pw.print(" rx="); pw.print(rx[i]);
- pw.print(" tx="); pw.println(tx[i]);
+ pw.print(" rxBytes="); pw.print(rxBytes[i]);
+ pw.print(" rxPackets="); pw.print(rxPackets[i]);
+ pw.print(" txBytes="); pw.print(txBytes[i]);
+ pw.print(" txPackets="); pw.println(txPackets[i]);
}
}
@@ -264,8 +352,10 @@ public class NetworkStats implements Parcelable {
dest.writeStringArray(iface);
dest.writeIntArray(uid);
dest.writeIntArray(tag);
- dest.writeLongArray(rx);
- dest.writeLongArray(tx);
+ dest.writeLongArray(rxBytes);
+ dest.writeLongArray(rxPackets);
+ dest.writeLongArray(txBytes);
+ dest.writeLongArray(txPackets);
}
public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index dd2945c..8bd1738 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -43,13 +43,20 @@ public class NetworkStatsHistory implements Parcelable {
private static final int VERSION_INIT = 1;
// TODO: teach about varint encoding to use less disk space
-
- public final long bucketDuration;
-
- public int bucketCount;
- public long[] bucketStart;
- public long[] rx;
- public long[] tx;
+ // TODO: extend to record rxPackets/txPackets
+
+ private final long bucketDuration;
+ private int bucketCount;
+ private long[] bucketStart;
+ private long[] rxBytes;
+ private long[] txBytes;
+
+ public static class Entry {
+ public long bucketStart;
+ public long bucketDuration;
+ public long rxBytes;
+ public long txBytes;
+ }
public NetworkStatsHistory(long bucketDuration) {
this(bucketDuration, 10);
@@ -58,16 +65,16 @@ public class NetworkStatsHistory implements Parcelable {
public NetworkStatsHistory(long bucketDuration, int initialSize) {
this.bucketDuration = bucketDuration;
bucketStart = new long[initialSize];
- rx = new long[initialSize];
- tx = new long[initialSize];
+ rxBytes = new long[initialSize];
+ txBytes = new long[initialSize];
bucketCount = 0;
}
public NetworkStatsHistory(Parcel in) {
bucketDuration = in.readLong();
bucketStart = readLongArray(in);
- rx = in.createLongArray();
- tx = in.createLongArray();
+ rxBytes = in.createLongArray();
+ txBytes = in.createLongArray();
bucketCount = bucketStart.length;
}
@@ -75,8 +82,8 @@ public class NetworkStatsHistory implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
out.writeLong(bucketDuration);
writeLongArray(out, bucketStart, bucketCount);
- writeLongArray(out, rx, bucketCount);
- writeLongArray(out, tx, bucketCount);
+ writeLongArray(out, rxBytes, bucketCount);
+ writeLongArray(out, txBytes, bucketCount);
}
public NetworkStatsHistory(DataInputStream in) throws IOException {
@@ -85,8 +92,8 @@ public class NetworkStatsHistory implements Parcelable {
case VERSION_INIT: {
bucketDuration = in.readLong();
bucketStart = readLongArray(in);
- rx = readLongArray(in);
- tx = readLongArray(in);
+ rxBytes = readLongArray(in);
+ txBytes = readLongArray(in);
bucketCount = bucketStart.length;
break;
}
@@ -100,8 +107,8 @@ public class NetworkStatsHistory implements Parcelable {
out.writeInt(VERSION_INIT);
out.writeLong(bucketDuration);
writeLongArray(out, bucketStart, bucketCount);
- writeLongArray(out, rx, bucketCount);
- writeLongArray(out, tx, bucketCount);
+ writeLongArray(out, rxBytes, bucketCount);
+ writeLongArray(out, txBytes, bucketCount);
}
/** {@inheritDoc} */
@@ -109,6 +116,42 @@ public class NetworkStatsHistory implements Parcelable {
return 0;
}
+ public int size() {
+ return bucketCount;
+ }
+
+ public long getBucketDuration() {
+ return bucketDuration;
+ }
+
+ public long getStart() {
+ if (bucketCount > 0) {
+ return bucketStart[0];
+ } else {
+ return Long.MAX_VALUE;
+ }
+ }
+
+ public long getEnd() {
+ if (bucketCount > 0) {
+ return bucketStart[bucketCount - 1] + bucketDuration;
+ } else {
+ return Long.MIN_VALUE;
+ }
+ }
+
+ /**
+ * Return specific stats entry.
+ */
+ public Entry getValues(int i, Entry recycle) {
+ final Entry entry = recycle != null ? recycle : new Entry();
+ entry.bucketStart = bucketStart[i];
+ entry.bucketDuration = bucketDuration;
+ entry.rxBytes = rxBytes[i];
+ entry.txBytes = txBytes[i];
+ return entry;
+ }
+
/**
* Record that data traffic occurred in the given time range. Will
* distribute across internal buckets, creating new buckets as needed.
@@ -135,8 +178,8 @@ public class NetworkStatsHistory implements Parcelable {
final long overlap = Math.min(curEnd, end) - Math.max(curStart, start);
if (overlap > 0) {
- this.rx[i] += rx * overlap / duration;
- this.tx[i] += tx * overlap / duration;
+ this.rxBytes[i] += rx * overlap / duration;
+ this.txBytes[i] += tx * overlap / duration;
}
}
}
@@ -149,7 +192,7 @@ public class NetworkStatsHistory implements Parcelable {
for (int i = 0; i < input.bucketCount; i++) {
final long start = input.bucketStart[i];
final long end = start + input.bucketDuration;
- recordData(start, end, input.rx[i], input.tx[i]);
+ recordData(start, end, input.rxBytes[i], input.txBytes[i]);
}
}
@@ -179,8 +222,8 @@ public class NetworkStatsHistory implements Parcelable {
if (bucketCount >= bucketStart.length) {
final int newLength = Math.max(bucketStart.length, 10) * 3 / 2;
bucketStart = Arrays.copyOf(bucketStart, newLength);
- rx = Arrays.copyOf(rx, newLength);
- tx = Arrays.copyOf(tx, newLength);
+ rxBytes = Arrays.copyOf(rxBytes, newLength);
+ txBytes = Arrays.copyOf(txBytes, newLength);
}
// create gap when inserting bucket in middle
@@ -189,13 +232,13 @@ public class NetworkStatsHistory implements Parcelable {
final int length = bucketCount - index;
System.arraycopy(bucketStart, index, bucketStart, dstPos, length);
- System.arraycopy(rx, index, rx, dstPos, length);
- System.arraycopy(tx, index, tx, dstPos, length);
+ System.arraycopy(rxBytes, index, rxBytes, dstPos, length);
+ System.arraycopy(txBytes, index, txBytes, dstPos, length);
}
bucketStart[index] = start;
- rx[index] = 0;
- tx[index] = 0;
+ rxBytes[index] = 0;
+ txBytes[index] = 0;
bucketCount++;
}
@@ -216,8 +259,8 @@ public class NetworkStatsHistory implements Parcelable {
if (i > 0) {
final int length = bucketStart.length;
bucketStart = Arrays.copyOfRange(bucketStart, i, length);
- rx = Arrays.copyOfRange(rx, i, length);
- tx = Arrays.copyOfRange(tx, i, length);
+ rxBytes = Arrays.copyOfRange(rxBytes, i, length);
+ txBytes = Arrays.copyOfRange(txBytes, i, length);
bucketCount -= i;
}
}
@@ -226,9 +269,20 @@ public class NetworkStatsHistory implements Parcelable {
* Return interpolated data usage across the requested range. Interpolates
* across buckets, so values may be rounded slightly.
*/
- public long[] getTotalData(long start, long end, long[] outTotal) {
- long rx = 0;
- long tx = 0;
+ public Entry getValues(long start, long end, Entry recycle) {
+ return getValues(start, end, Long.MAX_VALUE, recycle);
+ }
+
+ /**
+ * Return interpolated data usage across the requested range. Interpolates
+ * across buckets, so values may be rounded slightly.
+ */
+ public Entry getValues(long start, long end, long now, Entry recycle) {
+ final Entry entry = recycle != null ? recycle : new Entry();
+ entry.bucketStart = start;
+ entry.bucketDuration = end - start;
+ entry.rxBytes = 0;
+ entry.txBytes = 0;
for (int i = bucketCount - 1; i >= 0; i--) {
final long curStart = bucketStart[i];
@@ -239,19 +293,19 @@ public class NetworkStatsHistory implements Parcelable {
// bucket is newer than record; keep looking
if (curStart > end) continue;
+ // include full value for active buckets, otherwise only fractional
+ final boolean activeBucket = curStart < now && curEnd > now;
final long overlap = Math.min(curEnd, end) - Math.max(curStart, start);
- if (overlap > 0) {
- rx += this.rx[i] * overlap / bucketDuration;
- tx += this.tx[i] * overlap / bucketDuration;
+ if (activeBucket || overlap == bucketDuration) {
+ entry.rxBytes += rxBytes[i];
+ entry.txBytes += txBytes[i];
+ } else if (overlap > 0) {
+ entry.rxBytes += rxBytes[i] * overlap / bucketDuration;
+ entry.txBytes += txBytes[i] * overlap / bucketDuration;
}
}
- if (outTotal == null || outTotal.length != 2) {
- outTotal = new long[2];
- }
- outTotal[0] = rx;
- outTotal[1] = tx;
- return outTotal;
+ return entry;
}
/**
@@ -292,8 +346,8 @@ public class NetworkStatsHistory implements Parcelable {
for (int i = start; i < bucketCount; i++) {
pw.print(prefix);
pw.print(" bucketStart="); pw.print(bucketStart[i]);
- pw.print(" rx="); pw.print(rx[i]);
- pw.print(" tx="); pw.println(tx[i]);
+ pw.print(" rxBytes="); pw.print(rxBytes[i]);
+ pw.print(" txBytes="); pw.println(txBytes[i]);
}
}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 8a678d6..76534ef 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -38,8 +38,22 @@ public class NetworkUtils {
/** Bring the named network interface down. */
public native static int disableInterface(String interfaceName);
- /** Reset any sockets that are connected via the named interface. */
- public native static int resetConnections(String interfaceName);
+ /** Setting bit 0 indicates reseting of IPv4 addresses required */
+ public static final int RESET_IPV4_ADDRESSES = 0x01;
+
+ /** Setting bit 1 indicates reseting of IPv4 addresses required */
+ public static final int RESET_IPV6_ADDRESSES = 0x02;
+
+ /** Reset all addresses */
+ public static final int RESET_ALL_ADDRESSES = RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES;
+
+ /**
+ * Reset IPv6 or IPv4 sockets that are connected via the named interface.
+ *
+ * @param interfaceName is the interface to reset
+ * @param mask {@see #RESET_IPV4_ADDRESSES} and {@see #RESET_IPV6_ADDRESSES}
+ */
+ public native static int resetConnections(String interfaceName, int mask);
/**
* Start the DHCP client daemon, in order to have it request addresses
diff --git a/core/java/android/net/http/AndroidHttpClient.java b/core/java/android/net/http/AndroidHttpClient.java
index 641a576..c534e58 100644
--- a/core/java/android/net/http/AndroidHttpClient.java
+++ b/core/java/android/net/http/AndroidHttpClient.java
@@ -65,7 +65,7 @@ import android.util.Base64;
import android.util.Log;
/**
- * Subclass of the Apache {@link DefaultHttpClient} that is configured with
+ * Implementation of the Apache {@link DefaultHttpClient} that is configured with
* reasonable default settings and registered schemes for Android, and
* also lets the user add {@link HttpRequestInterceptor} classes.
* Don't create this directly, use the {@link #newInstance} factory method.
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 3edd692..c0be664 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -86,9 +86,7 @@ public class Looper {
public static final void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
- if (Process.supportsProcesses()) {
- myLooper().mQueue.mQuitAllowed = false;
- }
+ myLooper().mQueue.mQuitAllowed = false;
}
private synchronized static void setMainLooper(Looper looper) {
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 673b187..5b1f563 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -266,84 +266,29 @@ public class Process {
* @param uid The user-id under which the process will run.
* @param gid The group-id under which the process will run.
* @param gids Additional group-ids associated with the process.
- * @param enableDebugger True if debugging should be enabled for this process.
+ * @param debugFlags Additional flags.
+ * @param targetSdkVersion The target SDK version for the app.
* @param zygoteArgs Additional arguments to supply to the zygote process.
*
- * @return int If > 0 the pid of the new process; if 0 the process is
- * being emulated by a thread
+ * @return An object that describes the result of the attempt to start the process.
* @throws RuntimeException on fatal start failure
*
* {@hide}
*/
- public static final int start(final String processClass,
+ public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
- int debugFlags,
- String[] zygoteArgs)
- {
- if (supportsProcesses()) {
- try {
- return startViaZygote(processClass, niceName, uid, gid, gids,
- debugFlags, zygoteArgs);
- } catch (ZygoteStartFailedEx ex) {
- Log.e(LOG_TAG,
- "Starting VM process through Zygote failed");
- throw new RuntimeException(
- "Starting VM process through Zygote failed", ex);
- }
- } else {
- // Running in single-process mode
-
- Runnable runnable = new Runnable() {
- public void run() {
- Process.invokeStaticMain(processClass);
- }
- };
-
- // Thread constructors must not be called with null names (see spec).
- if (niceName != null) {
- new Thread(runnable, niceName).start();
- } else {
- new Thread(runnable).start();
- }
-
- return 0;
- }
- }
-
- /**
- * Start a new process. Don't supply a custom nice name.
- * {@hide}
- */
- public static final int start(String processClass, int uid, int gid,
- int[] gids, int debugFlags, String[] zygoteArgs) {
- return start(processClass, "", uid, gid, gids,
- debugFlags, zygoteArgs);
- }
-
- private static void invokeStaticMain(String className) {
- Class cl;
- Object args[] = new Object[1];
-
- args[0] = new String[0]; //this is argv
-
+ int debugFlags, int targetSdkVersion,
+ String[] zygoteArgs) {
try {
- cl = Class.forName(className);
- cl.getMethod("main", new Class[] { String[].class })
- .invoke(null, args);
- } catch (Exception ex) {
- // can be: ClassNotFoundException,
- // NoSuchMethodException, SecurityException,
- // IllegalAccessException, IllegalArgumentException
- // InvocationTargetException
- // or uncaught exception from main()
-
- Log.e(LOG_TAG, "Exception invoking static main on "
- + className, ex);
-
- throw new RuntimeException(ex);
+ return startViaZygote(processClass, niceName, uid, gid, gids,
+ debugFlags, targetSdkVersion, zygoteArgs);
+ } catch (ZygoteStartFailedEx ex) {
+ Log.e(LOG_TAG,
+ "Starting VM process through Zygote failed");
+ throw new RuntimeException(
+ "Starting VM process through Zygote failed", ex);
}
-
}
/** retry interval for opening a zygote socket */
@@ -430,14 +375,11 @@ public class Process {
* and returns the child's pid. Please note: the present implementation
* replaces newlines in the argument list with spaces.
* @param args argument list
- * @return PID of new child process
+ * @return An object that describes the result of the attempt to start the process.
* @throws ZygoteStartFailedEx if process start failed for any reason
*/
- private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
+ private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)
throws ZygoteStartFailedEx {
-
- int pid;
-
openZygoteSocketIfNeeded();
try {
@@ -448,7 +390,8 @@ public class Process {
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
- * the child or -1 on failure.
+ * the child or -1 on failure, followed by boolean to
+ * indicate whether a wrapper process was used.
*/
sZygoteWriter.write(Integer.toString(args.size()));
@@ -468,11 +411,13 @@ public class Process {
sZygoteWriter.flush();
// Should there be a timeout on this?
- pid = sZygoteInputStream.readInt();
-
- if (pid < 0) {
+ ProcessStartResult result = new ProcessStartResult();
+ result.pid = sZygoteInputStream.readInt();
+ if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
+ result.usingWrapper = sZygoteInputStream.readBoolean();
+ return result;
} catch (IOException ex) {
try {
if (sZygoteSocket != null) {
@@ -487,8 +432,6 @@ public class Process {
throw new ZygoteStartFailedEx(ex);
}
-
- return pid;
}
/**
@@ -500,20 +443,19 @@ public class Process {
* @param gid a POSIX gid that the new process shuold setgid() to
* @param gids null-ok; a list of supplementary group IDs that the
* new process should setgroup() to.
- * @param enableDebugger True if debugging should be enabled for this process.
+ * @param debugFlags Additional flags.
+ * @param targetSdkVersion The target SDK version for the app.
* @param extraArgs Additional arguments to supply to the zygote process.
- * @return PID
+ * @return An object that describes the result of the attempt to start the process.
* @throws ZygoteStartFailedEx if process start failed for any reason
*/
- private static int startViaZygote(final String processClass,
+ private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
- int debugFlags,
+ int debugFlags, int targetSdkVersion,
String[] extraArgs)
throws ZygoteStartFailedEx {
- int pid;
-
synchronized(Process.class) {
ArrayList<String> argsForZygote = new ArrayList<String>();
@@ -537,6 +479,7 @@ public class Process {
if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
argsForZygote.add("--enable-assert");
}
+ argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
//TODO optionally enable debuger
//argsForZygote.add("--enable-debugger");
@@ -568,15 +511,9 @@ public class Process {
argsForZygote.add(arg);
}
}
-
- pid = zygoteSendArgsAndGetPid(argsForZygote);
- }
- if (pid <= 0) {
- throw new ZygoteStartFailedEx("zygote start failed:" + pid);
+ return zygoteSendArgsAndGetResult(argsForZygote);
}
-
- return pid;
}
/**
@@ -736,8 +673,13 @@ public class Process {
*
* @return Returns true if the system can run in multiple processes, else
* false if everything is running in a single process.
+ *
+ * @deprecated This method always returns true. Do not use.
*/
- public static final native boolean supportsProcesses();
+ @Deprecated
+ public static final boolean supportsProcesses() {
+ return true;
+ }
/**
* Set the out-of-memory badness adjustment for a process.
@@ -855,4 +797,21 @@ public class Process {
* @hide
*/
public static final native long getPss(int pid);
+
+ /**
+ * Specifies the outcome of having started a process.
+ * @hide
+ */
+ public static final class ProcessStartResult {
+ /**
+ * The PID of the newly started process.
+ * Always >= 0. (If the start failed, an exception will have been thrown instead.)
+ */
+ public int pid;
+
+ /**
+ * True if the process was started with a wrapper attached.
+ */
+ public boolean usingWrapper;
+ }
}
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index b721665..1af24f4 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -114,7 +114,7 @@ public final class ServiceManager {
* @hide
*/
public static void initServiceCache(Map<String, IBinder> cache) {
- if (sCache.size() != 0 && Process.supportsProcesses()) {
+ if (sCache.size() != 0) {
throw new IllegalStateException("setServiceCache may only be called once");
}
sCache.putAll(cache);
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 792e4c1..2c4b863 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -34,6 +34,8 @@ public class StorageVolume implements Parcelable {
private final int mMtpReserveSpace;
private final boolean mAllowMassStorage;
private int mStorageId;
+ // maximum file size for the storage, or zero for no limit
+ private final long mMaxFileSize;
// StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING,
// ACTION_MEDIA_NOFS, ACTION_MEDIA_MOUNTED, ACTION_MEDIA_SHARED, ACTION_MEDIA_UNSHARED,
@@ -41,18 +43,20 @@ public class StorageVolume implements Parcelable {
public static final String EXTRA_STORAGE_VOLUME = "storage_volume";
public StorageVolume(String path, String description, boolean removable,
- boolean emulated, int mtpReserveSpace, boolean allowMassStorage) {
+ boolean emulated, int mtpReserveSpace, boolean allowMassStorage, long maxFileSize) {
mPath = path;
mDescription = description;
mRemovable = removable;
mEmulated = emulated;
mMtpReserveSpace = mtpReserveSpace;
mAllowMassStorage = allowMassStorage;
+ mMaxFileSize = maxFileSize;
}
// for parcelling only
private StorageVolume(String path, String description, boolean removable,
- boolean emulated, int mtpReserveSpace, int storageId, boolean allowMassStorage) {
+ boolean emulated, int mtpReserveSpace, int storageId,
+ boolean allowMassStorage, long maxFileSize) {
mPath = path;
mDescription = description;
mRemovable = removable;
@@ -60,6 +64,7 @@ public class StorageVolume implements Parcelable {
mMtpReserveSpace = mtpReserveSpace;
mAllowMassStorage = allowMassStorage;
mStorageId = storageId;
+ mMaxFileSize = maxFileSize;
}
/**
@@ -142,6 +147,15 @@ public class StorageVolume implements Parcelable {
return mAllowMassStorage;
}
+ /**
+ * Returns maximum file size for the volume, or zero if it is unbounded.
+ *
+ * @return maximum file size
+ */
+ public long getMaxFileSize() {
+ return mMaxFileSize;
+ }
+
@Override
public boolean equals(Object obj) {
if (obj instanceof StorageVolume && mPath != null) {
@@ -158,7 +172,10 @@ public class StorageVolume implements Parcelable {
@Override
public String toString() {
- return mPath;
+ return "StorageVolume [mAllowMassStorage=" + mAllowMassStorage + ", mDescription="
+ + mDescription + ", mEmulated=" + mEmulated + ", mMaxFileSize=" + mMaxFileSize
+ + ", mMtpReserveSpace=" + mMtpReserveSpace + ", mPath=" + mPath + ", mRemovable="
+ + mRemovable + ", mStorageId=" + mStorageId + "]";
}
public static final Parcelable.Creator<StorageVolume> CREATOR =
@@ -171,9 +188,10 @@ public class StorageVolume implements Parcelable {
int storageId = in.readInt();
int mtpReserveSpace = in.readInt();
int allowMassStorage = in.readInt();
+ long maxFileSize = in.readLong();
return new StorageVolume(path, description,
- removable == 1, emulated == 1,
- mtpReserveSpace, storageId, allowMassStorage == 1);
+ removable == 1, emulated == 1, mtpReserveSpace,
+ storageId, allowMassStorage == 1, maxFileSize);
}
public StorageVolume[] newArray(int size) {
@@ -193,5 +211,6 @@ public class StorageVolume implements Parcelable {
parcel.writeInt(mStorageId);
parcel.writeInt(mMtpReserveSpace);
parcel.writeInt(mAllowMassStorage ? 1 : 0);
+ parcel.writeLong(mMaxFileSize);
}
}
diff --git a/core/java/android/pim/EventRecurrence.java b/core/java/android/pim/EventRecurrence.java
deleted file mode 100644
index 128b697..0000000
--- a/core/java/android/pim/EventRecurrence.java
+++ /dev/null
@@ -1,892 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.pim;
-
-import android.text.TextUtils;
-import android.text.format.Time;
-import android.util.Log;
-import android.util.TimeFormatException;
-
-import java.util.Calendar;
-import java.util.HashMap;
-
-/**
- * Event recurrence utility functions.
- */
-public class EventRecurrence {
- private static String TAG = "EventRecur";
-
- public static final int SECONDLY = 1;
- public static final int MINUTELY = 2;
- public static final int HOURLY = 3;
- public static final int DAILY = 4;
- public static final int WEEKLY = 5;
- public static final int MONTHLY = 6;
- public static final int YEARLY = 7;
-
- public static final int SU = 0x00010000;
- public static final int MO = 0x00020000;
- public static final int TU = 0x00040000;
- public static final int WE = 0x00080000;
- public static final int TH = 0x00100000;
- public static final int FR = 0x00200000;
- public static final int SA = 0x00400000;
-
- public Time startDate; // set by setStartDate(), not parse()
-
- public int freq; // SECONDLY, MINUTELY, etc.
- public String until;
- public int count;
- public int interval;
- public int wkst; // SU, MO, TU, etc.
-
- /* lists with zero entries may be null references */
- public int[] bysecond;
- public int bysecondCount;
- public int[] byminute;
- public int byminuteCount;
- public int[] byhour;
- public int byhourCount;
- public int[] byday;
- public int[] bydayNum;
- public int bydayCount;
- public int[] bymonthday;
- public int bymonthdayCount;
- public int[] byyearday;
- public int byyeardayCount;
- public int[] byweekno;
- public int byweeknoCount;
- public int[] bymonth;
- public int bymonthCount;
- public int[] bysetpos;
- public int bysetposCount;
-
- /** maps a part string to a parser object */
- private static HashMap<String,PartParser> sParsePartMap;
- static {
- sParsePartMap = new HashMap<String,PartParser>();
- sParsePartMap.put("FREQ", new ParseFreq());
- sParsePartMap.put("UNTIL", new ParseUntil());
- sParsePartMap.put("COUNT", new ParseCount());
- sParsePartMap.put("INTERVAL", new ParseInterval());
- sParsePartMap.put("BYSECOND", new ParseBySecond());
- sParsePartMap.put("BYMINUTE", new ParseByMinute());
- sParsePartMap.put("BYHOUR", new ParseByHour());
- sParsePartMap.put("BYDAY", new ParseByDay());
- sParsePartMap.put("BYMONTHDAY", new ParseByMonthDay());
- sParsePartMap.put("BYYEARDAY", new ParseByYearDay());
- sParsePartMap.put("BYWEEKNO", new ParseByWeekNo());
- sParsePartMap.put("BYMONTH", new ParseByMonth());
- sParsePartMap.put("BYSETPOS", new ParseBySetPos());
- sParsePartMap.put("WKST", new ParseWkst());
- }
-
- /* values for bit vector that keeps track of what we have already seen */
- private static final int PARSED_FREQ = 1 << 0;
- private static final int PARSED_UNTIL = 1 << 1;
- private static final int PARSED_COUNT = 1 << 2;
- private static final int PARSED_INTERVAL = 1 << 3;
- private static final int PARSED_BYSECOND = 1 << 4;
- private static final int PARSED_BYMINUTE = 1 << 5;
- private static final int PARSED_BYHOUR = 1 << 6;
- private static final int PARSED_BYDAY = 1 << 7;
- private static final int PARSED_BYMONTHDAY = 1 << 8;
- private static final int PARSED_BYYEARDAY = 1 << 9;
- private static final int PARSED_BYWEEKNO = 1 << 10;
- private static final int PARSED_BYMONTH = 1 << 11;
- private static final int PARSED_BYSETPOS = 1 << 12;
- private static final int PARSED_WKST = 1 << 13;
-
- /** maps a FREQ value to an integer constant */
- private static final HashMap<String,Integer> sParseFreqMap = new HashMap<String,Integer>();
- static {
- sParseFreqMap.put("SECONDLY", SECONDLY);
- sParseFreqMap.put("MINUTELY", MINUTELY);
- sParseFreqMap.put("HOURLY", HOURLY);
- sParseFreqMap.put("DAILY", DAILY);
- sParseFreqMap.put("WEEKLY", WEEKLY);
- sParseFreqMap.put("MONTHLY", MONTHLY);
- sParseFreqMap.put("YEARLY", YEARLY);
- }
-
- /** maps a two-character weekday string to an integer constant */
- private static final HashMap<String,Integer> sParseWeekdayMap = new HashMap<String,Integer>();
- static {
- sParseWeekdayMap.put("SU", SU);
- sParseWeekdayMap.put("MO", MO);
- sParseWeekdayMap.put("TU", TU);
- sParseWeekdayMap.put("WE", WE);
- sParseWeekdayMap.put("TH", TH);
- sParseWeekdayMap.put("FR", FR);
- sParseWeekdayMap.put("SA", SA);
- }
-
- /** If set, allow lower-case recurrence rule strings. Minor performance impact. */
- private static final boolean ALLOW_LOWER_CASE = false;
-
- /** If set, validate the value of UNTIL parts. Minor performance impact. */
- private static final boolean VALIDATE_UNTIL = false;
-
- /** If set, require that only one of {UNTIL,COUNT} is present. Breaks compat w/ old parser. */
- private static final boolean ONLY_ONE_UNTIL_COUNT = false;
-
-
- /**
- * Thrown when a recurrence string provided can not be parsed according
- * to RFC2445.
- */
- public static class InvalidFormatException extends RuntimeException {
- InvalidFormatException(String s) {
- super(s);
- }
- }
-
-
- public void setStartDate(Time date) {
- startDate = date;
- }
-
- /**
- * Converts one of the Calendar.SUNDAY constants to the SU, MO, etc.
- * constants. btw, I think we should switch to those here too, to
- * get rid of this function, if possible.
- */
- public static int calendarDay2Day(int day)
- {
- switch (day)
- {
- case Calendar.SUNDAY:
- return SU;
- case Calendar.MONDAY:
- return MO;
- case Calendar.TUESDAY:
- return TU;
- case Calendar.WEDNESDAY:
- return WE;
- case Calendar.THURSDAY:
- return TH;
- case Calendar.FRIDAY:
- return FR;
- case Calendar.SATURDAY:
- return SA;
- default:
- throw new RuntimeException("bad day of week: " + day);
- }
- }
-
- public static int timeDay2Day(int day)
- {
- switch (day)
- {
- case Time.SUNDAY:
- return SU;
- case Time.MONDAY:
- return MO;
- case Time.TUESDAY:
- return TU;
- case Time.WEDNESDAY:
- return WE;
- case Time.THURSDAY:
- return TH;
- case Time.FRIDAY:
- return FR;
- case Time.SATURDAY:
- return SA;
- default:
- throw new RuntimeException("bad day of week: " + day);
- }
- }
- public static int day2TimeDay(int day)
- {
- switch (day)
- {
- case SU:
- return Time.SUNDAY;
- case MO:
- return Time.MONDAY;
- case TU:
- return Time.TUESDAY;
- case WE:
- return Time.WEDNESDAY;
- case TH:
- return Time.THURSDAY;
- case FR:
- return Time.FRIDAY;
- case SA:
- return Time.SATURDAY;
- default:
- throw new RuntimeException("bad day of week: " + day);
- }
- }
-
- /**
- * Converts one of the SU, MO, etc. constants to the Calendar.SUNDAY
- * constants. btw, I think we should switch to those here too, to
- * get rid of this function, if possible.
- */
- public static int day2CalendarDay(int day)
- {
- switch (day)
- {
- case SU:
- return Calendar.SUNDAY;
- case MO:
- return Calendar.MONDAY;
- case TU:
- return Calendar.TUESDAY;
- case WE:
- return Calendar.WEDNESDAY;
- case TH:
- return Calendar.THURSDAY;
- case FR:
- return Calendar.FRIDAY;
- case SA:
- return Calendar.SATURDAY;
- default:
- throw new RuntimeException("bad day of week: " + day);
- }
- }
-
- /**
- * Converts one of the internal day constants (SU, MO, etc.) to the
- * two-letter string representing that constant.
- *
- * @param day one the internal constants SU, MO, etc.
- * @return the two-letter string for the day ("SU", "MO", etc.)
- *
- * @throws IllegalArgumentException Thrown if the day argument is not one of
- * the defined day constants.
- */
- private static String day2String(int day) {
- switch (day) {
- case SU:
- return "SU";
- case MO:
- return "MO";
- case TU:
- return "TU";
- case WE:
- return "WE";
- case TH:
- return "TH";
- case FR:
- return "FR";
- case SA:
- return "SA";
- default:
- throw new IllegalArgumentException("bad day argument: " + day);
- }
- }
-
- private static void appendNumbers(StringBuilder s, String label,
- int count, int[] values)
- {
- if (count > 0) {
- s.append(label);
- count--;
- for (int i=0; i<count; i++) {
- s.append(values[i]);
- s.append(",");
- }
- s.append(values[count]);
- }
- }
-
- private void appendByDay(StringBuilder s, int i)
- {
- int n = this.bydayNum[i];
- if (n != 0) {
- s.append(n);
- }
-
- String str = day2String(this.byday[i]);
- s.append(str);
- }
-
- @Override
- public String toString()
- {
- StringBuilder s = new StringBuilder();
-
- s.append("FREQ=");
- switch (this.freq)
- {
- case SECONDLY:
- s.append("SECONDLY");
- break;
- case MINUTELY:
- s.append("MINUTELY");
- break;
- case HOURLY:
- s.append("HOURLY");
- break;
- case DAILY:
- s.append("DAILY");
- break;
- case WEEKLY:
- s.append("WEEKLY");
- break;
- case MONTHLY:
- s.append("MONTHLY");
- break;
- case YEARLY:
- s.append("YEARLY");
- break;
- }
-
- if (!TextUtils.isEmpty(this.until)) {
- s.append(";UNTIL=");
- s.append(until);
- }
-
- if (this.count != 0) {
- s.append(";COUNT=");
- s.append(this.count);
- }
-
- if (this.interval != 0) {
- s.append(";INTERVAL=");
- s.append(this.interval);
- }
-
- if (this.wkst != 0) {
- s.append(";WKST=");
- s.append(day2String(this.wkst));
- }
-
- appendNumbers(s, ";BYSECOND=", this.bysecondCount, this.bysecond);
- appendNumbers(s, ";BYMINUTE=", this.byminuteCount, this.byminute);
- appendNumbers(s, ";BYSECOND=", this.byhourCount, this.byhour);
-
- // day
- int count = this.bydayCount;
- if (count > 0) {
- s.append(";BYDAY=");
- count--;
- for (int i=0; i<count; i++) {
- appendByDay(s, i);
- s.append(",");
- }
- appendByDay(s, count);
- }
-
- appendNumbers(s, ";BYMONTHDAY=", this.bymonthdayCount, this.bymonthday);
- appendNumbers(s, ";BYYEARDAY=", this.byyeardayCount, this.byyearday);
- appendNumbers(s, ";BYWEEKNO=", this.byweeknoCount, this.byweekno);
- appendNumbers(s, ";BYMONTH=", this.bymonthCount, this.bymonth);
- appendNumbers(s, ";BYSETPOS=", this.bysetposCount, this.bysetpos);
-
- return s.toString();
- }
-
- public boolean repeatsOnEveryWeekDay() {
- if (this.freq != WEEKLY) {
- return false;
- }
-
- int count = this.bydayCount;
- if (count != 5) {
- return false;
- }
-
- for (int i = 0 ; i < count ; i++) {
- int day = byday[i];
- if (day == SU || day == SA) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Determines whether this rule specifies a simple monthly rule by weekday, such as
- * "FREQ=MONTHLY;BYDAY=3TU" (the 3rd Tuesday of every month).
- * <p>
- * Negative days, e.g. "FREQ=MONTHLY;BYDAY=-1TU" (the last Tuesday of every month),
- * will cause "false" to be returned.
- * <p>
- * Rules that fire every week, such as "FREQ=MONTHLY;BYDAY=TU" (every Tuesday of every
- * month) will cause "false" to be returned. (Note these are usually expressed as
- * WEEKLY rules, and hence are uncommon.)
- *
- * @return true if this rule is of the appropriate form
- */
- public boolean repeatsMonthlyOnDayCount() {
- if (this.freq != MONTHLY) {
- return false;
- }
-
- if (bydayCount != 1 || bymonthdayCount != 0) {
- return false;
- }
-
- if (bydayNum[0] <= 0) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Determines whether two integer arrays contain identical elements.
- * <p>
- * The native implementation over-allocated the arrays (and may have stuff left over from
- * a previous run), so we can't just check the arrays -- the separately-maintained count
- * field also matters. We assume that a null array will have a count of zero, and that the
- * array can hold as many elements as the associated count indicates.
- * <p>
- * TODO: replace this with Arrays.equals() when the old parser goes away.
- */
- private static boolean arraysEqual(int[] array1, int count1, int[] array2, int count2) {
- if (count1 != count2) {
- return false;
- }
-
- for (int i = 0; i < count1; i++) {
- if (array1[i] != array2[i])
- return false;
- }
-
- return true;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof EventRecurrence)) {
- return false;
- }
-
- EventRecurrence er = (EventRecurrence) obj;
- return (startDate == null ?
- er.startDate == null : Time.compare(startDate, er.startDate) == 0) &&
- freq == er.freq &&
- (until == null ? er.until == null : until.equals(er.until)) &&
- count == er.count &&
- interval == er.interval &&
- wkst == er.wkst &&
- arraysEqual(bysecond, bysecondCount, er.bysecond, er.bysecondCount) &&
- arraysEqual(byminute, byminuteCount, er.byminute, er.byminuteCount) &&
- arraysEqual(byhour, byhourCount, er.byhour, er.byhourCount) &&
- arraysEqual(byday, bydayCount, er.byday, er.bydayCount) &&
- arraysEqual(bydayNum, bydayCount, er.bydayNum, er.bydayCount) &&
- arraysEqual(bymonthday, bymonthdayCount, er.bymonthday, er.bymonthdayCount) &&
- arraysEqual(byyearday, byyeardayCount, er.byyearday, er.byyeardayCount) &&
- arraysEqual(byweekno, byweeknoCount, er.byweekno, er.byweeknoCount) &&
- arraysEqual(bymonth, bymonthCount, er.bymonth, er.bymonthCount) &&
- arraysEqual(bysetpos, bysetposCount, er.bysetpos, er.bysetposCount);
- }
-
- @Override public int hashCode() {
- // We overrode equals, so we must override hashCode(). Nobody seems to need this though.
- throw new UnsupportedOperationException();
- }
-
- /**
- * Resets parser-modified fields to their initial state. Does not alter startDate.
- * <p>
- * The original parser always set all of the "count" fields, "wkst", and "until",
- * essentially allowing the same object to be used multiple times by calling parse().
- * It's unclear whether this behavior was intentional. For now, be paranoid and
- * preserve the existing behavior by resetting the fields.
- * <p>
- * We don't need to touch the integer arrays; they will either be ignored or
- * overwritten. The "startDate" field is not set by the parser, so we ignore it here.
- */
- private void resetFields() {
- until = null;
- freq = count = interval = bysecondCount = byminuteCount = byhourCount =
- bydayCount = bymonthdayCount = byyeardayCount = byweeknoCount = bymonthCount =
- bysetposCount = 0;
- }
-
- /**
- * Parses an rfc2445 recurrence rule string into its component pieces. Attempting to parse
- * malformed input will result in an EventRecurrence.InvalidFormatException.
- *
- * @param recur The recurrence rule to parse (in un-folded form).
- */
- public void parse(String recur) {
- /*
- * From RFC 2445 section 4.3.10:
- *
- * recur = "FREQ"=freq *(
- * ; either UNTIL or COUNT may appear in a 'recur',
- * ; but UNTIL and COUNT MUST NOT occur in the same 'recur'
- *
- * ( ";" "UNTIL" "=" enddate ) /
- * ( ";" "COUNT" "=" 1*DIGIT ) /
- *
- * ; the rest of these keywords are optional,
- * ; but MUST NOT occur more than once
- *
- * ( ";" "INTERVAL" "=" 1*DIGIT ) /
- * ( ";" "BYSECOND" "=" byseclist ) /
- * ( ";" "BYMINUTE" "=" byminlist ) /
- * ( ";" "BYHOUR" "=" byhrlist ) /
- * ( ";" "BYDAY" "=" bywdaylist ) /
- * ( ";" "BYMONTHDAY" "=" bymodaylist ) /
- * ( ";" "BYYEARDAY" "=" byyrdaylist ) /
- * ( ";" "BYWEEKNO" "=" bywknolist ) /
- * ( ";" "BYMONTH" "=" bymolist ) /
- * ( ";" "BYSETPOS" "=" bysplist ) /
- * ( ";" "WKST" "=" weekday ) /
- * ( ";" x-name "=" text )
- * )
- *
- * Examples:
- * FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU
- * FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8
- *
- * Strategy:
- * (1) Split the string at ';' boundaries to get an array of rule "parts".
- * (2) For each part, find substrings for left/right sides of '=' (name/value).
- * (3) Call a <name>-specific parsing function to parse the <value> into an
- * output field.
- *
- * By keeping track of which names we've seen in a bit vector, we can verify the
- * constraints indicated above (FREQ appears first, none of them appear more than once --
- * though x-[name] would require special treatment), and we have either UNTIL or COUNT
- * but not both.
- *
- * In general, RFC 2445 property names (e.g. "FREQ") and enumerations ("TU") must
- * be handled in a case-insensitive fashion, but case may be significant for other
- * properties. We don't have any case-sensitive values in RRULE, except possibly
- * for the custom "X-" properties, but we ignore those anyway. Thus, we can trivially
- * convert the entire string to upper case and then use simple comparisons.
- *
- * Differences from previous version:
- * - allows lower-case property and enumeration values [optional]
- * - enforces that FREQ appears first
- * - enforces that only one of UNTIL and COUNT may be specified
- * - allows (but ignores) X-* parts
- * - improved validation on various values (e.g. UNTIL timestamps)
- * - error messages are more specific
- */
-
- /* TODO: replace with "if (freq != 0) throw" if nothing requires this */
- resetFields();
-
- int parseFlags = 0;
- String[] parts;
- if (ALLOW_LOWER_CASE) {
- parts = recur.toUpperCase().split(";");
- } else {
- parts = recur.split(";");
- }
- for (String part : parts) {
- int equalIndex = part.indexOf('=');
- if (equalIndex <= 0) {
- /* no '=' or no LHS */
- throw new InvalidFormatException("Missing LHS in " + part);
- }
-
- String lhs = part.substring(0, equalIndex);
- String rhs = part.substring(equalIndex + 1);
- if (rhs.length() == 0) {
- throw new InvalidFormatException("Missing RHS in " + part);
- }
-
- /*
- * In lieu of a "switch" statement that allows string arguments, we use a
- * map from strings to parsing functions.
- */
- PartParser parser = sParsePartMap.get(lhs);
- if (parser == null) {
- if (lhs.startsWith("X-")) {
- //Log.d(TAG, "Ignoring custom part " + lhs);
- continue;
- }
- throw new InvalidFormatException("Couldn't find parser for " + lhs);
- } else {
- int flag = parser.parsePart(rhs, this);
- if ((parseFlags & flag) != 0) {
- throw new InvalidFormatException("Part " + lhs + " was specified twice");
- }
- if (parseFlags == 0 && flag != PARSED_FREQ) {
- throw new InvalidFormatException("FREQ must be specified first");
- }
- parseFlags |= flag;
- }
- }
-
- // If not specified, week starts on Monday.
- if ((parseFlags & PARSED_WKST) == 0) {
- wkst = MO;
- }
-
- // FREQ is mandatory.
- if ((parseFlags & PARSED_FREQ) == 0) {
- throw new InvalidFormatException("Must specify a FREQ value");
- }
-
- // Can't have both UNTIL and COUNT.
- if ((parseFlags & (PARSED_UNTIL | PARSED_COUNT)) == (PARSED_UNTIL | PARSED_COUNT)) {
- if (ONLY_ONE_UNTIL_COUNT) {
- throw new InvalidFormatException("Must not specify both UNTIL and COUNT: " + recur);
- } else {
- Log.w(TAG, "Warning: rrule has both UNTIL and COUNT: " + recur);
- }
- }
- }
-
- /**
- * Base class for the RRULE part parsers.
- */
- abstract static class PartParser {
- /**
- * Parses a single part.
- *
- * @param value The right-hand-side of the part.
- * @param er The EventRecurrence into which the result is stored.
- * @return A bit value indicating which part was parsed.
- */
- public abstract int parsePart(String value, EventRecurrence er);
-
- /**
- * Parses an integer, with range-checking.
- *
- * @param str The string to parse.
- * @param minVal Minimum allowed value.
- * @param maxVal Maximum allowed value.
- * @param allowZero Is 0 allowed?
- * @return The parsed value.
- */
- public static int parseIntRange(String str, int minVal, int maxVal, boolean allowZero) {
- try {
- if (str.charAt(0) == '+') {
- // Integer.parseInt does not allow a leading '+', so skip it manually.
- str = str.substring(1);
- }
- int val = Integer.parseInt(str);
- if (val < minVal || val > maxVal || (val == 0 && !allowZero)) {
- throw new InvalidFormatException("Integer value out of range: " + str);
- }
- return val;
- } catch (NumberFormatException nfe) {
- throw new InvalidFormatException("Invalid integer value: " + str);
- }
- }
-
- /**
- * Parses a comma-separated list of integers, with range-checking.
- *
- * @param listStr The string to parse.
- * @param minVal Minimum allowed value.
- * @param maxVal Maximum allowed value.
- * @param allowZero Is 0 allowed?
- * @return A new array with values, sized to hold the exact number of elements.
- */
- public static int[] parseNumberList(String listStr, int minVal, int maxVal,
- boolean allowZero) {
- int[] values;
-
- if (listStr.indexOf(",") < 0) {
- // Common case: only one entry, skip split() overhead.
- values = new int[1];
- values[0] = parseIntRange(listStr, minVal, maxVal, allowZero);
- } else {
- String[] valueStrs = listStr.split(",");
- int len = valueStrs.length;
- values = new int[len];
- for (int i = 0; i < len; i++) {
- values[i] = parseIntRange(valueStrs[i], minVal, maxVal, allowZero);
- }
- }
- return values;
- }
- }
-
- /** parses FREQ={SECONDLY,MINUTELY,...} */
- private static class ParseFreq extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- Integer freq = sParseFreqMap.get(value);
- if (freq == null) {
- throw new InvalidFormatException("Invalid FREQ value: " + value);
- }
- er.freq = freq;
- return PARSED_FREQ;
- }
- }
- /** parses UNTIL=enddate, e.g. "19970829T021400" */
- private static class ParseUntil extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- if (VALIDATE_UNTIL) {
- try {
- // Parse the time to validate it. The result isn't retained.
- Time until = new Time();
- until.parse(value);
- } catch (TimeFormatException tfe) {
- throw new InvalidFormatException("Invalid UNTIL value: " + value);
- }
- }
- er.until = value;
- return PARSED_UNTIL;
- }
- }
- /** parses COUNT=[non-negative-integer] */
- private static class ParseCount extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- er.count = parseIntRange(value, 0, Integer.MAX_VALUE, true);
- return PARSED_COUNT;
- }
- }
- /** parses INTERVAL=[non-negative-integer] */
- private static class ParseInterval extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- er.interval = parseIntRange(value, 1, Integer.MAX_VALUE, false);
- return PARSED_INTERVAL;
- }
- }
- /** parses BYSECOND=byseclist */
- private static class ParseBySecond extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- int[] bysecond = parseNumberList(value, 0, 59, true);
- er.bysecond = bysecond;
- er.bysecondCount = bysecond.length;
- return PARSED_BYSECOND;
- }
- }
- /** parses BYMINUTE=byminlist */
- private static class ParseByMinute extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- int[] byminute = parseNumberList(value, 0, 59, true);
- er.byminute = byminute;
- er.byminuteCount = byminute.length;
- return PARSED_BYMINUTE;
- }
- }
- /** parses BYHOUR=byhrlist */
- private static class ParseByHour extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- int[] byhour = parseNumberList(value, 0, 23, true);
- er.byhour = byhour;
- er.byhourCount = byhour.length;
- return PARSED_BYHOUR;
- }
- }
- /** parses BYDAY=bywdaylist, e.g. "1SU,-1SU" */
- private static class ParseByDay extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- int[] byday;
- int[] bydayNum;
- int bydayCount;
-
- if (value.indexOf(",") < 0) {
- /* only one entry, skip split() overhead */
- bydayCount = 1;
- byday = new int[1];
- bydayNum = new int[1];
- parseWday(value, byday, bydayNum, 0);
- } else {
- String[] wdays = value.split(",");
- int len = wdays.length;
- bydayCount = len;
- byday = new int[len];
- bydayNum = new int[len];
- for (int i = 0; i < len; i++) {
- parseWday(wdays[i], byday, bydayNum, i);
- }
- }
- er.byday = byday;
- er.bydayNum = bydayNum;
- er.bydayCount = bydayCount;
- return PARSED_BYDAY;
- }
-
- /** parses [int]weekday, putting the pieces into parallel array entries */
- private static void parseWday(String str, int[] byday, int[] bydayNum, int index) {
- int wdayStrStart = str.length() - 2;
- String wdayStr;
-
- if (wdayStrStart > 0) {
- /* number is included; parse it out and advance to weekday */
- String numPart = str.substring(0, wdayStrStart);
- int num = parseIntRange(numPart, -53, 53, false);
- bydayNum[index] = num;
- wdayStr = str.substring(wdayStrStart);
- } else {
- /* just the weekday string */
- wdayStr = str;
- }
- Integer wday = sParseWeekdayMap.get(wdayStr);
- if (wday == null) {
- throw new InvalidFormatException("Invalid BYDAY value: " + str);
- }
- byday[index] = wday;
- }
- }
- /** parses BYMONTHDAY=bymodaylist */
- private static class ParseByMonthDay extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- int[] bymonthday = parseNumberList(value, -31, 31, false);
- er.bymonthday = bymonthday;
- er.bymonthdayCount = bymonthday.length;
- return PARSED_BYMONTHDAY;
- }
- }
- /** parses BYYEARDAY=byyrdaylist */
- private static class ParseByYearDay extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- int[] byyearday = parseNumberList(value, -366, 366, false);
- er.byyearday = byyearday;
- er.byyeardayCount = byyearday.length;
- return PARSED_BYYEARDAY;
- }
- }
- /** parses BYWEEKNO=bywknolist */
- private static class ParseByWeekNo extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- int[] byweekno = parseNumberList(value, -53, 53, false);
- er.byweekno = byweekno;
- er.byweeknoCount = byweekno.length;
- return PARSED_BYWEEKNO;
- }
- }
- /** parses BYMONTH=bymolist */
- private static class ParseByMonth extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- int[] bymonth = parseNumberList(value, 1, 12, false);
- er.bymonth = bymonth;
- er.bymonthCount = bymonth.length;
- return PARSED_BYMONTH;
- }
- }
- /** parses BYSETPOS=bysplist */
- private static class ParseBySetPos extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- int[] bysetpos = parseNumberList(value, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
- er.bysetpos = bysetpos;
- er.bysetposCount = bysetpos.length;
- return PARSED_BYSETPOS;
- }
- }
- /** parses WKST={SU,MO,...} */
- private static class ParseWkst extends PartParser {
- @Override public int parsePart(String value, EventRecurrence er) {
- Integer wkst = sParseWeekdayMap.get(value);
- if (wkst == null) {
- throw new InvalidFormatException("Invalid WKST value: " + value);
- }
- er.wkst = wkst;
- return PARSED_WKST;
- }
- }
-}
diff --git a/core/java/android/pim/ICalendar.java b/core/java/android/pim/ICalendar.java
deleted file mode 100644
index 58c5c63..0000000
--- a/core/java/android/pim/ICalendar.java
+++ /dev/null
@@ -1,660 +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.
- */
-
-package android.pim;
-
-import android.util.Log;
-
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.ArrayList;
-
-/**
- * Parses RFC 2445 iCalendar objects.
- */
-public class ICalendar {
-
- private static final String TAG = "Sync";
-
- // TODO: keep track of VEVENT, VTODO, VJOURNAL, VFREEBUSY, VTIMEZONE, VALARM
- // components, by type field or by subclass? subclass would allow us to
- // enforce grammars.
-
- /**
- * Exception thrown when an iCalendar object has invalid syntax.
- */
- public static class FormatException extends Exception {
- public FormatException() {
- super();
- }
-
- public FormatException(String msg) {
- super(msg);
- }
-
- public FormatException(String msg, Throwable cause) {
- super(msg, cause);
- }
- }
-
- /**
- * A component within an iCalendar (VEVENT, VTODO, VJOURNAL, VFEEBUSY,
- * VTIMEZONE, VALARM).
- */
- public static class Component {
-
- // components
- private static final String BEGIN = "BEGIN";
- private static final String END = "END";
- private static final String NEWLINE = "\n";
- public static final String VCALENDAR = "VCALENDAR";
- public static final String VEVENT = "VEVENT";
- public static final String VTODO = "VTODO";
- public static final String VJOURNAL = "VJOURNAL";
- public static final String VFREEBUSY = "VFREEBUSY";
- public static final String VTIMEZONE = "VTIMEZONE";
- public static final String VALARM = "VALARM";
-
- private final String mName;
- private final Component mParent; // see if we can get rid of this
- private LinkedList<Component> mChildren = null;
- private final LinkedHashMap<String, ArrayList<Property>> mPropsMap =
- new LinkedHashMap<String, ArrayList<Property>>();
-
- /**
- * Creates a new component with the provided name.
- * @param name The name of the component.
- */
- public Component(String name, Component parent) {
- mName = name;
- mParent = parent;
- }
-
- /**
- * Returns the name of the component.
- * @return The name of the component.
- */
- public String getName() {
- return mName;
- }
-
- /**
- * Returns the parent of this component.
- * @return The parent of this component.
- */
- public Component getParent() {
- return mParent;
- }
-
- /**
- * Helper that lazily gets/creates the list of children.
- * @return The list of children.
- */
- protected LinkedList<Component> getOrCreateChildren() {
- if (mChildren == null) {
- mChildren = new LinkedList<Component>();
- }
- return mChildren;
- }
-
- /**
- * Adds a child component to this component.
- * @param child The child component.
- */
- public void addChild(Component child) {
- getOrCreateChildren().add(child);
- }
-
- /**
- * Returns a list of the Component children of this component. May be
- * null, if there are no children.
- *
- * @return A list of the children.
- */
- public List<Component> getComponents() {
- return mChildren;
- }
-
- /**
- * Adds a Property to this component.
- * @param prop
- */
- public void addProperty(Property prop) {
- String name= prop.getName();
- ArrayList<Property> props = mPropsMap.get(name);
- if (props == null) {
- props = new ArrayList<Property>();
- mPropsMap.put(name, props);
- }
- props.add(prop);
- }
-
- /**
- * Returns a set of the property names within this component.
- * @return A set of property names within this component.
- */
- public Set<String> getPropertyNames() {
- return mPropsMap.keySet();
- }
-
- /**
- * Returns a list of properties with the specified name. Returns null
- * if there are no such properties.
- * @param name The name of the property that should be returned.
- * @return A list of properties with the requested name.
- */
- public List<Property> getProperties(String name) {
- return mPropsMap.get(name);
- }
-
- /**
- * Returns the first property with the specified name. Returns null
- * if there is no such property.
- * @param name The name of the property that should be returned.
- * @return The first property with the specified name.
- */
- public Property getFirstProperty(String name) {
- List<Property> props = mPropsMap.get(name);
- if (props == null || props.size() == 0) {
- return null;
- }
- return props.get(0);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- toString(sb);
- sb.append(NEWLINE);
- return sb.toString();
- }
-
- /**
- * Helper method that appends this component to a StringBuilder. The
- * caller is responsible for appending a newline at the end of the
- * component.
- */
- public void toString(StringBuilder sb) {
- sb.append(BEGIN);
- sb.append(":");
- sb.append(mName);
- sb.append(NEWLINE);
-
- // append the properties
- for (String propertyName : getPropertyNames()) {
- for (Property property : getProperties(propertyName)) {
- property.toString(sb);
- sb.append(NEWLINE);
- }
- }
-
- // append the sub-components
- if (mChildren != null) {
- for (Component component : mChildren) {
- component.toString(sb);
- sb.append(NEWLINE);
- }
- }
-
- sb.append(END);
- sb.append(":");
- sb.append(mName);
- }
- }
-
- /**
- * A property within an iCalendar component (e.g., DTSTART, DTEND, etc.,
- * within a VEVENT).
- */
- public static class Property {
- // properties
- // TODO: do we want to list these here? the complete list is long.
- public static final String DTSTART = "DTSTART";
- public static final String DTEND = "DTEND";
- public static final String DURATION = "DURATION";
- public static final String RRULE = "RRULE";
- public static final String RDATE = "RDATE";
- public static final String EXRULE = "EXRULE";
- public static final String EXDATE = "EXDATE";
- // ... need to add more.
-
- private final String mName;
- private LinkedHashMap<String, ArrayList<Parameter>> mParamsMap =
- new LinkedHashMap<String, ArrayList<Parameter>>();
- private String mValue; // TODO: make this final?
-
- /**
- * Creates a new property with the provided name.
- * @param name The name of the property.
- */
- public Property(String name) {
- mName = name;
- }
-
- /**
- * Creates a new property with the provided name and value.
- * @param name The name of the property.
- * @param value The value of the property.
- */
- public Property(String name, String value) {
- mName = name;
- mValue = value;
- }
-
- /**
- * Returns the name of the property.
- * @return The name of the property.
- */
- public String getName() {
- return mName;
- }
-
- /**
- * Returns the value of this property.
- * @return The value of this property.
- */
- public String getValue() {
- return mValue;
- }
-
- /**
- * Sets the value of this property.
- * @param value The desired value for this property.
- */
- public void setValue(String value) {
- mValue = value;
- }
-
- /**
- * Adds a {@link Parameter} to this property.
- * @param param The parameter that should be added.
- */
- public void addParameter(Parameter param) {
- ArrayList<Parameter> params = mParamsMap.get(param.name);
- if (params == null) {
- params = new ArrayList<Parameter>();
- mParamsMap.put(param.name, params);
- }
- params.add(param);
- }
-
- /**
- * Returns the set of parameter names for this property.
- * @return The set of parameter names for this property.
- */
- public Set<String> getParameterNames() {
- return mParamsMap.keySet();
- }
-
- /**
- * Returns the list of parameters with the specified name. May return
- * null if there are no such parameters.
- * @param name The name of the parameters that should be returned.
- * @return The list of parameters with the specified name.
- */
- public List<Parameter> getParameters(String name) {
- return mParamsMap.get(name);
- }
-
- /**
- * Returns the first parameter with the specified name. May return
- * nll if there is no such parameter.
- * @param name The name of the parameter that should be returned.
- * @return The first parameter with the specified name.
- */
- public Parameter getFirstParameter(String name) {
- ArrayList<Parameter> params = mParamsMap.get(name);
- if (params == null || params.size() == 0) {
- return null;
- }
- return params.get(0);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- toString(sb);
- return sb.toString();
- }
-
- /**
- * Helper method that appends this property to a StringBuilder. The
- * caller is responsible for appending a newline after this property.
- */
- public void toString(StringBuilder sb) {
- sb.append(mName);
- Set<String> parameterNames = getParameterNames();
- for (String parameterName : parameterNames) {
- for (Parameter param : getParameters(parameterName)) {
- sb.append(";");
- param.toString(sb);
- }
- }
- sb.append(":");
- sb.append(mValue);
- }
- }
-
- /**
- * A parameter defined for an iCalendar property.
- */
- // TODO: make this a proper class rather than a struct?
- public static class Parameter {
- public String name;
- public String value;
-
- /**
- * Creates a new empty parameter.
- */
- public Parameter() {
- }
-
- /**
- * Creates a new parameter with the specified name and value.
- * @param name The name of the parameter.
- * @param value The value of the parameter.
- */
- public Parameter(String name, String value) {
- this.name = name;
- this.value = value;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- toString(sb);
- return sb.toString();
- }
-
- /**
- * Helper method that appends this parameter to a StringBuilder.
- */
- public void toString(StringBuilder sb) {
- sb.append(name);
- sb.append("=");
- sb.append(value);
- }
- }
-
- private static final class ParserState {
- // public int lineNumber = 0;
- public String line; // TODO: just point to original text
- public int index;
- }
-
- // use factory method
- private ICalendar() {
- }
-
- // TODO: get rid of this -- handle all of the parsing in one pass through
- // the text.
- private static String normalizeText(String text) {
- // it's supposed to be \r\n, but not everyone does that
- text = text.replaceAll("\r\n", "\n");
- text = text.replaceAll("\r", "\n");
-
- // we deal with line folding, by replacing all "\n " strings
- // with nothing. The RFC specifies "\r\n " to be folded, but
- // we handle "\n " and "\r " too because we can get those.
- text = text.replaceAll("\n ", "");
-
- return text;
- }
-
- /**
- * Parses text into an iCalendar component. Parses into the provided
- * component, if not null, or parses into a new component. In the latter
- * case, expects a BEGIN as the first line. Returns the provided or newly
- * created top-level component.
- */
- // TODO: use an index into the text, so we can make this a recursive
- // function?
- private static Component parseComponentImpl(Component component,
- String text)
- throws FormatException {
- Component current = component;
- ParserState state = new ParserState();
- state.index = 0;
-
- // split into lines
- String[] lines = text.split("\n");
-
- // each line is of the format:
- // name *(";" param) ":" value
- for (String line : lines) {
- try {
- current = parseLine(line, state, current);
- // if the provided component was null, we will return the root
- // NOTE: in this case, if the first line is not a BEGIN, a
- // FormatException will get thrown.
- if (component == null) {
- component = current;
- }
- } catch (FormatException fe) {
- if (false) {
- Log.v(TAG, "Cannot parse " + line, fe);
- }
- // for now, we ignore the parse error. Google Calendar seems
- // to be emitting some misformatted iCalendar objects.
- }
- continue;
- }
- return component;
- }
-
- /**
- * Parses a line into the provided component. Creates a new component if
- * the line is a BEGIN, adding the newly created component to the provided
- * parent. Returns whatever component is the current one (to which new
- * properties will be added) in the parse.
- */
- private static Component parseLine(String line, ParserState state,
- Component component)
- throws FormatException {
- state.line = line;
- int len = state.line.length();
-
- // grab the name
- char c = 0;
- for (state.index = 0; state.index < len; ++state.index) {
- c = line.charAt(state.index);
- if (c == ';' || c == ':') {
- break;
- }
- }
- String name = line.substring(0, state.index);
-
- if (component == null) {
- if (!Component.BEGIN.equals(name)) {
- throw new FormatException("Expected BEGIN");
- }
- }
-
- Property property;
- if (Component.BEGIN.equals(name)) {
- // start a new component
- String componentName = extractValue(state);
- Component child = new Component(componentName, component);
- if (component != null) {
- component.addChild(child);
- }
- return child;
- } else if (Component.END.equals(name)) {
- // finish the current component
- String componentName = extractValue(state);
- if (component == null ||
- !componentName.equals(component.getName())) {
- throw new FormatException("Unexpected END " + componentName);
- }
- return component.getParent();
- } else {
- property = new Property(name);
- }
-
- if (c == ';') {
- Parameter parameter = null;
- while ((parameter = extractParameter(state)) != null) {
- property.addParameter(parameter);
- }
- }
- String value = extractValue(state);
- property.setValue(value);
- component.addProperty(property);
- return component;
- }
-
- /**
- * Extracts the value ":..." on the current line. The first character must
- * be a ':'.
- */
- private static String extractValue(ParserState state)
- throws FormatException {
- String line = state.line;
- if (state.index >= line.length() || line.charAt(state.index) != ':') {
- throw new FormatException("Expected ':' before end of line in "
- + line);
- }
- String value = line.substring(state.index + 1);
- state.index = line.length() - 1;
- return value;
- }
-
- /**
- * Extracts the next parameter from the line, if any. If there are no more
- * parameters, returns null.
- */
- private static Parameter extractParameter(ParserState state)
- throws FormatException {
- String text = state.line;
- int len = text.length();
- Parameter parameter = null;
- int startIndex = -1;
- int equalIndex = -1;
- while (state.index < len) {
- char c = text.charAt(state.index);
- if (c == ':') {
- if (parameter != null) {
- if (equalIndex == -1) {
- throw new FormatException("Expected '=' within "
- + "parameter in " + text);
- }
- parameter.value = text.substring(equalIndex + 1,
- state.index);
- }
- return parameter; // may be null
- } else if (c == ';') {
- if (parameter != null) {
- if (equalIndex == -1) {
- throw new FormatException("Expected '=' within "
- + "parameter in " + text);
- }
- parameter.value = text.substring(equalIndex + 1,
- state.index);
- return parameter;
- } else {
- parameter = new Parameter();
- startIndex = state.index;
- }
- } else if (c == '=') {
- equalIndex = state.index;
- if ((parameter == null) || (startIndex == -1)) {
- throw new FormatException("Expected ';' before '=' in "
- + text);
- }
- parameter.name = text.substring(startIndex + 1, equalIndex);
- } else if (c == '"') {
- if (parameter == null) {
- throw new FormatException("Expected parameter before '\"' in " + text);
- }
- if (equalIndex == -1) {
- throw new FormatException("Expected '=' within parameter in " + text);
- }
- if (state.index > equalIndex + 1) {
- throw new FormatException("Parameter value cannot contain a '\"' in " + text);
- }
- final int endQuote = text.indexOf('"', state.index + 1);
- if (endQuote < 0) {
- throw new FormatException("Expected closing '\"' in " + text);
- }
- parameter.value = text.substring(state.index + 1, endQuote);
- state.index = endQuote + 1;
- return parameter;
- }
- ++state.index;
- }
- throw new FormatException("Expected ':' before end of line in " + text);
- }
-
- /**
- * Parses the provided text into an iCalendar object. The top-level
- * component must be of type VCALENDAR.
- * @param text The text to be parsed.
- * @return The top-level VCALENDAR component.
- * @throws FormatException Thrown if the text could not be parsed into an
- * iCalendar VCALENDAR object.
- */
- public static Component parseCalendar(String text) throws FormatException {
- Component calendar = parseComponent(null, text);
- if (calendar == null || !Component.VCALENDAR.equals(calendar.getName())) {
- throw new FormatException("Expected " + Component.VCALENDAR);
- }
- return calendar;
- }
-
- /**
- * Parses the provided text into an iCalendar event. The top-level
- * component must be of type VEVENT.
- * @param text The text to be parsed.
- * @return The top-level VEVENT component.
- * @throws FormatException Thrown if the text could not be parsed into an
- * iCalendar VEVENT.
- */
- public static Component parseEvent(String text) throws FormatException {
- Component event = parseComponent(null, text);
- if (event == null || !Component.VEVENT.equals(event.getName())) {
- throw new FormatException("Expected " + Component.VEVENT);
- }
- return event;
- }
-
- /**
- * Parses the provided text into an iCalendar component.
- * @param text The text to be parsed.
- * @return The top-level component.
- * @throws FormatException Thrown if the text could not be parsed into an
- * iCalendar component.
- */
- public static Component parseComponent(String text) throws FormatException {
- return parseComponent(null, text);
- }
-
- /**
- * Parses the provided text, adding to the provided component.
- * @param component The component to which the parsed iCalendar data should
- * be added.
- * @param text The text to be parsed.
- * @return The top-level component.
- * @throws FormatException Thrown if the text could not be parsed as an
- * iCalendar object.
- */
- public static Component parseComponent(Component component, String text)
- throws FormatException {
- text = normalizeText(text);
- return parseComponentImpl(component, text);
- }
-}
diff --git a/core/java/android/pim/RecurrenceSet.java b/core/java/android/pim/RecurrenceSet.java
deleted file mode 100644
index b7fb320..0000000
--- a/core/java/android/pim/RecurrenceSet.java
+++ /dev/null
@@ -1,511 +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.
- */
-
-package android.pim;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.provider.CalendarContract;
-import android.text.TextUtils;
-import android.text.format.Time;
-import android.util.Log;
-
-import java.util.List;
-import java.util.regex.Pattern;
-
-/**
- * Basic information about a recurrence, following RFC 2445 Section 4.8.5.
- * Contains the RRULEs, RDATE, EXRULEs, and EXDATE properties.
- */
-public class RecurrenceSet {
-
- private final static String TAG = "CalendarProvider";
-
- private final static String RULE_SEPARATOR = "\n";
- private final static String FOLDING_SEPARATOR = "\n ";
-
- // TODO: make these final?
- public EventRecurrence[] rrules = null;
- public long[] rdates = null;
- public EventRecurrence[] exrules = null;
- public long[] exdates = null;
-
- /**
- * Creates a new RecurrenceSet from information stored in the
- * events table in the CalendarProvider.
- * @param values The values retrieved from the Events table.
- */
- public RecurrenceSet(ContentValues values)
- throws EventRecurrence.InvalidFormatException {
- 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);
- }
-
- /**
- * Creates a new RecurrenceSet from information stored in a database
- * {@link Cursor} pointing to the events table in the
- * CalendarProvider. The cursor must contain the RRULE, RDATE, EXRULE,
- * and EXDATE columns.
- *
- * @param cursor The cursor containing the RRULE, RDATE, EXRULE, and EXDATE
- * columns.
- */
- public RecurrenceSet(Cursor cursor)
- throws EventRecurrence.InvalidFormatException {
- 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);
- String exdateStr = cursor.getString(exdateColumn);
- init(rruleStr, rdateStr, exruleStr, exdateStr);
- }
-
- public RecurrenceSet(String rruleStr, String rdateStr,
- String exruleStr, String exdateStr)
- throws EventRecurrence.InvalidFormatException {
- init(rruleStr, rdateStr, exruleStr, exdateStr);
- }
-
- private void init(String rruleStr, String rdateStr,
- String exruleStr, String exdateStr)
- throws EventRecurrence.InvalidFormatException {
- if (!TextUtils.isEmpty(rruleStr) || !TextUtils.isEmpty(rdateStr)) {
-
- if (!TextUtils.isEmpty(rruleStr)) {
- String[] rruleStrs = rruleStr.split(RULE_SEPARATOR);
- rrules = new EventRecurrence[rruleStrs.length];
- for (int i = 0; i < rruleStrs.length; ++i) {
- EventRecurrence rrule = new EventRecurrence();
- rrule.parse(rruleStrs[i]);
- rrules[i] = rrule;
- }
- }
-
- if (!TextUtils.isEmpty(rdateStr)) {
- rdates = parseRecurrenceDates(rdateStr);
- }
-
- if (!TextUtils.isEmpty(exruleStr)) {
- String[] exruleStrs = exruleStr.split(RULE_SEPARATOR);
- exrules = new EventRecurrence[exruleStrs.length];
- for (int i = 0; i < exruleStrs.length; ++i) {
- EventRecurrence exrule = new EventRecurrence();
- exrule.parse(exruleStr);
- exrules[i] = exrule;
- }
- }
-
- if (!TextUtils.isEmpty(exdateStr)) {
- exdates = parseRecurrenceDates(exdateStr);
- }
- }
- }
-
- /**
- * Returns whether or not a recurrence is defined in this RecurrenceSet.
- * @return Whether or not a recurrence is defined in this RecurrenceSet.
- */
- public boolean hasRecurrence() {
- return (rrules != null || rdates != null);
- }
-
- /**
- * Parses the provided RDATE or EXDATE string into an array of longs
- * representing each date/time in the recurrence.
- * @param recurrence The recurrence to be parsed.
- * @return The list of date/times.
- */
- public static long[] parseRecurrenceDates(String recurrence) {
- // TODO: use "local" time as the default. will need to handle times
- // that end in "z" (UTC time) explicitly at that point.
- String tz = Time.TIMEZONE_UTC;
- int tzidx = recurrence.indexOf(";");
- if (tzidx != -1) {
- tz = recurrence.substring(0, tzidx);
- recurrence = recurrence.substring(tzidx + 1);
- }
- Time time = new Time(tz);
- String[] rawDates = recurrence.split(",");
- int n = rawDates.length;
- long[] dates = new long[n];
- for (int i = 0; i<n; ++i) {
- // The timezone is updated to UTC if the time string specified 'Z'.
- time.parse(rawDates[i]);
- dates[i] = time.toMillis(false /* use isDst */);
- time.timezone = tz;
- }
- return dates;
- }
-
- /**
- * Populates the database map of values with the appropriate RRULE, RDATE,
- * EXRULE, and EXDATE values extracted from the parsed iCalendar component.
- * @param component The iCalendar component containing the desired
- * recurrence specification.
- * @param values The db values that should be updated.
- * @return true if the component contained the necessary information
- * to specify a recurrence. The required fields are DTSTART,
- * one of DTEND/DURATION, and one of RRULE/RDATE. Returns false if
- * there was an error, including if the date is out of range.
- */
- public static boolean populateContentValues(ICalendar.Component component,
- ContentValues values) {
- ICalendar.Property dtstartProperty =
- component.getFirstProperty("DTSTART");
- String dtstart = dtstartProperty.getValue();
- ICalendar.Parameter tzidParam =
- dtstartProperty.getFirstParameter("TZID");
- // NOTE: the timezone may be null, if this is a floating time.
- String tzid = tzidParam == null ? null : tzidParam.value;
- Time start = new Time(tzidParam == null ? Time.TIMEZONE_UTC : tzid);
- boolean inUtc = start.parse(dtstart);
- boolean allDay = start.allDay;
-
- // We force TimeZone to UTC for "all day recurring events" as the server is sending no
- // TimeZone in DTSTART for them
- if (inUtc || allDay) {
- tzid = Time.TIMEZONE_UTC;
- }
-
- String duration = computeDuration(start, component);
- String rrule = flattenProperties(component, "RRULE");
- String rdate = extractDates(component.getFirstProperty("RDATE"));
- String exrule = flattenProperties(component, "EXRULE");
- String exdate = extractDates(component.getFirstProperty("EXDATE"));
-
- if ((TextUtils.isEmpty(dtstart))||
- (TextUtils.isEmpty(duration))||
- ((TextUtils.isEmpty(rrule))&&
- (TextUtils.isEmpty(rdate)))) {
- if (false) {
- Log.d(TAG, "Recurrence missing DTSTART, DTEND/DURATION, "
- + "or RRULE/RDATE: "
- + component.toString());
- }
- return false;
- }
-
- if (allDay) {
- start.timezone = Time.TIMEZONE_UTC;
- }
- long millis = start.toMillis(false /* use isDst */);
- values.put(CalendarContract.Events.DTSTART, millis);
- if (millis == -1) {
- if (false) {
- Log.d(TAG, "DTSTART is out of range: " + component.toString());
- }
- return false;
- }
-
- 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;
- }
-
- // This can be removed when the old CalendarSyncAdapter is removed.
- public static boolean populateComponent(Cursor cursor,
- ICalendar.Component component) {
-
- 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;
- if (!cursor.isNull(dtstartColumn)) {
- dtstart = cursor.getLong(dtstartColumn);
- }
- String duration = cursor.getString(durationColumn);
- String tzid = cursor.getString(tzidColumn);
- String rruleStr = cursor.getString(rruleColumn);
- String rdateStr = cursor.getString(rdateColumn);
- String exruleStr = cursor.getString(exruleColumn);
- String exdateStr = cursor.getString(exdateColumn);
- boolean allDay = cursor.getInt(allDayColumn) == 1;
-
- if ((dtstart == -1) ||
- (TextUtils.isEmpty(duration))||
- ((TextUtils.isEmpty(rruleStr))&&
- (TextUtils.isEmpty(rdateStr)))) {
- // no recurrence.
- return false;
- }
-
- ICalendar.Property dtstartProp = new ICalendar.Property("DTSTART");
- Time dtstartTime = null;
- if (!TextUtils.isEmpty(tzid)) {
- if (!allDay) {
- dtstartProp.addParameter(new ICalendar.Parameter("TZID", tzid));
- }
- dtstartTime = new Time(tzid);
- } else {
- // use the "floating" timezone
- dtstartTime = new Time(Time.TIMEZONE_UTC);
- }
-
- dtstartTime.set(dtstart);
- // make sure the time is printed just as a date, if all day.
- // TODO: android.pim.Time really should take care of this for us.
- if (allDay) {
- dtstartProp.addParameter(new ICalendar.Parameter("VALUE", "DATE"));
- dtstartTime.allDay = true;
- dtstartTime.hour = 0;
- dtstartTime.minute = 0;
- dtstartTime.second = 0;
- }
-
- dtstartProp.setValue(dtstartTime.format2445());
- component.addProperty(dtstartProp);
- ICalendar.Property durationProp = new ICalendar.Property("DURATION");
- durationProp.setValue(duration);
- component.addProperty(durationProp);
-
- addPropertiesForRuleStr(component, "RRULE", rruleStr);
- addPropertyForDateStr(component, "RDATE", rdateStr);
- addPropertiesForRuleStr(component, "EXRULE", exruleStr);
- addPropertyForDateStr(component, "EXDATE", exdateStr);
- return true;
- }
-
-public static boolean populateComponent(ContentValues values,
- ICalendar.Component component) {
- long dtstart = -1;
- if (values.containsKey(CalendarContract.Events.DTSTART)) {
- dtstart = values.getAsLong(CalendarContract.Events.DTSTART);
- }
- 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) ||
- (TextUtils.isEmpty(duration))||
- ((TextUtils.isEmpty(rruleStr))&&
- (TextUtils.isEmpty(rdateStr)))) {
- // no recurrence.
- return false;
- }
-
- ICalendar.Property dtstartProp = new ICalendar.Property("DTSTART");
- Time dtstartTime = null;
- if (!TextUtils.isEmpty(tzid)) {
- if (!allDay) {
- dtstartProp.addParameter(new ICalendar.Parameter("TZID", tzid));
- }
- dtstartTime = new Time(tzid);
- } else {
- // use the "floating" timezone
- dtstartTime = new Time(Time.TIMEZONE_UTC);
- }
-
- dtstartTime.set(dtstart);
- // make sure the time is printed just as a date, if all day.
- // TODO: android.pim.Time really should take care of this for us.
- if (allDay) {
- dtstartProp.addParameter(new ICalendar.Parameter("VALUE", "DATE"));
- dtstartTime.allDay = true;
- dtstartTime.hour = 0;
- dtstartTime.minute = 0;
- dtstartTime.second = 0;
- }
-
- dtstartProp.setValue(dtstartTime.format2445());
- component.addProperty(dtstartProp);
- ICalendar.Property durationProp = new ICalendar.Property("DURATION");
- durationProp.setValue(duration);
- component.addProperty(durationProp);
-
- addPropertiesForRuleStr(component, "RRULE", rruleStr);
- addPropertyForDateStr(component, "RDATE", rdateStr);
- addPropertiesForRuleStr(component, "EXRULE", exruleStr);
- addPropertyForDateStr(component, "EXDATE", exdateStr);
- return true;
- }
-
- private static void addPropertiesForRuleStr(ICalendar.Component component,
- String propertyName,
- String ruleStr) {
- if (TextUtils.isEmpty(ruleStr)) {
- return;
- }
- String[] rrules = getRuleStrings(ruleStr);
- for (String rrule : rrules) {
- ICalendar.Property prop = new ICalendar.Property(propertyName);
- prop.setValue(rrule);
- component.addProperty(prop);
- }
- }
-
- private static String[] getRuleStrings(String ruleStr) {
- if (null == ruleStr) {
- return new String[0];
- }
- String unfoldedRuleStr = unfold(ruleStr);
- String[] split = unfoldedRuleStr.split(RULE_SEPARATOR);
- int count = split.length;
- for (int n = 0; n < count; n++) {
- split[n] = fold(split[n]);
- }
- return split;
- }
-
-
- private static final Pattern IGNORABLE_ICAL_WHITESPACE_RE =
- Pattern.compile("(?:\\r\\n?|\\n)[ \t]");
-
- private static final Pattern FOLD_RE = Pattern.compile(".{75}");
-
- /**
- * fold and unfolds ical content lines as per RFC 2445 section 4.1.
- *
- * <h3>4.1 Content Lines</h3>
- *
- * <p>The iCalendar object is organized into individual lines of text, called
- * content lines. Content lines are delimited by a line break, which is a CRLF
- * sequence (US-ASCII decimal 13, followed by US-ASCII decimal 10).
- *
- * <p>Lines of text SHOULD NOT be longer than 75 octets, excluding the line
- * break. Long content lines SHOULD be split into a multiple line
- * representations using a line "folding" technique. That is, a long line can
- * be split between any two characters by inserting a CRLF immediately
- * followed by a single linear white space character (i.e., SPACE, US-ASCII
- * decimal 32 or HTAB, US-ASCII decimal 9). Any sequence of CRLF followed
- * immediately by a single linear white space character is ignored (i.e.,
- * removed) when processing the content type.
- */
- public static String fold(String unfoldedIcalContent) {
- return FOLD_RE.matcher(unfoldedIcalContent).replaceAll("$0\r\n ");
- }
-
- public static String unfold(String foldedIcalContent) {
- return IGNORABLE_ICAL_WHITESPACE_RE.matcher(
- foldedIcalContent).replaceAll("");
- }
-
- private static void addPropertyForDateStr(ICalendar.Component component,
- String propertyName,
- String dateStr) {
- if (TextUtils.isEmpty(dateStr)) {
- return;
- }
-
- ICalendar.Property prop = new ICalendar.Property(propertyName);
- String tz = null;
- int tzidx = dateStr.indexOf(";");
- if (tzidx != -1) {
- tz = dateStr.substring(0, tzidx);
- dateStr = dateStr.substring(tzidx + 1);
- }
- if (!TextUtils.isEmpty(tz)) {
- prop.addParameter(new ICalendar.Parameter("TZID", tz));
- }
- prop.setValue(dateStr);
- component.addProperty(prop);
- }
-
- private static String computeDuration(Time start,
- ICalendar.Component component) {
- // see if a duration is defined
- ICalendar.Property durationProperty =
- component.getFirstProperty("DURATION");
- if (durationProperty != null) {
- // just return the duration
- return durationProperty.getValue();
- }
-
- // must compute a duration from the DTEND
- ICalendar.Property dtendProperty =
- component.getFirstProperty("DTEND");
- if (dtendProperty == null) {
- // no DURATION, no DTEND: 0 second duration
- return "+P0S";
- }
- ICalendar.Parameter endTzidParameter =
- dtendProperty.getFirstParameter("TZID");
- String endTzid = (endTzidParameter == null)
- ? start.timezone : endTzidParameter.value;
-
- Time end = new Time(endTzid);
- end.parse(dtendProperty.getValue());
- long durationMillis = end.toMillis(false /* use isDst */)
- - start.toMillis(false /* use isDst */);
- long durationSeconds = (durationMillis / 1000);
- if (start.allDay && (durationSeconds % 86400) == 0) {
- return "P" + (durationSeconds / 86400) + "D"; // Server wants this instead of P86400S
- } else {
- return "P" + durationSeconds + "S";
- }
- }
-
- private static String flattenProperties(ICalendar.Component component,
- String name) {
- List<ICalendar.Property> properties = component.getProperties(name);
- if (properties == null || properties.isEmpty()) {
- return null;
- }
-
- if (properties.size() == 1) {
- return properties.get(0).getValue();
- }
-
- StringBuilder sb = new StringBuilder();
-
- boolean first = true;
- for (ICalendar.Property property : component.getProperties(name)) {
- if (first) {
- first = false;
- } else {
- // TODO: use commas. our RECUR parsing should handle that
- // anyway.
- sb.append(RULE_SEPARATOR);
- }
- sb.append(property.getValue());
- }
- return sb.toString();
- }
-
- private static String extractDates(ICalendar.Property recurrence) {
- if (recurrence == null) {
- return null;
- }
- ICalendar.Parameter tzidParam =
- recurrence.getFirstParameter("TZID");
- if (tzidParam != null) {
- return tzidParam.value + ";" + recurrence.getValue();
- }
- return recurrence.getValue();
- }
-}
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index b492615..5b29103 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -17,6 +17,8 @@
package android.provider;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ContentProviderClient;
@@ -83,7 +85,6 @@ import android.util.Log;
* adapters</li>
* </ul>
*
- * @hide
*/
public final class CalendarContract {
private static final String TAG = "Calendar";
@@ -92,8 +93,8 @@ public final class CalendarContract {
* Broadcast Action: This is the intent that gets fired when an alarm
* notification needs to be posted for a reminder.
*
- * @SdkConstant
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
/**
@@ -146,6 +147,11 @@ public final class CalendarContract {
public static final String ACCOUNT_TYPE_LOCAL = "LOCAL";
/**
+ * This utility class cannot be instantiated
+ */
+ private CalendarContract() {}
+
+ /**
* Generic columns for use by sync adapters. The specific functions of these
* columns are private to the sync adapter. Other clients of the API should
* not attempt to either read or write this column. These columns are
@@ -384,7 +390,7 @@ public final class CalendarContract {
* Class that represents a Calendar Entity. There is one entry per calendar.
* This is a helper class to make batch operations easier.
*/
- public static class CalendarEntity implements BaseColumns, SyncColumns, CalendarColumns {
+ public static final class CalendarEntity implements BaseColumns, SyncColumns, CalendarColumns {
/**
* The default Uri used when creating a new calendar EntityIterator.
@@ -394,6 +400,11 @@ public final class CalendarContract {
"/calendar_entities");
/**
+ * This utility class cannot be instantiated
+ */
+ private CalendarEntity() {}
+
+ /**
* Creates an entity iterator for the given cursor. It assumes the
* cursor contains a calendars query.
*
@@ -566,7 +577,13 @@ public final class CalendarContract {
* <li>{@link #CAL_SYNC10}</li>
* </ul>
*/
- public static class Calendars implements BaseColumns, SyncColumns, CalendarColumns {
+ public static final class Calendars implements BaseColumns, SyncColumns, CalendarColumns {
+
+ /**
+ * This utility class cannot be instantiated
+ */
+ private Calendars() {}
+
/**
* The content:// style URL for accessing Calendars
*/
@@ -687,7 +704,7 @@ public final class CalendarContract {
/**
* Fields and helpers for interacting with Attendees. Each row of this table
* represents a single attendee or guest of an event. Calling
- * {@link #query(ContentResolver, long)} will return a list of attendees for
+ * {@link #query(ContentResolver, long, String[])} will return a list of attendees for
* the event with the given eventId. Both apps and sync adapters may write
* to this table. There are six writable fields and all of them except
* {@link #ATTENDEE_NAME} must be included when inserting a new attendee.
@@ -708,12 +725,12 @@ public final class CalendarContract {
*/
@SuppressWarnings("hiding")
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/attendees");
+ private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=?";
+
/**
- * the projection used by the attendees query
+ * This utility class cannot be instantiated
*/
- public static final String[] PROJECTION = new String[] {
- _ID, ATTENDEE_NAME, ATTENDEE_EMAIL, ATTENDEE_RELATIONSHIP, ATTENDEE_STATUS,};
- private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=?";
+ private Attendees() {}
/**
* Queries all attendees associated with the given event. This is a
@@ -721,11 +738,12 @@ public final class CalendarContract {
*
* @param cr The content resolver to use for the query
* @param eventId The id of the event to retrieve attendees for
+ * @param projection the columns to return in the cursor
* @return A Cursor containing all attendees for the event
*/
- public static final Cursor query(ContentResolver cr, long eventId) {
+ public static final Cursor query(ContentResolver cr, long eventId, String[] projection) {
String[] attArgs = {Long.toString(eventId)};
- return cr.query(CONTENT_URI, PROJECTION, ATTENDEES_WHERE, attArgs /* selection args */,
+ return cr.query(CONTENT_URI, projection, ATTENDEES_WHERE, attArgs /* selection args */,
null /* sort order */);
}
}
@@ -1068,6 +1086,11 @@ public final class CalendarContract {
"/event_entities");
/**
+ * This utility class cannot be instantiated
+ */
+ private EventsEntity() {}
+
+ /**
* Creates a new iterator for events
*
* @param cursor An event query
@@ -1411,6 +1434,11 @@ public final class CalendarContract {
Uri.parse("content://" + AUTHORITY + "/exception");
/**
+ * This utility class cannot be instantiated
+ */
+ private Events() {}
+
+ /**
* The default sort order for this table
*/
private static final String DEFAULT_SORT_ORDER = "";
@@ -1484,6 +1512,11 @@ public final class CalendarContract {
};
/**
+ * This utility class cannot be instantiated
+ */
+ private Instances() {}
+
+ /**
* Performs a query to return all visible instances in the given range.
* This is a blocking function and should not be done on the UI thread.
* This will cause an expansion of recurring events to fill this time
@@ -1636,7 +1669,7 @@ public final class CalendarContract {
* time zone for the instances. These settings are stored using a key/value
* scheme. A {@link #KEY} must be specified when updating these values.
*/
- public static class CalendarCache implements CalendarCacheColumns {
+ public static final class CalendarCache implements CalendarCacheColumns {
/**
* The URI to use for retrieving the properties from the Calendar db.
*/
@@ -1644,6 +1677,11 @@ public final class CalendarContract {
Uri.parse("content://" + AUTHORITY + "/properties");
/**
+ * This utility class cannot be instantiated
+ */
+ private CalendarCache() {}
+
+ /**
* They key for updating the use of auto/home time zones in Calendar.
* Valid values are {@link #TIMEZONE_TYPE_AUTO} or
* {@link #TIMEZONE_TYPE_HOME}.
@@ -1724,6 +1762,11 @@ public final class CalendarContract {
* @hide
*/
public static final class CalendarMetaData implements CalendarMetaDataColumns, BaseColumns {
+
+ /**
+ * This utility class cannot be instantiated
+ */
+ private CalendarMetaData() {}
}
protected interface EventDaysColumns {
@@ -1746,14 +1789,12 @@ public final class CalendarContract {
public static final class EventDays implements EventDaysColumns {
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ "/instances/groupbyday");
+ private static final String SELECTION = "selected=1";
/**
- * The projection used by the EventDays query.
+ * This utility class cannot be instantiated
*/
- public static final String[] PROJECTION = {
- STARTDAY, ENDDAY
- };
- private static final String SELECTION = "selected=1";
+ private EventDays() {}
/**
* Retrieves the days with events for the Julian days starting at
@@ -1765,10 +1806,12 @@ public final class CalendarContract {
* @param cr the ContentResolver
* @param startDay the first Julian day in the range
* @param numDays the number of days to load (must be at least 1)
+ * @param projection the columns to return in the cursor
* @return a database cursor containing a list of start and end days for
* events
*/
- public static final Cursor query(ContentResolver cr, int startDay, int numDays) {
+ public static final Cursor query(ContentResolver cr, int startDay, int numDays,
+ String[] projection) {
if (numDays < 1) {
return null;
}
@@ -1776,7 +1819,7 @@ public final class CalendarContract {
Uri.Builder builder = CONTENT_URI.buildUpon();
ContentUris.appendId(builder, startDay);
ContentUris.appendId(builder, endDay);
- return cr.query(builder.build(), PROJECTION, SELECTION,
+ return cr.query(builder.build(), projection, SELECTION,
null /* selection args */, STARTDAY);
}
}
@@ -1821,7 +1864,7 @@ public final class CalendarContract {
/**
* Fields and helpers for accessing reminders for an event. Each row of this
* table represents a single reminder for an event. Calling
- * {@link #query(ContentResolver, long)} will return a list of reminders for
+ * {@link #query(ContentResolver, long, String[])} will return a list of reminders for
* the event with the given eventId. Both apps and sync adapters may write
* to this table. There are three writable fields and all of them must be
* included when inserting a new reminder. They are:
@@ -1833,25 +1876,26 @@ public final class CalendarContract {
*/
public static final class Reminders implements BaseColumns, RemindersColumns, EventsColumns {
private static final String REMINDERS_WHERE = CalendarContract.Reminders.EVENT_ID + "=?";
- /**
- * The projection used by the reminders query.
- */
- public static final String[] PROJECTION = new String[] {
- _ID, MINUTES, METHOD,};
@SuppressWarnings("hiding")
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/reminders");
/**
+ * This utility class cannot be instantiated
+ */
+ private Reminders() {}
+
+ /**
* Queries all reminders associated with the given event. This is a
* blocking call and should not be done on the UI thread.
*
* @param cr The content resolver to use for the query
* @param eventId The id of the event to retrieve reminders for
+ * @param projection the columns to return in the cursor
* @return A Cursor containing all reminders for the event
*/
- public static final Cursor query(ContentResolver cr, long eventId) {
+ public static final Cursor query(ContentResolver cr, long eventId, String[] projection) {
String[] remArgs = {Long.toString(eventId)};
- return cr.query(CONTENT_URI, PROJECTION, REMINDERS_WHERE, remArgs /* selection args */,
+ return cr.query(CONTENT_URI, projection, REMINDERS_WHERE, remArgs /*selection args*/,
null /* sort order */);
}
}
@@ -1964,6 +2008,11 @@ public final class CalendarContract {
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY +
"/calendar_alerts");
+ /**
+ * This utility class cannot be instantiated
+ */
+ private CalendarAlerts() {}
+
private static final String WHERE_ALARM_EXISTS = EVENT_ID + "=?"
+ " AND " + BEGIN + "=?"
+ " AND " + ALARM_TIME + "=?";
@@ -2134,7 +2183,7 @@ public final class CalendarContract {
* given event id, begin time and alarm time. If one is found then this
* alarm already exists and this method returns true. TODO Move to
* provider
- *
+ *
* @param cr the ContentResolver
* @param eventId the event id to match
* @param begin the start time of the event in UTC millis
@@ -2203,6 +2252,11 @@ public final class CalendarContract {
public static final Uri CONTENT_URI =
Uri.parse("content://" + AUTHORITY + "/extendedproperties");
+ /**
+ * This utility class cannot be instantiated
+ */
+ private ExtendedProperties() {}
+
// TODO: fill out this class when we actually start utilizing extendedproperties
// in the calendar application.
}
@@ -2271,5 +2325,10 @@ public final class CalendarContract {
* @hide
*/
public static final class EventsRawTimes implements BaseColumns, EventsRawTimesColumns {
+
+ /**
+ * This utility class cannot be instantiated
+ */
+ private EventsRawTimes() {}
}
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 61deea4..0dd9a4d 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -17,6 +17,7 @@
package android.provider;
import android.accounts.Account;
+import android.app.Activity;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
@@ -135,14 +136,6 @@ public final class ContactsContract {
public static final String ALLOW_PROFILE = "allow_profile";
/**
- * A query parameter key used to specify the package that is requesting a query.
- * This is used for restricting data based on package name.
- *
- * @hide
- */
- public static final String REQUESTING_PACKAGE_PARAM_KEY = "requesting_package";
-
- /**
* Query parameter that should be used by the client to access a specific
* {@link Directory}. The parameter value should be the _ID of the corresponding
* directory, e.g.
@@ -271,8 +264,6 @@ public final class ContactsContract {
* <li>The URI authority is replaced with the corresponding {@link #DIRECTORY_AUTHORITY}.</li>
* <li>The {@code accountName=} and {@code accountType=} parameters are added or
* replaced using the corresponding {@link #ACCOUNT_TYPE} and {@link #ACCOUNT_NAME} values.</li>
- * <li>If the URI is missing a ContactsContract.REQUESTING_PACKAGE_PARAM_KEY
- * parameter, this parameter is added.</li>
* </ul>
* </p>
* <p>
@@ -759,11 +750,25 @@ public final class ContactsContract {
public static final String PHOTO_ID = "photo_id";
/**
+ * Photo file ID of the full-size photo. If present, this will be used to populate
+ * {@link #PHOTO_URI}. The ID can also be used with
+ * {@link ContactsContract.DisplayPhoto#CONTENT_URI} to create a URI to the photo.
+ * If this is present, {@link #PHOTO_ID} is also guaranteed to be populated.
+ *
+ * <P>Type: INTEGER</P>
+ */
+ public static final String PHOTO_FILE_ID = "photo_file_id";
+
+ /**
* A URI that can be used to retrieve the contact's full-size photo.
+ * If PHOTO_FILE_ID is not null, this will be populated with a URI based off
+ * {@link ContactsContract.DisplayPhoto#CONTENT_URI}. Otherwise, this will
+ * be populated with the same value as {@link #PHOTO_THUMBNAIL_URI}.
* A photo can be referred to either by a URI (this field) or by ID
- * (see {@link #PHOTO_ID}). If PHOTO_ID is not null, PHOTO_URI and
- * PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa).
- * Thus using PHOTO_URI is a more robust method of retrieving contact photos.
+ * (see {@link #PHOTO_ID}). If either PHOTO_FILE_ID or PHOTO_ID is not null,
+ * PHOTO_URI and PHOTO_THUMBNAIL_URI shall not be null (but not necessarily
+ * vice versa). Thus using PHOTO_URI is a more robust method of retrieving
+ * contact photos.
*
* <P>Type: TEXT</P>
*/
@@ -776,7 +781,7 @@ public final class ContactsContract {
* PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa).
* If the content provider does not differentiate between full-size photos
* and thumbnail photos, PHOTO_THUMBNAIL_URI and {@link #PHOTO_URI} can contain
- * the same value, but either both shell be null or both not null.
+ * the same value, but either both shall be null or both not null.
*
* <P>Type: TEXT</P>
*/
@@ -1700,10 +1705,15 @@ public final class ContactsContract {
/**
* A <i>read-only</i> sub-directory of a single contact that contains
- * the contact's primary photo.
+ * the contact's primary photo. The photo may be stored in up to two ways -
+ * the default "photo" is a thumbnail-sized image stored directly in the data
+ * row, while the "display photo", if present, is a larger version stored as
+ * a file.
* <p>
* Usage example:
- *
+ * <dl>
+ * <dt>Retrieving the thumbnail-sized photo</dt>
+ * <dd>
* <pre>
* public InputStream openPhoto(long contactId) {
* Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
@@ -1726,10 +1736,29 @@ public final class ContactsContract {
* return null;
* }
* </pre>
+ * </dd>
+ * <dt>Retrieving the larger photo version</dt>
+ * <dd>
+ * <pre>
+ * public InputStream openDisplayPhoto(long contactId) {
+ * Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
+ * Uri displayPhotoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.DISPLAY_PHOTO);
+ * try {
+ * AssetFileDescriptor fd =
+ * getContentResolver().openAssetFile(displayPhotoUri, "r");
+ * return fd.createInputStream();
+ * } catch (FileNotFoundException e) {
+ * return null;
+ * }
+ * }
+ * </pre>
+ * </dd>
+ * </dl>
*
* </p>
- * <p>You should also consider using the convenience method
+ * <p>You may also consider using the convenience method
* {@link ContactsContract.Contacts#openContactPhotoInputStream(ContentResolver, Uri)}
+ * to retrieve the raw photo contents of the thumbnail-sized photo.
* </p>
* <p>
* This directory can be used either with a {@link #CONTENT_URI} or
@@ -1748,6 +1777,19 @@ public final class ContactsContract {
public static final String CONTENT_DIRECTORY = "photo";
/**
+ * The directory twig for retrieving the full-size display photo.
+ */
+ public static final String DISPLAY_PHOTO = "display_photo";
+
+ /**
+ * Full-size photo file ID of the raw contact.
+ * See {@link ContactsContract.DisplayPhoto}.
+ * <p>
+ * Type: NUMBER
+ */
+ public static final String PHOTO_FILE_ID = DATA14;
+
+ /**
* Thumbnail photo of the raw contact. This is the raw bytes of an image
* that could be inflated using {@link android.graphics.BitmapFactory}.
* <p>
@@ -1881,13 +1923,16 @@ public final class ContactsContract {
public static final String CONTACT_ID = "contact_id";
/**
- * Flag indicating that this {@link RawContacts} entry and its children have
- * been restricted to specific platform apps.
- * <P>Type: INTEGER (boolean)</P>
+ * The data set within the account that this row belongs to. This allows
+ * multiple sync adapters for the same account type to distinguish between
+ * each others' data.
*
- * @hide until finalized in future platform release
+ * This is empty by default, and is completely optional. It only needs to
+ * be populated if multiple sync adapters are entering distinct data for
+ * the same account type and account name.
+ * <P>Type: TEXT</P>
*/
- public static final String IS_RESTRICTED = "is_restricted";
+ public static final String DATA_SET = "data_set";
/**
* The aggregation mode for this contact.
@@ -2211,8 +2256,8 @@ public final class ContactsContract {
* <td>The name of the account instance to which this row belongs, which when paired with
* {@link #ACCOUNT_TYPE} identifies a specific account.
* For example, this will be the Gmail address if it is a Google account.
- * It should be set at the time
- * the raw contact is inserted and never changed afterwards.</td>
+ * It should be set at the time the raw contact is inserted and never
+ * changed afterwards.</td>
* </tr>
* <tr>
* <td>String</td>
@@ -2222,8 +2267,8 @@ public final class ContactsContract {
* <p>
* The type of account to which this row belongs, which when paired with
* {@link #ACCOUNT_NAME} identifies a specific account.
- * It should be set at the time
- * the raw contact is inserted and never changed afterwards.
+ * It should be set at the time the raw contact is inserted and never
+ * changed afterwards.
* </p>
* <p>
* To ensure uniqueness, new account types should be chosen according to the
@@ -2233,15 +2278,38 @@ public final class ContactsContract {
* </tr>
* <tr>
* <td>String</td>
+ * <td>{@link #DATA_SET}</td>
+ * <td>read/write-once</td>
+ * <td>
+ * <p>
+ * The data set within the account that this row belongs to. This allows
+ * multiple sync adapters for the same account type to distinguish between
+ * each others' data. The combination of {@link #ACCOUNT_TYPE},
+ * {@link #ACCOUNT_NAME}, and {@link #DATA_SET} identifies a set of data
+ * that is associated with a single sync adapter.
+ * </p>
+ * <p>
+ * This is empty by default, and is completely optional. It only needs to
+ * be populated if multiple sync adapters are entering distinct data for
+ * the same account type and account name.
+ * </p>
+ * <p>
+ * It should be set at the time the raw contact is inserted and never
+ * changed afterwards.
+ * </p>
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>String</td>
* <td>{@link #SOURCE_ID}</td>
* <td>read/write</td>
* <td>String that uniquely identifies this row to its source account.
* Typically it is set at the time the raw contact is inserted and never
* changed afterwards. The one notable exception is a new raw contact: it
- * will have an account name and type, but no source id. This
- * indicates to the sync adapter that a new contact needs to be created
- * server-side and its ID stored in the corresponding SOURCE_ID field on
- * the phone.
+ * will have an account name and type (and possibly a data set), but no
+ * source id. This indicates to the sync adapter that a new contact needs
+ * to be created server-side and its ID stored in the corresponding
+ * SOURCE_ID field on the phone.
* </td>
* </tr>
* <tr>
@@ -2482,6 +2550,56 @@ public final class ContactsContract {
}
/**
+ * <p>
+ * A sub-directory of a single raw contact that represents its primary
+ * display photo. To access this directory append
+ * {@link RawContacts.DisplayPhoto#CONTENT_DIRECTORY} to the raw contact URI.
+ * The resulting URI represents an image file, and should be interacted with
+ * using ContentProvider.openAssetFile.
+ * <p>
+ * <p>
+ * Note that this sub-directory also supports opening the photo as an asset file
+ * in write mode. Callers can create or replace the primary photo associated
+ * with this raw contact by opening the asset file and writing the full-size
+ * photo contents into it. When the file is closed, the image will be parsed,
+ * sized down if necessary for the full-size display photo and thumbnail
+ * dimensions, and stored.
+ * </p>
+ * <p>
+ * Usage example:
+ * <pre>
+ * public void writeDisplayPhoto(long rawContactId, byte[] photo) {
+ * Uri rawContactPhotoUri = Uri.withAppendedPath(
+ * ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
+ * RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
+ * try {
+ * AssetFileDescriptor fd =
+ * getContentResolver().openAssetFile(rawContactPhotoUri, "rw");
+ * OutputStream os = fd.createOutputStream();
+ * os.write(photo);
+ * os.close();
+ * fd.close();
+ * } catch (IOException e) {
+ * // Handle error cases.
+ * }
+ * }
+ * </pre>
+ * </p>
+ */
+ public static final class DisplayPhoto {
+ /**
+ * No public constructor since this is a utility class
+ */
+ private DisplayPhoto() {
+ }
+
+ /**
+ * The directory twig for this sub-table
+ */
+ public static final String CONTENT_DIRECTORY = "display_photo";
+ }
+
+ /**
* TODO: javadoc
* @param cursor
* @return
@@ -2537,7 +2655,6 @@ public final class ContactsContract {
DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DELETED);
DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, CONTACT_ID);
DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, STARRED);
- DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, IS_RESTRICTED);
DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, NAME_VERIFIED);
android.content.Entity contact = new android.content.Entity(cv);
@@ -3177,6 +3294,50 @@ public final class ContactsContract {
}
/**
+ * <p>
+ * Constants for the photo files table, which tracks metadata for hi-res photos
+ * stored in the file system.
+ * </p>
+ *
+ * @hide
+ */
+ public static final class PhotoFiles implements BaseColumns, PhotoFilesColumns {
+ /**
+ * No public constructor since this is a utility class
+ */
+ private PhotoFiles() {
+ }
+ }
+
+ /**
+ * Columns in the PhotoFiles table.
+ *
+ * @see ContactsContract.PhotoFiles
+ *
+ * @hide
+ */
+ protected interface PhotoFilesColumns {
+
+ /**
+ * The height, in pixels, of the photo this entry is associated with.
+ * <P>Type: NUMBER</P>
+ */
+ public static final String HEIGHT = "height";
+
+ /**
+ * The width, in pixels, of the photo this entry is associated with.
+ * <P>Type: NUMBER</P>
+ */
+ public static final String WIDTH = "width";
+
+ /**
+ * The size, in bytes, of the photo stored on disk.
+ * <P>Type: NUMBER</P>
+ */
+ public static final String FILESIZE = "filesize";
+ }
+
+ /**
* Columns in the Data table.
*
* @see ContactsContract.Data
@@ -3814,27 +3975,6 @@ public final class ContactsContract {
/**
* <p>
- * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward
- * Data.CONTENT_URI contains only exportable data.
- * </p>
- * <p>
- * This flag is useful (currently) only for vCard exporter in Contacts app, which
- * needs to exclude "un-exportable" data from available data to export, while
- * Contacts app itself has priviledge to access all data including "un-exportable"
- * ones and providers return all of them regardless of the callers' intention.
- * </p>
- * <p>
- * Type: INTEGER
- * </p>
- *
- * @hide Maybe available only in Eclair and not really ready for public use.
- * TODO: remove, or implement this feature completely. As of now (Eclair),
- * we only use this flag in queryEntities(), not query().
- */
- public static final String FOR_EXPORT_ONLY = "for_export_only";
-
- /**
- * <p>
* Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}
* style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts}
* entry of the given {@link ContactsContract.Data} entry.
@@ -5897,7 +6037,7 @@ public final class ContactsContract {
/**
* <p>
- * A data kind representing an photo for the contact.
+ * A data kind representing a photo for the contact.
* </p>
* <p>
* Some sync adapters will choose to download photos in a separate
@@ -5917,10 +6057,17 @@ public final class ContactsContract {
* <th>Alias</th><th colspan='2'>Data column</th>
* </tr>
* <tr>
+ * <td>NUMBER</td>
+ * <td>{@link #PHOTO_FILE_ID}</td>
+ * <td>{@link #DATA14}</td>
+ * <td>ID of the hi-res photo file.</td>
+ * </tr>
+ * <tr>
* <td>BLOB</td>
* <td>{@link #PHOTO}</td>
* <td>{@link #DATA15}</td>
- * <td>By convention, binary data is stored in DATA15.</td>
+ * <td>By convention, binary data is stored in DATA15. The thumbnail of the
+ * photo is stored in this column.</td>
* </tr>
* </table>
*/
@@ -5934,6 +6081,14 @@ public final class ContactsContract {
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
/**
+ * Photo file ID for the display photo of the raw contact.
+ * See {@link ContactsContract.DisplayPhoto}.
+ * <p>
+ * Type: NUMBER
+ */
+ public static final String PHOTO_FILE_ID = DATA14;
+
+ /**
* Thumbnail photo of the raw contact. This is the raw bytes of an image
* that could be inflated using {@link android.graphics.BitmapFactory}.
* <p>
@@ -6213,6 +6368,18 @@ public final class ContactsContract {
*/
protected interface GroupsColumns {
/**
+ * The data set within the account that this group belongs to. This allows
+ * multiple sync adapters for the same account type to distinguish between
+ * each others' group data.
+ *
+ * This is empty by default, and is completely optional. It only needs to
+ * be populated if multiple sync adapters are entering distinct group data
+ * for the same account type and account name.
+ * <P>Type: TEXT</P>
+ */
+ public static final String DATA_SET = "data_set";
+
+ /**
* The display title of this group.
* <p>
* Type: TEXT
@@ -6245,6 +6412,28 @@ public final class ContactsContract {
public static final String NOTES = "notes";
/**
+ * The Activity action to open the group in the source app (e.g.
+ * {@link Intent#ACTION_VIEW}). Can be NULL if the group does not have a dedicated viewer.
+ * This is used in conjunction with {@link #ACTION_URI}: In order to show an "Open in
+ * (sourceapp)"-button, both of these fields must be set
+ * <p>
+ * Type: TEXT
+ */
+ public static final String ACTION = "action";
+
+
+ /**
+ * Uri to open the group in the source app.
+ * Can be NULL if the group does not have a dedicated viewer.
+ * This is used in conjunction with {@link #ACTION}: In order to show an "Open in
+ * (sourceapp)"-button, both of these fields must be set
+ * <p>
+ * Type: TEXT
+ */
+ public static final String ACTION_URI = "action_uri";
+
+
+ /**
* The ID of this group if it is a System Group, i.e. a group that has a special meaning
* to the sync adapter, null otherwise.
* <P>Type: TEXT</P>
@@ -6338,6 +6527,29 @@ public final class ContactsContract {
* In other words, it would be a really bad idea to delete and reinsert a
* group. A sync adapter should always do an update instead.</td>
* </tr>
+ # <tr>
+ * <td>String</td>
+ * <td>{@link #DATA_SET}</td>
+ * <td>read/write-once</td>
+ * <td>
+ * <p>
+ * The data set within the account that this group belongs to. This allows
+ * multiple sync adapters for the same account type to distinguish between
+ * each others' group data. The combination of {@link #ACCOUNT_TYPE},
+ * {@link #ACCOUNT_NAME}, and {@link #DATA_SET} identifies a set of data
+ * that is associated with a single sync adapter.
+ * </p>
+ * <p>
+ * This is empty by default, and is completely optional. It only needs to
+ * be populated if multiple sync adapters are entering distinct data for
+ * the same account type and account name.
+ * </p>
+ * <p>
+ * It should be set at the time the group is inserted and never changed
+ * afterwards.
+ * </p>
+ * </td>
+ * </tr>
* <tr>
* <td>String</td>
* <td>{@link #TITLE}</td>
@@ -7018,6 +7230,66 @@ public final class ContactsContract {
}
/**
+ * Helper class for accessing full-size photos by photo file ID.
+ * <p>
+ * Usage example:
+ * <dl>
+ * <dt>Retrieving a full-size photo by photo file ID (see
+ * {@link ContactsContract.ContactsColumns#PHOTO_FILE_ID})
+ * </dt>
+ * <dd>
+ * <pre>
+ * public InputStream openDisplayPhoto(long photoFileId) {
+ * Uri displayPhotoUri = ContentUris.withAppendedId(DisplayPhoto.CONTENT_URI, photoKey);
+ * try {
+ * AssetFileDescriptor fd = getContentResolver().openAssetFile(displayPhotoUri, "r");
+ * return fd.createInputStream();
+ * } catch (FileNotFoundException e) {
+ * return null;
+ * }
+ * }
+ * </pre>
+ * </dd>
+ * </dl>
+ * </p>
+ */
+ public static final class DisplayPhoto {
+ /**
+ * no public constructor since this is a utility class
+ */
+ private DisplayPhoto() {}
+
+ /**
+ * The content:// style URI for this class, which allows access to full-size photos,
+ * given a key.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "display_photo");
+
+ /**
+ * This URI allows the caller to query for the maximum dimensions of a display photo
+ * or thumbnail. Requests to this URI can be performed on the UI thread because
+ * they are always unblocking.
+ */
+ public static final Uri CONTENT_MAX_DIMENSIONS_URI =
+ Uri.withAppendedPath(AUTHORITY_URI, "photo_dimensions");
+
+ /**
+ * Queries to {@link ContactsContract.DisplayPhoto#CONTENT_MAX_DIMENSIONS_URI} will
+ * contain this column, populated with the maximum height and width (in pixels)
+ * that will be stored for a display photo. Larger photos will be down-sized to
+ * fit within a square of this many pixels.
+ */
+ public static final String DISPLAY_MAX_DIM = "display_max_dim";
+
+ /**
+ * Queries to {@link ContactsContract.DisplayPhoto#CONTENT_MAX_DIMENSIONS_URI} will
+ * contain this column, populated with the height and width (in pixels) for photo
+ * thumbnails.
+ */
+ public static final String THUMBNAIL_MAX_DIM = "thumbnail_max_dim";
+ }
+
+ /**
* Contains helper classes used to create or manage {@link android.content.Intent Intents}
* that involve contacts.
*/
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 65babc2..23b53ae 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3833,6 +3833,11 @@ public final class Settings {
/** {@hide} */
public static final String NETSTATS_TAG_MAX_HISTORY = "netstats_tag_max_history";
+ /** Preferred NTP server. {@hide} */
+ public static final String NTP_SERVER = "ntp_server";
+ /** Timeout in milliseconds to wait for NTP server. {@hide} */
+ public static final String NTP_TIMEOUT = "ntp_timeout";
+
/**
* @hide
*/
diff --git a/core/java/android/server/BluetoothHealthProfileHandler.java b/core/java/android/server/BluetoothHealthProfileHandler.java
index 7f862e0..105ff33 100644
--- a/core/java/android/server/BluetoothHealthProfileHandler.java
+++ b/core/java/android/server/BluetoothHealthProfileHandler.java
@@ -20,15 +20,12 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHealth;
import android.bluetooth.BluetoothHealthAppConfiguration;
-import android.bluetooth.BluetoothHealth;
-import android.bluetooth.BluetoothInputDevice;
+import android.bluetooth.IBluetoothHealthCallback;
import android.content.Context;
-import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import android.provider.Settings;
import android.util.Log;
import java.util.ArrayList;
@@ -36,10 +33,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-
/**
* This handles all the operations on the Bluetooth Health profile.
* All functions are called by BluetoothService, as Bluetooth Service
@@ -58,6 +51,7 @@ final class BluetoothHealthProfileHandler {
private ArrayList<HealthChannel> mHealthChannels;
private HashMap <BluetoothHealthAppConfiguration, String> mHealthAppConfigs;
private HashMap <BluetoothDevice, Integer> mHealthDevices;
+ private HashMap <BluetoothHealthAppConfiguration, IBluetoothHealthCallback> mCallbacks;
private static final int MESSAGE_REGISTER_APPLICATION = 0;
private static final int MESSAGE_UNREGISTER_APPLICATION = 1;
@@ -103,6 +97,7 @@ final class BluetoothHealthProfileHandler {
}
if (path == null) {
+ mCallbacks.remove(registerApp);
callHealthApplicationStatusCallback(registerApp,
BluetoothHealth.APPLICATION_REGISTRATION_FAILURE);
} else {
@@ -118,6 +113,7 @@ final class BluetoothHealthProfileHandler {
boolean result = mBluetoothService.unregisterHealthApplicationNative(
mHealthAppConfigs.get(unregisterApp));
if (result) {
+ mCallbacks.remove(unregisterApp);
callHealthApplicationStatusCallback(unregisterApp,
BluetoothHealth.APPLICATION_UNREGISTRATION_SUCCESS);
} else {
@@ -149,6 +145,7 @@ final class BluetoothHealthProfileHandler {
mHealthAppConfigs = new HashMap<BluetoothHealthAppConfiguration, String>();
mHealthChannels = new ArrayList<HealthChannel>();
mHealthDevices = new HashMap<BluetoothDevice, Integer>();
+ mCallbacks = new HashMap<BluetoothHealthAppConfiguration, IBluetoothHealthCallback>();
}
static synchronized BluetoothHealthProfileHandler getInstance(Context context,
@@ -157,10 +154,12 @@ final class BluetoothHealthProfileHandler {
return sInstance;
}
- boolean registerAppConfiguration(BluetoothHealthAppConfiguration config) {
+ boolean registerAppConfiguration(BluetoothHealthAppConfiguration config,
+ IBluetoothHealthCallback callback) {
Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_APPLICATION);
msg.obj = config;
mHandler.sendMessage(msg);
+ mCallbacks.put(config, callback);
return true;
}
@@ -442,11 +441,11 @@ final class BluetoothHealthProfileHandler {
debugLog("Health Device Callback: " + device + " State Change: "
+ prevState + "->" + state);
- try {
- config.getCallback().onHealthChannelStateChange(config, device, prevState,
- state, fd);
- } catch (RemoteException e) {
- errorLog("Error while making health channel state change callback: " + e);
+ IBluetoothHealthCallback callback = mCallbacks.get(config);
+ if (callback != null) {
+ try {
+ callback.onHealthChannelStateChange(config, device, prevState, state, fd);
+ } catch (RemoteException e) {}
}
}
@@ -454,10 +453,11 @@ final class BluetoothHealthProfileHandler {
BluetoothHealthAppConfiguration config, int status) {
debugLog("Health Device Application: " + config + " State Change: status:"
+ status);
- try {
- config.getCallback().onHealthAppConfigurationStatusChange(config, status);
- } catch (RemoteException e) {
- errorLog("Error while making health app registration state change callback: " + e);
+ IBluetoothHealthCallback callback = mCallbacks.get(config);
+ if (callback != null) {
+ try {
+ callback.onHealthAppConfigurationStatusChange(config, status);
+ } catch (RemoteException e) {}
}
}
@@ -526,19 +526,19 @@ final class BluetoothHealthProfileHandler {
List<HealthChannel> chan;
switch (currDeviceState) {
case BluetoothHealth.STATE_DISCONNECTED:
- updateAndsendIntent(device, currDeviceState, newDeviceState);
+ updateAndSendIntent(device, currDeviceState, newDeviceState);
break;
case BluetoothHealth.STATE_CONNECTING:
// Channel got connected.
if (newDeviceState == BluetoothHealth.STATE_CONNECTED) {
- updateAndsendIntent(device, currDeviceState, newDeviceState);
+ updateAndSendIntent(device, currDeviceState, newDeviceState);
} else {
// Channel got disconnected
chan = findChannelByStates(device, new int [] {
BluetoothHealth.STATE_CHANNEL_CONNECTING,
BluetoothHealth.STATE_CHANNEL_DISCONNECTING});
if (chan.isEmpty()) {
- updateAndsendIntent(device, currDeviceState, newDeviceState);
+ updateAndSendIntent(device, currDeviceState, newDeviceState);
}
}
break;
@@ -548,22 +548,23 @@ final class BluetoothHealthProfileHandler {
BluetoothHealth.STATE_CHANNEL_CONNECTING,
BluetoothHealth.STATE_CHANNEL_CONNECTED});
if (chan.isEmpty()) {
- updateAndsendIntent(device, currDeviceState, newDeviceState);
+ updateAndSendIntent(device, currDeviceState, newDeviceState);
}
+ break;
case BluetoothHealth.STATE_DISCONNECTING:
// Channel got disconnected.
chan = findChannelByStates(device, new int [] {
BluetoothHealth.STATE_CHANNEL_CONNECTING,
BluetoothHealth.STATE_CHANNEL_DISCONNECTING});
if (chan.isEmpty()) {
- updateAndsendIntent(device, currDeviceState, newDeviceState);
+ updateAndSendIntent(device, currDeviceState, newDeviceState);
}
break;
}
}
}
- private void updateAndsendIntent(BluetoothDevice device, int prevDeviceState,
+ private void updateAndSendIntent(BluetoothDevice device, int prevDeviceState,
int newDeviceState) {
mHealthDevices.put(device, newDeviceState);
mBluetoothService.sendConnectionStateChange(device, prevDeviceState, newDeviceState);
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 9839f76..ff16c18 100644..100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -24,8 +24,6 @@
package android.server;
-import com.android.internal.app.IBatteryStats;
-
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
@@ -40,6 +38,7 @@ import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetooth;
import android.bluetooth.IBluetoothCallback;
+import android.bluetooth.IBluetoothHealthCallback;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -58,6 +57,8 @@ import android.provider.Settings;
import android.util.Log;
import android.util.Pair;
+import com.android.internal.app.IBatteryStats;
+
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@@ -2111,11 +2112,12 @@ public class BluetoothService extends IBluetooth.Stub {
/**** Handlers for Health Device Profile ****/
// TODO: All these need to be converted to a state machine.
- public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config) {
+ public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config,
+ IBluetoothHealthCallback callback) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
"Need BLUETOOTH permission");
synchronized (mBluetoothHealthProfileHandler) {
- return mBluetoothHealthProfileHandler.registerAppConfiguration(config);
+ return mBluetoothHealthProfileHandler.registerAppConfiguration(config, callback);
}
}
@@ -2401,6 +2403,7 @@ public class BluetoothService extends IBluetooth.Stub {
convertToAdapterState(state));
intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE,
convertToAdapterState(prevState));
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
Log.d(TAG, "CONNECTION_STATE_CHANGE: " + device + ": "
+ prevState + " -> " + state);
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index 8ef4295..1210941 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -384,7 +384,7 @@ class AudioPlaybackHandler {
}
count += written;
}
-
+ param.mBytesWritten += count;
param.mLogger.onPlaybackStart();
}
@@ -396,14 +396,16 @@ class AudioPlaybackHandler {
params.mLogger.onWriteData();
}
- // Flush all remaining data to the audio track, stop it and release
- // all it's resources.
+ // Wait for the audio track to stop playing, and then release it's resources.
private void handleSynthesisDone(SynthesisMessageParams params) {
if (DBG) Log.d(TAG, "handleSynthesisDone()");
final AudioTrack audioTrack = params.getAudioTrack();
try {
if (audioTrack != null) {
+ if (DBG) Log.d(TAG, "Waiting for audio track to complete : " +
+ audioTrack.hashCode());
+ blockUntilDone(params);
if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]");
// The last call to AudioTrack.write( ) will return only after
// all data from the audioTrack has been sent to the mixer, so
@@ -417,6 +419,18 @@ class AudioPlaybackHandler {
}
}
+ private static void blockUntilDone(SynthesisMessageParams params) {
+ if (params.mAudioTrack == null || params.mBytesWritten <= 0) {
+ return;
+ }
+
+ final AudioTrack track = params.mAudioTrack;
+ final int bytesPerFrame = getBytesPerFrame(params.mAudioFormat);
+ final int lengthInBytes = params.mBytesWritten;
+
+ blockUntilDone(track, bytesPerFrame, lengthInBytes);
+ }
+
private void handleSynthesisCompleteDataAvailable(MessageParams msg) {
final SynthesisMessageParams params = (SynthesisMessageParams) msg;
if (DBG) Log.d(TAG, "completeAudioAvailable(" + params + ")");
@@ -455,13 +469,18 @@ class AudioPlaybackHandler {
}
- private static void blockUntilDone(AudioTrack audioTrack, int bytesPerFrame, int length) {
- int lengthInFrames = length / bytesPerFrame;
+ private static void blockUntilDone(AudioTrack audioTrack, int bytesPerFrame,
+ int lengthInBytes) {
+ int lengthInFrames = lengthInBytes / bytesPerFrame;
int currentPosition = 0;
while ((currentPosition = audioTrack.getPlaybackHeadPosition()) < lengthInFrames) {
+ if (audioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
+ break;
+ }
+
long estimatedTimeMs = ((lengthInFrames - currentPosition) * 1000) /
audioTrack.getSampleRate();
- audioTrack.getPlayState();
+
if (DBG) Log.d(TAG, "About to sleep for : " + estimatedTimeMs + " ms," +
" Playback position : " + currentPosition);
try {
diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java
index caf02ef..ffe70e2 100644
--- a/core/java/android/speech/tts/SynthesisMessageParams.java
+++ b/core/java/android/speech/tts/SynthesisMessageParams.java
@@ -32,7 +32,9 @@ final class SynthesisMessageParams extends MessageParams {
final float mPan;
final EventLogger mLogger;
- public volatile AudioTrack mAudioTrack;
+ volatile AudioTrack mAudioTrack;
+ // Not volatile, accessed only from the synthesis thread.
+ int mBytesWritten;
private final LinkedList<ListEntry> mDataBufferList = new LinkedList<ListEntry>();
@@ -52,6 +54,7 @@ final class SynthesisMessageParams extends MessageParams {
// initially null.
mAudioTrack = null;
+ mBytesWritten = 0;
}
@Override
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 240ad9b..555aac5 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -22,12 +22,22 @@ import android.os.Parcelable;
import android.os.SystemClock;
import android.text.ParcelableSpan;
import android.text.TextUtils;
+import android.widget.TextView;
import java.util.Arrays;
import java.util.Locale;
/**
- * Holds suggestion candidates of words under this span.
+ * Holds suggestion candidates for the text enclosed in this span.
+ *
+ * When such a span is edited in an EditText, double tapping on the text enclosed in this span will
+ * display a popup dialog listing suggestion replacement for that text. The user can then replace
+ * the original text by one of the suggestions.
+ *
+ * These spans should typically be created by the input method to privide correction and alternates
+ * for the text.
+ *
+ * @see TextView#setSuggestionsEnabled(boolean)
*/
public class SuggestionSpan implements ParcelableSpan {
/**
@@ -115,14 +125,14 @@ public class SuggestionSpan implements ParcelableSpan {
}
/**
- * @return suggestions
+ * @return an array of suggestion texts for this span
*/
public String[] getSuggestions() {
return mSuggestions;
}
/**
- * @return locale of suggestions
+ * @return the locale of the suggestions
*/
public String getLocale() {
return mLocaleString;
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 5b19ecd..2179ff3 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -16,41 +16,71 @@
package android.util;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
import android.net.SntpClient;
import android.os.SystemClock;
+import android.provider.Settings;
/**
- * {@link TrustedTime} that connects with a remote NTP server as its remote
- * trusted time source.
+ * {@link TrustedTime} that connects with a remote NTP server as its trusted
+ * time source.
*
* @hide
*/
public class NtpTrustedTime implements TrustedTime {
- private String mNtpServer;
- private long mNtpTimeout;
+ private static final String TAG = "NtpTrustedTime";
+ private static final boolean LOGD = false;
+
+ private static NtpTrustedTime sSingleton;
+
+ private final String mServer;
+ private final long mTimeout;
private boolean mHasCache;
private long mCachedNtpTime;
private long mCachedNtpElapsedRealtime;
private long mCachedNtpCertainty;
- public NtpTrustedTime() {
+ private NtpTrustedTime(String server, long timeout) {
+ if (LOGD) Log.d(TAG, "creating NtpTrustedTime using " + server);
+ mServer = server;
+ mTimeout = timeout;
}
- public void setNtpServer(String server, long timeout) {
- mNtpServer = server;
- mNtpTimeout = timeout;
+ public static synchronized NtpTrustedTime getInstance(Context context) {
+ if (sSingleton == null) {
+ final Resources res = context.getResources();
+ final ContentResolver resolver = context.getContentResolver();
+
+ final String defaultServer = res.getString(
+ com.android.internal.R.string.config_ntpServer);
+ final long defaultTimeout = res.getInteger(
+ com.android.internal.R.integer.config_ntpTimeout);
+
+ final String secureServer = Settings.Secure.getString(
+ resolver, Settings.Secure.NTP_SERVER);
+ final long timeout = Settings.Secure.getLong(
+ resolver, Settings.Secure.NTP_TIMEOUT, defaultTimeout);
+
+ final String server = secureServer != null ? secureServer : defaultServer;
+ sSingleton = new NtpTrustedTime(server, timeout);
+ }
+
+ return sSingleton;
}
/** {@inheritDoc} */
public boolean forceRefresh() {
- if (mNtpServer == null) {
+ if (mServer == null) {
// missing server, so no trusted time available
return false;
}
+ if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
final SntpClient client = new SntpClient();
- if (client.requestTime(mNtpServer, (int) mNtpTimeout)) {
+ if (client.requestTime(mServer, (int) mTimeout)) {
mHasCache = true;
mCachedNtpTime = client.getNtpTime();
mCachedNtpElapsedRealtime = client.getNtpTimeReference();
@@ -89,9 +119,19 @@ public class NtpTrustedTime implements TrustedTime {
if (!mHasCache) {
throw new IllegalStateException("Missing authoritative time source");
}
+ if (LOGD) Log.d(TAG, "currentTimeMillis() cache hit");
// current time is age after the last ntp cache; callers who
// want fresh values will hit makeAuthoritative() first.
return mCachedNtpTime + getCacheAge();
}
+
+ public long getCachedNtpTime() {
+ if (LOGD) Log.d(TAG, "getCachedNtpTime() cache hit");
+ return mCachedNtpTime;
+ }
+
+ public long getCachedNtpTimeReference() {
+ return mCachedNtpElapsedRealtime;
+ }
}
diff --git a/core/java/android/view/ActionProvider.java b/core/java/android/view/ActionProvider.java
index 6491da0..5601dc5 100644
--- a/core/java/android/view/ActionProvider.java
+++ b/core/java/android/view/ActionProvider.java
@@ -28,7 +28,9 @@ import android.content.Context;
* {@link android.app.ActionBar} as a substitute for the menu item when the item is
* displayed as an action item. Also the provider is responsible for performing a
* default action if a menu item placed on the overflow menu of the ActionBar is
- * selected and none of the menu item callbacks has handled the selection.
+ * selected and none of the menu item callbacks has handled the selection. For this
+ * case the provider can also optionally provide a sub-menu for accomplishing the
+ * task at hand.
* </p>
* <p>
* There are two ways for using an action provider for creating and handling of action views:
@@ -76,7 +78,7 @@ public abstract class ActionProvider {
* Performs an optional default action.
* <p>
* For the case of an action provider placed in a menu item not shown as an action this
- * method is invoked if none of the callbacks for processing menu selection has handled
+ * method is invoked if previous callbacks for processing menu selection has handled
* the event.
* </p>
* <p>
@@ -104,11 +106,36 @@ public abstract class ActionProvider {
* </ul>
* </p>
* <p>
- * The default implementation does not perform any action.
+ * The default implementation does not perform any action and returns false.
* </p>
+ */
+ public boolean onPerformDefaultAction() {
+ return false;
+ }
+
+ /**
+ * Determines if this ActionProvider has a submenu associated with it.
+ *
+ * <p>Associated submenus will be shown when an action view is not. This
+ * provider instance will receive a call to {@link #onPrepareSubMenu(SubMenu)}
+ * after the call to {@link #onPerformDefaultAction()} and before a submenu is
+ * displayed to the user.
+ *
+ * @return true if the item backed by this provider should have an associated submenu
+ */
+ public boolean hasSubMenu() {
+ return false;
+ }
+
+ /**
+ * Called to prepare an associated submenu for the menu item backed by this ActionProvider.
+ *
+ * <p>if {@link #hasSubMenu()} returns true, this method will be called when the
+ * menu item is selected to prepare the submenu for presentation to the user. Apps
+ * may use this to create or alter submenu content right before display.
*
- * @param actionView A view created by {@link #onCreateActionView()}.
+ * @param subMenu Submenu that will be displayed
*/
- public void onPerformDefaultAction(View actionView) {
+ public void onPrepareSubMenu(SubMenu subMenu) {
}
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 188970c..011e44c 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -128,8 +128,23 @@ public abstract class HardwareRenderer {
abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
/**
- * Setup the hardware renderer for drawing. This is called for every
- * frame to draw.
+ * This method should be invoked whenever the current hardware renderer
+ * context should be reset.
+ */
+ abstract void invalidate();
+
+ /**
+ * This method should be invoked to ensure the hardware renderer is in
+ * valid state (for instance, to ensure the correct EGL context is bound
+ * to the current thread.)
+ *
+ * @return true if the renderer is now valid, false otherwise
+ */
+ abstract boolean validate();
+
+ /**
+ * Setup the hardware renderer for drawing. This is called whenever the
+ * size of the target surface changes or when the surface is first created.
*
* @param width Width of the drawing surface.
* @param height Height of the drawing surface.
@@ -289,9 +304,9 @@ public abstract class HardwareRenderer {
static abstract class GlRenderer extends HardwareRenderer {
// These values are not exposed in our EGL APIs
static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
- static final int EGL_SURFACE_TYPE = 0x3033;
- static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
static final int EGL_OPENGL_ES2_BIT = 4;
+ static final int EGL_SURFACE_TYPE = 0x3033;
+ static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
private static final int SURFACE_STATE_ERROR = 0;
private static final int SURFACE_STATE_SUCCESS = 1;
@@ -311,8 +326,16 @@ public abstract class HardwareRenderer {
int mFrameCount;
Paint mDebugPaint;
- boolean mDirtyRegions;
- final boolean mDirtyRegionsRequested;
+ static boolean sDirtyRegions;
+ static final boolean sDirtyRegionsRequested;
+ static {
+ String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true");
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ sDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty);
+ sDirtyRegionsRequested = sDirtyRegions;
+ }
+
+ boolean mDirtyRegionsEnabled;
final boolean mVsyncDisabled;
final int mGlVersion;
@@ -326,11 +349,6 @@ public abstract class HardwareRenderer {
mGlVersion = glVersion;
mTranslucent = translucent;
- final String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true");
- //noinspection PointlessBooleanExpression,ConstantConditions
- mDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty);
- mDirtyRegionsRequested = mDirtyRegions;
-
final String vsyncProperty = SystemProperties.get(DISABLE_VSYNC_PROPERTY, "false");
mVsyncDisabled = "true".equalsIgnoreCase(vsyncProperty);
if (mVsyncDisabled) {
@@ -342,7 +360,7 @@ public abstract class HardwareRenderer {
* Indicates whether this renderer instance can track and update dirty regions.
*/
boolean hasDirtyRegions() {
- return mDirtyRegions;
+ return mDirtyRegionsEnabled;
}
/**
@@ -479,8 +497,8 @@ public abstract class HardwareRenderer {
sEglConfig = chooseEglConfig();
if (sEglConfig == null) {
// We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
- if (mDirtyRegions) {
- mDirtyRegions = false;
+ if (sDirtyRegions) {
+ sDirtyRegions = false;
sEglConfig = chooseEglConfig();
if (sEglConfig == null) {
throw new RuntimeException("eglConfig not initialized");
@@ -500,7 +518,7 @@ public abstract class HardwareRenderer {
private EGLConfig chooseEglConfig() {
int[] configsCount = new int[1];
EGLConfig[] configs = new EGLConfig[1];
- int[] configSpec = getConfig(mDirtyRegions);
+ int[] configSpec = getConfig(sDirtyRegions);
if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) {
throw new IllegalArgumentException("eglChooseConfig failed " +
getEGLErrorString(sEgl.eglGetError()));
@@ -566,18 +584,18 @@ public abstract class HardwareRenderer {
// If mDirtyRegions is set, this means we have an EGL configuration
// with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
- if (mDirtyRegions) {
- if (!GLES20Canvas.preserveBackBuffer()) {
+ if (sDirtyRegions) {
+ if (!(mDirtyRegionsEnabled = GLES20Canvas.preserveBackBuffer())) {
Log.w(LOG_TAG, "Backbuffer cannot be preserved");
}
- } else if (mDirtyRegionsRequested) {
+ } else if (sDirtyRegionsRequested) {
// If mDirtyRegions is not set, our EGL configuration does not
// have EGL_SWAP_BEHAVIOR_PRESERVED_BIT; however, the default
// swap behavior might be EGL_BUFFER_PRESERVED, which means we
// want to set mDirtyRegions. We try to do this only if dirty
// regions were initially requested as part of the device
// configuration (see RENDER_DIRTY_REGIONS)
- mDirtyRegions = GLES20Canvas.isBackBufferPreserved();
+ mDirtyRegionsEnabled = GLES20Canvas.isBackBufferPreserved();
}
return sEglContext.getGL();
@@ -620,6 +638,19 @@ public abstract class HardwareRenderer {
}
@Override
+ void invalidate() {
+ // Cancels any existing buffer to ensure we'll get a buffer
+ // of the right size before we call eglSwapBuffers
+ sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+ }
+
+ @Override
+ boolean validate() {
+ return checkCurrent() != SURFACE_STATE_ERROR;
+ }
+
+ @Override
void setup(int width, int height) {
mCanvas.setViewport(width, height);
}
@@ -645,7 +676,7 @@ public abstract class HardwareRenderer {
attachInfo.mDrawingTime = SystemClock.uptimeMillis();
view.mPrivateFlags |= View.DRAWN;
-
+
final int surfaceState = checkCurrent();
if (surfaceState != SURFACE_STATE_ERROR) {
// We had to change the current surface and/or context, redraw everything
@@ -706,10 +737,21 @@ public abstract class HardwareRenderer {
}
}
}
-
+
+ /**
+ * Ensures the currnet EGL context is the one we expect.
+ *
+ * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
+ * {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
+ * {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
+ */
private int checkCurrent() {
- // TODO: Don't check the current context when we have one per UI thread
- // TODO: Use a threadlocal flag to know whether the surface has changed
+ if (sEglThread != Thread.currentThread()) {
+ throw new IllegalStateException("Hardware acceleration can only be used with a " +
+ "single UI thread.\nOriginal thread: " + sEglThread + "\n" +
+ "Current thread: " + Thread.currentThread());
+ }
+
if (!sEglContext.equals(sEgl.eglGetCurrentContext()) ||
!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index a7f0cba..c46e43a 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -166,7 +166,12 @@ public class MenuInflater {
// Add the item if it hasn't been added (if the item was
// a submenu, it would have been added already)
if (!menuState.hasAddedItem()) {
- menuState.addItem();
+ if (menuState.itemActionProvider != null &&
+ menuState.itemActionProvider.hasSubMenu()) {
+ menuState.addSubMenuItem();
+ } else {
+ menuState.addItem();
+ }
}
} else if (tagName.equals(XML_MENU)) {
reachedEndOfMenu = true;
@@ -270,6 +275,8 @@ public class MenuInflater {
private String itemListenerMethodName;
+ private ActionProvider itemActionProvider;
+
private static final int defaultGroupId = NO_ID;
private static final int defaultItemId = NO_ID;
private static final int defaultItemCategory = 0;
@@ -347,6 +354,19 @@ public class MenuInflater {
itemActionViewClassName = a.getString(com.android.internal.R.styleable.MenuItem_actionViewClass);
itemActionProviderClassName = a.getString(com.android.internal.R.styleable.MenuItem_actionProviderClass);
+ final boolean hasActionProvider = itemActionProviderClassName != null;
+ if (hasActionProvider && itemActionViewLayout == 0 && itemActionViewClassName == null) {
+ itemActionProvider = newInstance(itemActionProviderClassName,
+ ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE,
+ mActionProviderConstructorArguments);
+ } else {
+ if (hasActionProvider) {
+ Log.w(LOG_TAG, "Ignoring attribute 'actionProviderClass'."
+ + " Action view already specified.");
+ }
+ itemActionProvider = null;
+ }
+
a.recycle();
itemAdded = false;
@@ -406,16 +426,8 @@ public class MenuInflater {
+ " Action view already specified.");
}
}
- if (itemActionProviderClassName != null) {
- if (!actionViewSpecified) {
- ActionProvider actionProvider = newInstance(itemActionProviderClassName,
- ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE,
- mActionProviderConstructorArguments);
- item.setActionProvider(actionProvider);
- } else {
- Log.w(LOG_TAG, "Ignoring attribute 'itemActionProviderClass'."
- + " Action view already specified.");
- }
+ if (itemActionProvider != null) {
+ item.setActionProvider(itemActionProvider);
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1245898..74dc100 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4474,7 +4474,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
@RemotableViewMethod
public void setLayoutDirection(int layoutDirection) {
if (getLayoutDirection() != layoutDirection) {
- resetLayoutDirectionResolution();
+ resetResolvedLayoutDirection();
// Setting the flag will also request a layout.
setFlags(layoutDirection, LAYOUT_DIRECTION_MASK);
}
@@ -9043,10 +9043,8 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
}
jumpDrawablesToCurrentState();
- resetLayoutDirectionResolution();
resolveLayoutDirectionIfNeeded();
resolvePadding();
- resetResolvedTextDirection();
resolveTextDirection();
if (isFocused()) {
InputMethodManager imm = InputMethodManager.peekInstance();
@@ -9143,7 +9141,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
*
* @hide
*/
- protected void resetLayoutDirectionResolution() {
+ protected void resetResolvedLayoutDirection() {
// Reset the current View resolution
mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED;
}
@@ -9190,6 +9188,9 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
}
mCurrentAnimation = null;
+
+ resetResolvedLayoutDirection();
+ resetResolvedTextDirection();
}
/**
diff --git a/core/java/android/view/ViewAncestor.java b/core/java/android/view/ViewAncestor.java
index d70c798..1dcbc26 100644
--- a/core/java/android/view/ViewAncestor.java
+++ b/core/java/android/view/ViewAncestor.java
@@ -901,6 +901,7 @@ public final class ViewAncestor extends Handler implements ViewParent,
!mAttachInfo.mTurnOffWindowResizeAnim &&
mAttachInfo.mHardwareRenderer != null &&
mAttachInfo.mHardwareRenderer.isEnabled() &&
+ mAttachInfo.mHardwareRenderer.validate() &&
lp != null && !PixelFormat.formatHasAlpha(lp.format)) {
disposeResizeBuffer();
@@ -1315,6 +1316,9 @@ public final class ViewAncestor extends Handler implements ViewParent,
mAttachInfo.mHardwareRenderer != null &&
mAttachInfo.mHardwareRenderer.isEnabled())) {
mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
+ if (!hwInitialized) {
+ mAttachInfo.mHardwareRenderer.invalidate();
+ }
}
if (!mStopped) {
@@ -3845,10 +3849,6 @@ public final class ViewAncestor extends Handler implements ViewParent,
}
private static int checkCallingPermission(String permission) {
- if (!Process.supportsProcesses()) {
- return PackageManager.PERMISSION_GRANTED;
- }
-
try {
return ActivityManagerNative.getDefault().checkPermission(
permission, Binder.getCallingPid(), Binder.getCallingUid());
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index e6fdb17..752fd5a 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4999,15 +4999,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
@Override
- protected void resetLayoutDirectionResolution() {
- super.resetLayoutDirectionResolution();
+ protected void resetResolvedLayoutDirection() {
+ super.resetResolvedLayoutDirection();
// Take care of resetting the children resolution too
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getLayoutDirection() == LAYOUT_DIRECTION_INHERIT) {
- child.resetLayoutDirectionResolution();
+ child.resetResolvedLayoutDirection();
}
}
}
diff --git a/core/java/android/webkit/L10nUtils.java b/core/java/android/webkit/L10nUtils.java
index f9d0067d..a1c6a53 100644
--- a/core/java/android/webkit/L10nUtils.java
+++ b/core/java/android/webkit/L10nUtils.java
@@ -75,7 +75,18 @@ public class L10nUtils {
com.android.internal.R.string.autofill_area_code_notext_re, // IDS_AUTOFILL_AREA_CODE_NOTEXT_RE
com.android.internal.R.string.autofill_phone_prefix_separator_re, // IDS_AUTOFILL_PHONE_PREFIX_SEPARATOR_RE
com.android.internal.R.string.autofill_phone_suffix_separator_re, // IDS_AUTOFILL_PHONE_SUFFIX_SEPARATOR_RE
- com.android.internal.R.string.credit_card_number_preview_format // IDS_CREDIT_CARD_NUMBER_PREVIEW_FORMAT
+ com.android.internal.R.string.autofill_province, // IDS_AUTOFILL_DIALOG_PROVINCE
+ com.android.internal.R.string.autofill_postal_code, // IDS_AUTOFILL_DIALOG_POSTAL_CODE
+ com.android.internal.R.string.autofill_state, // IDS_AUTOFILL_DIALOG_STATE
+ com.android.internal.R.string.autofill_zip_code, // IDS_AUTOFILL_DIALOG_ZIP_CODE
+ com.android.internal.R.string.autofill_county, // IDS_AUTOFILL_DIALOG_COUNTY
+ com.android.internal.R.string.autofill_island, // IDS_AUTOFILL_DIALOG_ISLAND
+ com.android.internal.R.string.autofill_district, // IDS_AUTOFILL_DIALOG_DISTRICT
+ com.android.internal.R.string.autofill_department, // IDS_AUTOFILL_DIALOG_DEPARTMENT
+ com.android.internal.R.string.autofill_prefecture, // IDS_AUTOFILL_DIALOG_PREFECTURE
+ com.android.internal.R.string.autofill_parish, // IDS_AUTOFILL_DIALOG_PARISH
+ com.android.internal.R.string.autofill_area, // IDS_AUTOFILL_DIALOG_AREA
+ com.android.internal.R.string.autofill_emirate // IDS_AUTOFILL_DIALOG_EMIRATE
};
private static Context mApplicationContext;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 7ba86a5..3ae10fe 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -9089,6 +9089,52 @@ public class WebView extends AbsoluteLayout
}
}
+ /**
+ * Begin collecting per-tile profiling data
+ *
+ * @hide only used by profiling tests
+ */
+ public void tileProfilingStart() {
+ nativeTileProfilingStart();
+ }
+ /**
+ * Return per-tile profiling data
+ *
+ * @hide only used by profiling tests
+ */
+ public float tileProfilingStop() {
+ return nativeTileProfilingStop();
+ }
+
+ /** @hide only used by profiling tests */
+ public void tileProfilingClear() {
+ nativeTileProfilingClear();
+ }
+ /** @hide only used by profiling tests */
+ public int tileProfilingNumFrames() {
+ return nativeTileProfilingNumFrames();
+ }
+ /** @hide only used by profiling tests */
+ public int tileProfilingNumTilesInFrame(int frame) {
+ return nativeTileProfilingNumTilesInFrame(frame);
+ }
+ /** @hide only used by profiling tests */
+ public int tileProfilingGetX(int frame, int tile) {
+ return nativeTileProfilingGetX(frame, tile);
+ }
+ /** @hide only used by profiling tests */
+ public int tileProfilingGetY(int frame, int tile) {
+ return nativeTileProfilingGetY(frame, tile);
+ }
+ /** @hide only used by profiling tests */
+ public boolean tileProfilingGetReady(int frame, int tile) {
+ return nativeTileProfilingGetReady(frame, tile);
+ }
+ /** @hide only used by profiling tests */
+ public int tileProfilingGetLevel(int frame, int tile) {
+ return nativeTileProfilingGetLevel(frame, tile);
+ }
+
private native int nativeCacheHitFramePointer();
private native boolean nativeCacheHitIsPlugin();
private native Rect nativeCacheHitNodeBounds();
@@ -9211,6 +9257,15 @@ public class WebView extends AbsoluteLayout
private native void nativeStopGL();
private native Rect nativeSubtractLayers(Rect content);
private native int nativeTextGeneration();
+ private native void nativeTileProfilingStart();
+ private native float nativeTileProfilingStop();
+ private native void nativeTileProfilingClear();
+ private native int nativeTileProfilingNumFrames();
+ private native int nativeTileProfilingNumTilesInFrame(int frame);
+ private native int nativeTileProfilingGetX(int frame, int tile);
+ private native int nativeTileProfilingGetY(int frame, int tile);
+ private native boolean nativeTileProfilingGetReady(int frame, int tile);
+ private native int nativeTileProfilingGetLevel(int frame, int tile);
// Never call this version except by updateCachedTextfield(String) -
// we always want to pass in our generation number.
private native void nativeUpdateCachedTextfield(String updatedText,
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 252fc8f..49ea944 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -300,7 +300,7 @@ class ZoomManager {
}
public final float getDefaultScale() {
- return mDefaultScale;
+ return mInitialScale > 0 ? mInitialScale : mDefaultScale;
}
public final float getReadingLevelScale() {
@@ -344,6 +344,8 @@ class ZoomManager {
public final void setInitialScaleInPercent(int scaleInPercent) {
mInitialScale = scaleInPercent * 0.01f;
+ mActualScale = mInitialScale > 0 ? mInitialScale : mDefaultScale;
+ mInvActualScale = 1 / mActualScale;
}
public final float computeScaleWithLimits(float scale) {
@@ -1087,6 +1089,7 @@ class ZoomManager {
float scale;
if (mInitialScale > 0) {
scale = mInitialScale;
+ mTextWrapScale = scale;
} else if (viewState.mViewScale > 0) {
mTextWrapScale = viewState.mTextWrapScale;
scale = viewState.mViewScale;
@@ -1105,7 +1108,7 @@ class ZoomManager {
}
boolean reflowText = false;
if (!viewState.mIsRestored) {
- if (settings.getUseFixedViewport()) {
+ if (settings.getUseFixedViewport() && mInitialScale == 0) {
// Override the scale only in case of fixed viewport.
scale = Math.max(scale, overviewScale);
mTextWrapScale = Math.max(mTextWrapScale, overviewScale);
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index 83f80ff..32c44d8 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -126,7 +126,7 @@ public class ActivityChooserModel extends DataSetObservable {
*/
// This cannot be done by a simple comparator since an Activity weight
// is computed from history. Note that Activity implements Comparable.
- public void sort(Intent intent, List<Activity> activities,
+ public void sort(Intent intent, List<ActivityResolveInfo> activities,
List<HistoricalRecord> historicalRecords);
}
@@ -215,7 +215,7 @@ public class ActivityChooserModel extends DataSetObservable {
/**
* List of activities that can handle the current intent.
*/
- private final List<Activity> mActivitys = new ArrayList<Activity>();
+ private final List<ActivityResolveInfo> mActivites = new ArrayList<ActivityResolveInfo>();
/**
* List with historical choice records.
@@ -311,9 +311,6 @@ public class ActivityChooserModel extends DataSetObservable {
* @return The model.
*/
public static ActivityChooserModel get(Context context, String historyFileName) {
- if (historyFileName == null) {
- return new ActivityChooserModel(context, historyFileName);
- }
synchronized (sRegistryLock) {
ActivityChooserModel dataModel = sDataModelRegistry.get(historyFileName);
if (dataModel == null) {
@@ -380,7 +377,7 @@ public class ActivityChooserModel extends DataSetObservable {
*/
public int getActivityCount() {
synchronized (mInstanceLock) {
- return mActivitys.size();
+ return mActivites.size();
}
}
@@ -389,12 +386,12 @@ public class ActivityChooserModel extends DataSetObservable {
*
* @return The activity.
*
- * @see Activity
+ * @see ActivityResolveInfo
* @see #setIntent(Intent)
*/
public ResolveInfo getActivity(int index) {
synchronized (mInstanceLock) {
- return mActivitys.get(index).resolveInfo;
+ return mActivites.get(index).resolveInfo;
}
}
@@ -406,10 +403,10 @@ public class ActivityChooserModel extends DataSetObservable {
* @return The index if found, -1 otherwise.
*/
public int getActivityIndex(ResolveInfo activity) {
- List<Activity> activities = mActivitys;
+ List<ActivityResolveInfo> activities = mActivites;
final int activityCount = activities.size();
for (int i = 0; i < activityCount; i++) {
- Activity currentActivity = activities.get(i);
+ ActivityResolveInfo currentActivity = activities.get(i);
if (currentActivity.resolveInfo == activity) {
return i;
}
@@ -433,8 +430,8 @@ public class ActivityChooserModel extends DataSetObservable {
* @see HistoricalRecord
*/
public Intent chooseActivity(int index) {
- Activity chosenActivity = mActivitys.get(index);
- Activity defaultActivity = mActivitys.get(0);
+ ActivityResolveInfo chosenActivity = mActivites.get(index);
+ ActivityResolveInfo defaultActivity = mActivites.get(0);
ComponentName chosenName = new ComponentName(
chosenActivity.resolveInfo.activityInfo.packageName,
@@ -460,8 +457,8 @@ public class ActivityChooserModel extends DataSetObservable {
*/
public ResolveInfo getDefaultActivity() {
synchronized (mInstanceLock) {
- if (!mActivitys.isEmpty()) {
- return mActivitys.get(0).resolveInfo;
+ if (!mActivites.isEmpty()) {
+ return mActivites.get(0).resolveInfo;
}
}
return null;
@@ -478,8 +475,8 @@ public class ActivityChooserModel extends DataSetObservable {
* @param index The index of the activity to set as default.
*/
public void setDefaultActivity(int index) {
- Activity newDefaultActivity = mActivitys.get(index);
- Activity oldDefaultActivity = mActivitys.get(0);
+ ActivityResolveInfo newDefaultActivity = mActivites.get(index);
+ ActivityResolveInfo oldDefaultActivity = mActivites.get(0);
final float weight;
if (oldDefaultActivity != null) {
@@ -572,8 +569,8 @@ public class ActivityChooserModel extends DataSetObservable {
*/
private void sortActivities() {
synchronized (mInstanceLock) {
- if (mActivitySorter != null && !mActivitys.isEmpty()) {
- mActivitySorter.sort(mIntent, mActivitys,
+ if (mActivitySorter != null && !mActivites.isEmpty()) {
+ mActivitySorter.sort(mIntent, mActivites,
Collections.unmodifiableList(mHistoricalRecords));
notifyChanged();
}
@@ -661,14 +658,14 @@ public class ActivityChooserModel extends DataSetObservable {
* Loads the activities.
*/
private void loadActivitiesLocked() {
- mActivitys.clear();
+ mActivites.clear();
if (mIntent != null) {
List<ResolveInfo> resolveInfos =
mContext.getPackageManager().queryIntentActivities(mIntent, 0);
final int resolveInfoCount = resolveInfos.size();
for (int i = 0; i < resolveInfoCount; i++) {
ResolveInfo resolveInfo = resolveInfos.get(i);
- mActivitys.add(new Activity(resolveInfo));
+ mActivites.add(new ActivityResolveInfo(resolveInfo));
}
sortActivities();
} else {
@@ -797,7 +794,7 @@ public class ActivityChooserModel extends DataSetObservable {
/**
* Represents an activity.
*/
- public final class Activity implements Comparable<Activity> {
+ public final class ActivityResolveInfo implements Comparable<ActivityResolveInfo> {
/**
* The {@link ResolveInfo} of the activity.
@@ -814,7 +811,7 @@ public class ActivityChooserModel extends DataSetObservable {
*
* @param resolveInfo activity {@link ResolveInfo}.
*/
- public Activity(ResolveInfo resolveInfo) {
+ public ActivityResolveInfo(ResolveInfo resolveInfo) {
this.resolveInfo = resolveInfo;
}
@@ -834,14 +831,14 @@ public class ActivityChooserModel extends DataSetObservable {
if (getClass() != obj.getClass()) {
return false;
}
- Activity other = (Activity) obj;
+ ActivityResolveInfo other = (ActivityResolveInfo) obj;
if (Float.floatToIntBits(weight) != Float.floatToIntBits(other.weight)) {
return false;
}
return true;
}
- public int compareTo(Activity another) {
+ public int compareTo(ActivityResolveInfo another) {
return Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight);
}
@@ -862,18 +859,18 @@ public class ActivityChooserModel extends DataSetObservable {
private final class DefaultSorter implements ActivitySorter {
private static final float WEIGHT_DECAY_COEFFICIENT = 0.95f;
- private final Map<String, Activity> mPackageNameToActivityMap =
- new HashMap<String, Activity>();
+ private final Map<String, ActivityResolveInfo> mPackageNameToActivityMap =
+ new HashMap<String, ActivityResolveInfo>();
- public void sort(Intent intent, List<Activity> activities,
+ public void sort(Intent intent, List<ActivityResolveInfo> activities,
List<HistoricalRecord> historicalRecords) {
- Map<String, Activity> packageNameToActivityMap =
+ Map<String, ActivityResolveInfo> packageNameToActivityMap =
mPackageNameToActivityMap;
packageNameToActivityMap.clear();
final int activityCount = activities.size();
for (int i = 0; i < activityCount; i++) {
- Activity activity = activities.get(i);
+ ActivityResolveInfo activity = activities.get(i);
activity.weight = 0.0f;
String packageName = activity.resolveInfo.activityInfo.packageName;
packageNameToActivityMap.put(packageName, activity);
@@ -884,9 +881,11 @@ public class ActivityChooserModel extends DataSetObservable {
for (int i = lastShareIndex; i >= 0; i--) {
HistoricalRecord historicalRecord = historicalRecords.get(i);
String packageName = historicalRecord.activity.getPackageName();
- Activity activity = packageNameToActivityMap.get(packageName);
- activity.weight += historicalRecord.weight * nextRecordWeight;
- nextRecordWeight = nextRecordWeight * WEIGHT_DECAY_COEFFICIENT;
+ ActivityResolveInfo activity = packageNameToActivityMap.get(packageName);
+ if (activity != null) {
+ activity.weight += historicalRecord.weight * nextRecordWeight;
+ nextRecordWeight = nextRecordWeight * WEIGHT_DECAY_COEFFICIENT;
+ }
}
Collections.sort(activities);
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 2fe8162..f500b39 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -16,10 +16,7 @@
package android.widget;
-import android.app.AlertDialog;
-import android.app.AlertDialog.Builder;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -27,12 +24,20 @@ import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
-import android.os.Debug;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ActivityChooserModel;
import android.widget.ActivityChooserModel.ActivityChooserModelClient;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListPopupWindow;
+import android.widget.PopupWindow;
+import android.widget.TextView;
import com.android.internal.R;
@@ -56,11 +61,6 @@ import com.android.internal.R;
* </li>
* </ul>
* </p>
- * </p>
- * This view is backed by a {@link ActivityChooserModel}. Calling {@link #showPopup()}
- * while this view is attached to the view hierarchy will show a popup with
- * activities while if the view is not attached it will show a dialog.
- * </p>
*
* @hide
*/
@@ -92,29 +92,21 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
private final ImageButton mDefaultActionButton;
/**
- * The header for handlers list.
+ * Observer for the model data.
*/
- private final View mListHeaderView;
+ private final DataSetObserver mModelDataSetOberver = new DataSetObserver() {
- /**
- * The footer for handlers list.
- */
- private final View mListFooterView;
-
- /**
- * The title of the header view.
- */
- private TextView mListHeaderViewTitle;
-
- /**
- * The title for expanding the activities list.
- */
- private final String mListHeaderViewTitleSelectDefault;
-
- /**
- * The title if no activity exist.
- */
- private final String mListHeaderViewTitleNoActivities;
+ @Override
+ public void onChanged() {
+ super.onChanged();
+ mAdapter.notifyDataSetChanged();
+ }
+ @Override
+ public void onInvalidated() {
+ super.onInvalidated();
+ mAdapter.notifyDataSetInvalidated();
+ }
+ };
/**
* Popup window for showing the activity overflow list.
@@ -122,11 +114,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
private ListPopupWindow mListPopupWindow;
/**
- * Alert dialog for showing the activity overflow list.
- */
- private AlertDialog mAlertDialog;
-
- /**
* Listener for the dismissal of the popup/alert.
*/
private PopupWindow.OnDismissListener mOnDismissListener;
@@ -147,16 +134,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
private boolean mIsAttachedToWindow;
/**
- * Flag whether this view is showing an alert dialog.
- */
- private boolean mIsShowingAlertDialog;
-
- /**
- * Flag whether this view is showing a popup window.
- */
- private boolean mIsShowingPopuWindow;
-
- /**
* Create a new instance.
*
* @param context The application environment.
@@ -195,8 +172,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable(
R.styleable.ActivityChooserView_expandActivityOverflowButtonDrawable);
- LayoutInflater inflater = (LayoutInflater) context.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
+ LayoutInflater inflater = LayoutInflater.from(mContext);
inflater.inflate(R.layout.activity_chooser_view, this, true);
mCallbacks = new Callbacks();
@@ -211,15 +187,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
mExpandActivityOverflowButton.setOnClickListener(mCallbacks);
mExpandActivityOverflowButton.setBackgroundDrawable(expandActivityOverflowButtonDrawable);
- mListHeaderView = inflater.inflate(R.layout.activity_chooser_list_header, null);
- mListFooterView = inflater.inflate(R.layout.activity_chooser_list_footer, null);
-
- mListHeaderViewTitle = (TextView) mListHeaderView.findViewById(R.id.title);
- mListHeaderViewTitleSelectDefault = context.getString(
- R.string.activity_chooser_view_select_default);
- mListHeaderViewTitleNoActivities = context.getString(
- R.string.activity_chooser_view_no_activities);
-
mAdapter = new ActivityChooserViewAdapter();
mAdapter.registerDataSetObserver(new DataSetObserver() {
@Override
@@ -262,7 +229,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
* @return True if the popup was shown, false if already showing.
*/
public boolean showPopup() {
- if (isShowingPopup()) {
+ if (isShowingPopup() || !mIsAttachedToWindow) {
return false;
}
mIsSelectingDefaultActivity = false;
@@ -276,38 +243,29 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
* @param maxActivityCount The max number of activities to display.
*/
private void showPopupUnchecked(int maxActivityCount) {
- mAdapter.setMaxActivityCount(maxActivityCount);
- if (mIsSelectingDefaultActivity) {
- if (mAdapter.getActivityCount() > 0) {
- mListHeaderViewTitle.setText(mListHeaderViewTitleSelectDefault);
- } else {
- mListHeaderViewTitle.setText(mListHeaderViewTitleNoActivities);
- }
- mAdapter.setHeaderView(mListHeaderView);
- } else {
- mAdapter.setHeaderView(null);
+ if (mAdapter.getDataModel() == null) {
+ throw new IllegalStateException("No data model. Did you call #setDataModel?");
}
- if (mAdapter.getActivityCount() > maxActivityCount + 1) {
- mAdapter.setFooterView(mListFooterView);
+ mAdapter.setMaxActivityCount(maxActivityCount);
+
+ final int activityCount = mAdapter.getActivityCount();
+ if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED
+ && activityCount > maxActivityCount + 1) {
+ mAdapter.setShowFooterView(true);
} else {
- mAdapter.setFooterView(null);
+ mAdapter.setShowFooterView(false);
}
- if (!mIsAttachedToWindow || mIsShowingAlertDialog) {
- AlertDialog alertDialog = getAlertDilalog();
- if (!alertDialog.isShowing()) {
- alertDialog.setCustomTitle(this);
- alertDialog.show();
- mIsShowingAlertDialog = true;
- }
- } else {
- ListPopupWindow popupWindow = getListPopupWindow();
- if (!popupWindow.isShowing()) {
- popupWindow.setContentWidth(mAdapter.measureContentWidth());
- popupWindow.show();
- mIsShowingPopuWindow = true;
+ ListPopupWindow popupWindow = getListPopupWindow();
+ if (!popupWindow.isShowing()) {
+ if (mIsSelectingDefaultActivity) {
+ mAdapter.setShowDefaultActivity(true);
+ } else {
+ mAdapter.setShowDefaultActivity(false);
}
+ popupWindow.setContentWidth(mAdapter.measureContentWidth());
+ popupWindow.show();
}
}
@@ -317,12 +275,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
* @return True if dismissed, false if already dismissed.
*/
public boolean dismissPopup() {
- if (!isShowingPopup()) {
- return false;
- }
- if (mIsShowingAlertDialog) {
- getAlertDilalog().dismiss();
- } else if (mIsShowingPopuWindow) {
+ if (isShowingPopup()) {
getListPopupWindow().dismiss();
}
return true;
@@ -334,12 +287,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
* @return True if the popup is shown.
*/
public boolean isShowingPopup() {
- if (mIsShowingAlertDialog) {
- return getAlertDilalog().isShowing();
- } else if (mIsShowingPopuWindow) {
- return getListPopupWindow().isShowing();
- }
- return false;
+ return getListPopupWindow().isShowing();
}
@Override
@@ -347,6 +295,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
super.onAttachedToWindow();
ActivityChooserModel dataModel = mAdapter.getDataModel();
if (dataModel != null) {
+ dataModel.registerObserver(mModelDataSetOberver);
dataModel.readHistoricalData();
}
mIsAttachedToWindow = true;
@@ -357,6 +306,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
super.onDetachedFromWindow();
ActivityChooserModel dataModel = mAdapter.getDataModel();
if (dataModel != null) {
+ dataModel.unregisterObserver(mModelDataSetOberver);
dataModel.persistHistoricalData();
}
mIsAttachedToWindow = false;
@@ -371,13 +321,11 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- mActivityChooserContent.layout(left, top, right, bottom);
- if (mIsShowingPopuWindow) {
- if (isShown()) {
- showPopupUnchecked(mAdapter.getMaxActivityCount());
- } else {
- dismissPopup();
- }
+ mActivityChooserContent.layout(0, 0, right - left, bottom - top);
+ if (getListPopupWindow().isShowing()) {
+ showPopupUnchecked(mAdapter.getMaxActivityCount());
+ } else {
+ dismissPopup();
}
}
@@ -429,22 +377,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
}
/**
- * Gets the alert dialog which is lazily initialized.
- *
- * @return The popup.
- */
- private AlertDialog getAlertDilalog() {
- if (mAlertDialog == null) {
- Builder builder = new Builder(getContext());
- builder.setAdapter(mAdapter, null);
- mAlertDialog = builder.create();
- mAlertDialog.getListView().setOnItemClickListener(mCallbacks);
- mAlertDialog.setOnDismissListener(mCallbacks);
- }
- return mAlertDialog;
- }
-
- /**
* Updates the buttons state.
*/
private void updateButtons() {
@@ -469,24 +401,23 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
* Interface implementation to avoid publishing them in the APIs.
*/
private class Callbacks implements AdapterView.OnItemClickListener,
- View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener,
- DialogInterface.OnDismissListener {
+ View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener {
// AdapterView#OnItemClickListener
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ActivityChooserViewAdapter adapter = (ActivityChooserViewAdapter) parent.getAdapter();
final int itemViewType = adapter.getItemViewType(position);
switch (itemViewType) {
- case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_HEADER: {
- /* do nothing */
- } break;
case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_FOOTER: {
showPopupUnchecked(ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED);
} break;
case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_ACTIVITY: {
dismissPopup();
if (mIsSelectingDefaultActivity) {
- mAdapter.getDataModel().setDefaultActivity(position);
+ // The item at position zero is the default already.
+ if (position > 0) {
+ mAdapter.getDataModel().setDefaultActivity(position);
+ }
} else {
// The first item in the model is default action => adjust index
Intent launchIntent = mAdapter.getDataModel().chooseActivity(position + 1);
@@ -530,16 +461,6 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
// PopUpWindow.OnDismissListener#onDismiss
public void onDismiss() {
- mIsShowingPopuWindow = false;
- notifyOnDismissListener();
- }
-
- // DialogInterface.OnDismissListener#onDismiss
- @Override
- public void onDismiss(DialogInterface dialog) {
- mIsShowingAlertDialog = false;
- AlertDialog alertDialog = (AlertDialog) dialog;
- alertDialog.setCustomTitle(null);
notifyOnDismissListener();
}
@@ -559,59 +480,35 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
public static final int MAX_ACTIVITY_COUNT_DEFAULT = 4;
- private static final int ITEM_VIEW_TYPE_HEADER = 0;
+ private static final int ITEM_VIEW_TYPE_ACTIVITY = 0;
- private static final int ITEM_VIEW_TYPE_ACTIVITY = 1;
-
- private static final int ITEM_VIEW_TYPE_FOOTER = 2;
+ private static final int ITEM_VIEW_TYPE_FOOTER = 1;
private static final int ITEM_VIEW_TYPE_COUNT = 3;
- private final DataSetObserver mDataSetOberver = new DataSetObserver() {
-
- @Override
- public void onChanged() {
- super.onChanged();
- notifyDataSetChanged();
- }
- @Override
- public void onInvalidated() {
- super.onInvalidated();
- notifyDataSetInvalidated();
- }
- };
-
private ActivityChooserModel mDataModel;
private int mMaxActivityCount = MAX_ACTIVITY_COUNT_DEFAULT;
- private ResolveInfo mDefaultActivity;
+ private boolean mShowDefaultActivity;
- private View mHeaderView;
-
- private View mFooterView;
+ private boolean mShowFooterView;
public void setDataModel(ActivityChooserModel dataModel) {
+ ActivityChooserModel oldDataModel = mAdapter.getDataModel();
+ if (oldDataModel != null && isShown()) {
+ oldDataModel.unregisterObserver(mModelDataSetOberver);
+ }
mDataModel = dataModel;
- mDataModel.registerObserver(mDataSetOberver);
- notifyDataSetChanged();
- }
-
- @Override
- public void notifyDataSetChanged() {
- if (mDataModel.getActivityCount() > 0) {
- mDefaultActivity = mDataModel.getDefaultActivity();
- } else {
- mDefaultActivity = null;
+ if (dataModel != null && isShown()) {
+ dataModel.registerObserver(mModelDataSetOberver);
}
- super.notifyDataSetChanged();
+ notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
- if (mHeaderView != null && position == 0) {
- return ITEM_VIEW_TYPE_HEADER;
- } else if (mFooterView != null && position == getCount() - 1) {
+ if (mShowFooterView && position == getCount() - 1) {
return ITEM_VIEW_TYPE_FOOTER;
} else {
return ITEM_VIEW_TYPE_ACTIVITY;
@@ -626,14 +523,11 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
public int getCount() {
int count = 0;
int activityCount = mDataModel.getActivityCount();
- if (activityCount > 0) {
+ if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) {
activityCount--;
}
count = Math.min(activityCount, mMaxActivityCount);
- if (mHeaderView != null) {
- count++;
- }
- if (mFooterView != null) {
+ if (mShowFooterView) {
count++;
}
return count;
@@ -642,16 +536,13 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
public Object getItem(int position) {
final int itemViewType = getItemViewType(position);
switch (itemViewType) {
- case ITEM_VIEW_TYPE_HEADER:
- return mHeaderView;
case ITEM_VIEW_TYPE_FOOTER:
- return mFooterView;
+ return null;
case ITEM_VIEW_TYPE_ACTIVITY:
- int targetIndex = (mHeaderView == null) ? position : position - 1;
- if (mDefaultActivity != null) {
- targetIndex++;
+ if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) {
+ position++;
}
- return mDataModel.getActivity(targetIndex);
+ return mDataModel.getActivity(position);
default:
throw new IllegalArgumentException();
}
@@ -661,27 +552,19 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
return position;
}
- @Override
- public boolean isEnabled(int position) {
- final int itemViewType = getItemViewType(position);
- switch (itemViewType) {
- case ITEM_VIEW_TYPE_HEADER:
- return false;
- case ITEM_VIEW_TYPE_FOOTER:
- case ITEM_VIEW_TYPE_ACTIVITY:
- return true;
- default:
- throw new IllegalArgumentException();
- }
- }
-
public View getView(int position, View convertView, ViewGroup parent) {
final int itemViewType = getItemViewType(position);
switch (itemViewType) {
- case ITEM_VIEW_TYPE_HEADER:
- return mHeaderView;
case ITEM_VIEW_TYPE_FOOTER:
- return mFooterView;
+ if (convertView == null || convertView.getId() != ITEM_VIEW_TYPE_FOOTER) {
+ convertView = LayoutInflater.from(getContext()).inflate(
+ R.layout.activity_chooser_view_list_item, parent, false);
+ convertView.setId(ITEM_VIEW_TYPE_FOOTER);
+ TextView titleView = (TextView) convertView.findViewById(R.id.title);
+ titleView.setText(mContext.getString(
+ R.string.activity_chooser_view_see_all));
+ }
+ return convertView;
case ITEM_VIEW_TYPE_ACTIVITY:
if (convertView == null || convertView.getId() != R.id.list_item) {
convertView = LayoutInflater.from(getContext()).inflate(
@@ -695,6 +578,12 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
// Set the title.
TextView titleView = (TextView) convertView.findViewById(R.id.title);
titleView.setText(activity.loadLabel(packageManager));
+ // Highlight the default.
+ if (mShowDefaultActivity && position == 0) {
+ convertView.setActivated(true);
+ } else {
+ convertView.setActivated(false);
+ }
return convertView;
default:
throw new IllegalArgumentException();
@@ -702,7 +591,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
}
public int measureContentWidth() {
- // The user may have specified some of the target not to be show but we
+ // The user may have specified some of the target not to be shown but we
// want to measure all of them since after expansion they should fit.
final int oldMaxActivityCount = mMaxActivityCount;
mMaxActivityCount = MAX_ACTIVITY_COUNT_UNLIMITED;
@@ -733,19 +622,12 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
}
public ResolveInfo getDefaultActivity() {
- return mDefaultActivity;
- }
-
- public void setHeaderView(View headerView) {
- if (mHeaderView != headerView) {
- mHeaderView = headerView;
- notifyDataSetChanged();
- }
+ return mDataModel.getDefaultActivity();
}
- public void setFooterView(View footerView) {
- if (mFooterView != footerView) {
- mFooterView = footerView;
+ public void setShowFooterView(boolean showFooterView) {
+ if (mShowFooterView != showFooterView) {
+ mShowFooterView = showFooterView;
notifyDataSetChanged();
}
}
@@ -761,5 +643,12 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
public ActivityChooserModel getDataModel() {
return mDataModel;
}
+
+ public void setShowDefaultActivity(boolean showDefaultActivity) {
+ if (mShowDefaultActivity != showDefaultActivity) {
+ mShowDefaultActivity = showDefaultActivity;
+ notifyDataSetChanged();
+ }
+ }
}
}
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index f8c76f2..1b713c3 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -21,6 +21,7 @@ import com.android.internal.R;
import android.annotation.Widget;
import android.app.Service;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Canvas;
@@ -239,21 +240,11 @@ public class CalendarView extends FrameLayout {
private String[] mDayLabels;
/**
- * Temporary instance to avoid multiple instantiations.
- */
- private Calendar mTempDate = Calendar.getInstance();
-
- /**
* The first day of the week.
*/
private int mFirstDayOfWeek;
/**
- * The first day of the focused month.
- */
- private Calendar mFirstDayOfMonth = Calendar.getInstance();
-
- /**
* Which month should be displayed/highlighted [0-11].
*/
private int mCurrentMonthDisplayed;
@@ -289,14 +280,24 @@ public class CalendarView extends FrameLayout {
private ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable();
/**
+ * Temporary instance to avoid multiple instantiations.
+ */
+ private Calendar mTempDate;
+
+ /**
+ * The first day of the focused month.
+ */
+ private Calendar mFirstDayOfMonth;
+
+ /**
* The start date of the range supported by this picker.
*/
- private Calendar mMinDate = Calendar.getInstance();
+ private Calendar mMinDate;
/**
* The end date of the range supported by this picker.
*/
- private Calendar mMaxDate = Calendar.getInstance();
+ private Calendar mMaxDate;
/**
* Date format for parsing dates.
@@ -304,6 +305,11 @@ public class CalendarView extends FrameLayout {
private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
/**
+ * The current locale.
+ */
+ private Locale mCurrentLocale;
+
+ /**
* The callback used to indicate the user changes the date.
*/
public interface OnDateChangeListener {
@@ -330,6 +336,9 @@ public class CalendarView extends FrameLayout {
public CalendarView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, 0);
+ // initialization based on locale
+ setCurrentLocale(Locale.getDefault());
+
TypedValue calendarViewStyle = new TypedValue();
context.getTheme().resolveAttribute(R.attr.calendarViewStyle, calendarViewStyle, true);
TypedArray attributesArray = context.obtainStyledAttributes(calendarViewStyle.resourceId,
@@ -366,6 +375,7 @@ public class CalendarView extends FrameLayout {
com.android.internal.R.styleable.TextAppearance);
mDateTextSize = dateTextAppearance.getDimensionPixelSize(
R.styleable.TextAppearance_textSize, DEFAULT_DATE_TEXT_SIZE);
+ dateTextAppearance.recycle();
int weekDayTextAppearanceResId = attributesArray.getResourceId(
R.styleable.CalendarView_weekDayTextAppearance,
@@ -413,6 +423,12 @@ public class CalendarView extends FrameLayout {
return mListView.isEnabled();
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ setCurrentLocale(newConfig.locale);
+ }
+
/**
* Gets the minimal date supported by this {@link CalendarView} in milliseconds
* since January 1, 1970 00:00:00 in {@link TimeZone#getDefault()} time
@@ -624,6 +640,41 @@ public class CalendarView extends FrameLayout {
}
/**
+ * Sets the current locale.
+ *
+ * @param locale The current locale.
+ */
+ private void setCurrentLocale(Locale locale) {
+ if (locale.equals(mCurrentLocale)) {
+ return;
+ }
+
+ mCurrentLocale = locale;
+
+ mTempDate = getCalendarForLocale(mTempDate, locale);
+ mFirstDayOfMonth = getCalendarForLocale(mFirstDayOfMonth, locale);
+ mMinDate = getCalendarForLocale(mMinDate, locale);
+ mMaxDate = getCalendarForLocale(mMaxDate, locale);
+ }
+
+ /**
+ * Gets a calendar for locale bootstrapped with the value of a given calendar.
+ *
+ * @param oldCalendar The old calendar.
+ * @param locale The locale.
+ */
+ private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
+ if (oldCalendar == null) {
+ return Calendar.getInstance(locale);
+ } else {
+ final long currentTimeMillis = oldCalendar.getTimeInMillis();
+ Calendar newCalendar = Calendar.getInstance(locale);
+ newCalendar.setTimeInMillis(currentTimeMillis);
+ return newCalendar;
+ }
+ }
+
+ /**
* @return True if the <code>firstDate</code> is the same as the <code>
* secondDate</code>.
*/
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 30fb927..4812283 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -16,10 +16,9 @@
package android.widget;
-import com.android.internal.R;
-
import android.annotation.Widget;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,6 +32,8 @@ import android.view.LayoutInflater;
import android.view.accessibility.AccessibilityEvent;
import android.widget.NumberPicker.OnValueChangeListener;
+import com.android.internal.R;
+
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
@@ -89,23 +90,23 @@ public class DatePicker extends FrameLayout {
private final CalendarView mCalendarView;
- private OnDateChangedListener mOnDateChangedListener;
+ private Locale mCurrentLocale;
- private Locale mMonthLocale;
+ private OnDateChangedListener mOnDateChangedListener;
- private final Calendar mTempDate = Calendar.getInstance();
+ private String[] mShortMonths;
- private final int mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
+ private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
- private final String[] mShortMonths = new String[mNumberOfMonths];
+ private int mNumberOfMonths;
- private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
+ private Calendar mTempDate;
- private final Calendar mMinDate = Calendar.getInstance();
+ private Calendar mMinDate;
- private final Calendar mMaxDate = Calendar.getInstance();
+ private Calendar mMaxDate;
- private final Calendar mCurrentDate = Calendar.getInstance();
+ private Calendar mCurrentDate;
private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
@@ -137,6 +138,9 @@ public class DatePicker extends FrameLayout {
public DatePicker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ // initialization based on locale
+ setCurrentLocale(Locale.getDefault());
+
TypedArray attributesArray = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
defStyle, 0);
boolean spinnersShown = attributesArray.getBoolean(R.styleable.DatePicker_spinnersShown,
@@ -213,7 +217,7 @@ public class DatePicker extends FrameLayout {
mMonthSpinner = (NumberPicker) findViewById(R.id.month);
mMonthSpinner.setMinValue(0);
mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
- mMonthSpinner.setDisplayedValues(getShortMonths());
+ mMonthSpinner.setDisplayedValues(mShortMonths);
mMonthSpinner.setOnLongPressUpdateInterval(200);
mMonthSpinner.setOnValueChangedListener(onChangeListener);
@@ -363,6 +367,12 @@ public class DatePicker extends FrameLayout {
event.getText().add(selectedDateUtterance);
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ setCurrentLocale(newConfig.locale);
+ }
+
/**
* Gets whether the {@link CalendarView} is shown.
*
@@ -411,6 +421,48 @@ public class DatePicker extends FrameLayout {
}
/**
+ * Sets the current locale.
+ *
+ * @param locale The current locale.
+ */
+ private void setCurrentLocale(Locale locale) {
+ if (locale.equals(mCurrentLocale)) {
+ return;
+ }
+
+ mCurrentLocale = locale;
+
+ mTempDate = getCalendarForLocale(mTempDate, locale);
+ mMinDate = getCalendarForLocale(mMinDate, locale);
+ mMaxDate = getCalendarForLocale(mMaxDate, locale);
+ mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
+
+ mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
+ mShortMonths = new String[mNumberOfMonths];
+ for (int i = 0; i < mNumberOfMonths; i++) {
+ mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
+ DateUtils.LENGTH_MEDIUM);
+ }
+ }
+
+ /**
+ * Gets a calendar for locale bootstrapped with the value of a given calendar.
+ *
+ * @param oldCalendar The old calendar.
+ * @param locale The locale.
+ */
+ private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
+ if (oldCalendar == null) {
+ return Calendar.getInstance(locale);
+ } else {
+ final long currentTimeMillis = oldCalendar.getTimeInMillis();
+ Calendar newCalendar = Calendar.getInstance(locale);
+ newCalendar.setTimeInMillis(currentTimeMillis);
+ return newCalendar;
+ }
+ }
+
+ /**
* Reorders the spinners according to the date format that is
* explicitly set by the user and if no such is set fall back
* to the current locale's default format.
@@ -507,23 +559,6 @@ public class DatePicker extends FrameLayout {
}
}
- /**
- * @return The short month abbreviations.
- */
- private String[] getShortMonths() {
- final Locale currentLocale = Locale.getDefault();
- if (currentLocale.equals(mMonthLocale)) {
- return mShortMonths;
- } else {
- for (int i = 0; i < mNumberOfMonths; i++) {
- mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i,
- DateUtils.LENGTH_MEDIUM);
- }
- mMonthLocale = currentLocale;
- return mShortMonths;
- }
- }
-
private boolean isNewDate(int year, int month, int dayOfMonth) {
return (mCurrentDate.get(Calendar.YEAR) != year
|| mCurrentDate.get(Calendar.MONTH) != dayOfMonth
@@ -569,7 +604,7 @@ public class DatePicker extends FrameLayout {
// make sure the month names are a zero based array
// with the months in the month spinner
- String[] displayedValues = Arrays.copyOfRange(getShortMonths(),
+ String[] displayedValues = Arrays.copyOfRange(mShortMonths,
mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
mMonthSpinner.setDisplayedValues(displayedValues);
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index d6e426f..2e0cc62 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -18,18 +18,23 @@ package android.widget;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.ActionProvider;
+import android.view.Menu;
import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.SubMenu;
import android.view.View;
import com.android.internal.R;
/**
* This is a provider for a share action. It is responsible for creating views
- * that enable data sharing and also to perform a default action for showing
- * a share dialog.
+ * that enable data sharing and also to show a sub menu with sharing activities
+ * if the hosting item is placed on the overflow menu.
* <p>
* Here is how to use the action provider with custom backing file in a {@link MenuItem}:
* </p>
@@ -47,15 +52,13 @@ import com.android.internal.R;
* // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
* // line if using the default share history file is desired.
* mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
- * // Get the action view and hold onto it to set the share intent.
- * mActionView = menuItem.getActionView();
* . . .
* }
*
* // Somewhere in the application.
* public void doShare(Intent shareIntent) {
* // When you want to share set the share intent.
- * mShareActionProvider.setShareIntent(mActionView, shareIntent);
+ * mShareActionProvider.setShareIntent(shareIntent);
* }
* </pre>
* </code>
@@ -70,11 +73,34 @@ import com.android.internal.R;
public class ShareActionProvider extends ActionProvider {
/**
+ * The default for the maximal number of activities shown in the sub-menu.
+ */
+ private static final int DEFAULT_INITIAL_ACTIVITY_COUNT = 4;
+
+ /**
+ * The the maximum number activities shown in the sub-menu.
+ */
+ private int mMaxShownActivityCount = DEFAULT_INITIAL_ACTIVITY_COUNT;
+
+ /**
+ * Listener for handling menu item clicks.
+ */
+ private final ShareMenuItemOnMenuItemClickListener mOnMenuItemClickListener =
+ new ShareMenuItemOnMenuItemClickListener();
+
+ /**
* The default name for storing share history.
*/
public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
+ /**
+ * Context for accessing resources.
+ */
private final Context mContext;
+
+ /**
+ * The name of the file with share history data.
+ */
private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;
/**
@@ -92,13 +118,17 @@ public class ShareActionProvider extends ActionProvider {
*/
@Override
public View onCreateActionView() {
+ // Create the view and set its data model.
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
activityChooserView.setActivityChooserModel(dataModel);
+
+ // Lookup and set the expand action icon.
TypedValue outTypedValue = new TypedValue();
mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true);
Drawable drawable = mContext.getResources().getDrawable(outTypedValue.resourceId);
activityChooserView.setExpandActivityOverflowButtonDrawable(drawable);
+
return activityChooserView;
}
@@ -106,12 +136,40 @@ public class ShareActionProvider extends ActionProvider {
* {@inheritDoc}
*/
@Override
- public void onPerformDefaultAction(View actionView) {
- if (actionView instanceof ActivityChooserView) {
- ActivityChooserView activityChooserView = (ActivityChooserView) actionView;
- activityChooserView.showPopup();
- } else {
- throw new IllegalArgumentException("actionView not instance of ActivityChooserView");
+ public boolean hasSubMenu() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onPrepareSubMenu(SubMenu subMenu) {
+ // Clear since the order of items may change.
+ subMenu.clear();
+
+ ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
+ PackageManager packageManager = mContext.getPackageManager();
+
+ final int expandedActivityCount = dataModel.getActivityCount();
+ final int collapsedActivityCount = Math.min(expandedActivityCount, mMaxShownActivityCount);
+
+ // Populate the sub-menu with a sub set of the activities.
+ for (int i = 0; i < collapsedActivityCount; i++) {
+ ResolveInfo activity = dataModel.getActivity(i);
+ subMenu.add(0, i, i, activity.loadLabel(packageManager))
+ .setIcon(activity.loadIcon(packageManager))
+ .setOnMenuItemClickListener(mOnMenuItemClickListener);
+ }
+
+ // Add a sub-menu for showing all activities as a list item.
+ SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount,
+ collapsedActivityCount, mContext.getString(R.string.activity_chooser_view_see_all));
+ for (int i = 0; i < expandedActivityCount; i++) {
+ ResolveInfo activity = dataModel.getActivity(i);
+ expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager))
+ .setIcon(activity.loadIcon(packageManager))
+ .setOnMenuItemClickListener(mOnMenuItemClickListener);
}
}
@@ -147,18 +205,29 @@ public class ShareActionProvider extends ActionProvider {
* </code>
* </p>
*
- * @param actionView An action view created by {@link #onCreateActionView()}.
* @param shareIntent The share intent.
*
* @see Intent#ACTION_SEND
* @see Intent#ACTION_SEND_MULTIPLE
*/
- public void setShareIntent(View actionView, Intent shareIntent) {
- if (actionView instanceof ActivityChooserView) {
- ActivityChooserView activityChooserView = (ActivityChooserView) actionView;
- activityChooserView.getDataModel().setIntent(shareIntent);
- } else {
- throw new IllegalArgumentException("actionView not instance of ActivityChooserView");
+ public void setShareIntent(Intent shareIntent) {
+ ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
+ mShareHistoryFileName);
+ dataModel.setIntent(shareIntent);
+ }
+
+ /**
+ * Reusable listener for handling share item clicks.
+ */
+ private class ShareMenuItemOnMenuItemClickListener implements OnMenuItemClickListener {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
+ mShareHistoryFileName);
+ final int itemId = item.getItemId();
+ Intent launchIntent = dataModel.chooseActivity(itemId);
+ mContext.startActivity(launchIntent);
+ return true;
}
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1e63e26..6b4e454 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -16,11 +16,6 @@
package android.widget;
-import com.android.internal.util.FastMath;
-import com.android.internal.widget.EditableInputConnection;
-
-import org.xmlpull.v1.XmlPullParserException;
-
import android.R;
import android.content.ClipData;
import android.content.ClipData.Item;
@@ -132,6 +127,11 @@ import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.RemoteViews.RemoteView;
+import com.android.internal.util.FastMath;
+import com.android.internal.widget.EditableInputConnection;
+
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.text.BreakIterator;
@@ -260,9 +260,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
class Drawables {
final Rect mCompoundRect = new Rect();
- Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight;
- int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight;
- int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight;
+ Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight,
+ mDrawableStart, mDrawableEnd;
+ int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight,
+ mDrawableSizeStart, mDrawableSizeEnd;
+ int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight,
+ mDrawableHeightStart, mDrawableHeightEnd;
int mDrawablePadding;
}
private Drawables mDrawables;
@@ -352,6 +355,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
INHERIT, GRAVITY, TEXT_START, TEXT_END, CENTER, VIEW_START, VIEW_END;
}
+ private boolean bResolvedDrawables = false;
+
/*
* Kick-start the font cache for the zygote process (to pay the cost of
* initializing freetype for our default font only once).
@@ -494,7 +499,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int buffertype = 0;
boolean selectallonfocus = false;
Drawable drawableLeft = null, drawableTop = null, drawableRight = null,
- drawableBottom = null;
+ drawableBottom = null, drawableStart = null, drawableEnd = null;
int drawablePadding = 0;
int ellipsize = -1;
boolean singleLine = false;
@@ -571,6 +576,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
drawableBottom = a.getDrawable(attr);
break;
+ case com.android.internal.R.styleable.TextView_drawableStart:
+ drawableStart = a.getDrawable(attr);
+ break;
+
+ case com.android.internal.R.styleable.TextView_drawableEnd:
+ drawableEnd = a.getDrawable(attr);
+ break;
+
case com.android.internal.R.styleable.TextView_drawablePadding:
drawablePadding = a.getDimensionPixelSize(attr, drawablePadding);
break;
@@ -980,6 +993,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
setCompoundDrawablesWithIntrinsicBounds(
drawableLeft, drawableTop, drawableRight, drawableBottom);
+ setRelativeDrawablesIfNeeded(drawableStart, drawableEnd);
setCompoundDrawablePadding(drawablePadding);
// Same as setSingleLine(), but make sure the transformation method and the maximum number
@@ -1105,6 +1119,42 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
setTypeface(tf, styleIndex);
}
+ private void setRelativeDrawablesIfNeeded(Drawable start, Drawable end) {
+ boolean hasRelativeDrawables = (start != null) || (end != null);
+ if (hasRelativeDrawables) {
+ Drawables dr = mDrawables;
+ if (dr == null) {
+ mDrawables = dr = new Drawables();
+ }
+ final Rect compoundRect = dr.mCompoundRect;
+ int[] state = getDrawableState();
+ if (start != null) {
+ start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight());
+ start.setState(state);
+ start.copyBounds(compoundRect);
+ start.setCallback(this);
+
+ dr.mDrawableStart = start;
+ dr.mDrawableSizeStart = compoundRect.width();
+ dr.mDrawableHeightStart = compoundRect.height();
+ } else {
+ dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0;
+ }
+ if (end != null) {
+ end.setBounds(0, 0, end.getIntrinsicWidth(), end.getIntrinsicHeight());
+ end.setState(state);
+ end.copyBounds(compoundRect);
+ end.setCallback(this);
+
+ dr.mDrawableEnd = end;
+ dr.mDrawableSizeEnd = compoundRect.width();
+ dr.mDrawableHeightEnd = compoundRect.height();
+ } else {
+ dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0;
+ }
+ }
+ }
+
@Override
public void setEnabled(boolean enabled) {
if (enabled == isEnabled()) {
@@ -1119,6 +1169,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
super.setEnabled(enabled);
+ prepareCursorControllers();
}
/**
@@ -1410,6 +1461,40 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
+ * Returns the start padding of the view, plus space for the start
+ * Drawable if any.
+ *
+ * @hide
+ */
+ public int getCompoundPaddingStart() {
+ resolveDrawables();
+ switch(getResolvedLayoutDirection()) {
+ default:
+ case LAYOUT_DIRECTION_LTR:
+ return getCompoundPaddingLeft();
+ case LAYOUT_DIRECTION_RTL:
+ return getCompoundPaddingRight();
+ }
+ }
+
+ /**
+ * Returns the end padding of the view, plus space for the end
+ * Drawable if any.
+ *
+ * @hide
+ */
+ public int getCompoundPaddingEnd() {
+ resolveDrawables();
+ switch(getResolvedLayoutDirection()) {
+ default:
+ case LAYOUT_DIRECTION_LTR:
+ return getCompoundPaddingRight();
+ case LAYOUT_DIRECTION_RTL:
+ return getCompoundPaddingLeft();
+ }
+ }
+
+ /**
* Returns the extended top padding of the view, including both the
* top Drawable if any and any extra space to keep more than maxLines
* of text from showing. It is only valid to call this after measuring.
@@ -1492,6 +1577,26 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
+ * Returns the total start padding of the view, including the start
+ * Drawable if any.
+ *
+ * @hide
+ */
+ public int getTotalPaddingStart() {
+ return getCompoundPaddingStart();
+ }
+
+ /**
+ * Returns the total end padding of the view, including the end
+ * Drawable if any.
+ *
+ * @hide
+ */
+ public int getTotalPaddingEnd() {
+ return getCompoundPaddingEnd();
+ }
+
+ /**
* Returns the total top padding of the view, including the top
* Drawable if any, the extra space to keep more than maxLines
* from showing, and the vertical offset for gravity, if any.
@@ -1678,6 +1783,185 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
+ * Sets the Drawables (if any) to appear to the start of, above,
+ * to the end of, and below the text. Use null if you do not
+ * want a Drawable there. The Drawables must already have had
+ * {@link Drawable#setBounds} called.
+ *
+ * @attr ref android.R.styleable#TextView_drawableStart
+ * @attr ref android.R.styleable#TextView_drawableTop
+ * @attr ref android.R.styleable#TextView_drawableEnd
+ * @attr ref android.R.styleable#TextView_drawableBottom
+ *
+ * @hide
+ */
+ public void setCompoundDrawablesRelative(Drawable start, Drawable top,
+ Drawable end, Drawable bottom) {
+ Drawables dr = mDrawables;
+
+ final boolean drawables = start != null || top != null
+ || end != null || bottom != null;
+
+ if (!drawables) {
+ // Clearing drawables... can we free the data structure?
+ if (dr != null) {
+ if (dr.mDrawablePadding == 0) {
+ mDrawables = null;
+ } else {
+ // We need to retain the last set padding, so just clear
+ // out all of the fields in the existing structure.
+ if (dr.mDrawableStart != null) dr.mDrawableStart.setCallback(null);
+ dr.mDrawableStart = null;
+ if (dr.mDrawableTop != null) dr.mDrawableTop.setCallback(null);
+ dr.mDrawableTop = null;
+ if (dr.mDrawableEnd != null) dr.mDrawableEnd.setCallback(null);
+ dr.mDrawableEnd = null;
+ if (dr.mDrawableBottom != null) dr.mDrawableBottom.setCallback(null);
+ dr.mDrawableBottom = null;
+ dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0;
+ dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0;
+ dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0;
+ dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0;
+ }
+ }
+ } else {
+ if (dr == null) {
+ mDrawables = dr = new Drawables();
+ }
+
+ if (dr.mDrawableStart != start && dr.mDrawableStart != null) {
+ dr.mDrawableStart.setCallback(null);
+ }
+ dr.mDrawableStart = start;
+
+ if (dr.mDrawableTop != top && dr.mDrawableTop != null) {
+ dr.mDrawableTop.setCallback(null);
+ }
+ dr.mDrawableTop = top;
+
+ if (dr.mDrawableEnd != end && dr.mDrawableEnd != null) {
+ dr.mDrawableEnd.setCallback(null);
+ }
+ dr.mDrawableEnd = end;
+
+ if (dr.mDrawableBottom != bottom && dr.mDrawableBottom != null) {
+ dr.mDrawableBottom.setCallback(null);
+ }
+ dr.mDrawableBottom = bottom;
+
+ final Rect compoundRect = dr.mCompoundRect;
+ int[] state;
+
+ state = getDrawableState();
+
+ if (start != null) {
+ start.setState(state);
+ start.copyBounds(compoundRect);
+ start.setCallback(this);
+ dr.mDrawableSizeStart = compoundRect.width();
+ dr.mDrawableHeightStart = compoundRect.height();
+ } else {
+ dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0;
+ }
+
+ if (end != null) {
+ end.setState(state);
+ end.copyBounds(compoundRect);
+ end.setCallback(this);
+ dr.mDrawableSizeEnd = compoundRect.width();
+ dr.mDrawableHeightEnd = compoundRect.height();
+ } else {
+ dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0;
+ }
+
+ if (top != null) {
+ top.setState(state);
+ top.copyBounds(compoundRect);
+ top.setCallback(this);
+ dr.mDrawableSizeTop = compoundRect.height();
+ dr.mDrawableWidthTop = compoundRect.width();
+ } else {
+ dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0;
+ }
+
+ if (bottom != null) {
+ bottom.setState(state);
+ bottom.copyBounds(compoundRect);
+ bottom.setCallback(this);
+ dr.mDrawableSizeBottom = compoundRect.height();
+ dr.mDrawableWidthBottom = compoundRect.width();
+ } else {
+ dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0;
+ }
+ }
+
+ resolveDrawables();
+ invalidate();
+ requestLayout();
+ }
+
+ /**
+ * Sets the Drawables (if any) to appear to the start of, above,
+ * to the end of, and below the text. Use 0 if you do not
+ * want a Drawable there. The Drawables' bounds will be set to
+ * their intrinsic bounds.
+ *
+ * @param start Resource identifier of the start Drawable.
+ * @param top Resource identifier of the top Drawable.
+ * @param end Resource identifier of the end Drawable.
+ * @param bottom Resource identifier of the bottom Drawable.
+ *
+ * @attr ref android.R.styleable#TextView_drawableStart
+ * @attr ref android.R.styleable#TextView_drawableTop
+ * @attr ref android.R.styleable#TextView_drawableEnd
+ * @attr ref android.R.styleable#TextView_drawableBottom
+ *
+ * @hide
+ */
+ public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end,
+ int bottom) {
+ resetResolvedDrawables();
+ final Resources resources = getContext().getResources();
+ setCompoundDrawablesRelativeWithIntrinsicBounds(
+ start != 0 ? resources.getDrawable(start) : null,
+ top != 0 ? resources.getDrawable(top) : null,
+ end != 0 ? resources.getDrawable(end) : null,
+ bottom != 0 ? resources.getDrawable(bottom) : null);
+ }
+
+ /**
+ * Sets the Drawables (if any) to appear to the start of, above,
+ * to the end of, and below the text. Use null if you do not
+ * want a Drawable there. The Drawables' bounds will be set to
+ * their intrinsic bounds.
+ *
+ * @attr ref android.R.styleable#TextView_drawableStart
+ * @attr ref android.R.styleable#TextView_drawableTop
+ * @attr ref android.R.styleable#TextView_drawableEnd
+ * @attr ref android.R.styleable#TextView_drawableBottom
+ *
+ * @hide
+ */
+ public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top,
+ Drawable end, Drawable bottom) {
+
+ resetResolvedDrawables();
+ if (start != null) {
+ start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight());
+ }
+ if (end != null) {
+ end.setBounds(0, 0, end.getIntrinsicWidth(), end.getIntrinsicHeight());
+ }
+ if (top != null) {
+ top.setBounds(0, 0, top.getIntrinsicWidth(), top.getIntrinsicHeight());
+ }
+ if (bottom != null) {
+ bottom.setBounds(0, 0, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight());
+ }
+ setCompoundDrawablesRelative(start, top, end, bottom);
+ }
+
+ /**
* Returns drawables for the left, top, right, and bottom borders.
*/
public Drawable[] getCompoundDrawables() {
@@ -1692,6 +1976,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
+ * Returns drawables for the start, top, end, and bottom borders.
+ *
+ * @hide
+ */
+ public Drawable[] getCompoundDrawablesRelative() {
+ final Drawables dr = mDrawables;
+ if (dr != null) {
+ return new Drawable[] {
+ dr.mDrawableStart, dr.mDrawableTop, dr.mDrawableEnd, dr.mDrawableBottom
+ };
+ } else {
+ return new Drawable[] { null, null, null, null };
+ }
+ }
+
+ /**
* Sets the size of the padding between the compound drawables and
* the text.
*
@@ -2494,6 +2794,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (dr.mDrawableRight != null && dr.mDrawableRight.isStateful()) {
dr.mDrawableRight.setState(state);
}
+ if (dr.mDrawableStart != null && dr.mDrawableStart.isStateful()) {
+ dr.mDrawableStart.setState(state);
+ }
+ if (dr.mDrawableEnd != null && dr.mDrawableEnd.isStateful()) {
+ dr.mDrawableEnd.setState(state);
+ }
}
}
@@ -2841,8 +3147,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Do not change the movement method for text that support text selection as it
// would prevent an arbitrary cursor displacement.
- final boolean hasTextSelection = this instanceof EditText || mTextIsSelectable;
- if (mLinksClickable && !hasTextSelection) {
+ if (mLinksClickable && !textCanBeSelected()) {
setMovementMethod(LinkMovementMethod.getInstance());
}
}
@@ -3546,7 +3851,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mErrorWasChanged = true;
final Drawables dr = mDrawables;
if (dr != null) {
- setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon, dr.mDrawableBottom);
+ switch (getResolvedLayoutDirection()) {
+ default:
+ case LAYOUT_DIRECTION_LTR:
+ setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon,
+ dr.mDrawableBottom);
+ break;
+ case LAYOUT_DIRECTION_RTL:
+ setCompoundDrawables(icon, dr.mDrawableTop, dr.mDrawableRight,
+ dr.mDrawableBottom);
+ break;
+ }
} else {
setCompoundDrawables(null, null, icon, null);
}
@@ -4048,6 +4363,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mSelectionModifierCursorController != null) {
observer.addOnTouchModeChangeListener(mSelectionModifierCursorController);
}
+
+ // Resolve drawables as the layout direction has been resolved
+ resolveDrawables();
}
@Override
@@ -4077,6 +4395,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
hideControllers();
+
+ resetResolvedDrawables();
}
@Override
@@ -4111,7 +4431,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final boolean verified = super.verifyDrawable(who);
if (!verified && mDrawables != null) {
return who == mDrawables.mDrawableLeft || who == mDrawables.mDrawableTop ||
- who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom;
+ who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom ||
+ who == mDrawables.mDrawableStart || who == mDrawables.mDrawableEnd;
}
return verified;
}
@@ -4132,6 +4453,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mDrawables.mDrawableBottom != null) {
mDrawables.mDrawableBottom.jumpToCurrentState();
}
+ if (mDrawables.mDrawableStart != null) {
+ mDrawables.mDrawableStart.jumpToCurrentState();
+ }
+ if (mDrawables.mDrawableEnd != null) {
+ mDrawables.mDrawableEnd.jumpToCurrentState();
+ }
}
}
@@ -4192,7 +4519,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mDrawables != null) {
final Drawables drawables = mDrawables;
if (who == drawables.mDrawableLeft || who == drawables.mDrawableRight ||
- who == drawables.mDrawableTop || who == drawables.mDrawableBottom) {
+ who == drawables.mDrawableTop || who == drawables.mDrawableBottom ||
+ who == drawables.mDrawableStart || who == drawables.mDrawableEnd) {
return getResolvedLayoutDirection();
}
}
@@ -4211,6 +4539,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (dr.mDrawableTop != null) dr.mDrawableTop.mutate().setAlpha(alpha);
if (dr.mDrawableRight != null) dr.mDrawableRight.mutate().setAlpha(alpha);
if (dr.mDrawableBottom != null) dr.mDrawableBottom.mutate().setAlpha(alpha);
+ if (dr.mDrawableStart != null) dr.mDrawableStart.mutate().setAlpha(alpha);
+ if (dr.mDrawableEnd != null) dr.mDrawableEnd.mutate().setAlpha(alpha);
}
return true;
}
@@ -4228,7 +4558,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* {@link android.R.styleable#TextView_textIsSelectable} XML attribute to make this TextView
* selectable (text is not selectable by default).
*
- * Note that the content of an EditText is always selectable.
+ * Note that this method simply returns the state of this flag. Although this flag has to be set
+ * in order to select text in non-editable TextView, the content of an {@link EditText} can
+ * always be selected, independently of the value of this flag.
*
* @return True if the text displayed in this TextView can be selected by the user.
*
@@ -4465,12 +4797,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
selStart = getSelectionStart();
selEnd = getSelectionEnd();
- if ((isCursorVisible() || mTextIsSelectable) && selStart >= 0 && isEnabled()) {
+ if (selStart >= 0) {
if (mHighlightPath == null)
mHighlightPath = new Path();
if (selStart == selEnd) {
- if (!mTextIsSelectable &&
+ if (isCursorVisible() &&
(SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK) < BLINK) {
if (mHighlightPathBogus) {
mHighlightPath.reset();
@@ -4489,7 +4821,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
highlight = mHighlightPath;
drawCursor = mCursorCount > 0;
}
- } else {
+ } else if (textCanBeSelected()) {
if (mHighlightPathBogus) {
mHighlightPath.reset();
mLayout.getSelectionPath(selStart, selEnd, mHighlightPath);
@@ -5571,8 +5903,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
@Override
- protected void resetLayoutDirectionResolution() {
- super.resetLayoutDirectionResolution();
+ protected void resetResolvedLayoutDirection() {
+ super.resetResolvedLayoutDirection();
if (mLayoutAlignment != null &&
(mTextAlign == TextAlign.VIEW_START ||
@@ -6212,6 +6544,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int scrollx, scrolly;
+ // Convert to left, center, or right alignment.
+ if (a == Layout.Alignment.ALIGN_NORMAL) {
+ a = dir == Layout.DIR_LEFT_TO_RIGHT ? Layout.Alignment.ALIGN_LEFT :
+ Layout.Alignment.ALIGN_RIGHT;
+ } else if (a == Layout.Alignment.ALIGN_OPPOSITE){
+ a = dir == Layout.DIR_LEFT_TO_RIGHT ? Layout.Alignment.ALIGN_RIGHT :
+ Layout.Alignment.ALIGN_LEFT;
+ }
+
if (a == Layout.Alignment.ALIGN_CENTER) {
/*
* Keep centered if possible, or, if it is too wide to fit,
@@ -6230,28 +6571,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
scrollx = left;
}
}
- } else if (a == Layout.Alignment.ALIGN_NORMAL) {
- /*
- * Keep leading edge in view.
- */
-
- if (dir < 0) {
- int right = (int) FloatMath.ceil(mLayout.getLineRight(line));
- scrollx = right - hspace;
- } else {
- scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line));
- }
- } else /* a == Layout.Alignment.ALIGN_OPPOSITE */ {
- /*
- * Keep trailing edge in view.
- */
-
- if (dir < 0) {
- scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line));
- } else {
- int right = (int) FloatMath.ceil(mLayout.getLineRight(line));
- scrollx = right - hspace;
- }
+ } else if (a == Layout.Alignment.ALIGN_LEFT) {
+ scrollx = (int) FloatMath.floor(mLayout.getLineLeft(line));
+ } else { // a == Layout.Alignment.ALIGN_RIGHT
+ int right = (int) FloatMath.ceil(mLayout.getLineRight(line));
+ scrollx = right - hspace;
}
if (ht < vspace) {
@@ -6293,20 +6617,24 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int grav;
switch (mLayout.getParagraphAlignment(line)) {
- case ALIGN_NORMAL:
+ case ALIGN_LEFT:
grav = 1;
break;
-
- case ALIGN_OPPOSITE:
+ case ALIGN_RIGHT:
grav = -1;
break;
-
+ case ALIGN_NORMAL:
+ grav = mLayout.getParagraphDirection(line);
+ break;
+ case ALIGN_OPPOSITE:
+ grav = -mLayout.getParagraphDirection(line);
+ break;
+ case ALIGN_CENTER:
default:
grav = 0;
+ break;
}
- grav *= mLayout.getParagraphDirection(line);
-
int hspace = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight();
int vspace = mBottom - mTop - getExtendedPaddingTop() - getExtendedPaddingBottom();
@@ -7454,9 +7782,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked();
- if (hasInsertionController()) {
- getInsertionController().onTouchEvent(event);
- }
if (hasSelectionController()) {
getSelectionController().onTouchEvent(event);
}
@@ -7884,7 +8209,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// prepareCursorController() relies on this method.
// If you change this condition, make sure prepareCursorController is called anywhere
// the value of this condition might be changed.
- return mText instanceof Spannable && mMovement != null && mMovement.canSelectArbitrarily();
+ if (mMovement == null || !mMovement.canSelectArbitrarily()) return false;
+ return isTextEditable() || (mTextIsSelectable && mText instanceof Spannable && isEnabled());
}
private boolean canCut() {
@@ -7972,6 +8298,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final int minOffset = extractRangeStartFromLong(lastTouchOffsets);
final int maxOffset = extractRangeEndFromLong(lastTouchOffsets);
+ // Safety check in case standard touch event handling has been bypassed
+ if (minOffset < 0 || minOffset >= mText.length()) return false;
+ if (maxOffset < 0 || maxOffset >= mText.length()) return false;
+
int selectionStart, selectionEnd;
// If a URLSpan (web address, email, phone...) is found at that position, select it.
@@ -9727,13 +10057,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public void hide();
/**
- * This method is called by {@link #onTouchEvent(MotionEvent)} and gives the controller
- * a chance to become active and/or visible.
- * @param event The touch event
- */
- public boolean onTouchEvent(MotionEvent event);
-
- /**
* Called when the view is detached from window. Perform house keeping task, such as
* stopping Runnable thread that would otherwise keep a reference on the context, thus
* preventing the activity from being recycled.
@@ -9760,10 +10083,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- public boolean onTouchEvent(MotionEvent ev) {
- return false;
- }
-
public void onTouchModeChanged(boolean isInTouchMode) {
if (!isInTouchMode) {
hide();
@@ -9822,52 +10141,49 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mEndHandle != null) mEndHandle.hide();
}
- public boolean onTouchEvent(MotionEvent event) {
+ public void onTouchEvent(MotionEvent event) {
// This is done even when the View does not have focus, so that long presses can start
// selection and tap can move cursor from this tap position.
- if (isTextEditable() || mTextIsSelectable) {
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- final float x = event.getX();
- final float y = event.getY();
-
- // Remember finger down position, to be able to start selection from there
- mMinTouchOffset = mMaxTouchOffset = getOffsetForPosition(x, y);
-
- // Double tap detection
- long duration = SystemClock.uptimeMillis() - mPreviousTapUpTime;
- if (duration <= ViewConfiguration.getDoubleTapTimeout() &&
- isPositionOnText(x, y)) {
- final float deltaX = x - mPreviousTapPositionX;
- final float deltaY = y - mPreviousTapPositionY;
- final float distanceSquared = deltaX * deltaX + deltaY * deltaY;
- if (distanceSquared < mSquaredTouchSlopDistance) {
- showSuggestions();
- mDiscardNextActionUp = true;
- }
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ final float x = event.getX();
+ final float y = event.getY();
+
+ // Remember finger down position, to be able to start selection from there
+ mMinTouchOffset = mMaxTouchOffset = getOffsetForPosition(x, y);
+
+ // Double tap detection
+ long duration = SystemClock.uptimeMillis() - mPreviousTapUpTime;
+ if (duration <= ViewConfiguration.getDoubleTapTimeout() &&
+ isPositionOnText(x, y)) {
+ final float deltaX = x - mPreviousTapPositionX;
+ final float deltaY = y - mPreviousTapPositionY;
+ final float distanceSquared = deltaX * deltaX + deltaY * deltaY;
+ if (distanceSquared < mSquaredTouchSlopDistance) {
+ showSuggestions();
+ mDiscardNextActionUp = true;
}
+ }
- mPreviousTapPositionX = x;
- mPreviousTapPositionY = y;
+ mPreviousTapPositionX = x;
+ mPreviousTapPositionY = y;
- break;
+ break;
- case MotionEvent.ACTION_POINTER_DOWN:
- case MotionEvent.ACTION_POINTER_UP:
- // Handle multi-point gestures. Keep min and max offset positions.
- // Only activated for devices that correctly handle multi-touch.
- if (mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)) {
- updateMinAndMaxOffsets(event);
- }
- break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ case MotionEvent.ACTION_POINTER_UP:
+ // Handle multi-point gestures. Keep min and max offset positions.
+ // Only activated for devices that correctly handle multi-touch.
+ if (mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)) {
+ updateMinAndMaxOffsets(event);
+ }
+ break;
- case MotionEvent.ACTION_UP:
- mPreviousTapUpTime = SystemClock.uptimeMillis();
- break;
- }
+ case MotionEvent.ACTION_UP:
+ mPreviousTapUpTime = SystemClock.uptimeMillis();
+ break;
}
- return false;
}
/**
@@ -10289,6 +10605,68 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return (dir == Character.DIRECTIONALITY_LEFT_TO_RIGHT);
}
+ /**
+ * Subclasses will need to override this method to implement their own way of resolving
+ * drawables depending on the layout direction.
+ *
+ * A call to the super method will be required from the subclasses implementation.
+ *
+ */
+ protected void resolveDrawables() {
+ // No need to resolve twice
+ if (bResolvedDrawables) {
+ return;
+ }
+ // No drawable to resolve
+ if (mDrawables == null) {
+ return;
+ }
+ // No relative drawable to resolve
+ if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) {
+ bResolvedDrawables = true;
+ return;
+ }
+
+ Drawables dr = mDrawables;
+ switch(getResolvedLayoutDirection()) {
+ case LAYOUT_DIRECTION_RTL:
+ if (dr.mDrawableStart != null) {
+ dr.mDrawableRight = dr.mDrawableStart;
+
+ dr.mDrawableSizeRight = dr.mDrawableSizeStart;
+ dr.mDrawableHeightRight = dr.mDrawableHeightStart;
+ }
+ if (dr.mDrawableEnd != null) {
+ dr.mDrawableLeft = dr.mDrawableEnd;
+
+ dr.mDrawableSizeLeft = dr.mDrawableSizeEnd;
+ dr.mDrawableHeightLeft = dr.mDrawableHeightEnd;
+ }
+ break;
+
+ case LAYOUT_DIRECTION_LTR:
+ default:
+ if (dr.mDrawableStart != null) {
+ dr.mDrawableLeft = dr.mDrawableStart;
+
+ dr.mDrawableSizeLeft = dr.mDrawableSizeStart;
+ dr.mDrawableHeightLeft = dr.mDrawableHeightStart;
+ }
+ if (dr.mDrawableEnd != null) {
+ dr.mDrawableRight = dr.mDrawableEnd;
+
+ dr.mDrawableSizeRight = dr.mDrawableSizeEnd;
+ dr.mDrawableHeightRight = dr.mDrawableHeightEnd;
+ }
+ break;
+ }
+ bResolvedDrawables = true;
+ }
+
+ protected void resetResolvedDrawables() {
+ bResolvedDrawables = false;
+ }
+
@ViewDebug.ExportedProperty(category = "text")
private CharSequence mText;
private CharSequence mTransformed;
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 423e735..0547438 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -20,6 +20,7 @@ import com.android.internal.R;
import android.annotation.Widget;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,6 +33,7 @@ import android.widget.NumberPicker.OnValueChangeListener;
import java.text.DateFormatSymbols;
import java.util.Calendar;
+import java.util.Locale;
/**
* A view for selecting the time of day, in either 24 hour or AM/PM mode. The
@@ -92,6 +94,8 @@ public class TimePicker extends FrameLayout {
private Calendar mTempCalendar;
+ private Locale mCurrentLocale;
+
/**
* The callback interface used to indicate the time has been adjusted.
*/
@@ -116,6 +120,9 @@ public class TimePicker extends FrameLayout {
public TimePicker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ // initialization based on locale
+ setCurrentLocale(Locale.getDefault());
+
// process style attributes
TypedArray attributesArray = context.obtainStyledAttributes(
attrs, R.styleable.TimePicker, defStyle, 0);
@@ -211,8 +218,6 @@ public class TimePicker extends FrameLayout {
updateHourControl();
updateAmPmControl();
- // initialize to current time
- mTempCalendar = Calendar.getInstance();
setOnTimeChangedListener(NO_OP_CHANGE_LISTENER);
// set to current time
@@ -248,6 +253,25 @@ public class TimePicker extends FrameLayout {
return mIsEnabled;
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ setCurrentLocale(newConfig.locale);
+ }
+
+ /**
+ * Sets the current locale.
+ *
+ * @param locale The current locale.
+ */
+ private void setCurrentLocale(Locale locale) {
+ if (locale.equals(mCurrentLocale)) {
+ return;
+ }
+ mCurrentLocale = locale;
+ mTempCalendar = Calendar.getInstance(locale);
+ }
+
/**
* Used to save / restore state of time picker
*/
diff --git a/core/java/com/android/internal/os/PkgUsageStats.java b/core/java/com/android/internal/os/PkgUsageStats.java
index 1ac191b..8c2c405 100755
--- a/core/java/com/android/internal/os/PkgUsageStats.java
+++ b/core/java/com/android/internal/os/PkgUsageStats.java
@@ -19,6 +19,9 @@ package com.android.internal.os;
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* implementation of PkgUsageStats associated with an
* application package.
@@ -28,6 +31,7 @@ public class PkgUsageStats implements Parcelable {
public String packageName;
public int launchCount;
public long usageTime;
+ public Map<String, Long> componentResumeTimes;
public static final Parcelable.Creator<PkgUsageStats> CREATOR
= new Parcelable.Creator<PkgUsageStats>() {
@@ -46,31 +50,45 @@ public class PkgUsageStats implements Parcelable {
+ " " + packageName + "}";
}
- public PkgUsageStats(String pkgName, int count, long time) {
+ public PkgUsageStats(String pkgName, int count, long time, Map<String, Long> lastResumeTimes) {
packageName = pkgName;
launchCount = count;
usageTime = time;
+ componentResumeTimes = new HashMap<String, Long>(lastResumeTimes);
}
public PkgUsageStats(Parcel source) {
packageName = source.readString();
launchCount = source.readInt();
usageTime = source.readLong();
+ final int N = source.readInt();
+ componentResumeTimes = new HashMap<String, Long>(N);
+ for (int i = 0; i < N; i++) {
+ String component = source.readString();
+ long lastResumeTime = source.readLong();
+ componentResumeTimes.put(component, lastResumeTime);
+ }
}
public PkgUsageStats(PkgUsageStats pStats) {
packageName = pStats.packageName;
launchCount = pStats.launchCount;
usageTime = pStats.usageTime;
+ componentResumeTimes = new HashMap<String, Long>(pStats.componentResumeTimes);
}
public int describeContents() {
return 0;
}
- public void writeToParcel(Parcel dest, int parcelableFlags){
+ public void writeToParcel(Parcel dest, int parcelableFlags) {
dest.writeString(packageName);
dest.writeInt(launchCount);
dest.writeLong(usageTime);
+ dest.writeInt(componentResumeTimes.size());
+ for (Map.Entry<String, Long> ent : componentResumeTimes.entrySet()) {
+ dest.writeString(ent.getKey());
+ dest.writeLong(ent.getValue());
+ }
}
}
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index f13e770..53516c0 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -252,9 +252,10 @@ public class RuntimeInit {
* <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
* </ul>
*
+ * @param targetSdkVersion target SDK version
* @param argv arg strings
*/
- public static final void zygoteInit(String[] argv)
+ public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
@@ -263,7 +264,7 @@ public class RuntimeInit {
commonInit();
zygoteInitNative();
- applicationInit(argv);
+ applicationInit(targetSdkVersion, argv);
}
/**
@@ -274,20 +275,22 @@ public class RuntimeInit {
* which calls {@link WrapperInit#main} which then calls this method.
* So we don't need to call commonInit() here.
*
+ * @param targetSdkVersion target SDK version
* @param argv arg strings
*/
- public static void wrapperInit(String[] argv)
+ public static void wrapperInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from wrapper");
- applicationInit(argv);
+ applicationInit(targetSdkVersion, argv);
}
- private static void applicationInit(String[] argv)
+ private static void applicationInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
+ VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 860a08c..c6b3e7c 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -47,16 +47,22 @@ public class WrapperInit {
* wrapper process instead of by forking Zygote.
*
* The first argument specifies the file descriptor for a pipe that should receive
- * the pid of this process, or 0 if none. The remaining arguments are passed to
- * the runtime.
+ * the pid of this process, or 0 if none.
+ *
+ * The second argument is the target SDK version for the app.
+ *
+ * The remaining arguments are passed to the runtime.
*
* @param args The command-line arguments.
*/
public static void main(String[] args) {
try {
+ // Parse our mandatory arguments.
+ int fdNum = Integer.parseInt(args[0], 10);
+ int targetSdkVersion = Integer.parseInt(args[1], 10);
+
// 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 {
FileDescriptor fd = ZygoteInit.createFileDescriptor(fdNum);
@@ -73,9 +79,9 @@ public class WrapperInit {
ZygoteInit.preload();
// Launch the application.
- String[] runtimeArgs = new String[args.length - 1];
- System.arraycopy(args, 1, runtimeArgs, 0, runtimeArgs.length);
- RuntimeInit.wrapperInit(runtimeArgs);
+ String[] runtimeArgs = new String[args.length - 2];
+ System.arraycopy(args, 2, runtimeArgs, 0, runtimeArgs.length);
+ RuntimeInit.wrapperInit(targetSdkVersion, runtimeArgs);
} catch (ZygoteInit.MethodAndArgsCaller caller) {
caller.run();
}
@@ -87,11 +93,12 @@ public class WrapperInit {
*
* @param invokeWith The wrapper command.
* @param niceName The nice name for the application, or null if none.
+ * @param targetSdkVersion The target SDK version for the app.
* @param pipeFd The pipe to which the application's pid should be written, or null if none.
* @param args Arguments for {@link RuntimeInit.main}.
*/
public static void execApplication(String invokeWith, String niceName,
- FileDescriptor pipeFd, String[] args) {
+ int targetSdkVersion, FileDescriptor pipeFd, String[] args) {
StringBuilder command = new StringBuilder(invokeWith);
command.append(" /system/bin/app_process /system/bin --application");
if (niceName != null) {
@@ -99,6 +106,8 @@ public class WrapperInit {
}
command.append(" com.android.internal.os.WrapperInit ");
command.append(pipeFd != null ? pipeFd.getInt$() : 0);
+ command.append(' ');
+ command.append(targetSdkVersion);
Zygote.appendQuotedShellArgs(command, args);
Zygote.execShell(command.toString());
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 7cb002c..9af7e96 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -18,6 +18,7 @@ package com.android.internal.os;
import android.net.Credentials;
import android.net.LocalSocket;
+import android.os.Build;
import android.os.Process;
import android.os.SystemProperties;
import android.util.Log;
@@ -333,6 +334,10 @@ class ZygoteConnection {
*/
int debugFlags;
+ /** from --target-sdk-version. */
+ int targetSdkVersion;
+ boolean targetSdkVersionSpecified;
+
/** from --classpath */
String classpath;
@@ -402,6 +407,14 @@ class ZygoteConnection {
gidSpecified = true;
gid = Integer.parseInt(
arg.substring(arg.indexOf('=') + 1));
+ } else if (arg.startsWith("--target-sdk-version=")) {
+ if (targetSdkVersionSpecified) {
+ throw new IllegalArgumentException(
+ "Duplicate target-sdk-version specified");
+ }
+ targetSdkVersionSpecified = true;
+ targetSdkVersion = Integer.parseInt(
+ arg.substring(arg.indexOf('=') + 1));
} else if (arg.equals("--enable-debugger")) {
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
} else if (arg.equals("--enable-safemode")) {
@@ -821,9 +834,11 @@ class ZygoteConnection {
if (parsedArgs.runtimeInit) {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
- parsedArgs.niceName, pipeFd, parsedArgs.remainingArgs);
+ parsedArgs.niceName, parsedArgs.targetSdkVersion,
+ pipeFd, parsedArgs.remainingArgs);
} else {
- RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
+ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
+ parsedArgs.remainingArgs);
}
} else {
String className;
@@ -885,6 +900,7 @@ class ZygoteConnection {
}
}
+ boolean usingWrapper = false;
if (pipeFd != null && pid > 0) {
DataInputStream is = new DataInputStream(new FileInputStream(pipeFd));
int innerPid = -1;
@@ -909,6 +925,7 @@ class ZygoteConnection {
if (parentPid > 0) {
Log.i(TAG, "Wrapped process has pid " + innerPid);
pid = innerPid;
+ usingWrapper = true;
} else {
Log.w(TAG, "Wrapped process reported a pid that is not a child of "
+ "the process that we forked: childPid=" + pid
@@ -919,6 +936,7 @@ class ZygoteConnection {
try {
mSocketOutStream.writeInt(pid);
+ mSocketOutStream.writeBoolean(usingWrapper);
} catch (IOException ex) {
Log.e(TAG, "Error reading from command socket", ex);
return true;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index b4a7e52..6ec186d 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -48,7 +48,7 @@ import java.util.ArrayList;
* Startup class for the zygote process.
*
* Pre-initializes some classes, and then waits for commands on a UNIX domain
- * socket. Based on these commands, forks of child processes that inherit
+ * socket. Based on these commands, forks off child processes that inherit
* the initial state of the VM.
*
* Please see {@link ZygoteConnection.Arguments} for documentation on the
@@ -453,12 +453,13 @@ public class ZygoteInit {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
- parsedArgs.niceName, null, parsedArgs.remainingArgs);
+ parsedArgs.niceName, parsedArgs.targetSdkVersion,
+ null, parsedArgs.remainingArgs);
} else {
/*
* Pass the remaining arguments to SystemServer.
*/
- RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
+ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
/* should never reach here */
@@ -491,7 +492,9 @@ public class ZygoteInit {
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
- parsedArgs.gids, parsedArgs.debugFlags, null,
+ parsedArgs.gids,
+ parsedArgs.debugFlags,
+ null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index b86eb13..9c06d69 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -20,7 +20,8 @@ import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView;
import android.content.Context;
import android.content.res.Resources;
-import android.util.Log;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.util.SparseBooleanArray;
import android.view.MenuItem;
import android.view.SoundEffectConstants;
@@ -60,6 +61,9 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
private OpenOverflowRunnable mPostedOpenRunnable;
+ final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback();
+ int mOpenSubMenuId;
+
public ActionMenuPresenter() {
super(com.android.internal.R.layout.action_menu_layout,
com.android.internal.R.layout.action_menu_item_layout);
@@ -196,8 +200,12 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
topSubMenu = (SubMenuBuilder) topSubMenu.getParentMenu();
}
View anchor = findViewForItem(topSubMenu.getItem());
- if (anchor == null) return false;
+ if (anchor == null) {
+ if (mOverflowButton == null) return false;
+ anchor = mOverflowButton;
+ }
+ mOpenSubMenuId = subMenu.getItem().getItemId();
mActionButtonPopup = new ActionButtonSubmenu(mContext, subMenu);
mActionButtonPopup.setAnchorView(anchor);
mActionButtonPopup.show();
@@ -426,6 +434,57 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
super.onCloseMenu(menu, allMenusAreClosing);
}
+ @Override
+ public Parcelable onSaveInstanceState() {
+ SavedState state = new SavedState();
+ state.openSubMenuId = mOpenSubMenuId;
+ return state;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ SavedState saved = (SavedState) state;
+ if (saved.openSubMenuId > 0) {
+ MenuItem item = mMenu.findItem(saved.openSubMenuId);
+ if (item != null) {
+ SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
+ onSubMenuSelected(subMenu);
+ }
+ }
+ }
+
+ private static class SavedState implements Parcelable {
+ public int openSubMenuId;
+
+ SavedState() {
+ }
+
+ SavedState(Parcel in) {
+ openSubMenuId = in.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(openSubMenuId);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR
+ = new Parcelable.Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
private class OverflowMenuButton extends ImageButton implements ActionMenuChildView {
public OverflowMenuButton(Context context) {
super(context, null, com.android.internal.R.attr.actionOverflowButtonStyle);
@@ -460,6 +519,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
public OverflowPopup(Context context, MenuBuilder menu, View anchorView,
boolean overflowOnly) {
super(context, menu, anchorView, overflowOnly);
+ setCallback(mPopupPresenterCallback);
}
@Override
@@ -482,6 +542,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
// Give a reasonable anchor to nested submenus.
setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton);
}
+
+ setCallback(mPopupPresenterCallback);
}
@Override
@@ -489,6 +551,20 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
super.onDismiss();
mSubMenu.close();
mActionButtonPopup = null;
+ mOpenSubMenuId = 0;
+ }
+ }
+
+ private class PopupPresenterCallback implements MenuPresenter.Callback {
+
+ @Override
+ public boolean onOpenSubMenu(MenuBuilder subMenu) {
+ mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
+ return false;
+ }
+
+ @Override
+ public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
}
}
diff --git a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
index ddbb08c..ed9d34a 100644
--- a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
@@ -39,6 +39,8 @@ public abstract class BaseMenuPresenter implements MenuPresenter {
protected MenuView mMenuView;
+ private int mId;
+
/**
* Construct a new BaseMenuPresenter.
*
@@ -200,4 +202,12 @@ public abstract class BaseMenuPresenter implements MenuPresenter {
public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
return false;
}
+
+ public int getId() {
+ return mId;
+ }
+
+ public void setId(int id) {
+ mId = id;
+ }
}
diff --git a/core/java/com/android/internal/view/menu/IconMenuPresenter.java b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
index f717904..56128d4 100644
--- a/core/java/com/android/internal/view/menu/IconMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
@@ -23,6 +23,7 @@ import android.os.Parcelable;
import android.util.SparseArray;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
@@ -35,7 +36,12 @@ public class IconMenuPresenter extends BaseMenuPresenter {
private IconMenuItemView mMoreView;
private int mMaxItems = -1;
+ int mOpenSubMenuId;
+ SubMenuPresenterCallback mSubMenuPresenterCallback = new SubMenuPresenterCallback();
+ MenuDialogHelper mOpenSubMenu;
+
private static final String VIEWS_TAG = "android:menu:icon";
+ private static final String OPEN_SUBMENU_KEY = "android:menu:icon:submenu";
public IconMenuPresenter() {
super(com.android.internal.R.layout.icon_menu_layout,
@@ -86,7 +92,11 @@ public class IconMenuPresenter extends BaseMenuPresenter {
if (!subMenu.hasVisibleItems()) return false;
// The window manager will give us a token.
- new MenuDialogHelper(subMenu).show(null);
+ MenuDialogHelper helper = new MenuDialogHelper(subMenu);
+ helper.setPresenterCallback(mSubMenuPresenterCallback);
+ helper.show(null);
+ mOpenSubMenu = helper;
+ mOpenSubMenuId = subMenu.getItem().getItemId();
super.onSubMenuSelected(subMenu);
return true;
}
@@ -137,5 +147,47 @@ public class IconMenuPresenter extends BaseMenuPresenter {
if (viewStates != null) {
((View) mMenuView).restoreHierarchyState(viewStates);
}
+ int subMenuId = inState.getInt(OPEN_SUBMENU_KEY, 0);
+ if (subMenuId > 0 && mMenu != null) {
+ MenuItem item = mMenu.findItem(subMenuId);
+ if (item != null) {
+ onSubMenuSelected((SubMenuBuilder) item.getSubMenu());
+ }
+ }
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ if (mMenuView == null) {
+ return null;
+ }
+
+ Bundle state = new Bundle();
+ saveHierarchyState(state);
+ if (mOpenSubMenuId > 0) {
+ state.putInt(OPEN_SUBMENU_KEY, mOpenSubMenuId);
+ }
+ return state;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ restoreHierarchyState((Bundle) state);
+ }
+
+ class SubMenuPresenterCallback implements MenuPresenter.Callback {
+ @Override
+ public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+ mOpenSubMenuId = 0;
+ mOpenSubMenu.dismiss();
+ mOpenSubMenu = null;
+ }
+
+ @Override
+ public boolean onOpenSubMenu(MenuBuilder subMenu) {
+ mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
+ return false;
+ }
+
}
}
diff --git a/core/java/com/android/internal/view/menu/ListMenuPresenter.java b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
index 27e4191..146c7ac 100644
--- a/core/java/com/android/internal/view/menu/ListMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
@@ -47,6 +47,8 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick
private Callback mCallback;
private MenuAdapter mAdapter;
+ private int mId;
+
public static final String VIEWS_TAG = "android:menu:list";
/**
@@ -182,6 +184,31 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick
}
}
+ public void setId(int id) {
+ mId = id;
+ }
+
+ @Override
+ public int getId() {
+ return mId;
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ if (mMenuView == null) {
+ return null;
+ }
+
+ Bundle state = new Bundle();
+ saveHierarchyState(state);
+ return state;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ restoreHierarchyState((Bundle) state);
+ }
+
private class MenuAdapter extends BaseAdapter {
public int getCount() {
ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index fdfa954..164d581 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -25,9 +25,10 @@ import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.os.Parcelable;
-import android.util.Log;
import android.util.SparseArray;
+import android.view.ActionProvider;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
@@ -38,7 +39,6 @@ import android.view.View;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -49,6 +49,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class MenuBuilder implements Menu {
private static final String LOGTAG = "MenuBuilder";
+ private static final String PRESENTER_KEY = "android:menu:presenters";
+
private static final int[] sCategoryToOrder = new int[] {
1, /* No category */
4, /* CONTAINER */
@@ -254,6 +256,58 @@ public class MenuBuilder implements Menu {
return result;
}
+ private void dispatchSaveInstanceState(Bundle outState) {
+ if (mPresenters.isEmpty()) return;
+
+ SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>();
+
+ for (WeakReference<MenuPresenter> ref : mPresenters) {
+ final MenuPresenter presenter = ref.get();
+ if (presenter == null) {
+ mPresenters.remove(ref);
+ } else {
+ final int id = presenter.getId();
+ if (id > 0) {
+ final Parcelable state = presenter.onSaveInstanceState();
+ if (state != null) {
+ presenterStates.put(id, state);
+ }
+ }
+ }
+ }
+
+ outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates);
+ }
+
+ private void dispatchRestoreInstanceState(Bundle state) {
+ SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY);
+
+ if (presenterStates == null || mPresenters.isEmpty()) return;
+
+ for (WeakReference<MenuPresenter> ref : mPresenters) {
+ final MenuPresenter presenter = ref.get();
+ if (presenter == null) {
+ mPresenters.remove(ref);
+ } else {
+ final int id = presenter.getId();
+ if (id > 0) {
+ Parcelable parcel = presenterStates.get(id);
+ if (parcel != null) {
+ presenter.onRestoreInstanceState(parcel);
+ }
+ }
+ }
+ }
+ }
+
+ public void savePresenterStates(Bundle outState) {
+ dispatchSaveInstanceState(outState);
+ }
+
+ public void restorePresenterStates(Bundle state) {
+ dispatchRestoreInstanceState(state);
+ }
+
public void setCallback(Callback cb) {
mCallback = cb;
}
@@ -745,7 +799,7 @@ public class MenuBuilder implements Menu {
if (itemImpl == null || !itemImpl.isEnabled()) {
return false;
}
-
+
boolean invoked = itemImpl.invoke();
if (itemImpl.hasCollapsibleActionView()) {
@@ -754,7 +808,12 @@ public class MenuBuilder implements Menu {
} else if (item.hasSubMenu()) {
close(false);
- invoked |= dispatchSubMenuSelected((SubMenuBuilder) item.getSubMenu());
+ final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
+ final ActionProvider provider = item.getActionProvider();
+ if (provider != null && provider.hasSubMenu()) {
+ provider.onPrepareSubMenu(subMenu);
+ }
+ invoked |= dispatchSubMenuSelected(subMenu);
if (!invoked) close(true);
} else {
if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 20b7d80..541d101 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -164,10 +164,7 @@ public final class MenuItemImpl implements MenuItem {
}
}
- if (mActionProvider != null) {
- // The action view is created by the provider in this case.
- View actionView = getActionView();
- mActionProvider.onPerformDefaultAction(actionView);
+ if (mActionProvider != null && mActionProvider.onPerformDefaultAction()) {
return true;
}
@@ -323,11 +320,6 @@ public final class MenuItemImpl implements MenuItem {
}
void setSubMenu(SubMenuBuilder subMenu) {
- if ((mMenu != null) && (mMenu instanceof SubMenu)) {
- throw new UnsupportedOperationException(
- "Attempt to add a sub-menu to a sub-menu.");
- }
-
mSubMenu = subMenu;
subMenu.setHeaderTitle(getTitle());
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index cffbb4e..4ecc828 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -18,6 +18,7 @@ package com.android.internal.view.menu;
import android.content.Context;
import android.content.res.Resources;
+import android.os.Parcelable;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -296,4 +297,18 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On
return convertView;
}
}
+
+ @Override
+ public int getId() {
+ return 0;
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ return null;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ }
}
diff --git a/core/java/com/android/internal/view/menu/MenuPresenter.java b/core/java/com/android/internal/view/menu/MenuPresenter.java
index bd66448..d913a39 100644
--- a/core/java/com/android/internal/view/menu/MenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/MenuPresenter.java
@@ -17,6 +17,7 @@
package com.android.internal.view.menu;
import android.content.Context;
+import android.os.Parcelable;
import android.view.Menu;
import android.view.ViewGroup;
@@ -125,4 +126,24 @@ public interface MenuPresenter {
* @return true if this presenter collapsed the action view, false otherwise.
*/
public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item);
+
+ /**
+ * Returns an ID for determining how to save/restore instance state.
+ * @return a valid ID value.
+ */
+ public int getId();
+
+ /**
+ * Returns a Parcelable describing the current state of the presenter.
+ * It will be passed to the {@link #onRestoreInstanceState(Parcelable)}
+ * method of the presenter sharing the same ID later.
+ * @return The saved instance state
+ */
+ public Parcelable onSaveInstanceState();
+
+ /**
+ * Supplies the previously saved instance state to be restored.
+ * @param state The previously saved instance state
+ */
+ public void onRestoreInstanceState(Parcelable state);
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 09bc1fc..595753a 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -337,6 +337,7 @@ public class ActionBarView extends AbsActionBarView {
if (mActionMenuPresenter == null) {
mActionMenuPresenter = new ActionMenuPresenter();
mActionMenuPresenter.setCallback(cb);
+ mActionMenuPresenter.setId(com.android.internal.R.id.action_menu_presenter);
mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter();
}
@@ -1301,5 +1302,19 @@ public class ActionBarView extends AbsActionBarView {
item.setActionViewExpanded(false);
return true;
}
+
+ @Override
+ public int getId() {
+ return 0;
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ return null;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ }
}
}
diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java
index 2871073..c446cfb 100644
--- a/core/java/com/android/server/NetworkManagementSocketTagger.java
+++ b/core/java/com/android/server/NetworkManagementSocketTagger.java
@@ -16,24 +16,37 @@
package com.android.server;
+import android.os.SystemProperties;
+import android.util.Log;
+
import dalvik.system.SocketTagger;
+
import java.io.FileDescriptor;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.math.BigInteger;
import java.net.SocketException;
import java.nio.charset.Charsets;
+import libcore.io.IoUtils;
+
/**
* Assigns tags to sockets for traffic stats.
*/
public final class NetworkManagementSocketTagger extends SocketTagger {
+ private static final String TAG = "NetworkManagementSocketTagger";
+ private static final boolean LOGD = false;
- private static final boolean LOGI = false;
- private static final boolean ENABLE_TAGGING = false;
+ /**
+ * {@link SystemProperties} key that indicates if {@code qtaguid} bandwidth
+ * controls have been enabled.
+ */
+ // TODO: remove when always enabled, or once socket tagging silently fails.
+ public static final String PROP_QTAGUID_ENABLED = "net.qtaguid_enabled";
private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() {
- @Override protected SocketTags initialValue() {
+ @Override
+ protected SocketTags initialValue() {
return new SocketTags();
}
};
@@ -50,11 +63,12 @@ public final class NetworkManagementSocketTagger extends SocketTagger {
threadSocketTags.get().statsUid = uid;
}
- @Override public void tag(FileDescriptor fd) throws SocketException {
+ @Override
+ public void tag(FileDescriptor fd) throws SocketException {
final SocketTags options = threadSocketTags.get();
- if (LOGI) {
- System.logI("tagSocket(" + fd.getInt$() + ") with statsTag="
- + options.statsTag + ", statsUid=" + options.statsUid);
+ if (LOGD) {
+ Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=" + options.statsTag
+ + ", statsUid=" + options.statsUid);
}
try {
// TODO: skip tagging when options would be no-op
@@ -82,9 +96,10 @@ public final class NetworkManagementSocketTagger extends SocketTagger {
internalModuleCtrl(cmd);
}
- @Override public void untag(FileDescriptor fd) throws SocketException {
- if (LOGI) {
- System.logI("untagSocket(" + fd.getInt$() + ")");
+ @Override
+ public void untag(FileDescriptor fd) throws SocketException {
+ if (LOGD) {
+ Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
}
try {
unTagSocketFd(fd);
@@ -125,31 +140,22 @@ public final class NetworkManagementSocketTagger extends SocketTagger {
*
*/
private void internalModuleCtrl(String cmd) throws IOException {
- if (!ENABLE_TAGGING) return;
+ if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return;
- final FileOutputStream procOut;
- // TODO: Use something like
- // android.os.SystemProperties.getInt("persist.bandwidth.enable", 0)
- // to see if tagging should happen or not.
+ // TODO: migrate to native library for tagging commands
+ FileOutputStream procOut = null;
try {
procOut = new FileOutputStream("/proc/net/xt_qtaguid/ctrl");
- } catch (FileNotFoundException e) {
- if (LOGI) {
- System.logI("Can't talk to kernel module:" + e);
- }
- return;
- }
- try {
procOut.write(cmd.getBytes(Charsets.US_ASCII));
} finally {
- procOut.close();
+ IoUtils.closeQuietly(procOut);
}
}
/**
* Convert {@link Integer} tag to {@code /proc/} format. Assumes unsigned
* base-10 format like {@code 2147483647}. Currently strips signed bit to
- * avoid using {@link java.math.BigInteger}.
+ * avoid using {@link BigInteger}.
*/
public static String tagToKernel(int tag) {
// TODO: eventually write in hex, since that's what proc exports
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 63fa504..58e7c8d 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -224,22 +224,14 @@ LOCAL_CFLAGS += -DHAVE_BLUETOOTH
LOCAL_SHARED_LIBRARIES += libbluedroid libdbus
endif
-ifneq ($(TARGET_SIMULATOR),true)
LOCAL_SHARED_LIBRARIES += \
libdl
- # we need to access the private Bionic header
- # <bionic_tls.h> in com_google_android_gles_jni_GLImpl.cpp
- LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
-endif
+# we need to access the private Bionic header
+# <bionic_tls.h> in com_google_android_gles_jni_GLImpl.cpp
+LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
LOCAL_LDLIBS += -lpthread -ldl
-ifeq ($(TARGET_SIMULATOR),true)
-ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
-LOCAL_LDLIBS += -lrt
-endif
-endif
-
ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
endif
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index ddae505..d9bd50e 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -26,7 +26,7 @@
extern "C" {
int ifc_enable(const char *ifname);
int ifc_disable(const char *ifname);
-int ifc_reset_connections(const char *ifname);
+int ifc_reset_connections(const char *ifname, int reset_mask);
int dhcp_do_request(const char *ifname,
const char *ipaddr,
@@ -90,12 +90,17 @@ static jint android_net_utils_disableInterface(JNIEnv* env, jobject clazz, jstri
return (jint)result;
}
-static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, jstring ifname)
+static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz,
+ jstring ifname, jint mask)
{
int result;
const char *nameStr = env->GetStringUTFChars(ifname, NULL);
- result = ::ifc_reset_connections(nameStr);
+
+ LOGD("android_net_utils_resetConnections in env=%p clazz=%p iface=%s mask=0x%x\n",
+ env, clazz, nameStr, mask);
+
+ result = ::ifc_reset_connections(nameStr, mask);
env->ReleaseStringUTFChars(ifname, nameStr);
return (jint)result;
}
@@ -206,7 +211,7 @@ static JNINativeMethod gNetworkUtilMethods[] = {
{ "enableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_enableInterface },
{ "disableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_disableInterface },
- { "resetConnections", "(Ljava/lang/String;)I", (void *)android_net_utils_resetConnections },
+ { "resetConnections", "(Ljava/lang/String;I)I", (void *)android_net_utils_resetConnections },
{ "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z", (void *)android_net_utils_runDhcp },
{ "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z", (void *)android_net_utils_runDhcpRenew },
{ "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp },
diff --git a/core/jni/android_net_TrafficStats.cpp b/core/jni/android_net_TrafficStats.cpp
index 203b5ef..d54981e 100644
--- a/core/jni/android_net_TrafficStats.cpp
+++ b/core/jni/android_net_TrafficStats.cpp
@@ -67,10 +67,35 @@ static jlong readNumber(char const* filename) {
#endif
}
-// Return the number from the first file which exists and contains data
-static jlong tryBoth(char const* a, char const* b) {
- jlong num = readNumber(a);
- return num >= 0 ? num : readNumber(b);
+static const char* mobile_iface_list[] = {
+ "rmnet0",
+ "rmnet1",
+ "rmnet2",
+ "rmnet3",
+ "ppp0",
+ 0
+};
+
+static jlong getAll(const char** iface_list, const char* what) {
+
+ char filename[80];
+ int idx = 0;
+ bool supported = false;
+ jlong total = 0;
+ while (iface_list[idx] != 0) {
+
+ snprintf(filename, sizeof(filename), "/sys/class/net/%s/statistics/%s",
+ iface_list[idx], what);
+ jlong number = readNumber(filename);
+ if (number >= 0) {
+ supported = true;
+ total += number;
+ }
+ idx++;
+ }
+ if (supported) return total;
+
+ return -1;
}
// Returns the sum of numbers from the specified path under /sys/class/net/*,
@@ -108,27 +133,19 @@ static jlong readTotal(char const* suffix) {
// each file every time (rather than caching which ones exist).
static jlong getMobileTxPackets(JNIEnv* env, jobject clazz) {
- return tryBoth(
- "/sys/class/net/rmnet0/statistics/tx_packets",
- "/sys/class/net/ppp0/statistics/tx_packets");
+ return getAll(mobile_iface_list, "tx_packets");
}
static jlong getMobileRxPackets(JNIEnv* env, jobject clazz) {
- return tryBoth(
- "/sys/class/net/rmnet0/statistics/rx_packets",
- "/sys/class/net/ppp0/statistics/rx_packets");
+ return getAll(mobile_iface_list, "rx_packets");
}
static jlong getMobileTxBytes(JNIEnv* env, jobject clazz) {
- return tryBoth(
- "/sys/class/net/rmnet0/statistics/tx_bytes",
- "/sys/class/net/ppp0/statistics/tx_bytes");
+ return getAll(mobile_iface_list, "tx_bytes");
}
static jlong getMobileRxBytes(JNIEnv* env, jobject clazz) {
- return tryBoth(
- "/sys/class/net/rmnet0/statistics/rx_bytes",
- "/sys/class/net/ppp0/statistics/rx_bytes");
+ return getAll(mobile_iface_list, "rx_bytes");
}
static jlong getData(JNIEnv* env, const char* what, jstring javaInterface) {
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index 1166ae4..86e7cc0 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -1396,7 +1396,6 @@ static jstring registerSinkHealthApplicationNative(JNIEnv *env, jobject object,
LOG_AND_FREE_DBUS_ERROR(&err);
}
} else {
- LOGE("--_Call made getting the patch...");
if (!dbus_message_get_args(reply, &err,
DBUS_TYPE_OBJECT_PATH, &c_path,
DBUS_TYPE_INVALID)) {
@@ -1405,7 +1404,6 @@ static jstring registerSinkHealthApplicationNative(JNIEnv *env, jobject object,
}
} else {
path = env->NewStringUTF(c_path);
- LOGE("----Path is %s", c_path);
}
dbus_message_unref(reply);
}
@@ -1459,7 +1457,6 @@ static jboolean createChannelNative(JNIEnv *env, jobject object,
const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
const char *c_app_path = env->GetStringUTFChars(appPath, NULL);
const char *c_config = env->GetStringUTFChars(config, NULL);
- LOGE("Params...%s, %s, %s \n", c_device_path, c_app_path, c_config);
DBusMessage *reply = dbus_func_args(env, nat->conn,
c_device_path,
@@ -1531,7 +1528,6 @@ static jstring getMainChannelNative(JNIEnv *env, jobject object, jstring deviceP
DBusError err;
dbus_error_init(&err);
- LOGE("---Args %s", c_device_path);
DBusMessage *reply = dbus_func_args(env, nat->conn,
c_device_path,
DBUS_HEALTH_DEVICE_IFACE, "GetProperties",
@@ -1566,8 +1562,6 @@ static jstring getChannelApplicationNative(JNIEnv *env, jobject object, jstring
DBusError err;
dbus_error_init(&err);
- LOGE("---Args %s", c_channel_path);
-
DBusMessage *reply = dbus_func_args(env, nat->conn,
c_channel_path,
DBUS_HEALTH_CHANNEL_IFACE, "GetProperties",
@@ -1596,7 +1590,6 @@ static jstring getChannelApplicationNative(JNIEnv *env, jobject object, jstring
if (!strcmp(c_name, "Application")) {
path = (jstring) env->GetObjectArrayElement(str_array, i+1);
- LOGE("----Path is %s", env->GetStringUTFChars(path, NULL));
env->ReleaseStringUTFChars(name, c_name);
return path;
}
@@ -1655,13 +1648,11 @@ static jobject getChannelFdNative(JNIEnv *env, jobject object, jstring channelPa
fd = dbus_returns_unixfd(env, reply);
if (fd == -1) return NULL;
- LOGE("---got fd %d\n", fd);
// Create FileDescriptor object
jobject fileDesc = jniCreateFileDescriptor(env, fd);
if (fileDesc == NULL) {
// FileDescriptor constructor has thrown an exception
releaseChannelFdNative(env, object, channelPath);
- LOGE("---File Desc is null");
return NULL;
}
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 0960b25..d1ba2d1 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -318,17 +318,15 @@ jboolean android_os_Process_setOomAdj(JNIEnv* env, jobject clazz,
jint pid, jint adj)
{
#ifdef HAVE_OOM_ADJ
- if (ProcessState::self()->supportsProcesses()) {
- char text[64];
- sprintf(text, "/proc/%d/oom_adj", pid);
- int fd = open(text, O_WRONLY);
- if (fd >= 0) {
- sprintf(text, "%d", adj);
- write(fd, text, strlen(text));
- close(fd);
- }
- return true;
+ char text[64];
+ sprintf(text, "/proc/%d/oom_adj", pid);
+ int fd = open(text, O_WRONLY);
+ if (fd >= 0) {
+ sprintf(text, "%d", adj);
+ write(fd, text, strlen(text));
+ close(fd);
}
+ return true;
#endif
return false;
}
@@ -370,11 +368,6 @@ jint android_os_Process_setGid(JNIEnv* env, jobject clazz, jint uid)
#endif
}
-jboolean android_os_Process_supportsProcesses(JNIEnv* env, jobject clazz)
-{
- return ProcessState::self()->supportsProcesses();
-}
-
static int pid_compare(const void* v1, const void* v2)
{
//LOGI("Compare %d vs %d\n", *((const jint*)v1), *((const jint*)v2));
@@ -878,7 +871,6 @@ static const JNINativeMethod methods[] = {
{"setGid", "(I)I", (void*)android_os_Process_setGid},
{"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
{"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
- {"supportsProcesses", "()Z", (void*)android_os_Process_supportsProcesses},
{"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
{"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V", (void*)android_os_Process_readProcLines},
{"getPids", "(Ljava/lang/String;[I)[I", (void*)android_os_Process_getPids},
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
index 5225a81..acbbb38 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
index 2e7e973..6009528 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
index 4591627..30727d7 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
index 9cf1826..7cea5e1 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
index a47ef40..ba0d612 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
index 9b50c73..e8646b9 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
index a0d36de..14cb4c9 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
index 805b956..80fd218 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_back.png b/core/res/res/drawable-hdpi/ic_btn_back.png
deleted file mode 100644
index f8b3285..0000000
--- a/core/res/res/drawable-hdpi/ic_btn_back.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_next.png b/core/res/res/drawable-hdpi/ic_btn_next.png
deleted file mode 100644
index b2c6e1b..0000000
--- a/core/res/res/drawable-hdpi/ic_btn_next.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
index b0fba52..1014d8a 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
index 3ef8935..18cd171 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/toast_frame.9.png b/core/res/res/drawable-hdpi/toast_frame.9.png
index 9769bbb..ad2cb5a 100644
--- a/core/res/res/drawable-hdpi/toast_frame.9.png
+++ b/core/res/res/drawable-hdpi/toast_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/toast_frame_holo.9.png b/core/res/res/drawable-hdpi/toast_frame_holo.9.png
index 9769bbb..ad2cb5a 100644
--- a/core/res/res/drawable-hdpi/toast_frame_holo.9.png
+++ b/core/res/res/drawable-hdpi/toast_frame_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
index a0bd4e3..4836da1 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
index 12abcd2..c299931 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
index adb8104..86edad7 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
index d7c6bbf..53ee68b 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
index 42cfc52..606adaf 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
index 9a08e15..14d2e5e 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
index 5d86b2a..2646332 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
index ad22f5b..48ec0a4 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_back.png b/core/res/res/drawable-mdpi/ic_btn_back.png
deleted file mode 100644
index c9bff4c..0000000
--- a/core/res/res/drawable-mdpi/ic_btn_back.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_next.png b/core/res/res/drawable-mdpi/ic_btn_next.png
deleted file mode 100755
index c6cf436..0000000
--- a/core/res/res/drawable-mdpi/ic_btn_next.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
index 923f92d..dd5dd39 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
index afada39..12d65be 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/toast_frame.9.png b/core/res/res/drawable-mdpi/toast_frame.9.png
index 06cfc70..b9105de 100755
--- a/core/res/res/drawable-mdpi/toast_frame.9.png
+++ b/core/res/res/drawable-mdpi/toast_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/toast_frame_holo.9.png b/core/res/res/drawable-mdpi/toast_frame_holo.9.png
index 06cfc70..b9105de 100755
--- a/core/res/res/drawable-mdpi/toast_frame_holo.9.png
+++ b/core/res/res/drawable-mdpi/toast_frame_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
index b33e117..077e4d3 100644
--- a/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
index d84d427..357c17f 100644
--- a/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
index 9c0ff47..5b51072 100644
--- a/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
index 331a4f2..2705a39 100644
--- a/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
index cdc887d..101876f 100644
--- a/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
index bdb6824..0df1503 100644
--- a/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
index 600efb3..344a4e2 100644
--- a/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
index aa8401d..249848f 100644
--- a/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
new file mode 100644
index 0000000..92acc47
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
new file mode 100644
index 0000000..4e54b4b6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/toast_frame.9.png b/core/res/res/drawable-xhdpi/toast_frame.9.png
index f7debee..9f39a77 100644
--- a/core/res/res/drawable-xhdpi/toast_frame.9.png
+++ b/core/res/res/drawable-xhdpi/toast_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/toast_frame_holo.9.png b/core/res/res/drawable-xhdpi/toast_frame_holo.9.png
index f7debee..9f39a77 100644
--- a/core/res/res/drawable-xhdpi/toast_frame_holo.9.png
+++ b/core/res/res/drawable-xhdpi/toast_frame_holo.9.png
Binary files differ
diff --git a/core/res/res/layout-sw600dp/preference_list_content.xml b/core/res/res/layout-sw600dp/preference_list_content.xml
index 5a345c6..a5320a7 100644
--- a/core/res/res/layout-sw600dp/preference_list_content.xml
+++ b/core/res/res/layout-sw600dp/preference_list_content.xml
@@ -87,7 +87,6 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="0"
- android:background="@android:drawable/bottom_bar"
android:visibility="gone">
<Button android:id="@+id/back_button"
@@ -95,8 +94,6 @@
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:layout_alignParentLeft="true"
- android:drawableLeft="@drawable/ic_btn_back"
- android:drawablePadding="3dip"
android:text="@string/back_button_label"
/>
<LinearLayout
@@ -117,8 +114,6 @@
android:layout_width="150dip"
android:layout_height="wrap_content"
android:layout_margin="5dip"
- android:drawableRight="@drawable/ic_btn_next"
- android:drawablePadding="3dip"
android:text="@string/next_button_label"
/>
</LinearLayout>
diff --git a/core/res/res/layout-w600dp/preference_list_content_single.xml b/core/res/res/layout-w600dp/preference_list_content_single.xml
index 6725996..bbad296 100644
--- a/core/res/res/layout-w600dp/preference_list_content_single.xml
+++ b/core/res/res/layout-w600dp/preference_list_content_single.xml
@@ -61,7 +61,6 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="0"
- android:background="@android:drawable/bottom_bar"
android:visibility="gone">
<Button android:id="@+id/back_button"
@@ -69,8 +68,6 @@
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:layout_alignParentLeft="true"
- android:drawableLeft="@drawable/ic_btn_back"
- android:drawablePadding="3dip"
android:text="@string/back_button_label"
/>
<LinearLayout
@@ -91,8 +88,6 @@
android:layout_width="150dip"
android:layout_height="wrap_content"
android:layout_margin="5dip"
- android:drawableRight="@drawable/ic_btn_next"
- android:drawablePadding="3dip"
android:text="@string/next_button_label"
/>
</LinearLayout>
diff --git a/core/res/res/layout-xlarge/activity_list.xml b/core/res/res/layout-xlarge/activity_list.xml
index ad485c1..5093a5e 100644
--- a/core/res/res/layout-xlarge/activity_list.xml
+++ b/core/res/res/layout-xlarge/activity_list.xml
@@ -54,21 +54,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
- <ImageView android:id="@+id/titleDivider"
+ <View android:id="@+id/titleDivider"
android:layout_width="match_parent"
- android:layout_height="4dip"
- android:layout_marginLeft="16dip"
- android:layout_marginRight="16dip"
- android:scaleType="fitXY"
- android:gravity="fill_horizontal"
- android:src="@android:drawable/divider_strong_holo" />
+ android:layout_height="2dip"
+ android:background="@android:color/holo_blue_light" />
<!-- If the client uses a customTitle, it will be added here. -->
</LinearLayout>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_marginLeft="32dip"
- android:layout_marginRight="32dip"
android:layout_height="0dip"
android:layout_weight="1">
@@ -95,15 +89,12 @@
android:minHeight="54dip"
android:orientation="vertical"
android:divider="?android:attr/dividerHorizontal"
- android:showDividers="beginning"
- android:dividerPadding="16dip">
+ android:showDividers="beginning">
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
- android:paddingLeft="2dip"
- android:paddingRight="2dip"
android:measureWithLargestChild="true">
<LinearLayout android:id="@+id/leftSpacer"
android:layout_weight="0.25"
diff --git a/core/res/res/layout/activity_chooser_list_footer.xml b/core/res/res/layout/activity_chooser_list_footer.xml
deleted file mode 100644
index 7603a31..0000000
--- a/core/res/res/layout/activity_chooser_list_footer.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/list_footer"
- android:paddingLeft="16dip"
- android:paddingRight="16dip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:orientation="vertical">
-
- <ImageView
- android:id="@+id/divider"
- android:layout_width="match_parent"
- android:layout_height="2dip"
- android:scaleType="fitXY"
- android:gravity="fill_horizontal"
- android:src="@drawable/divider_strong_holo" />
-
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="48dip"
- android:gravity="center"
- android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
- android:duplicateParentState="true"
- android:singleLine="true"
- android:text="@string/activity_chooser_view_see_all" />
-
-</LinearLayout>
diff --git a/core/res/res/layout/activity_chooser_list_header.xml b/core/res/res/layout/activity_chooser_list_header.xml
deleted file mode 100644
index 867014b..0000000
--- a/core/res/res/layout/activity_chooser_list_header.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/list_header"
- android:paddingLeft="16dip"
- android:paddingRight="16dip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="?android:attr/dropdownListPreferredItemHeight"
- android:gravity="center"
- android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
- android:duplicateParentState="true"
- android:singleLine="true" />
-
- <ImageView
- android:id="@+id/divider"
- android:layout_width="match_parent"
- android:layout_height="2dip"
- android:scaleType="fitXY"
- android:gravity="fill_horizontal"
- android:src="@drawable/divider_strong_holo" />
-
-</LinearLayout>
diff --git a/core/res/res/layout/activity_chooser_view.xml b/core/res/res/layout/activity_chooser_view.xml
index ccf49fc..902b3c0 100644
--- a/core/res/res/layout/activity_chooser_view.xml
+++ b/core/res/res/layout/activity_chooser_view.xml
@@ -25,11 +25,11 @@
<ImageButton android:id="@+id/default_activity_button"
android:layout_width="32dip"
android:layout_height="32dip"
- android:layout_marginLeft="16dip" />
+ android:layout_marginRight="8dip" />
<ImageButton android:id="@+id/expand_activities_button"
android:layout_width="32dip"
android:layout_height="32dip"
- android:layout_marginLeft="16dip" />
+ android:layout_marginLeft="8dip" />
</LinearLayout>
diff --git a/core/res/res/layout/activity_chooser_view_list_item.xml b/core/res/res/layout/activity_chooser_view_list_item.xml
index 61b7e70..f90044e 100644
--- a/core/res/res/layout/activity_chooser_view_list_item.xml
+++ b/core/res/res/layout/activity_chooser_view_list_item.xml
@@ -18,26 +18,35 @@
android:id="@+id/list_item"
android:layout_width="match_parent"
android:layout_height="?android:attr/dropdownListPreferredItemHeight"
- android:gravity="center_vertical"
android:paddingLeft="16dip"
- android:paddingRight="16dip">
-
- <ImageView
- android:id="@+id/icon"
- android:layout_width="32dip"
- android:layout_height="32dip"
- android:layout_gravity="center_vertical"
- android:layout_marginRight="8dip"
- android:duplicateParentState="true" />
-
- <TextView
- android:id="@+id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
- android:singleLine="true"
- android:duplicateParentState="true"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal" />
+ android:paddingRight="16dip"
+ android:background="?android:attr/activatedBackgroundIndicator"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:duplicateParentState="true" >
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="32dip"
+ android:layout_height="32dip"
+ android:layout_gravity="center_vertical"
+ android:layout_marginRight="8dip"
+ android:duplicateParentState="true" />
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
+ android:duplicateParentState="true"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
+
+ </LinearLayout>
</LinearLayout>
diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml
index 2185467..2b686bd 100644
--- a/core/res/res/layout/alert_dialog_holo.xml
+++ b/core/res/res/layout/alert_dialog_holo.xml
@@ -30,13 +30,11 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
- <ImageView android:id="@+id/titleDividerTop"
+ <View android:id="@+id/titleDividerTop"
android:layout_width="match_parent"
- android:layout_height="1dip"
+ android:layout_height="2dip"
android:visibility="gone"
- android:scaleType="fitXY"
- android:gravity="fill_horizontal"
- android:src="@android:drawable/divider_strong_holo" />
+ android:background="@android:color/holo_blue_light" />
<LinearLayout android:id="@+id/title_template"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -51,20 +49,17 @@
android:paddingRight="8dip"
android:src="@null" />
<com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
- style="?android:attr/textAppearanceLarge"
- android:textColor="@android:color/holo_blue"
+ style="?android:attr/windowTitleStyle"
android:singleLine="true"
android:ellipsize="end"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
- <ImageView android:id="@+id/titleDivider"
+ <View android:id="@+id/titleDivider"
android:layout_width="match_parent"
- android:layout_height="1dip"
+ android:layout_height="2dip"
android:visibility="gone"
- android:scaleType="fitXY"
- android:gravity="fill_horizontal"
- android:src="@android:drawable/divider_strong_holo" />
+ android:background="@android:color/holo_blue_light" />
<!-- If the client uses a customTitle, it will be added here. -->
</LinearLayout>
diff --git a/core/res/res/layout/dialog_custom_title_holo.xml b/core/res/res/layout/dialog_custom_title_holo.xml
index 5261553..e2335a7 100644
--- a/core/res/res/layout/dialog_custom_title_holo.xml
+++ b/core/res/res/layout/dialog_custom_title_holo.xml
@@ -28,12 +28,10 @@ This is an custom layout for a dialog.
android:gravity="center_vertical|left"
style="?android:attr/windowTitleBackgroundStyle">
</FrameLayout>
- <ImageView android:id="@+id/titleDivider"
+ <View android:id="@+id/titleDivider"
android:layout_width="match_parent"
- android:layout_height="1dip"
- android:scaleType="fitXY"
- android:gravity="fill_horizontal"
- android:src="@android:drawable/divider_strong_holo" />
+ android:layout_height="2dip"
+ android:background="@android:color/holo_blue_light" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_holo.xml b/core/res/res/layout/dialog_title_holo.xml
index 400ef60..50bb0ba 100644
--- a/core/res/res/layout/dialog_title_holo.xml
+++ b/core/res/res/layout/dialog_title_holo.xml
@@ -30,12 +30,10 @@ enabled.
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:gravity="center_vertical|left" />
- <ImageView android:id="@+id/titleDivider"
+ <View android:id="@+id/titleDivider"
android:layout_width="match_parent"
- android:layout_height="1dip"
- android:scaleType="fitXY"
- android:gravity="fill_horizontal"
- android:src="@android:drawable/divider_strong_holo" />
+ android:layout_height="2dip"
+ android:background="@android:color/holo_blue_light" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_icons_holo.xml b/core/res/res/layout/dialog_title_icons_holo.xml
index f780ab0..7d7959f 100644
--- a/core/res/res/layout/dialog_title_icons_holo.xml
+++ b/core/res/res/layout/dialog_title_icons_holo.xml
@@ -48,12 +48,10 @@ enabled.
android:layout_marginLeft="8dip" />
</LinearLayout>
- <ImageView android:id="@+id/titleDivider"
+ <View android:id="@+id/titleDivider"
android:layout_width="match_parent"
android:layout_height="1dip"
- android:scaleType="fitXY"
- android:gravity="fill_horizontal"
- android:src="@android:drawable/divider_strong_holo" />
+ android:background="@android:color/holo_blue_light" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index 82b3a4c..fb898ee 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -85,7 +85,6 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="0"
- android:background="@android:drawable/bottom_bar"
android:visibility="gone">
<Button android:id="@+id/back_button"
@@ -93,8 +92,6 @@
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:layout_alignParentLeft="true"
- android:drawableLeft="@drawable/ic_btn_back"
- android:drawablePadding="3dip"
android:text="@string/back_button_label"
/>
<LinearLayout
@@ -115,8 +112,6 @@
android:layout_width="150dip"
android:layout_height="wrap_content"
android:layout_margin="5dip"
- android:drawableRight="@drawable/ic_btn_next"
- android:drawablePadding="3dip"
android:text="@string/next_button_label"
/>
</LinearLayout>
diff --git a/core/res/res/layout/preference_list_content_single.xml b/core/res/res/layout/preference_list_content_single.xml
index a015761..6902ffd 100644
--- a/core/res/res/layout/preference_list_content_single.xml
+++ b/core/res/res/layout/preference_list_content_single.xml
@@ -56,7 +56,6 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="0"
- android:background="@android:drawable/bottom_bar"
android:visibility="gone">
<Button android:id="@+id/back_button"
@@ -64,8 +63,6 @@
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:layout_alignParentLeft="true"
- android:drawableLeft="@drawable/ic_btn_back"
- android:drawablePadding="3dip"
android:text="@string/back_button_label"
/>
<LinearLayout
@@ -86,8 +83,6 @@
android:layout_width="150dip"
android:layout_height="wrap_content"
android:layout_margin="5dip"
- android:drawableRight="@drawable/ic_btn_next"
- android:drawablePadding="3dip"
android:text="@string/next_button_label"
/>
</LinearLayout>
diff --git a/core/res/res/layout/preference_list_fragment.xml b/core/res/res/layout/preference_list_fragment.xml
index 986536e..315f708 100644
--- a/core/res/res/layout/preference_list_fragment.xml
+++ b/core/res/res/layout/preference_list_fragment.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-/*
+/*
** Copyright 2010, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
@@ -41,7 +41,6 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="0"
- android:background="@android:drawable/bottom_bar"
android:visibility="gone">
<Button android:id="@+id/back_button"
@@ -49,8 +48,6 @@
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:layout_alignParentLeft="true"
- android:drawableLeft="@drawable/ic_btn_back"
- android:drawablePadding="3dip"
android:text="@string/back_button_label"
/>
<LinearLayout
@@ -71,8 +68,6 @@
android:layout_width="150dip"
android:layout_height="wrap_content"
android:layout_margin="5dip"
- android:drawableRight="@drawable/ic_btn_next"
- android:drawablePadding="3dip"
android:text="@string/next_button_label"
/>
</LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 39de054..cfc5041 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -40,6 +40,21 @@
to use accelerated drawing (thus setting state_accelerated), the
cache hint is ignored and always assumed to be transparent. -->
<attr name="colorBackgroundCacheHint" format="color" />
+
+ <!-- Default highlight color for items that are pressed. -->
+ <attr name="colorPressedHighlight" format="color" />
+ <!-- Default highlight color for items that are long-pressed. -->
+ <attr name="colorLongPressedHighlight" format="color" />
+ <!-- Default highlight color for items that are
+ focused. (Focused meaning cursor-based selection.) -->
+ <attr name="colorFocusedHighlight" format="color" />
+ <!-- Default highlight color for items that are
+ activated. (Activated meaning persistent selection.) -->
+ <attr name="colorActivatedHighlight" format="color" />
+ <!-- Default highlight color for items in multiple selection
+ mode. -->
+ <attr name="colorMultiSelectHighlight" format="color" />
+
<!-- Default disabled alpha for widgets that set enabled/disabled alpha programmatically. -->
<attr name="disabledAlpha" format="float" />
<!-- Default background dim amount when a menu, dialog, or something similar pops up. -->
@@ -3000,6 +3015,10 @@
<attr name="drawableLeft" format="reference|color" />
<!-- The drawable to be drawn to the right of the text. -->
<attr name="drawableRight" format="reference|color" />
+ <!-- The drawable to be drawn to the start of the text. -->
+ <attr name="drawableStart" format="reference|color" />
+ <!-- The drawable to be drawn to the end of the text. -->
+ <attr name="drawableEnd" format="reference|color" />
<!-- The padding between the drawables and the text. -->
<attr name="drawablePadding" format="dimension" />
<!-- Extra spacing between lines of text. -->
@@ -5303,6 +5322,8 @@
<attr name="mtpReserve" format="integer" />
<!-- true if the storage can be shared via USB mass storage -->
<attr name="allowMassStorage" format="boolean" />
+ <!-- maximum file size for the volume in megabytes, zero or unspecified if it is unbounded -->
+ <attr name="maxFileSize" format="integer" />
</declare-styleable>
<declare-styleable name="SwitchPreference">
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 2a1ebfc..631d8c6 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -143,19 +143,42 @@
<color name="link_text_holo_light">#0000ee</color>
<!-- Group buttons -->
+ <eat-comment />
<color name="group_button_dialog_pressed_holo_dark">#46c5c1ff</color>
<color name="group_button_dialog_focused_holo_dark">#2699cc00</color>
<color name="group_button_dialog_pressed_holo_light">#ffffffff</color>
<color name="group_button_dialog_focused_holo_light">#4699cc00</color>
+ <!-- Highlight colors for the legacy themes -->
+ <eat-comment />
+ <color name="legacy_pressed_highlight">#fffeaa0c</color>
+ <color name="legacy_selected_highlight">#fff17a0a</color>
+ <color name="legacy_long_pressed_highlight">#ffffffff</color>
+
<!-- General purpose colors for Holo-themed elements -->
<eat-comment />
- <!-- A Holo shade of blue -->
- <color name="holo_blue">#ff6699ff</color>
- <!-- A Holo shade of green -->
- <color name="holo_green">#ff99cc00</color>
+ <!-- A light Holo shade of blue -->
+ <color name="holo_blue_light">#ff33b5e5</color>
+ <!-- A light Holo shade of green -->
+ <color name="holo_green_light">#ff99cc00</color>
+ <!-- A light Holo shade of red -->
+ <color name="holo_red_light">#ffff4444</color>
+ <!-- A dark Holo shade of blue -->
+ <color name="holo_blue_dark">#ff0099cc</color>
+ <!-- A dark Holo shade of green -->
+ <color name="holo_green_dark">#ff669900</color>
+ <!-- A dark Holo shade of red -->
+ <color name="holo_red_dark">#ffcc0000</color>
+ <!-- A Holo shade of purple -->
+ <color name="holo_purple">#ffaa66cc</color>
+ <!-- A light Holo shade of orange -->
+ <color name="holo_orange_light">#ffffbb33</color>
+ <!-- A dark Holo shade of orange -->
+ <color name="holo_orange_dark">#ffff8800</color>
+ <!-- A really bright Holo shade of blue -->
+ <color name="holo_blue_bright">#ff00ddff</color>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9f05cbc..1f2b7fb 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -660,4 +660,9 @@
extremely limited. -->
<bool name="config_allowActionMenuItemTextWithIcon">false</bool>
+ <!-- Remote server that can provide NTP responses. -->
+ <string translatable="false" name="config_ntpServer">pool.ntp.org</string>
+ <!-- Timeout to wait for NTP server response. -->
+ <integer name="config_ntpTimeout">20000</integer>
+
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index a5e5f70..0f6e5cf 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -133,4 +133,7 @@
<!-- Size of right margin on Unsecure unlock LockScreen -->
<dimen name="keyguard_lockscreen_status_line_font_right_margin">45dip</dimen>
+ <!-- Minimum popup width for selecting an activity in ActivityChooserDialog/ActivityChooserView. -->
+ <dimen name="activity_chooser_popup_min_width">200dip</dimen>
+
</resources>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index d05685c..547a192 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -74,4 +74,9 @@
<item type="id" name="rowTypeId" />
<item type="id" name="up" />
<item type="id" name="action_menu_divider" />
+ <item type="id" name="icon_menu_presenter" />
+ <item type="id" name="list_menu_presenter" />
+ <item type="id" name="action_menu_presenter" />
+ <item type="id" name="overflow_menu_presenter" />
+ <item type="id" name="popup_submenu_presenter" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 3c23add..6dedc83 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1781,6 +1781,12 @@
<public type="attr" name="textAllCaps" />
+ <public type="attr" name="colorPressedHighlight" />
+ <public type="attr" name="colorLongPressedHighlight" />
+ <public type="attr" name="colorFocusedHighlight" />
+ <public type="attr" name="colorActivatedHighlight" />
+ <public type="attr" name="colorMultiSelectHighlight" />
+
<public type="style" name="TextAppearance.SuggestionHighlight" />
<public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" />
<public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" />
@@ -1809,4 +1815,18 @@
<public type="integer" name="status_bar_notification_info_maxnum" />
<public type="string" name="status_bar_notification_info_overflow" />
+ <public type="color" name="holo_blue_light" />
+ <public type="color" name="holo_blue_dark" />
+ <public type="color" name="holo_green_light" />
+ <public type="color" name="holo_green_dark" />
+ <public type="color" name="holo_red_light" />
+ <public type="color" name="holo_red_dark" />
+ <public type="color" name="holo_orange_light" />
+ <public type="color" name="holo_orange_dark" />
+ <public type="color" name="holo_purple" />
+ <public type="color" name="holo_blue_bright" />
+
+ <public type="attr" name="drawableStart" />
+ <public type="attr" name="drawableEnd" />
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 97a8c0b..d0e3f14 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2038,13 +2038,13 @@
<string name="autofill_phone_re">phone<!-- de-DE -->|telefonnummer<!-- es -->|telefono|teléfono<!-- fr-FR -->|telfixe<!-- ja-JP -->|電話<!-- pt-BR, pt-PT -->|telefone|telemovel<!-- ru -->|телефон<!-- zh-CN -->|电话</string>
<!-- Do not translate. Regex used by AutoFill. -->
- <string name="autofill_area_code_re">area code</string>
+ <string name="autofill_area_code_re">area.*code|acode|area</string>
<!-- Do not translate. Regex used by AutoFill. -->
- <string name="autofill_phone_prefix_re">^-$|\\)$|prefix<!-- fr-FR -->|preselection<!-- pt-BR, pt-PT -->|ddd</string>
+ <string name="autofill_phone_prefix_re">prefix<!-- fr-FR -->|preselection<!-- pt-BR, pt-PT -->|ddd</string>
<!-- Do not translate. Regex used by AutoFill. -->
- <string name="autofill_phone_suffix_re">^-$|suffix</string>
+ <string name="autofill_phone_suffix_re">suffix</string>
<!-- Do not translate. Regex used by AutoFill. -->
<string name="autofill_phone_extension_re">ext<!-- pt-BR, pt-PT -->|ramal</string>
@@ -2077,17 +2077,49 @@
<string name="autofill_country_code_re">country.*code|ccode|_cc</string>
<!-- Do not translate. Regex used by AutoFill. -->
- <string name="autofill_area_code_notext_re">^\($</string>
+ <string name="autofill_area_code_notext_re">^\\($</string>
<!-- Do not translate. Regex used by AutoFill. -->
- <string name="autofill_phone_prefix_separator_re">^-$|^\)$</string>
+ <string name="autofill_phone_prefix_separator_re">^-$|^\\)$</string>
<!-- Do not translate. Regex used by AutoFill. -->
<string name="autofill_phone_suffix_separator_re">^-$</string>
- <!-- Do not translate. Regex used by AutoFill. -->
- <!-- Ex: ************1234 -->
- <string name="credit_card_number_preview_format">$1</string>
+ <!-- Label in a web form for "Province" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_province">Province</string>
+
+ <!-- Label in a web form for "Postal code" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_postal_code">Postal code</string>
+
+ <!-- Label in a web form for "State" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_state">State</string>
+
+ <!-- Label in a web form for "ZIP code" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_zip_code">ZIP code</string>
+
+ <!-- Label in a web form for "County" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_county">County</string>
+
+ <!-- Label in a web form for "Island" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_island">Island</string>
+
+ <!-- Label in a web form for "District" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_district">District</string>
+
+ <!-- Label in a web form for "Department" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_department">Department</string>
+
+ <!-- Label in a web form for "Prefecture" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_prefecture">Prefecture</string>
+
+ <!-- Label in a web form for "Parish" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_parish">Parish</string>
+
+ <!-- Label in a web form for "Area" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_area">Area</string>
+
+ <!-- Label in a web form for "Emirate" [CHAR-LIMIT=NONE] -->
+ <string name="autofill_emirate">Emirate</string>
<!-- Title of an application permission, listed so the user can choose whether
they want to allow the application to do this. -->
@@ -3004,9 +3036,10 @@
<!-- Title for a button to expand the list of activities in ActivityChooserView [CHAR LIMIT=25] -->
<string name="activity_chooser_view_see_all">See all...</string>
- <!-- Title for a message that there are no activities in ActivityChooserView [CHAR LIMIT=25] -->
- <string name="activity_chooser_view_no_activities">No activities</string>
- <!-- Title for a message that prompts selection of a default share handler in ActivityChooserView [CHAR LIMIT=25] -->
- <string name="activity_chooser_view_select_default">Select default</string>
+ <!-- Title default for a dialog showing possible activities in ActivityChooserView [CHAR LIMIT=25] -->
+ <string name="activity_chooser_view_dialog_title_default">Select activity</string>
+
+ <!-- Title for a dialog showing possible activities for sharing in ShareActionProvider [CHAR LIMIT=25] -->
+ <string name="share_action_provider_share_with">Share with...</string>
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 8a8f81a..a5cd6e3 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1356,7 +1356,7 @@
<style name="TextAppearance.Holo.DialogWindowTitle">
<item name="android:textSize">22sp</item>
- <item name="android:textColor">@android:color/holo_blue</item>
+ <item name="android:textColor">@android:color/holo_blue_light</item>
</style>
<style name="TextAppearance.Holo.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView">
@@ -1455,7 +1455,7 @@
<style name="TextAppearance.Holo.Light.DialogWindowTitle">
<item name="android:textSize">22sp</item>
- <item name="android:textColor">@android:color/holo_blue</item>
+ <item name="android:textColor">@android:color/holo_blue_light</item>
</style>
<style name="TextAppearance.Holo.Light.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 9a52cff..90f3602 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -31,6 +31,13 @@
<item name="colorForegroundInverse">@android:color/bright_foreground_dark_inverse</item>
<item name="colorBackground">@android:color/background_dark</item>
<item name="colorBackgroundCacheHint">?android:attr/colorBackground</item>
+
+ <item name="colorPressedHighlight">@color/legacy_pressed_highlight</item>
+ <item name="colorLongPressedHighlight">@color/legacy_long_pressed_highlight</item>
+ <item name="colorFocusedHighlight">@color/legacy_selected_highlight</item>
+ <item name="colorMultiSelectHighlight">@color/legacy_selected_highlight</item>
+ <item name="colorActivatedHighlight">@color/legacy_selected_highlight</item>
+
<item name="disabledAlpha">0.5</item>
<item name="backgroundDimAmount">0.6</item>
@@ -799,6 +806,12 @@
<item name="disabledAlpha">0.5</item>
<item name="backgroundDimAmount">0.6</item>
+ <item name="colorPressedHighlight">@color/holo_blue_light</item>
+ <item name="colorLongPressedHighlight">@color/holo_blue_bright</item>
+ <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
+ <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
+ <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
+
<!-- Text styles -->
<item name="textAppearance">@android:style/TextAppearance.Holo</item>
<item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Inverse</item>
@@ -1090,6 +1103,11 @@
<item name="disabledAlpha">0.5</item>
<item name="backgroundDimAmount">0.6</item>
+ <item name="colorPressedHighlight">@color/holo_blue_light</item>
+ <item name="colorLongPressedHighlight">@color/holo_blue_bright</item>
+ <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
+ <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
+ <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
<!-- Text styles -->
<item name="textAppearance">@android:style/TextAppearance.Holo.Light</item>
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 00f47fa..b2ebb08 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -12,7 +12,7 @@ LOCAL_SRC_FILES := \
$(call all-java-files-under, EnabledTestApp/src)
LOCAL_DX_FLAGS := --core-library
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests android-common frameworks-core-util-lib mockwebserver
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests android-common frameworks-core-util-lib mockwebserver guava
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_PACKAGE_NAME := FrameworksCoreTests
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 8e2d925..146466f 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1051,6 +1051,13 @@
</intent-filter>
</activity>
+ <activity android:name="android.widget.TextViewTestActivity" android:label="TextViewTestActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<!-- Activity-level metadata -->
@@ -1235,6 +1242,13 @@
</intent-filter>
</activity>
+ <activity android:name="android.animation.BasicAnimatorActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
</application>
<instrumentation android:name="android.test.InstrumentationTestRunner"
diff --git a/core/tests/coretests/res/layout/animator_basic.xml b/core/tests/coretests/res/layout/animator_basic.xml
new file mode 100644
index 0000000..7b8ef11
--- /dev/null
+++ b/core/tests/coretests/res/layout/animator_basic.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/animatingButton"/>
+</LinearLayout> \ No newline at end of file
diff --git a/core/tests/coretests/res/layout/textview_test.xml b/core/tests/coretests/res/layout/textview_test.xml
new file mode 100644
index 0000000..f0c7b9e
--- /dev/null
+++ b/core/tests/coretests/res/layout/textview_test.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/textviewtest_layout"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <TextView android:id="@+id/textviewtest_textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/textview_hebrew_text"/>
+
+</LinearLayout> \ No newline at end of file
diff --git a/core/tests/coretests/res/values/strings.xml b/core/tests/coretests/res/values/strings.xml
index f51b08e..71f3520 100644
--- a/core/tests/coretests/res/values/strings.xml
+++ b/core/tests/coretests/res/values/strings.xml
@@ -129,4 +129,6 @@
<string name="button8">Button8</string>
<string name="button9">Button9</string>
+ <string name="textview_hebrew_text">&#x05DD;&#x05DE;ab?!</string>
+
</resources>
diff --git a/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java b/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java
new file mode 100644
index 0000000..65f2b8e
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java
@@ -0,0 +1,39 @@
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package android.animation;
+
+import android.widget.Button;
+import com.android.frameworks.coretests.R;
+
+/**
+ * Listener tests for AnimatorSet.
+ */
+public class AnimatorSetEventsTest extends EventsTest {
+
+ @Override
+ public void setUp() throws Exception {
+ final BasicAnimatorActivity activity = getActivity();
+ Button button = (Button) activity.findViewById(R.id.animatingButton);
+
+ ObjectAnimator xAnim = ObjectAnimator.ofFloat(button, "translationX", 0, 100);
+ ObjectAnimator yAnim = ObjectAnimator.ofFloat(button, "translationX", 0, 100);
+ mAnimator = new AnimatorSet();
+ ((AnimatorSet)mAnimator).playSequentially(xAnim, yAnim);
+
+ super.setUp();
+ }
+
+}
diff --git a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
new file mode 100644
index 0000000..93808d9
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation;
+
+import com.android.frameworks.coretests.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class BasicAnimatorActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.animator_basic);
+ }
+}
diff --git a/core/tests/coretests/src/android/animation/EventsTest.java b/core/tests/coretests/src/android/animation/EventsTest.java
new file mode 100644
index 0000000..f970ffc
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/EventsTest.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation;
+
+import android.os.Handler;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests for the various lifecycle events of Animators. This abstract class is subclassed by
+ * concrete implementations that provide the actual Animator objects being tested. All of the
+ * testing mechanisms are in this class; the subclasses are only responsible for providing
+ * the mAnimator object.
+ *
+ * This test is more complicated than a typical synchronous test because much of the functionality
+ * must happen on the UI thread. Some tests do this by using the UiThreadTest annotation to
+ * automatically run the whole test on that thread. Other tests must run on the UI thread and also
+ * wait for some later event to occur before ending. These tests use a combination of an
+ * AbstractFuture mechanism and a delayed action to release that Future later.
+ */
+public abstract class EventsTest
+ extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> {
+
+ private static final int ANIM_DURATION = 400;
+ private static final int ANIM_DELAY = 100;
+ private static final int ANIM_MID_DURATION = ANIM_DURATION / 2;
+ private static final int ANIM_MID_DELAY = ANIM_DELAY / 2;
+
+ private boolean mRunning; // tracks whether we've started the animator
+ private boolean mCanceled; // trackes whether we've canceled the animator
+ private Animator.AnimatorListener mFutureListener; // mechanism for delaying the end of the test
+ private FutureWaiter mFuture; // Mechanism for waiting for the UI test to complete
+ private Animator.AnimatorListener mListener; // Listener that handles/tests the events
+
+ protected Animator mAnimator; // The animator used in the tests. Must be set in subclass
+ // setup() method prior to calling the superclass setup()
+
+ /**
+ * Cancels the given animator. Used to delay cancelation until some later time (after the
+ * animator has started playing).
+ */
+ static class Canceler implements Runnable {
+ Animator mAnim;
+ public Canceler(Animator anim) {
+ mAnim = anim;
+ }
+ @Override
+ public void run() {
+ mAnim.cancel();
+ }
+ };
+
+ /**
+ * Releases the given Future object when the listener's end() event is called. Specifically,
+ * it releases it after some further delay, to give the test time to do other things right
+ * after an animation ends.
+ */
+ static class FutureReleaseListener extends AnimatorListenerAdapter {
+ FutureWaiter mFuture;
+
+ public FutureReleaseListener(FutureWaiter future) {
+ mFuture = future;
+ }
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ Handler handler = new Handler();
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mFuture.release();
+ }
+ }, ANIM_MID_DURATION);
+ }
+ };
+
+ public EventsTest() {
+ super(BasicAnimatorActivity.class);
+ }
+
+
+ /**
+ * Sets up the fields used by each test. Subclasses must override this method to create
+ * the protected mAnimator object used in all tests. Overrides must create that animator
+ * and then call super.setup(), where further properties are set on that animator.
+ * @throws Exception
+ */
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ // mListener is the main testing mechanism of this file. The asserts of each test
+ // are embedded in the listener callbacks that it implements.
+ mListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ // This should only be called on an animation that has been started and not
+ // yet canceled or ended
+ assertFalse(mCanceled);
+ assertTrue(mRunning);
+ mCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // This should only be called on an animation that has been started and not
+ // yet ended
+ assertTrue(mRunning);
+ mRunning = false;
+ super.onAnimationEnd(animation);
+ }
+ };
+
+ mAnimator.addListener(mListener);
+ mAnimator.setDuration(ANIM_DURATION);
+
+ mFuture = new FutureWaiter();
+
+ mRunning = false;
+ mCanceled = false;
+ }
+
+ /**
+ * Verify that calling cancel on an unstarted animator does nothing.
+ */
+ @UiThreadTest
+ @SmallTest
+ public void testCancel() throws Exception {
+ mAnimator.cancel();
+ }
+
+ /**
+ * Verify that calling cancel on a started animator does the right thing.
+ */
+ @UiThreadTest
+ @SmallTest
+ public void testStartCancel() throws Exception {
+ mRunning = true;
+ mAnimator.start();
+ mAnimator.cancel();
+ }
+
+ /**
+ * Same as testStartCancel, but with a startDelayed animator
+ */
+ @UiThreadTest
+ @SmallTest
+ public void testStartDelayedCancel() throws Exception {
+ mAnimator.setStartDelay(ANIM_DELAY);
+ mRunning = true;
+ mAnimator.start();
+ mAnimator.cancel();
+ }
+
+ /**
+ * Verify that canceling an animator that is playing does the right thing.
+ */
+ @MediumTest
+ public void testPlayingCancel() throws Exception {
+ mFutureListener = new FutureReleaseListener(mFuture);
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Handler handler = new Handler();
+ mAnimator.addListener(mFutureListener);
+ mRunning = true;
+ mAnimator.start();
+ handler.postDelayed(new Canceler(mAnimator), ANIM_MID_DURATION);
+ } catch (junit.framework.AssertionFailedError e) {
+ mFuture.setException(new RuntimeException(e));
+ }
+ }
+ });
+ mFuture.get();
+ }
+
+ /**
+ * Same as testPlayingCancel, but with a startDelayed animator
+ */
+ @MediumTest
+ public void testPlayingDelayedCancel() throws Exception {
+ mAnimator.setStartDelay(ANIM_DELAY);
+ mFutureListener = new FutureReleaseListener(mFuture);
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Handler handler = new Handler();
+ mAnimator.addListener(mFutureListener);
+ mRunning = true;
+ mAnimator.start();
+ handler.postDelayed(new Canceler(mAnimator), ANIM_MID_DURATION);
+ } catch (junit.framework.AssertionFailedError e) {
+ mFuture.setException(new RuntimeException(e));
+ }
+ }
+ });
+ mFuture.get();
+ }
+
+ /**
+ * Verifies that canceling a started animation after it has already been canceled
+ * does nothing.
+ */
+ @MediumTest
+ public void testStartDoubleCancel() throws Exception {
+ mFutureListener = new FutureReleaseListener(mFuture);
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mRunning = true;
+ mAnimator.start();
+ mAnimator.cancel();
+ mAnimator.cancel();
+ mFuture.release();
+ } catch (junit.framework.AssertionFailedError e) {
+ mFuture.setException(new RuntimeException(e));
+ }
+ }
+ });
+ mFuture.get();
+ }
+
+ /**
+ * Same as testStartDoubleCancel, but with a startDelayed animator
+ */
+ @MediumTest
+ public void testStartDelayedDoubleCancel() throws Exception {
+ mAnimator.setStartDelay(ANIM_DELAY);
+ mFutureListener = new FutureReleaseListener(mFuture);
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mRunning = true;
+ mAnimator.start();
+ mAnimator.cancel();
+ mAnimator.cancel();
+ mFuture.release();
+ } catch (junit.framework.AssertionFailedError e) {
+ mFuture.setException(new RuntimeException(e));
+ }
+ }
+ });
+ mFuture.get();
+ }
+
+
+}
diff --git a/core/tests/coretests/src/android/animation/FutureWaiter.java b/core/tests/coretests/src/android/animation/FutureWaiter.java
new file mode 100644
index 0000000..320a1c2
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/FutureWaiter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation;
+
+import com.google.common.util.concurrent.AbstractFuture;
+
+/**
+ * Simple extension of {@link com.google.common.util.concurrent.AbstractFuture} which exposes a new
+ * release() method which calls the protected
+ * {@link com.google.common.util.concurrent.AbstractFuture#set(Object)} method internally. It
+ * also exposes the protected {@link AbstractFuture#setException(Throwable)} method.
+ */
+public class FutureWaiter extends AbstractFuture<Void> {
+
+ /**
+ * Release the Future currently waiting on
+ * {@link com.google.common.util.concurrent.AbstractFuture#get()}.
+ */
+ public void release() {
+ super.set(null);
+ }
+
+ @Override
+ public boolean setException(Throwable throwable) {
+ return super.setException(throwable);
+ }
+}
diff --git a/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java b/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java
new file mode 100644
index 0000000..606a939
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation;
+
+import android.widget.Button;
+import com.android.frameworks.coretests.R;
+
+/**
+ * Listener tests for ObjectAnimator.
+ */
+public class ObjectAnimatorEventsTest extends EventsTest {
+
+ @Override
+ public void setUp() throws Exception {
+ final BasicAnimatorActivity activity = getActivity();
+ Button button = (Button) activity.findViewById(R.id.animatingButton);
+
+ mAnimator = ObjectAnimator.ofFloat(button, "translationX", 0, 100);
+ super.setUp();
+ }
+
+}
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java b/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java
new file mode 100644
index 0000000..c25d050
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.animation;
+
+/**
+ * Listener tests for ValueAnimator.
+ */
+public class ValueAnimatorEventsTest extends EventsTest {
+
+ @Override
+ public void setUp() throws Exception {
+ mAnimator = ValueAnimator.ofFloat(0, 1);
+ super.setUp();
+ }
+
+}
diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
index 0b72c3c..9403d95 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
@@ -54,8 +54,8 @@ public class NetworkStatsHistoryTest extends TestCase {
// record data into narrow window to get single bucket
stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 1024L, 2048L);
- assertEquals(1, stats.bucketCount);
- assertBucket(stats, 0, 1024L, 2048L);
+ assertEquals(1, stats.size());
+ assertValues(stats, 0, 1024L, 2048L);
}
public void testRecordEqualBuckets() throws Exception {
@@ -66,9 +66,9 @@ public class NetworkStatsHistoryTest extends TestCase {
final long recordStart = TEST_START + (bucketDuration / 2);
stats.recordData(recordStart, recordStart + bucketDuration, 1024L, 128L);
- assertEquals(2, stats.bucketCount);
- assertBucket(stats, 0, 512L, 64L);
- assertBucket(stats, 1, 512L, 64L);
+ assertEquals(2, stats.size());
+ assertValues(stats, 0, 512L, 64L);
+ assertValues(stats, 1, 512L, 64L);
}
public void testRecordTouchingBuckets() throws Exception {
@@ -81,13 +81,13 @@ public class NetworkStatsHistoryTest extends TestCase {
final long recordEnd = (TEST_START + (BUCKET_SIZE * 2)) + (MINUTE_IN_MILLIS * 4);
stats.recordData(recordStart, recordEnd, 1000L, 5000L);
- assertEquals(3, stats.bucketCount);
+ assertEquals(3, stats.size());
// first bucket should have (1/20 of value)
- assertBucket(stats, 0, 50L, 250L);
+ assertValues(stats, 0, 50L, 250L);
// second bucket should have (15/20 of value)
- assertBucket(stats, 1, 750L, 3750L);
+ assertValues(stats, 1, 750L, 3750L);
// final bucket should have (4/20 of value)
- assertBucket(stats, 2, 200L, 1000L);
+ assertValues(stats, 2, 200L, 1000L);
}
public void testRecordGapBuckets() throws Exception {
@@ -101,9 +101,9 @@ public class NetworkStatsHistoryTest extends TestCase {
stats.recordData(lastStart, lastStart + SECOND_IN_MILLIS, 64L, 512L);
// we should have two buckets, far apart from each other
- assertEquals(2, stats.bucketCount);
- assertBucket(stats, 0, 128L, 256L);
- assertBucket(stats, 1, 64L, 512L);
+ assertEquals(2, stats.size());
+ assertValues(stats, 0, 128L, 256L);
+ assertValues(stats, 1, 64L, 512L);
// now record something in middle, spread across two buckets
final long middleStart = TEST_START + DAY_IN_MILLIS;
@@ -111,11 +111,11 @@ public class NetworkStatsHistoryTest extends TestCase {
stats.recordData(middleStart, middleEnd, 2048L, 2048L);
// now should have four buckets, with new record in middle two buckets
- assertEquals(4, stats.bucketCount);
- assertBucket(stats, 0, 128L, 256L);
- assertBucket(stats, 1, 1024L, 1024L);
- assertBucket(stats, 2, 1024L, 1024L);
- assertBucket(stats, 3, 64L, 512L);
+ assertEquals(4, stats.size());
+ assertValues(stats, 0, 128L, 256L);
+ assertValues(stats, 1, 1024L, 1024L);
+ assertValues(stats, 2, 1024L, 1024L);
+ assertValues(stats, 3, 64L, 512L);
}
public void testRecordOverlapBuckets() throws Exception {
@@ -128,14 +128,12 @@ public class NetworkStatsHistoryTest extends TestCase {
stats.recordData(midStart, midStart + HOUR_IN_MILLIS, 1024L, 1024L);
// should have two buckets, with some data mixed together
- assertEquals(2, stats.bucketCount);
- assertBucket(stats, 0, 768L, 768L);
- assertBucket(stats, 1, 512L, 512L);
+ assertEquals(2, stats.size());
+ assertValues(stats, 0, 768L, 768L);
+ assertValues(stats, 1, 512L, 512L);
}
public void testRecordEntireGapIdentical() throws Exception {
- final long[] total = new long[2];
-
// first, create two separate histories far apart
final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS);
stats1.recordData(TEST_START, TEST_START + 2 * HOUR_IN_MILLIS, 2000L, 1000L);
@@ -150,19 +148,16 @@ public class NetworkStatsHistoryTest extends TestCase {
stats.recordEntireHistory(stats2);
// first verify that totals match up
- stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total);
- assertTotalEquals(total, 3000L, 1500L);
+ assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 3000L, 1500L);
// now inspect internal buckets
- assertBucket(stats, 0, 1000L, 500L);
- assertBucket(stats, 1, 1000L, 500L);
- assertBucket(stats, 2, 500L, 250L);
- assertBucket(stats, 3, 500L, 250L);
+ assertValues(stats, 0, 1000L, 500L);
+ assertValues(stats, 1, 1000L, 500L);
+ assertValues(stats, 2, 500L, 250L);
+ assertValues(stats, 3, 500L, 250L);
}
public void testRecordEntireOverlapVaryingBuckets() throws Exception {
- final long[] total = new long[2];
-
// create history just over hour bucket boundary
final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS);
stats1.recordData(TEST_START, TEST_START + MINUTE_IN_MILLIS * 60, 600L, 600L);
@@ -177,17 +172,16 @@ public class NetworkStatsHistoryTest extends TestCase {
stats.recordEntireHistory(stats2);
// first verify that totals match up
- stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total);
- assertTotalEquals(total, 650L, 650L);
+ assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 650L, 650L);
// now inspect internal buckets
- assertBucket(stats, 0, 10L, 10L);
- assertBucket(stats, 1, 20L, 20L);
- assertBucket(stats, 2, 20L, 20L);
- assertBucket(stats, 3, 20L, 20L);
- assertBucket(stats, 4, 20L, 20L);
- assertBucket(stats, 5, 20L, 20L);
- assertBucket(stats, 6, 10L, 10L);
+ assertValues(stats, 0, 10L, 10L);
+ assertValues(stats, 1, 20L, 20L);
+ assertValues(stats, 2, 20L, 20L);
+ assertValues(stats, 3, 20L, 20L);
+ assertValues(stats, 4, 20L, 20L);
+ assertValues(stats, 5, 20L, 20L);
+ assertValues(stats, 6, 10L, 10L);
// now combine using 15min buckets
stats = new NetworkStatsHistory(HOUR_IN_MILLIS / 4);
@@ -195,14 +189,13 @@ public class NetworkStatsHistoryTest extends TestCase {
stats.recordEntireHistory(stats2);
// first verify that totals match up
- stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total);
- assertTotalEquals(total, 650L, 650L);
+ assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 650L, 650L);
// and inspect buckets
- assertBucket(stats, 0, 200L, 200L);
- assertBucket(stats, 1, 150L, 150L);
- assertBucket(stats, 2, 150L, 150L);
- assertBucket(stats, 3, 150L, 150L);
+ assertValues(stats, 0, 200L, 200L);
+ assertValues(stats, 1, 150L, 150L);
+ assertValues(stats, 2, 150L, 150L);
+ assertValues(stats, 3, 150L, 150L);
}
public void testRemove() throws Exception {
@@ -210,28 +203,28 @@ public class NetworkStatsHistoryTest extends TestCase {
// record some data across 24 buckets
stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 24L, 24L);
- assertEquals(24, stats.bucketCount);
+ assertEquals(24, stats.size());
// try removing far before buckets; should be no change
stats.removeBucketsBefore(TEST_START - YEAR_IN_MILLIS);
- assertEquals(24, stats.bucketCount);
+ assertEquals(24, stats.size());
// try removing just moments into first bucket; should be no change
// since that bucket contains data beyond the cutoff
stats.removeBucketsBefore(TEST_START + SECOND_IN_MILLIS);
- assertEquals(24, stats.bucketCount);
+ assertEquals(24, stats.size());
// try removing single bucket
stats.removeBucketsBefore(TEST_START + HOUR_IN_MILLIS);
- assertEquals(23, stats.bucketCount);
+ assertEquals(23, stats.size());
// try removing multiple buckets
stats.removeBucketsBefore(TEST_START + (4 * HOUR_IN_MILLIS));
- assertEquals(20, stats.bucketCount);
+ assertEquals(20, stats.size());
// try removing all buckets
stats.removeBucketsBefore(TEST_START + YEAR_IN_MILLIS);
- assertEquals(0, stats.bucketCount);
+ assertEquals(0, stats.size());
}
public void testTotalData() throws Exception {
@@ -241,27 +234,20 @@ public class NetworkStatsHistoryTest extends TestCase {
// record uniform data across day
stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 2400L, 4800L);
- final long[] total = new long[2];
-
// verify that total outside range is 0
- stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START - DAY_IN_MILLIS, total);
- assertTotalEquals(total, 0, 0);
+ assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START - DAY_IN_MILLIS, 0L, 0L);
// verify total in first hour
- stats.getTotalData(TEST_START, TEST_START + HOUR_IN_MILLIS, total);
- assertTotalEquals(total, 100, 200);
+ assertValues(stats, TEST_START, TEST_START + HOUR_IN_MILLIS, 100L, 200L);
// verify total across 1.5 hours
- stats.getTotalData(TEST_START, TEST_START + (long) (1.5 * HOUR_IN_MILLIS), total);
- assertTotalEquals(total, 150, 300);
+ assertValues(stats, TEST_START, TEST_START + (long) (1.5 * HOUR_IN_MILLIS), 150L, 300L);
// verify total beyond end
- stats.getTotalData(TEST_START + (23 * HOUR_IN_MILLIS), TEST_START + WEEK_IN_MILLIS, total);
- assertTotalEquals(total, 100, 200);
+ assertValues(stats, TEST_START + (23 * HOUR_IN_MILLIS), TEST_START + WEEK_IN_MILLIS, 100L, 200L);
// verify everything total
- stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total);
- assertTotalEquals(total, 2400, 4800);
+ assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 2400L, 4800L);
}
@@ -293,19 +279,27 @@ public class NetworkStatsHistoryTest extends TestCase {
private static void assertConsistent(NetworkStatsHistory stats) {
// verify timestamps are monotonic
- for (int i = 1; i < stats.bucketCount; i++) {
- assertTrue(stats.bucketStart[i - 1] < stats.bucketStart[i]);
+ long lastStart = Long.MIN_VALUE;
+ NetworkStatsHistory.Entry entry = null;
+ for (int i = 0; i < stats.size(); i++) {
+ entry = stats.getValues(i, entry);
+ assertTrue(lastStart < entry.bucketStart);
+ lastStart = entry.bucketStart;
}
}
- private static void assertTotalEquals(long[] total, long rx, long tx) {
- assertEquals("unexpected rx", rx, total[0]);
- assertEquals("unexpected tx", tx, total[1]);
+ private static void assertValues(
+ NetworkStatsHistory stats, int index, long rxBytes, long txBytes) {
+ final NetworkStatsHistory.Entry entry = stats.getValues(index, null);
+ assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
+ assertEquals("unexpected txBytes", txBytes, entry.txBytes);
}
- private static void assertBucket(NetworkStatsHistory stats, int index, long rx, long tx) {
- assertEquals("unexpected rx", rx, stats.rx[index]);
- assertEquals("unexpected tx", tx, stats.tx[index]);
+ private static void assertValues(
+ NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) {
+ final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null);
+ assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
+ assertEquals("unexpected txBytes", txBytes, entry.txBytes);
}
}
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index 3cb64c7..2434e9f 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -31,9 +31,9 @@ public class NetworkStatsTest extends TestCase {
public void testFindIndex() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
- .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L)
- .addEntry(TEST_IFACE, 102, TAG_NONE, 1024L, 1024L);
+ .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L)
+ .addValues(TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L);
assertEquals(2, stats.findIndex(TEST_IFACE, 102, TAG_NONE));
assertEquals(2, stats.findIndex(TEST_IFACE, 102, TAG_NONE));
@@ -44,110 +44,106 @@ public class NetworkStatsTest extends TestCase {
public void testAddEntryGrow() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 2);
- assertEquals(0, stats.size);
- assertEquals(2, stats.iface.length);
+ assertEquals(0, stats.size());
+ assertEquals(2, stats.internalSize());
- stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 1L, 2L);
- stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L);
+ stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 1L, 1L, 2L, 2L);
+ stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L, 2L, 2L);
- assertEquals(2, stats.size);
- assertEquals(2, stats.iface.length);
+ assertEquals(2, stats.size());
+ assertEquals(2, stats.internalSize());
- stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 3L, 4L);
- stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 4L, 4L);
- stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 5L, 5L);
+ stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 3L, 30L, 4L, 40L);
+ stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 4L, 40L, 4L, 40L);
+ stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 5L, 50L, 5L, 50L);
- assertEquals(5, stats.size);
- assertTrue(stats.iface.length >= 5);
+ assertEquals(5, stats.size());
+ assertTrue(stats.internalSize() >= 5);
- assertEquals(1L, stats.rx[0]);
- assertEquals(2L, stats.rx[1]);
- assertEquals(3L, stats.rx[2]);
- assertEquals(4L, stats.rx[3]);
- assertEquals(5L, stats.rx[4]);
+ assertEntry(stats, 0, TEST_IFACE, TEST_UID, TAG_NONE, 1L, 1L, 2L, 2L);
+ assertEntry(stats, 1, TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L, 2L, 2L);
+ assertEntry(stats, 2, TEST_IFACE, TEST_UID, TAG_NONE, 3L, 30L, 4L, 40L);
+ assertEntry(stats, 3, TEST_IFACE, TEST_UID, TAG_NONE, 4L, 40L, 4L, 40L);
+ assertEntry(stats, 4, TEST_IFACE, TEST_UID, TAG_NONE, 5L, 50L, 5L, 50L);
}
public void testCombineExisting() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 10);
- stats.addEntry(TEST_IFACE, 1001, TAG_NONE, 512L, 256L);
- stats.addEntry(TEST_IFACE, 1001, 0xff, 128L, 128L);
- stats.combineEntry(TEST_IFACE, 1001, TAG_NONE, -128L, -128L);
+ stats.addValues(TEST_IFACE, 1001, TAG_NONE, 512L, 4L, 256L, 2L);
+ stats.addValues(TEST_IFACE, 1001, 0xff, 128L, 1L, 128L, 1L);
+ stats.combineValues(TEST_IFACE, 1001, TAG_NONE, -128L, -1L, -128L, -1L);
- assertStatsEntry(stats, 0, TEST_IFACE, 1001, TAG_NONE, 384L, 128L);
- assertStatsEntry(stats, 1, TEST_IFACE, 1001, 0xff, 128L, 128L);
+ assertEntry(stats, 0, TEST_IFACE, 1001, TAG_NONE, 384L, 3L, 128L, 1L);
+ assertEntry(stats, 1, TEST_IFACE, 1001, 0xff, 128L, 1L, 128L, 1L);
// now try combining that should create row
- stats.combineEntry(TEST_IFACE, 5005, TAG_NONE, 128L, 128L);
- assertStatsEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 128L, 128L);
- stats.combineEntry(TEST_IFACE, 5005, TAG_NONE, 128L, 128L);
- assertStatsEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 256L, 256L);
+ stats.combineValues(TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L);
+ assertEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L);
+ stats.combineValues(TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L);
+ assertEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 256L, 2L, 256L, 2L);
}
public void testSubtractIdenticalData() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
- .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
+ .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L);
final NetworkStats after = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
- .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
+ .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L);
final NetworkStats result = after.subtract(before);
// identical data should result in zero delta
- assertEquals(0, result.rx[0]);
- assertEquals(0, result.tx[0]);
- assertEquals(0, result.rx[1]);
- assertEquals(0, result.tx[1]);
+ assertEntry(result, 0, TEST_IFACE, 100, TAG_NONE, 0L, 0L, 0L, 0L);
+ assertEntry(result, 1, TEST_IFACE, 101, TAG_NONE, 0L, 0L, 0L, 0L);
}
public void testSubtractIdenticalRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
- .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
+ .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L);
final NetworkStats after = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, TAG_NONE, 1025L, 2L)
- .addEntry(TEST_IFACE, 101, TAG_NONE, 3L, 1028L);
+ .addValues(TEST_IFACE, 100, TAG_NONE, 1025L, 9L, 2L, 1L)
+ .addValues(TEST_IFACE, 101, TAG_NONE, 3L, 1L, 1028L, 9L);
final NetworkStats result = after.subtract(before);
// expect delta between measurements
- assertEquals(1, result.rx[0]);
- assertEquals(2, result.tx[0]);
- assertEquals(3, result.rx[1]);
- assertEquals(4, result.tx[1]);
+ assertEntry(result, 0, TEST_IFACE, 100, TAG_NONE, 1L, 1L, 2L, 1L);
+ assertEntry(result, 1, TEST_IFACE, 101, TAG_NONE, 3L, 1L, 4L, 1L);
}
public void testSubtractNewRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
- .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
+ .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L);
final NetworkStats after = new NetworkStats(TEST_START, 3)
- .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
- .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L)
- .addEntry(TEST_IFACE, 102, TAG_NONE, 1024L, 1024L);
+ .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L)
+ .addValues(TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L);
final NetworkStats result = after.subtract(before);
// its okay to have new rows
- assertEquals(0, result.rx[0]);
- assertEquals(0, result.tx[0]);
- assertEquals(0, result.rx[1]);
- assertEquals(0, result.tx[1]);
- assertEquals(1024, result.rx[2]);
- assertEquals(1024, result.tx[2]);
+ assertEntry(result, 0, TEST_IFACE, 100, TAG_NONE, 0L, 0L, 0L, 0L);
+ assertEntry(result, 1, TEST_IFACE, 101, TAG_NONE, 0L, 0L, 0L, 0L);
+ assertEntry(result, 2, TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L);
}
- private static void assertStatsEntry(
- NetworkStats stats, int i, String iface, int uid, int tag, long rx, long tx) {
- assertEquals(iface, stats.iface[i]);
- assertEquals(uid, stats.uid[i]);
- assertEquals(tag, stats.tag[i]);
- assertEquals(rx, stats.rx[i]);
- assertEquals(tx, stats.tx[i]);
+ private static void assertEntry(NetworkStats stats, int index, String iface, int uid, int tag,
+ long rxBytes, long rxPackets, long txBytes, long txPackets) {
+ final NetworkStats.Entry entry = stats.getValues(index, null);
+ assertEquals(iface, entry.iface);
+ assertEquals(uid, entry.uid);
+ assertEquals(tag, entry.tag);
+ assertEquals(rxBytes, entry.rxBytes);
+ assertEquals(rxPackets, entry.rxPackets);
+ assertEquals(txBytes, entry.txBytes);
+ assertEquals(txPackets, entry.txPackets);
}
}
diff --git a/core/tests/coretests/src/android/pim/EventRecurrenceTest.java b/core/tests/coretests/src/android/pim/EventRecurrenceTest.java
deleted file mode 100644
index 05000f1..0000000
--- a/core/tests/coretests/src/android/pim/EventRecurrenceTest.java
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.pim;
-
-import android.pim.EventRecurrence.InvalidFormatException;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
-
-import junit.framework.TestCase;
-
-import java.util.Arrays;
-
-/**
- * Test android.pim.EventRecurrence.
- *
- * adb shell am instrument -w -e class android.pim.EventRecurrenceTest \
- * com.android.frameworks.coretests/android.test.InstrumentationTestRunner
- */
-public class EventRecurrenceTest extends TestCase {
-
- @SmallTest
- public void test0() throws Exception {
- verifyRecurType("FREQ=SECONDLY",
- /* int freq */ EventRecurrence.SECONDLY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- @SmallTest
- public void test1() throws Exception {
- verifyRecurType("FREQ=MINUTELY",
- /* int freq */ EventRecurrence.MINUTELY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- @SmallTest
- public void test2() throws Exception {
- verifyRecurType("FREQ=HOURLY",
- /* int freq */ EventRecurrence.HOURLY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- @SmallTest
- public void test3() throws Exception {
- verifyRecurType("FREQ=DAILY",
- /* int freq */ EventRecurrence.DAILY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- @SmallTest
- public void test4() throws Exception {
- verifyRecurType("FREQ=WEEKLY",
- /* int freq */ EventRecurrence.WEEKLY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- @SmallTest
- public void test5() throws Exception {
- verifyRecurType("FREQ=MONTHLY",
- /* int freq */ EventRecurrence.MONTHLY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- @SmallTest
- public void test6() throws Exception {
- verifyRecurType("FREQ=YEARLY",
- /* int freq */ EventRecurrence.YEARLY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- @SmallTest
- public void test7() throws Exception {
- // with an until
- verifyRecurType("FREQ=DAILY;UNTIL=112233T223344Z",
- /* int freq */ EventRecurrence.DAILY,
- /* String until */ "112233T223344Z",
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- @SmallTest
- public void test8() throws Exception {
- // with a count
- verifyRecurType("FREQ=DAILY;COUNT=334",
- /* int freq */ EventRecurrence.DAILY,
- /* String until */ null,
- /* int count */ 334,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- @SmallTest
- public void test9() throws Exception {
- // with a count
- verifyRecurType("FREQ=DAILY;INTERVAL=5000",
- /* int freq */ EventRecurrence.DAILY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 5000,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- @SmallTest
- public void test10() throws Exception {
- // verifyRecurType all of the BY* ones with one element
- verifyRecurType("FREQ=DAILY"
- + ";BYSECOND=0"
- + ";BYMINUTE=1"
- + ";BYHOUR=2"
- + ";BYMONTHDAY=30"
- + ";BYYEARDAY=300"
- + ";BYWEEKNO=53"
- + ";BYMONTH=12"
- + ";BYSETPOS=-15"
- + ";WKST=SU",
- /* int freq */ EventRecurrence.DAILY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ new int[]{0},
- /* int[] byminute */ new int[]{1},
- /* int[] byhour */ new int[]{2},
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ new int[]{30},
- /* int[] byyearday */ new int[]{300},
- /* int[] byweekno */ new int[]{53},
- /* int[] bymonth */ new int[]{12},
- /* int[] bysetpos */ new int[]{-15},
- /* int wkst */ EventRecurrence.SU
- );
- }
-
- @SmallTest
- public void test11() throws Exception {
- // verifyRecurType all of the BY* ones with one element
- verifyRecurType("FREQ=DAILY"
- + ";BYSECOND=0,30,59"
- + ";BYMINUTE=0,41,59"
- + ";BYHOUR=0,4,23"
- + ";BYMONTHDAY=-31,-1,1,31"
- + ";BYYEARDAY=-366,-1,1,366"
- + ";BYWEEKNO=-53,-1,1,53"
- + ";BYMONTH=1,12"
- + ";BYSETPOS=1,2,3,4,500,10000"
- + ";WKST=SU",
- /* int freq */ EventRecurrence.DAILY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ new int[]{0, 30, 59},
- /* int[] byminute */ new int[]{0, 41, 59},
- /* int[] byhour */ new int[]{0, 4, 23},
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ new int[]{-31, -1, 1, 31},
- /* int[] byyearday */ new int[]{-366, -1, 1, 366},
- /* int[] byweekno */ new int[]{-53, -1, 1, 53},
- /* int[] bymonth */ new int[]{1, 12},
- /* int[] bysetpos */ new int[]{1, 2, 3, 4, 500, 10000},
- /* int wkst */ EventRecurrence.SU
- );
- }
-
- private static class Check {
- Check(String k, int... v) {
- key = k;
- values = v;
- }
-
- String key;
- int[] values;
- }
-
- // this is a negative verifyRecurType case to verifyRecurType the range of the numbers accepted
- @SmallTest
- public void test12() throws Exception {
- Check[] checks = new Check[]{
- new Check("BYSECOND", -100, -1, 60, 100),
- new Check("BYMINUTE", -100, -1, 60, 100),
- new Check("BYHOUR", -100, -1, 24, 100),
- new Check("BYMONTHDAY", -100, -32, 0, 32, 100),
- new Check("BYYEARDAY", -400, -367, 0, 367, 400),
- new Check("BYWEEKNO", -100, -54, 0, 54, 100),
- new Check("BYMONTH", -100, -5, 0, 13, 100)
- };
-
- for (Check ck : checks) {
- for (int n : ck.values) {
- String recur = "FREQ=DAILY;" + ck.key + "=" + n;
- try {
- EventRecurrence er = new EventRecurrence();
- er.parse(recur);
- fail("Negative verifyRecurType failed. "
- + " parse failed to throw an exception for '"
- + recur + "'");
- } catch (EventRecurrence.InvalidFormatException e) {
- // expected
- }
- }
- }
- }
-
- // verifyRecurType BYDAY
- @SmallTest
- public void test13() throws Exception {
- verifyRecurType("FREQ=DAILY;BYDAY=1SU,-2MO,+33TU,WE,TH,FR,SA",
- /* int freq */ EventRecurrence.DAILY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ new int[] {
- EventRecurrence.SU,
- EventRecurrence.MO,
- EventRecurrence.TU,
- EventRecurrence.WE,
- EventRecurrence.TH,
- EventRecurrence.FR,
- EventRecurrence.SA
- },
- /* int[] bydayNum */ new int[]{1, -2, 33, 0, 0, 0, 0},
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- @Suppress
- // Repro bug #2331761 - this should fail because of the last comma into BYDAY
- public void test14() throws Exception {
- verifyRecurType("FREQ=WEEKLY;WKST=MO;UNTIL=20100129T130000Z;INTERVAL=1;BYDAY=MO,TU,WE,",
- /* int freq */ EventRecurrence.WEEKLY,
- /* String until */ "20100129T130000Z",
- /* int count */ 0,
- /* int interval */ 1,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ new int[] {
- EventRecurrence.MO,
- EventRecurrence.TU,
- EventRecurrence.WE,
- },
- /* int[] bydayNum */ new int[]{0, 0, 0},
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- // This test should pass
- public void test15() throws Exception {
- verifyRecurType("FREQ=WEEKLY;WKST=MO;UNTIL=20100129T130000Z;INTERVAL=1;"
- + "BYDAY=MO,TU,WE,TH,FR,SA,SU",
- /* int freq */ EventRecurrence.WEEKLY,
- /* String until */ "20100129T130000Z",
- /* int count */ 0,
- /* int interval */ 1,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ new int[] {
- EventRecurrence.MO,
- EventRecurrence.TU,
- EventRecurrence.WE,
- EventRecurrence.TH,
- EventRecurrence.FR,
- EventRecurrence.SA,
- EventRecurrence.SU
- },
- /* int[] bydayNum */ new int[]{0, 0, 0, 0, 0, 0, 0},
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- // Sample coming from RFC2445
- public void test16() throws Exception {
- verifyRecurType("FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1",
- /* int freq */ EventRecurrence.MONTHLY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ new int[] {
- EventRecurrence.MO,
- EventRecurrence.TU,
- EventRecurrence.WE,
- EventRecurrence.TH,
- EventRecurrence.FR
- },
- /* int[] bydayNum */ new int[] {0, 0, 0, 0, 0},
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ new int[] { -1 },
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- // Sample coming from RFC2445
- public void test17() throws Exception {
- verifyRecurType("FREQ=DAILY;COUNT=10;INTERVAL=2",
- /* int freq */ EventRecurrence.DAILY,
- /* String until */ null,
- /* int count */ 10,
- /* int interval */ 2,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- // Sample coming from RFC2445
- public void test18() throws Exception {
- verifyRecurType("FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10",
- /* int freq */ EventRecurrence.YEARLY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ new int[] {
- EventRecurrence.SU
- },
- /* int[] bydayNum */ new int[] { -1 },
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ new int[] { 10 },
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- // Sample coming from bug #1640517
- public void test19() throws Exception {
- verifyRecurType("FREQ=YEARLY;BYMONTH=3;BYDAY=TH",
- /* int freq */ EventRecurrence.YEARLY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ new int[] {
- EventRecurrence.TH
- },
- /* int[] bydayNum */ new int[] { 0 },
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ new int[] { 3 },
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- // for your copying pleasure
- public void fakeTestXX() throws Exception {
- verifyRecurType("FREQ=DAILY;",
- /* int freq */ EventRecurrence.DAILY,
- /* String until */ null,
- /* int count */ 0,
- /* int interval */ 0,
- /* int[] bysecond */ null,
- /* int[] byminute */ null,
- /* int[] byhour */ null,
- /* int[] byday */ null,
- /* int[] bydayNum */ null,
- /* int[] bymonthday */ null,
- /* int[] byyearday */ null,
- /* int[] byweekno */ null,
- /* int[] bymonth */ null,
- /* int[] bysetpos */ null,
- /* int wkst */ EventRecurrence.MO
- );
- }
-
- private static void cmp(int vlen, int[] v, int[] correct, String name) {
- if ((correct == null && v != null)
- || (correct != null && v == null)) {
- throw new RuntimeException("One is null, one isn't for " + name
- + ": correct=" + Arrays.toString(correct)
- + " actual=" + Arrays.toString(v));
- }
- if ((correct == null && vlen != 0)
- || (vlen != (correct == null ? 0 : correct.length))) {
- throw new RuntimeException("Reported length mismatch for " + name
- + ": correct=" + ((correct == null) ? "null" : correct.length)
- + " actual=" + vlen);
- }
- if (correct == null) {
- return;
- }
- if (v.length < correct.length) {
- throw new RuntimeException("Array length mismatch for " + name
- + ": correct=" + Arrays.toString(correct)
- + " actual=" + Arrays.toString(v));
- }
- for (int i = 0; i < correct.length; i++) {
- if (v[i] != correct[i]) {
- throw new RuntimeException("Array value mismatch for " + name
- + ": correct=" + Arrays.toString(correct)
- + " actual=" + Arrays.toString(v));
- }
- }
- }
-
- private static boolean eq(String a, String b) {
- if ((a == null && b != null) || (a != null && b == null)) {
- return false;
- } else {
- return a == b || a.equals(b);
- }
- }
-
- private static void verifyRecurType(String recur,
- int freq, String until, int count, int interval,
- int[] bysecond, int[] byminute, int[] byhour,
- int[] byday, int[] bydayNum, int[] bymonthday,
- int[] byyearday, int[] byweekno, int[] bymonth,
- int[] bysetpos, int wkst) {
- EventRecurrence eventRecurrence = new EventRecurrence();
- eventRecurrence.parse(recur);
- if (eventRecurrence.freq != freq
- || !eq(eventRecurrence.until, until)
- || eventRecurrence.count != count
- || eventRecurrence.interval != interval
- || eventRecurrence.wkst != wkst) {
- System.out.println("Error... got:");
- print(eventRecurrence);
- System.out.println("expected:");
- System.out.println("{");
- System.out.println(" freq=" + freq);
- System.out.println(" until=" + until);
- System.out.println(" count=" + count);
- System.out.println(" interval=" + interval);
- System.out.println(" wkst=" + wkst);
- System.out.println(" bysecond=" + Arrays.toString(bysecond));
- System.out.println(" byminute=" + Arrays.toString(byminute));
- System.out.println(" byhour=" + Arrays.toString(byhour));
- System.out.println(" byday=" + Arrays.toString(byday));
- System.out.println(" bydayNum=" + Arrays.toString(bydayNum));
- System.out.println(" bymonthday=" + Arrays.toString(bymonthday));
- System.out.println(" byyearday=" + Arrays.toString(byyearday));
- System.out.println(" byweekno=" + Arrays.toString(byweekno));
- System.out.println(" bymonth=" + Arrays.toString(bymonth));
- System.out.println(" bysetpos=" + Arrays.toString(bysetpos));
- System.out.println("}");
- throw new RuntimeException("Mismatch in fields");
- }
- cmp(eventRecurrence.bysecondCount, eventRecurrence.bysecond, bysecond, "bysecond");
- cmp(eventRecurrence.byminuteCount, eventRecurrence.byminute, byminute, "byminute");
- cmp(eventRecurrence.byhourCount, eventRecurrence.byhour, byhour, "byhour");
- cmp(eventRecurrence.bydayCount, eventRecurrence.byday, byday, "byday");
- cmp(eventRecurrence.bydayCount, eventRecurrence.bydayNum, bydayNum, "bydayNum");
- cmp(eventRecurrence.bymonthdayCount, eventRecurrence.bymonthday, bymonthday, "bymonthday");
- cmp(eventRecurrence.byyeardayCount, eventRecurrence.byyearday, byyearday, "byyearday");
- cmp(eventRecurrence.byweeknoCount, eventRecurrence.byweekno, byweekno, "byweekno");
- cmp(eventRecurrence.bymonthCount, eventRecurrence.bymonth, bymonth, "bymonth");
- cmp(eventRecurrence.bysetposCount, eventRecurrence.bysetpos, bysetpos, "bysetpos");
- }
-
- private static void print(EventRecurrence er) {
- System.out.println("{");
- System.out.println(" freq=" + er.freq);
- System.out.println(" until=" + er.until);
- System.out.println(" count=" + er.count);
- System.out.println(" interval=" + er.interval);
- System.out.println(" wkst=" + er.wkst);
- System.out.println(" bysecond=" + Arrays.toString(er.bysecond));
- System.out.println(" bysecondCount=" + er.bysecondCount);
- System.out.println(" byminute=" + Arrays.toString(er.byminute));
- System.out.println(" byminuteCount=" + er.byminuteCount);
- System.out.println(" byhour=" + Arrays.toString(er.byhour));
- System.out.println(" byhourCount=" + er.byhourCount);
- System.out.println(" byday=" + Arrays.toString(er.byday));
- System.out.println(" bydayNum=" + Arrays.toString(er.bydayNum));
- System.out.println(" bydayCount=" + er.bydayCount);
- System.out.println(" bymonthday=" + Arrays.toString(er.bymonthday));
- System.out.println(" bymonthdayCount=" + er.bymonthdayCount);
- System.out.println(" byyearday=" + Arrays.toString(er.byyearday));
- System.out.println(" byyeardayCount=" + er.byyeardayCount);
- System.out.println(" byweekno=" + Arrays.toString(er.byweekno));
- System.out.println(" byweeknoCount=" + er.byweeknoCount);
- System.out.println(" bymonth=" + Arrays.toString(er.bymonth));
- System.out.println(" bymonthCount=" + er.bymonthCount);
- System.out.println(" bysetpos=" + Arrays.toString(er.bysetpos));
- System.out.println(" bysetposCount=" + er.bysetposCount);
- System.out.println("}");
- }
-
-
- /** A list of valid rules. The parser must accept these. */
- private static final String[] GOOD_RRULES = {
- /* extracted wholesale from from RFC 2445 section 4.8.5.4 */
- "FREQ=DAILY;COUNT=10",
- "FREQ=DAILY;UNTIL=19971224T000000Z",
- "FREQ=DAILY;INTERVAL=2",
- "FREQ=DAILY;INTERVAL=10;COUNT=5",
- "FREQ=YEARLY;UNTIL=20000131T090000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA",
- "FREQ=DAILY;UNTIL=20000131T090000Z;BYMONTH=1",
- "FREQ=WEEKLY;COUNT=10",
- "FREQ=WEEKLY;UNTIL=19971224T000000Z",
- "FREQ=WEEKLY;INTERVAL=2;WKST=SU",
- "FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH",
- "FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH",
- "FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR",
- "FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH",
- "FREQ=MONTHLY;COUNT=10;BYDAY=1FR",
- "FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR",
- "FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU",
- "FREQ=MONTHLY;COUNT=6;BYDAY=-2MO",
- "FREQ=MONTHLY;BYMONTHDAY=-3",
- "FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15",
- "FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1",
- "FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15",
- "FREQ=MONTHLY;INTERVAL=2;BYDAY=TU",
- "FREQ=YEARLY;COUNT=10;BYMONTH=6,7",
- "FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3",
- "FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200",
- "FREQ=YEARLY;BYDAY=20MO",
- "FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO",
- "FREQ=YEARLY;BYMONTH=3;BYDAY=TH",
- "FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8",
- "FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13",
- "FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13",
- "FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8",
- "FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3",
- "FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2",
- "FREQ=HOURLY;INTERVAL=3;UNTIL=19970902T170000Z",
- "FREQ=MINUTELY;INTERVAL=15;COUNT=6",
- "FREQ=MINUTELY;INTERVAL=90;COUNT=4",
- "FREQ=DAILY;BYHOUR=9,10,11,12,13,14,15,16;BYMINUTE=0,20,40",
- "FREQ=MINUTELY;INTERVAL=20;BYHOUR=9,10,11,12,13,14,15,16",
- "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO",
- "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU",
- /* a few more */
- "FREQ=SECONDLY;BYSECOND=0,15,59",
- "FREQ=MINUTELY;BYMINUTE=0,15,59",
- "FREQ=HOURLY;BYHOUR=+0,+15,+23",
- "FREQ=DAILY;X-WHATEVER=blah", // fails on old parser
- //"freq=daily;wkst=su", // fails on old parser
- };
-
- /** The parser must reject these. */
- private static final String[] BAD_RRULES = {
- "INTERVAL=4;FREQ=YEARLY", // FREQ must come first
- "FREQ=MONTHLY;FREQ=MONTHLY", // can't specify twice
- "FREQ=MONTHLY;COUNT=1;COUNT=1", // can't specify twice
- "FREQ=SECONDLY;BYSECOND=60", // range
- "FREQ=MINUTELY;BYMINUTE=-1", // range
- "FREQ=HOURLY;BYHOUR=24", // range
- "FREQ=YEARLY;BYMONTHDAY=0", // zero not valid
- //"FREQ=YEARLY;COUNT=1;UNTIL=12345", // can't have both COUNT and UNTIL
- //"FREQ=DAILY;UNTIL=19970829T021400e", // invalid date
- };
-
- /**
- * Simple test of good/bad rules.
- */
- @SmallTest
- public void testBasicParse() {
- for (String rule : GOOD_RRULES) {
- EventRecurrence recur = new EventRecurrence();
- recur.parse(rule);
- }
-
- for (String rule : BAD_RRULES) {
- EventRecurrence recur = new EventRecurrence();
- boolean didThrow = false;
-
- try {
- recur.parse(rule);
- } catch (InvalidFormatException ife) {
- didThrow = true;
- }
-
- assertTrue("Expected throw on " + rule, didThrow);
- }
- }
-}
diff --git a/core/tests/coretests/src/android/pim/RecurrenceSetTest.java b/core/tests/coretests/src/android/pim/RecurrenceSetTest.java
deleted file mode 100644
index e5ab179..0000000
--- a/core/tests/coretests/src/android/pim/RecurrenceSetTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.pim;
-
-import android.content.ContentValues;
-import android.pim.ICalendar;
-import android.pim.RecurrenceSet;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-import android.provider.CalendarContract;
-import junit.framework.TestCase;
-
-/**
- * Test some pim.RecurrenceSet functionality.
- */
-public class RecurrenceSetTest extends TestCase {
-
- // Test a recurrence
- @SmallTest
- public void testRecurrenceSet0() throws Exception {
- String recurrence = "DTSTART;TZID=America/New_York:20080221T070000\n"
- + "DTEND;TZID=America/New_York:20080221T190000\n"
- + "RRULE:FREQ=DAILY;UNTIL=20080222T000000Z\n"
- + "EXDATE:20080222T120000Z";
- verifyPopulateContentValues(recurrence, "FREQ=DAILY;UNTIL=20080222T000000Z", null,
- null, "20080222T120000Z", 1203595200000L, "America/New_York", "P43200S", 0);
- }
-
- // Test 1 day all-day event
- @SmallTest
- public void testRecurrenceSet1() throws Exception {
- String recurrence = "DTSTART;VALUE=DATE:20090821\nDTEND;VALUE=DATE:20090822\n"
- + "RRULE:FREQ=YEARLY;WKST=SU";
- verifyPopulateContentValues(recurrence, "FREQ=YEARLY;WKST=SU", null,
- null, null, 1250812800000L, "UTC", "P1D", 1);
- }
-
- // Test 2 day all-day event
- @SmallTest
- public void testRecurrenceSet2() throws Exception {
- String recurrence = "DTSTART;VALUE=DATE:20090821\nDTEND;VALUE=DATE:20090823\n"
- + "RRULE:FREQ=YEARLY;WKST=SU";
- verifyPopulateContentValues(recurrence, "FREQ=YEARLY;WKST=SU", null,
- null, null, 1250812800000L, "UTC", "P2D", 1);
- }
-
- // run populateContentValues and verify the results
- private void verifyPopulateContentValues(String recurrence, String rrule, String rdate,
- String exrule, String exdate, long dtstart, String tzid, String duration, int allDay)
- throws ICalendar.FormatException {
- ICalendar.Component recurrenceComponent =
- new ICalendar.Component("DUMMY", null /* parent */);
- ICalendar.parseComponent(recurrenceComponent, recurrence);
- ContentValues values = new ContentValues();
- RecurrenceSet.populateContentValues(recurrenceComponent, values);
- Log.d("KS", "values " + values);
-
- 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.CalendarContract.Events.ALL_DAY));
- }
-}
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 6db67c0..c54e4a1 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -16,23 +16,25 @@
package android.widget;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
+import com.android.frameworks.coretests.R;
-import android.test.AndroidTestCase;
+import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.GetChars;
import android.view.View;
-import android.widget.TextView;
/**
* TextViewTest tests {@link TextView}.
*/
-public class TextViewTest extends AndroidTestCase {
+public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewTestActivity> {
+
+ public TextViewTest() {
+ super(TextViewTestActivity.class);
+ }
@SmallTest
public void testArray() throws Exception {
- TextView tv = new TextView(mContext);
+ TextView tv = new TextView(getActivity());
char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ',
'W', 'o', 'r', 'l', 'd', '!' };
@@ -62,13 +64,13 @@ public class TextViewTest extends AndroidTestCase {
@SmallTest
public void testTextDirectionDefault() {
- TextView tv = new TextView(mContext);
+ TextView tv = new TextView(getActivity());
assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getTextDirection());
}
@SmallTest
public void testSetGetTextDirection() {
- TextView tv = new TextView(mContext);
+ TextView tv = new TextView(getActivity());
tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
@@ -88,7 +90,7 @@ public class TextViewTest extends AndroidTestCase {
@SmallTest
public void testGetResolvedTextDirectionLtr() {
- TextView tv = new TextView(mContext);
+ TextView tv = new TextView(getActivity());
tv.setText("this is a test");
tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
@@ -109,10 +111,10 @@ public class TextViewTest extends AndroidTestCase {
@SmallTest
public void testGetResolvedTextDirectionLtrWithInheritance() {
- LinearLayout ll = new LinearLayout(mContext);
+ LinearLayout ll = new LinearLayout(getActivity());
ll.setTextDirection(View.TEXT_DIRECTION_RTL);
- TextView tv = new TextView(mContext);
+ TextView tv = new TextView(getActivity());
tv.setText("this is a test");
ll.addView(tv);
@@ -134,7 +136,7 @@ public class TextViewTest extends AndroidTestCase {
@SmallTest
public void testGetResolvedTextDirectionRtl() {
- TextView tv = new TextView(mContext);
+ TextView tv = new TextView(getActivity());
tv.setText("\u05DD\u05DE"); // hebrew
tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
@@ -155,10 +157,9 @@ public class TextViewTest extends AndroidTestCase {
@SmallTest
public void testGetResolvedTextDirectionRtlWithInheritance() {
- LinearLayout ll = new LinearLayout(mContext);
- ll.setTextDirection(View.TEXT_DIRECTION_RTL);
+ LinearLayout ll = new LinearLayout(getActivity());
- TextView tv = new TextView(mContext);
+ TextView tv = new TextView(getActivity());
tv.setText("\u05DD\u05DE"); // hebrew
ll.addView(tv);
@@ -169,6 +170,24 @@ public class TextViewTest extends AndroidTestCase {
assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+ assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+ // Force to RTL text direction on the layout
+ ll.setTextDirection(View.TEXT_DIRECTION_RTL);
+
+ tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
tv.setTextDirection(View.TEXT_DIRECTION_LTR);
@@ -180,10 +199,10 @@ public class TextViewTest extends AndroidTestCase {
@SmallTest
public void testCharCountHeuristic() {
- LinearLayout ll = new LinearLayout(mContext);
+ LinearLayout ll = new LinearLayout(getActivity());
ll.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
- TextView tv = new TextView(mContext);
+ TextView tv = new TextView(getActivity());
ll.addView(tv);
tv.setTextDirection(View.TEXT_DIRECTION_CHAR_COUNT);
@@ -211,4 +230,23 @@ public class TextViewTest extends AndroidTestCase {
tv.setText("ab \u05DD\u05DE"); // latin + hebrew at 50% each
assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
}
+
+ @SmallTest
+ public void testResetTextDirection() {
+ final TextViewTestActivity activity = getActivity();
+
+ final LinearLayout ll = (LinearLayout) activity.findViewById(R.id.textviewtest_layout);
+ final TextView tv = (TextView) activity.findViewById(R.id.textviewtest_textview);
+
+ getActivity().runOnUiThread(new Runnable() {
+ public void run() {
+ tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+ assertEquals(true, tv.isResolvedTextDirection());
+
+ ll.removeView(tv);
+ assertEquals(false, tv.isResolvedTextDirection());
+ }
+ });
+ }
}
diff --git a/core/tests/coretests/src/android/widget/TextViewTestActivity.java b/core/tests/coretests/src/android/widget/TextViewTestActivity.java
new file mode 100644
index 0000000..1bb4d24
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/TextViewTestActivity.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.widget;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
+
+public class TextViewTestActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.textview_test);
+ }
+}
diff --git a/docs/html/guide/developing/tools/adb.jd b/docs/html/guide/developing/tools/adb.jd
index a109dc8..78d12ef 100644
--- a/docs/html/guide/developing/tools/adb.jd
+++ b/docs/html/guide/developing/tools/adb.jd
@@ -503,7 +503,7 @@ application and send 500 pseudo-random events to it.</p>
<ul>
<li><code>V</code> &mdash; Verbose (lowest priority)</li>
<li><code>D</code> &mdash; Debug</li>
- <li><code>I</code> &mdash; Info</li>
+ <li><code>I</code> &mdash; Info (default priority)</li>
<li><code>W</code> &mdash; Warning</li>
<li><code>E</code> &mdash; Error</li>
<li><code>F</code> &mdash; Fatal</li>
@@ -520,7 +520,7 @@ of each message, given as <code>&lt;priority&gt;/&lt;tag&gt;</code>. </p>
<p>To reduce the log output to a manageable level, you can restrict log output using <em>filter expressions</em>. Filter expressions let you indicate to the system the tags-priority combinations that you are interested in &mdash; the system suppresses other messages for the specified tags. </p>
-<p>A filter expression follows this format <code>tag:priority ...</code>, where <code>tag</code> indicates the tag of interest and <code>priority</code> indicates the <em>minimum</em> level of priority to report for that tag. Messages for that tag at or above the specified priority are written to the log. You can supply any number of <code>tag:priority</code> specifications in a single filter expression. The series of specifications is whitespace-delimited. </p>
+<p>A filter expression follows this format <code>tag:priority ...</code>, where <code>tag</code> indicates the tag of interest and <code>priority</code> indicates the <em>minimum</em> level of priority to report for that tag. Messages for that tag at or above the specified priority are written to the log. You can supply any number of <code>tag:priority</code> specifications in a single filter expression. The series of specifications is whitespace-delimited. The default output is to show all log messages with the Info priority (*:I).</p>
<p>Here's an example of a filter expression that suppresses all log messages except those with the tag "ActivityManager", at priority "Info" or above, and all log messages with tag "MyApp", with priority "Debug" or above:</p>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 3ec174e..f7dbe30 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -256,8 +256,7 @@
<li class="toggle-list">
<div><a href="<?cs var:toroot ?>guide/topics/renderscript/index.html">
<span class="en">RenderScript</span>
- </a>
- <span class="new">new!</span></div>
+ </a></div>
<ul>
<li><a href="<?cs var:toroot ?>guide/topics/renderscript/graphics.html">
<span class="en">3D Graphics</span>
@@ -304,11 +303,9 @@
<!--<li><a style="color:gray;">Localization</a></li> -->
<li><a href="<?cs var:toroot ?>guide/topics/appwidgets/index.html">
<span class="en">App Widgets</span></a>
- <span class="new">updated</span>
</li>
<li><a href="<?cs var:toroot?>guide/topics/wireless/bluetooth.html">
<span class="en">Bluetooth</span></a>
- <span class="new">updated</span>
</li>
<li><a href="<?cs var:toroot?>guide/topics/nfc/index.html">
<span class="en">Near Field Communication</span>
@@ -316,7 +313,6 @@
<li class="toggle-list">
<div><a href="<?cs var:toroot?>guide/topics/usb/index.html">
<span class="en">USB</span></a>
- <span class="new">new!</span>
</div>
<ul>
<li><a href="<?cs var:toroot ?>guide/topics/usb/accessory.html">Accessory</a></li>
@@ -341,7 +337,6 @@
</li>
<li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html">
<span class="en">Device Administration</span></a>
- <span class="new">updated</span>
</li>
<li class="toggle-list">
<div>
diff --git a/docs/html/index.jd b/docs/html/index.jd
index eeeedd0..dce46f9 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -148,19 +148,18 @@ href="{@docRoot}resources/dashboard/platform-versions.html">Learn more &raquo;</
'tv': {
'layout':"imgLeft",
- 'icon':"tv_s.png",
+ 'icon':"GTV_icon_small.png",
'name':"Google TV",
- 'img':"tv_l.png",
- 'title':"Announcing Google TV!",
- 'desc': "<p><a href='http://www.google.com/tv/'>Google TV</a> is a new platform "
- + "for television built on Android. Google "
- + "has partnered with Sony and Logitech to integrate "
- + "this platform into TVs, blu-ray players, and companion "
- + "boxes. </p>"
- + "<p><a href='http://www.google.com/tv/'>Learn more about "
- + "Google TV &raquo;</a></p>"
+ 'img':"GTV_icon_large.png",
+ 'title':"Google TV!",
+ 'desc': "<p>Build something big. By big, we mean <em>worthy-of-the-living-room</em> big.</p>"
+ + " <p>Use <a href='http://code.google.com/tv'>Google TV</a> to bring the power of Android"
+ + " and Google Chrome to television."
+ + " The average American watches five hours of TV per day. Give them the web and apps"
+ + " to update their status, listen to music, watch web videos, and much more...</p>"
},
+
'devphone': {
'layout':"imgLeft",
'icon':"devphone-small.png",
diff --git a/docs/html/resources/dashboard/opengl.jd b/docs/html/resources/dashboard/opengl.jd
index 3fcfa89..362ee16 100644
--- a/docs/html/resources/dashboard/opengl.jd
+++ b/docs/html/resources/dashboard/opengl.jd
@@ -74,6 +74,6 @@ src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=
</tr>
</table>
-<p><em>Data collected during a 7-day period ending on May 6, 2011</em></p>
+<p><em>Data collected during a 7-day period ending on July 1, 2011</em></p>
</div>
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index b4f1b27..18f47a6 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -99,7 +99,7 @@ padding: .25em 1em;
<a href="#" onclick="return toggleDiv(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px"
width="9px" />
-ADT 12.0.0</a> <em>(June 2011)</em>
+ADT 12.0.0</a> <em>(July 2011)</em>
<div class="toggleme">
<dl>
diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd
index e980ca5..97df84f 100644
--- a/docs/html/sdk/ndk/index.jd
+++ b/docs/html/sdk/ndk/index.jd
@@ -1,16 +1,16 @@
ndk=true
-ndk.win_download=android-ndk-r5c-windows.zip
-ndk.win_bytes=61627716
-ndk.win_checksum=2c7423842fa0f46871eab118495d4b45
+ndk.win_download=android-ndk-r6-windows.zip
+ndk.win_bytes=67642809
+ndk.win_checksum=9c7d5ccc02151a3e5e950c70dc05ac6d
-ndk.mac_download=android-ndk-r5c-darwin-x86.tar.bz2
-ndk.mac_bytes=50714712
-ndk.mac_checksum=183bfbbd85cf8e4c0bd7531e8803e75d
+ndk.mac_download=android-ndk-r6-darwin-x86.tar.bz2
+ndk.mac_bytes=52682746
+ndk.mac_checksum=a154905e49a6246abd823b75b6eda738
-ndk.linux_download=android-ndk-r5c-linux-x86.tar.bz2
-ndk.linux_bytes=44539890
-ndk.linux_checksum=7659dfdc97026ed1d913e224d0531f61
+ndk.linux_download=android-ndk-r6-linux-x86.tar.bz2
+ndk.linux_bytes=46425290
+ndk.linux_checksum=ff0a43085fe206696d5cdcef3f4f4637
page.title=Android NDK
@jd:body
@@ -62,6 +62,58 @@ padding: .25em 1em;
<div class="toggleable open">
<a href="#" onclick="return toggleDiv(this)"><img src=
"{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px">
+ Android NDK, Revision 6</a> <em>(July 2011)</em>
+
+ <div class="toggleme">
+ <p>This release of the NDK includes support for the x86 ABI and other minor changes.
+ For detailed information describing the changes in this release, read the
+ <code>CHANGES.HTML</code> document included in the NDK package.
+ </p>
+ <dl>
+ <dt>General notes:</dt>
+ <dd>
+ <ul>
+ <li>Adds support for the x86 ABI, which allows you to generate machine code
+ that runs on compatible x86-based Android devices. Major features for x86
+ include x86-specific toolchains, system headers, libraries and
+ debugging support. For all of the details regarding x86 support,
+ see <code>docs/CPU-X86.html</code> in the NDK package.
+
+ <p>By default, code is generated for ARM-based devices, but you can add x86 to your
+ <code>APP_ABI</code> definition in your <code>Application.mk</code> file to build
+ for x86 platforms. For example, the following line instructs <code>ndk-build</code>
+ to build your code for three distinct ABIs:</p>
+
+ <pre>APP_ABI := armeabi armeabi-v7a x86</pre>
+
+ <p>Unless you rely on ARM-based assembly sources, you shouldn't need to touch
+ your <code>Android.mk</code> files to build x86 machine code.</p>
+
+ </li>
+
+ <li>You can build a standalone x86 toolchain using the <code>--toolchain=x86-4.4.3</code>
+ option when calling <code>make-standalone-toolchain.sh</code>. See
+ <code>docs/STANDALONE-TOOLCHAIN.html</code> for more details.
+ </li>
+ <li>The new <code>ndk-stack</code> tool lets you translate stack traces in
+ <code>logcat</code> that are generated by native code. The tool translates
+ instruction addresses into a readable format that contains things such
+ as the function, source file, and line number corresponding to each stack frame.
+ For more information and a usage example, see <code>docs/NDK-STACK.html</code>.
+ </li>
+ </ul>
+ </dd>
+ <dt>Other changes:</dt>
+ <dd><code>arm-eabi-4.4.0</code>, which had been deprecated since NDK r5, has been
+ removed from the NDK distribution.</dd>
+
+ </dl>
+ </div>
+ </div>
+
+<div class="toggleable closed">
+ <a href="#" onclick="return toggleDiv(this)"><img src=
+ "{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px">
Android NDK, Revision 5c</a> <em>(June 2011)</em>
<div class="toggleme">
diff --git a/docs/html/sdk/ndk/overview.jd b/docs/html/sdk/ndk/overview.jd
index 2562a25..93c664d 100644
--- a/docs/html/sdk/ndk/overview.jd
+++ b/docs/html/sdk/ndk/overview.jd
@@ -53,11 +53,7 @@ page.title=What is the NDK?
<li>ARMv7-A (including Thumb-2 and VFPv3-D16 instructions, with optional support for
NEON/VFPv3-D32 instructions)</li>
- </ul>
-
- <p>Future releases of the NDK will also support:</p>
- <ul>
<li>x86 instructions (see CPU-ARCH-ABIS.HTML for more information)</li>
</ul>
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 0607aad..0539adb 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -77,7 +77,7 @@ class="new">new!</span></li>
<ul>
<li class="toggle-list">
<div><a href="<?cs var:toroot ?>sdk/android-3.1.html">
- <span class="en">Android 3.1 Platform</span></a> <span class="new">new!</span></div>
+ <span class="en">Android 3.1 Platform</span></a></div>
<ul>
<li><a href="<?cs var:toroot ?>sdk/android-3.1-highlights.html">Platform Highlights</a></li>
<li><a href="<?cs var:toroot ?>sdk/api_diff/12/changes.html">API Differences Report &raquo;</a></li>
@@ -91,7 +91,7 @@ class="new">new!</span></li>
<li><a href="<?cs var:toroot ?>sdk/api_diff/11/changes.html">API Differences Report &raquo;</a></li>
</ul>
</li>
- <li><a href="<?cs var:toroot ?>sdk/android-2.3.4.html">Android 2.3.4 Platform</span></a> <span class="new">new!</span></li>
+ <li><a href="<?cs var:toroot ?>sdk/android-2.3.4.html">Android 2.3.4 Platform</span></a></li>
<li class="toggle-list">
<div><a href="<?cs var:toroot ?>sdk/android-2.3.3.html">
<span class="en">Android 2.3.3 Platform</span></a></div>
@@ -137,8 +137,8 @@ class="new">new!</span></li>
<li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r12</a> <span
class="new">new!</span></li>
<li><a href="<?cs var:toroot ?>sdk/win-usb.html">Google USB Driver, r4</a></li>
- <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Compatibility Library, r2</a> <span
-class="new">new!</span></li>
+ <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Compatibility Library,
+r2</a></li>
</ul>
</li>
<li>
@@ -175,7 +175,7 @@ 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, r5c <span
+ <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6 <span
class="new">new!</span></a>
</li>
<li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li>
diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd
index d4ebf8a..8c4d037 100644
--- a/docs/html/sdk/tools-notes.jd
+++ b/docs/html/sdk/tools-notes.jd
@@ -66,7 +66,7 @@ padding: .25em 1em;
<div class="toggleable opened">
<a href="#" onclick="return toggleDiv(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
-SDK Tools, Revision 12</a> <em>(June 2011)</em>
+SDK Tools, Revision 12</a> <em>(July 2011)</em>
<div class="toggleme">
<dl>
<dt>Dependencies:</dt>
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk
index e3cd44f..fd417cb 100644
--- a/drm/drmserver/Android.mk
+++ b/drm/drmserver/Android.mk
@@ -24,13 +24,8 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES := \
libmedia \
libutils \
- libbinder
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
+ libbinder \
+ libdl
LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon
diff --git a/drm/jni/Android.mk b/drm/jni/Android.mk
index 69bb48d..4a55fc0 100644
--- a/drm/jni/Android.mk
+++ b/drm/jni/Android.mk
@@ -26,13 +26,8 @@ LOCAL_SHARED_LIBRARIES := \
libutils \
libandroid_runtime \
libnativehelper \
- libbinder
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
+ libbinder \
+ libdl
LOCAL_STATIC_LIBRARIES :=
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
index f1526a4..c534402 100644
--- a/drm/libdrmframework/Android.mk
+++ b/drm/libdrmframework/Android.mk
@@ -25,13 +25,8 @@ LOCAL_MODULE:= libdrmframework
LOCAL_SHARED_LIBRARIES := \
libutils \
- libbinder
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
+ libbinder \
+ libdl
LOCAL_STATIC_LIBRARIES := \
libdrmframeworkcommon
diff --git a/drm/libdrmframework/plugins/passthru/Android.mk b/drm/libdrmframework/plugins/passthru/Android.mk
index be18b64..d0d1439 100644
--- a/drm/libdrmframework/plugins/passthru/Android.mk
+++ b/drm/libdrmframework/plugins/passthru/Android.mk
@@ -24,14 +24,8 @@ LOCAL_MODULE := libdrmpassthruplugin
LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon
LOCAL_SHARED_LIBRARIES := \
- libutils
-
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
-
+ libutils \
+ libdl
LOCAL_C_INCLUDES += \
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 1324431..c5d7500 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -40,6 +40,7 @@ public class Path {
*/
public Region rects;
private boolean mDetectSimplePaths;
+ private Direction mLastDirection = null;
/**
* Create an empty path
@@ -70,6 +71,7 @@ public class Path {
public void reset() {
isSimplePath = true;
if (mDetectSimplePaths) {
+ mLastDirection = null;
if (rects != null) rects.setEmpty();
}
native_reset(mNativePath);
@@ -82,6 +84,7 @@ public class Path {
public void rewind() {
isSimplePath = true;
if (mDetectSimplePaths) {
+ mLastDirection = null;
if (rects != null) rects.setEmpty();
}
native_rewind(mNativePath);
@@ -378,6 +381,20 @@ public class Path {
final int nativeInt;
}
+ private void detectSimplePath(float left, float top, float right, float bottom, Direction dir) {
+ if (mDetectSimplePaths) {
+ if (mLastDirection == null) {
+ mLastDirection = dir;
+ }
+ if (mLastDirection != dir) {
+ isSimplePath = false;
+ } else {
+ if (rects == null) rects = new Region();
+ rects.op((int) left, (int) top, (int) right, (int) bottom, Region.Op.UNION);
+ }
+ }
+ }
+
/**
* Add a closed rectangle contour to the path
*
@@ -388,11 +405,7 @@ public class Path {
if (rect == null) {
throw new NullPointerException("need rect parameter");
}
- if (mDetectSimplePaths) {
- if (rects == null) rects = new Region();
- rects.op((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom,
- Region.Op.UNION);
- }
+ detectSimplePath(rect.left, rect.top, rect.right, rect.bottom, dir);
native_addRect(mNativePath, rect, dir.nativeInt);
}
@@ -406,10 +419,7 @@ public class Path {
* @param dir The direction to wind the rectangle's contour
*/
public void addRect(float left, float top, float right, float bottom, Direction dir) {
- if (mDetectSimplePaths) {
- if (rects == null) rects = new Region();
- rects.op((int) left, (int) top, (int) right, (int) bottom, Region.Op.UNION);
- }
+ detectSimplePath(left, top, right, bottom, dir);
native_addRect(mNativePath, left, top, right, bottom, dir.nativeInt);
}
diff --git a/graphics/java/android/renderscript/ScriptC.java b/graphics/java/android/renderscript/ScriptC.java
index f865753..90f959f 100644
--- a/graphics/java/android/renderscript/ScriptC.java
+++ b/graphics/java/android/renderscript/ScriptC.java
@@ -95,7 +95,7 @@ public class ScriptC extends Script {
// E.g, /system/apps/Fountain.apk
//String packageName = rs.getApplicationContext().getPackageResourcePath();
// For res/raw/fountain.bc, it wil be /com.android.fountain:raw/fountain
- String resName = resources.getResourceName(resourceID);
+ String resName = resources.getResourceEntryName(resourceID);
String cacheDir = rs.getApplicationContext().getCacheDir().toString();
Log.v(TAG, "Create script for resource = " + resName);
diff --git a/graphics/jni/Android.mk b/graphics/jni/Android.mk
index 084f54a..652189f 100644
--- a/graphics/jni/Android.mk
+++ b/graphics/jni/Android.mk
@@ -1,10 +1,3 @@
-
-# libRS needs libacc, which isn't 64-bit clean, and so can't be built
-# for the simulator on gHardy, and therefore libRS needs to be excluded
-# from the simulator as well, and so in turn librs_jni needs to be
-# excluded.
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -41,5 +34,3 @@ LOCAL_MODULE_TAGS := optional
LOCAL_REQUIRED_MODULES := libRS
include $(BUILD_SHARED_LIBRARY)
-
-endif #simulator
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
index feeb3c3..9725822 100644
--- a/include/binder/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -39,8 +39,6 @@ class ProcessState : public virtual RefBase
public:
static sp<ProcessState> self();
- static void setSingleProcess(bool singleProcess);
-
void setContextObject(const sp<IBinder>& object);
sp<IBinder> getContextObject(const sp<IBinder>& caller);
@@ -48,8 +46,6 @@ public:
const String16& name);
sp<IBinder> getContextObject(const String16& name,
const sp<IBinder>& caller);
-
- bool supportsProcesses() const;
void startThreadPool();
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 6ce44fc..9db7364 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -65,6 +65,8 @@ private:
int dispatchDisconnect(va_list args);
int dispatchSetBufferCount(va_list args);
int dispatchSetBuffersGeometry(va_list args);
+ int dispatchSetBuffersDimensions(va_list args);
+ int dispatchSetBuffersFormat(va_list args);
int dispatchSetBuffersTransform(va_list args);
int dispatchSetBuffersTimestamp(va_list args);
int dispatchSetCrop(va_list args);
@@ -73,7 +75,8 @@ private:
int connect(int api);
int disconnect(int api);
int setBufferCount(int bufferCount);
- int setBuffersGeometry(int w, int h, int format);
+ int setBuffersDimensions(int w, int h);
+ int setBuffersFormat(int format);
int setBuffersTransform(int transform);
int setBuffersTimestamp(int64_t timestamp);
int setCrop(Rect const* rect);
diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h
index d310cee..cc63356 100644
--- a/include/media/IStreamSource.h
+++ b/include/media/IStreamSource.h
@@ -51,6 +51,17 @@ struct IStreamListener : public IInterface {
// will be suppressed until media time reaches this timestamp.
static const char *const kKeyResumeAtPTS;
+ // When signalling a discontinuity you can optionally
+ // signal that this is a "hard" discontinuity, i.e. the format
+ // or configuration of subsequent stream data differs from that
+ // currently active. To do so, include a non-zero int32_t value
+ // under the key "kKeyFormatChange" when issuing the DISCONTINUITY
+ // command.
+ // The new logical stream must start with proper codec initialization
+ // information for playback to continue, i.e. SPS and PPS in the case
+ // of AVC video etc.
+ static const char *const kKeyFormatChange;
+
virtual void issueCommand(
Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0;
};
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 80b7c1c..8c1c593 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -197,6 +197,12 @@ private:
status_t init(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId, Size videoSize, int32_t frameRate,
bool storeMetaDataInVideoBuffers);
+
+ status_t initWithCameraAccess(
+ const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId, Size videoSize, int32_t frameRate,
+ bool storeMetaDataInVideoBuffers);
+
status_t isCameraAvailable(const sp<ICamera>& camera,
const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId);
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 904ce2a..77166ed 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -71,7 +71,8 @@ private:
bool mUse32BitOffset;
bool mIsFileSizeLimitExplicitlyRequested;
bool mPaused;
- bool mStarted;
+ bool mStarted; // Writer thread + track threads started successfully
+ bool mWriterThreadStarted; // Only writer thread started successfully
off64_t mOffset;
off_t mMdatOffset;
uint8_t *mMoovBoxBuffer;
@@ -182,6 +183,7 @@ private:
void writeLatitude(int degreex10000);
void writeLongitude(int degreex10000);
void sendSessionSummary();
+ void release();
MPEG4Writer(const MPEG4Writer &);
MPEG4Writer &operator=(const MPEG4Writer &);
diff --git a/include/media/stagefright/MetadataBufferType.h b/include/media/stagefright/MetadataBufferType.h
index 275c19f..52a3257 100644
--- a/include/media/stagefright/MetadataBufferType.h
+++ b/include/media/stagefright/MetadataBufferType.h
@@ -17,7 +17,11 @@
#ifndef METADATA_BUFFER_TYPE_H
#define METADATA_BUFFER_TYPE_H
+#ifdef __cplusplus
+extern "C" {
namespace android {
+#endif
+
/*
* MetadataBufferType defines the type of the metadata buffers that
* can be passed to video encoder component for encoding, via Stagefright
@@ -72,6 +76,9 @@ typedef enum {
} MetadataBufferType;
+#ifdef __cplusplus
} // namespace android
+}
+#endif
#endif // METADATA_BUFFER_TYPE_H
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 2d4e10d..7264ac4 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -43,8 +43,6 @@
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
-static bool gSingleProcess = false;
-
// ---------------------------------------------------------------------------
@@ -82,12 +80,6 @@ sp<ProcessState> ProcessState::self()
return gProcess;
}
-void ProcessState::setSingleProcess(bool singleProcess)
-{
- gSingleProcess = singleProcess;
-}
-
-
void ProcessState::setContextObject(const sp<IBinder>& object)
{
setContextObject(object, String16("default"));
@@ -95,11 +87,7 @@ void ProcessState::setContextObject(const sp<IBinder>& object)
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
- if (supportsProcesses()) {
- return getStrongProxyForHandle(0);
- } else {
- return getContextObject(String16("default"), caller);
- }
+ return getStrongProxyForHandle(0);
}
void ProcessState::setContextObject(const sp<IBinder>& object, const String16& name)
@@ -144,11 +132,6 @@ sp<IBinder> ProcessState::getContextObject(const String16& name, const sp<IBinde
return object;
}
-bool ProcessState::supportsProcesses() const
-{
- return mDriverFD >= 0;
-}
-
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
@@ -169,24 +152,19 @@ bool ProcessState::becomeContextManager(context_check_func checkFunc, void* user
AutoMutex _l(mLock);
mBinderContextCheckFunc = checkFunc;
mBinderContextUserData = userData;
- if (mDriverFD >= 0) {
- int dummy = 0;
+
+ int dummy = 0;
#if defined(HAVE_ANDROID_OS)
- status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
+ status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
#else
- status_t result = INVALID_OPERATION;
+ status_t result = INVALID_OPERATION;
#endif
- if (result == 0) {
- mManagesContexts = true;
- } else if (result == -1) {
- mBinderContextCheckFunc = NULL;
- mBinderContextUserData = NULL;
- LOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
- }
- } else {
- // If there is no driver, our only world is the local
- // process so we can always become the context manager there.
+ if (result == 0) {
mManagesContexts = true;
+ } else if (result == -1) {
+ mBinderContextCheckFunc = NULL;
+ mBinderContextUserData = NULL;
+ LOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
}
}
return mManagesContexts;
@@ -322,10 +300,6 @@ void ProcessState::spawnPooledThread(bool isMain)
static int open_driver()
{
- if (gSingleProcess) {
- return -1;
- }
-
int fd = open("/dev/binder", O_RDWR);
if (fd >= 0) {
fcntl(fd, F_SETFD, FD_CLOEXEC);
@@ -386,9 +360,8 @@ ProcessState::ProcessState()
mDriverFD = -1;
#endif
}
- if (mDriverFD < 0) {
- // Need to run without the driver, starting our own thread pool.
- }
+
+ LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
ProcessState::~ProcessState()
diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk
index dc00957..7286f92 100644
--- a/libs/camera/Android.mk
+++ b/libs/camera/Android.mk
@@ -20,8 +20,4 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_MODULE:= libcamera_client
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -lpthread
-endif
-
include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 4070eba..ed319f5 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -32,10 +32,6 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_MODULE:= libgui
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -lpthread
-endif
-
include $(BUILD_SHARED_LIBRARY)
ifeq (,$(ONE_SHOT_MAKEFILE))
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index b9b2310..e203035 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -254,6 +254,12 @@ int SurfaceTextureClient::perform(int operation, va_list args)
case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
res = dispatchSetBuffersTimestamp(args);
break;
+ case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
+ res = dispatchSetBuffersDimensions(args);
+ break;
+ case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
+ res = dispatchSetBuffersFormat(args);
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -290,7 +296,22 @@ int SurfaceTextureClient::dispatchSetBuffersGeometry(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 err = setBuffersDimensions(w, h);
+ if (err != 0) {
+ return err;
+ }
+ return setBuffersFormat(f);
+}
+
+int SurfaceTextureClient::dispatchSetBuffersDimensions(va_list args) {
+ int w = va_arg(args, int);
+ int h = va_arg(args, int);
+ return setBuffersDimensions(w, h);
+}
+
+int SurfaceTextureClient::dispatchSetBuffersFormat(va_list args) {
+ int f = va_arg(args, int);
+ return setBuffersFormat(f);
}
int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
@@ -390,12 +411,12 @@ int SurfaceTextureClient::setBufferCount(int bufferCount)
return err;
}
-int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format)
+int SurfaceTextureClient::setBuffersDimensions(int w, int h)
{
- LOGV("SurfaceTextureClient::setBuffersGeometry");
+ LOGV("SurfaceTextureClient::setBuffersDimensions");
Mutex::Autolock lock(mMutex);
- if (w<0 || h<0 || format<0)
+ if (w<0 || h<0)
return BAD_VALUE;
if ((w && !h) || (!w && h))
@@ -403,7 +424,6 @@ int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format)
mReqWidth = w;
mReqHeight = h;
- mReqFormat = format;
status_t err = mSurfaceTexture->setCrop(Rect(0, 0));
LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err));
@@ -411,6 +431,19 @@ int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format)
return err;
}
+int SurfaceTextureClient::setBuffersFormat(int format)
+{
+ LOGV("SurfaceTextureClient::setBuffersFormat");
+ Mutex::Autolock lock(mMutex);
+
+ if (format<0)
+ return BAD_VALUE;
+
+ mReqFormat = format;
+
+ return NO_ERROR;
+}
+
int SurfaceTextureClient::setBuffersTransform(int transform)
{
LOGV("SurfaceTextureClient::setBuffersTransform");
diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk
index 8d3a9b5..0308af3 100644
--- a/libs/gui/tests/Android.mk
+++ b/libs/gui/tests/Android.mk
@@ -2,8 +2,6 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_MODULE := SurfaceTexture_test
LOCAL_MODULE_TAGS := tests
@@ -36,8 +34,6 @@ LOCAL_C_INCLUDES := \
include $(BUILD_EXECUTABLE)
-endif
-
# Include subdirectory makefiles
# ============================================================
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 563d7e4..e232ddd 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -73,7 +73,6 @@ void Caches::dumpMemoryUsage() {
String8 stringLog;
dumpMemoryUsage(stringLog);
LOGD("%s", stringLog.string());
- delete stringLog;
}
void Caches::dumpMemoryUsage(String8 &log) {
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 7c10518..47049e2 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -43,7 +43,7 @@ enum DebugLevel {
kDebugDisabled = 0,
kDebugMemory = 1,
kDebugCaches = 2,
- kDebugMoreCaches = 3
+ kDebugMoreCaches = kDebugMemory | kDebugCaches
};
// These properties are defined in mega-bytes
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index b048469..f4d9686 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -537,7 +537,7 @@ PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *pat
const float pathWidth = fmax(bounds.width(), 1.0f);
const float pathHeight = fmax(bounds.height(), 1.0f);
- const float offset = fmax(paint->getStrokeWidth(), 1.0f) * 1.5f;
+ const float offset = (int) floorf(fmax(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f);
const uint32_t width = uint32_t(pathWidth + offset * 2.0 + 0.5);
const uint32_t height = uint32_t(pathHeight + offset * 2.0 + 0.5);
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index d9cc6b6..a8aa0c7 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -77,11 +77,6 @@ rs_generated_source += $(GEN)
LOCAL_GENERATED_SOURCES += $(GEN)
-# libRS needs libacc, which isn't 64-bit clean, and so can't be built
-# for the simulator on gHardy, and therefore libRS needs to be excluded
-# from the simulator as well.
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_SRC_FILES:= \
rsAdapter.cpp \
rsAllocation.cpp \
@@ -228,5 +223,3 @@ LOCAL_STATIC_LIBRARIES := libcutils libutils
LOCAL_LDLIBS := -lpthread
include $(BUILD_HOST_STATIC_LIBRARY)
-
-endif #simulator
diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp
index 27fc41f..bbf2836 100644
--- a/libs/rs/driver/rsdBcc.cpp
+++ b/libs/rs/driver/rsdBcc.cpp
@@ -66,65 +66,6 @@ static Script * setTLS(Script *sc) {
}
-// Input: cacheDir
-// Input: resName
-// Input: extName
-//
-// Note: cacheFile = resName + extName
-//
-// Output: Returns cachePath == cacheDir + cacheFile
-static char *genCacheFileName(const char *cacheDir,
- const char *resName,
- const char *extName) {
- char cachePath[512];
- char cacheFile[sizeof(cachePath)];
- const size_t kBufLen = sizeof(cachePath) - 1;
-
- cacheFile[0] = '\0';
- // Note: resName today is usually something like
- // "/com.android.fountain:raw/fountain"
- if (resName[0] != '/') {
- // Get the absolute path of the raw/***.bc file.
-
- // Generate the absolute path. This doesn't do everything it
- // should, e.g. if resName is "./out/whatever" it doesn't crunch
- // the leading "./" out because this if-block is not triggered,
- // but it'll make do.
- //
- if (getcwd(cacheFile, kBufLen) == NULL) {
- LOGE("Can't get CWD while opening raw/***.bc file\n");
- return NULL;
- }
- // Append "/" at the end of cacheFile so far.
- strncat(cacheFile, "/", kBufLen);
- }
-
- // cacheFile = resName + extName
- //
- strncat(cacheFile, resName, kBufLen);
- if (extName != NULL) {
- // TODO(srhines): strncat() is a bit dangerous
- strncat(cacheFile, extName, kBufLen);
- }
-
- // Turn the path into a flat filename by replacing
- // any slashes after the first one with '@' characters.
- char *cp = cacheFile + 1;
- while (*cp != '\0') {
- if (*cp == '/') {
- *cp = '@';
- }
- cp++;
- }
-
- // Tack on the file name for the actual cache file path.
- strncpy(cachePath, cacheDir, kBufLen);
- strncat(cachePath, cacheFile, kBufLen);
-
- LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath);
- return strdup(cachePath);
-}
-
bool rsdScriptInit(const Context *rsc,
ScriptC *script,
char const *resName,
@@ -164,15 +105,12 @@ bool rsdScriptInit(const Context *rsc,
goto error;
}
-#if 1
if (bccLinkFile(drv->mBccScript, "/system/lib/libclcore.bc", 0) != 0) {
LOGE("bcc: FAILS to link bitcode");
goto error;
}
-#endif
- cachePath = genCacheFileName(cacheDir, resName, ".oBCC");
- if (bccPrepareExecutable(drv->mBccScript, cachePath, 0) != 0) {
+ if (bccPrepareExecutableEx(drv->mBccScript, cacheDir, resName, 0) != 0) {
LOGE("bcc: FAILS to prepare executable");
goto error;
}
@@ -214,14 +152,13 @@ bool rsdScriptInit(const Context *rsc,
const char ** mPragmaKeys;
const char ** mPragmaValues;
- const static int pragmaMax = 16;
drv->mPragmaCount = bccGetPragmaCount(drv->mBccScript);
if (drv->mPragmaCount <= 0) {
drv->mPragmaKeys = NULL;
drv->mPragmaValues = NULL;
} else {
- drv->mPragmaKeys = (const char **) calloc(drv->mFieldCount, sizeof(const char *));
- drv->mPragmaValues = (const char **) calloc(drv->mFieldCount, sizeof(const char *));
+ drv->mPragmaKeys = (const char **) calloc(drv->mPragmaCount, sizeof(const char *));
+ drv->mPragmaValues = (const char **) calloc(drv->mPragmaCount, sizeof(const char *));
bccGetPragmaList(drv->mBccScript, drv->mPragmaCount, drv->mPragmaKeys, drv->mPragmaValues);
}
diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp
index 1f7bb0f..04446ad 100644
--- a/libs/rs/driver/rsdGL.cpp
+++ b/libs/rs/driver/rsdGL.cpp
@@ -99,9 +99,8 @@ static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
EGLint value = -1;
- EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
- EGLint error = eglGetError();
- if (returnVal && error == EGL_SUCCESS) {
+ EGLBoolean returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+ if (returnVal) {
LOGV(" %s: %d (0x%x)", names[j].name, value, value);
}
}
@@ -169,6 +168,24 @@ bool rsdGLInit(const Context *rsc) {
configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
configAttribsPtr += 2;
+ configAttribsPtr[0] = EGL_RED_SIZE;
+ configAttribsPtr[1] = 8;
+ configAttribsPtr += 2;
+
+ configAttribsPtr[0] = EGL_GREEN_SIZE;
+ configAttribsPtr[1] = 8;
+ configAttribsPtr += 2;
+
+ configAttribsPtr[0] = EGL_BLUE_SIZE;
+ configAttribsPtr[1] = 8;
+ configAttribsPtr += 2;
+
+ if (rsc->mUserSurfaceConfig.alphaMin > 0) {
+ configAttribsPtr[0] = EGL_ALPHA_SIZE;
+ configAttribsPtr[1] = rsc->mUserSurfaceConfig.alphaMin;
+ configAttribsPtr += 2;
+ }
+
if (rsc->mUserSurfaceConfig.depthMin > 0) {
configAttribsPtr[0] = EGL_DEPTH_SIZE;
configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin;
@@ -191,16 +208,53 @@ bool rsdGLInit(const Context *rsc) {
eglInitialize(dc->gl.egl.display, &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion);
checkEglError("eglInitialize");
- PixelFormat pf = PIXEL_FORMAT_RGBA_8888;
- if (rsc->mUserSurfaceConfig.alphaMin == 0) {
- pf = PIXEL_FORMAT_RGBX_8888;
- }
+ EGLBoolean ret;
- status_t err = EGLUtils::selectConfigForPixelFormat(dc->gl.egl.display, configAttribs,
- pf, &dc->gl.egl.config);
- if (err) {
- LOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
+ EGLint numConfigs = -1, n = 0;
+ ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs);
+ checkEglError("eglGetConfigs", ret);
+
+ if (numConfigs) {
+ EGLConfig* const configs = new EGLConfig[numConfigs];
+
+ ret = eglChooseConfig(dc->gl.egl.display,
+ configAttribs, configs, numConfigs, &n);
+ if (!ret || !n) {
+ checkEglError("eglChooseConfig", ret);
+ LOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
+ }
+
+ // The first config is guaranteed to over-satisfy the constraints
+ dc->gl.egl.config = configs[0];
+
+ // go through the list and skip configs that over-satisfy our needs
+ for (int i=0 ; i<n ; i++) {
+ if (rsc->mUserSurfaceConfig.alphaMin <= 0) {
+ EGLint alphaSize;
+ eglGetConfigAttrib(dc->gl.egl.display,
+ configs[i], EGL_ALPHA_SIZE, &alphaSize);
+ if (alphaSize > 0) {
+ continue;
+ }
+ }
+
+ if (rsc->mUserSurfaceConfig.depthMin <= 0) {
+ EGLint depthSize;
+ eglGetConfigAttrib(dc->gl.egl.display,
+ configs[i], EGL_DEPTH_SIZE, &depthSize);
+ if (depthSize > 0) {
+ continue;
+ }
+ }
+
+ // Found one!
+ dc->gl.egl.config = configs[i];
+ break;
+ }
+
+ delete [] configs;
}
+
//if (props.mLogVisual) {
if (0) {
printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config);
@@ -227,8 +281,8 @@ bool rsdGLInit(const Context *rsc) {
return false;
}
- EGLBoolean ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
- dc->gl.egl.surfaceDefault, dc->gl.egl.context);
+ ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
+ dc->gl.egl.surfaceDefault, dc->gl.egl.context);
if (ret == EGL_FALSE) {
LOGE("eglMakeCurrent returned EGL_FALSE");
checkEglError("eglMakeCurrent", ret);
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 2b58e9e..b77b18a 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -263,10 +263,10 @@ void Element::incRefs(const void *ptr) const {
const uint8_t *p = static_cast<const uint8_t *>(ptr);
for (uint32_t i=0; i < mFieldCount; i++) {
if (mFields[i].e->mHasReference) {
- p = &p[mFields[i].offsetBits >> 3];
+ const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
- mFields[i].e->incRefs(p);
- p += mFields[i].e->getSizeBytes();
+ mFields[i].e->incRefs(p2);
+ p2 += mFields[i].e->getSizeBytes();
}
}
}
@@ -285,10 +285,10 @@ void Element::decRefs(const void *ptr) const {
const uint8_t *p = static_cast<const uint8_t *>(ptr);
for (uint32_t i=0; i < mFieldCount; i++) {
if (mFields[i].e->mHasReference) {
- p = &p[mFields[i].offsetBits >> 3];
+ const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
- mFields[i].e->decRefs(p);
- p += mFields[i].e->getSizeBytes();
+ mFields[i].e->decRefs(p2);
+ p2 += mFields[i].e->getSizeBytes();
}
}
}
diff --git a/libs/storage/Android.mk b/libs/storage/Android.mk
index 1e52fa4..b42c34f 100644
--- a/libs/storage/Android.mk
+++ b/libs/storage/Android.mk
@@ -13,8 +13,4 @@ LOCAL_STATIC_LIBRARIES := \
LOCAL_MODULE:= libstorage
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -lpthread
-endif
-
include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk
index 267e3edf..5fca1ce 100644
--- a/libs/surfaceflinger_client/Android.mk
+++ b/libs/surfaceflinger_client/Android.mk
@@ -7,8 +7,4 @@ LOCAL_SHARED_LIBRARIES :=
LOCAL_MODULE:= libsurfaceflinger_client
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -lpthread
-endif
-
include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 427bbba..fbabfc4 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -68,10 +68,6 @@ LOCAL_C_INCLUDES := \
LOCAL_MODULE:= libui
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -lpthread
-endif
-
include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/ui/EGLUtils.cpp b/libs/ui/EGLUtils.cpp
index f24a71d..020646b 100644
--- a/libs/ui/EGLUtils.cpp
+++ b/libs/ui/EGLUtils.cpp
@@ -24,6 +24,8 @@
#include <EGL/egl.h>
+#include <system/graphics.h>
+
#include <private/ui/android_natives_priv.h>
// ----------------------------------------------------------------------------
@@ -67,31 +69,49 @@ status_t EGLUtils::selectConfigForPixelFormat(
return BAD_VALUE;
// Get all the "potential match" configs...
- if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE)
+ if (eglChooseConfig(dpy, attrs, 0, 0, &numConfigs) == EGL_FALSE)
return BAD_VALUE;
- EGLConfig* const configs = (EGLConfig*)malloc(sizeof(EGLConfig)*numConfigs);
- if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) {
- free(configs);
- return BAD_VALUE;
- }
-
- int i;
- EGLConfig config = NULL;
- for (i=0 ; i<n ; i++) {
- EGLint nativeVisualId = 0;
- eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
- if (nativeVisualId>0 && format == nativeVisualId) {
+ if (numConfigs) {
+ EGLConfig* const configs = new EGLConfig[numConfigs];
+ if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) {
+ delete [] configs;
+ return BAD_VALUE;
+ }
+
+ bool hasAlpha = false;
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ hasAlpha = true;
+ break;
+ }
+
+ // The first config is guaranteed to over-satisfy the constraints
+ EGLConfig config = configs[0];
+
+ // go through the list and skip configs that over-satisfy our needs
+ int i;
+ for (i=0 ; i<n ; i++) {
+ if (!hasAlpha) {
+ EGLint alphaSize;
+ eglGetConfigAttrib(dpy, configs[i], EGL_ALPHA_SIZE, &alphaSize);
+ if (alphaSize > 0) {
+ continue;
+ }
+ }
config = configs[i];
break;
}
- }
- free(configs);
-
- if (i<n) {
- *outConfig = config;
- return NO_ERROR;
+ delete [] configs;
+
+ if (i<n) {
+ *outConfig = config;
+ return NO_ERROR;
+ }
}
return NAME_NOT_FOUND;
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 4393504..9c10c75 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -299,6 +299,7 @@ int FramebufferNativeWindow::perform(ANativeWindow* window,
{
switch (operation) {
case NATIVE_WINDOW_SET_USAGE:
+ case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
case NATIVE_WINDOW_CONNECT:
case NATIVE_WINDOW_DISCONNECT:
break;
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index e231971..693a32a 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -2,8 +2,6 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-ifneq ($(TARGET_SIMULATOR),true)
-
# Build the unit tests.
test_src_files := \
InputChannel_test.cpp \
@@ -48,5 +46,3 @@ $(foreach file,$(test_src_files), \
# Build the manual test programs.
include $(call all-subdir-makefiles)
-
-endif \ No newline at end of file
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 774e8c9..f633357 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -103,17 +103,14 @@ LOCAL_SHARED_LIBRARIES := \
liblog \
libcutils
-ifneq ($(TARGET_SIMULATOR),true)
ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
# This is needed on x86 to bring in dl_iterate_phdr for CallStack.cpp
LOCAL_SHARED_LIBRARIES += libdl
endif # linux-x86
-endif # sim
LOCAL_MODULE:= libutils
include $(BUILD_SHARED_LIBRARY)
-ifneq ($(TARGET_SIMULATOR),true)
ifeq ($(TARGET_OS),linux)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += external/zlib external/icu4c/common
@@ -122,7 +119,6 @@ LOCAL_MODULE := libutils
LOCAL_SRC_FILES := $(commonSources) BackupData.cpp BackupHelpers.cpp
include $(BUILD_STATIC_LIBRARY)
endif
-endif
# Include subdirectory makefiles
diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp
index 87549fe..7ef30f9 100644
--- a/libs/utils/BackupHelpers.cpp
+++ b/libs/utils/BackupHelpers.cpp
@@ -481,6 +481,14 @@ static int write_pax_header_entry(char* buf, const char* key, const char* value)
return sprintf(buf, "%d %s=%s\n", len, key, value);
}
+// Wire format to the backup manager service is chunked: each chunk is prefixed by
+// a 4-byte count of its size. A chunk size of zero (four zero bytes) indicates EOD.
+void send_tarfile_chunk(BackupDataWriter* writer, const char* buffer, size_t size) {
+ uint32_t chunk_size_no = htonl(size);
+ writer->WriteEntityData(&chunk_size_no, 4);
+ if (size != 0) writer->WriteEntityData(buffer, size);
+}
+
int write_tarfile(const String8& packageName, const String8& domain,
const String8& rootpath, const String8& filepath, BackupDataWriter* writer)
{
@@ -660,16 +668,16 @@ int write_tarfile(const String8& packageName, const String8& domain,
// Checksum and write the pax block header
calc_tar_checksum(paxHeader);
- writer->WriteEntityData(paxHeader, 512);
+ send_tarfile_chunk(writer, paxHeader, 512);
// Now write the pax data itself
int paxblocks = (paxLen + 511) / 512;
- writer->WriteEntityData(paxData, 512 * paxblocks);
+ send_tarfile_chunk(writer, paxData, 512 * paxblocks);
}
// Checksum and write the 512-byte ustar file header block to the output
calc_tar_checksum(buf);
- writer->WriteEntityData(buf, 512);
+ send_tarfile_chunk(writer, buf, 512);
// Now write the file data itself, for real files. We honor tar's convention that
// only full 512-byte blocks are sent to write().
@@ -699,7 +707,7 @@ int write_tarfile(const String8& packageName, const String8& domain,
memset(buf + nRead, 0, remainder);
nRead += remainder;
}
- writer->WriteEntityData(buf, nRead);
+ send_tarfile_chunk(writer, buf, nRead);
toWrite -= nRead;
}
}
diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp
index 289c826..87ae3d5 100644
--- a/libs/utils/VectorImpl.cpp
+++ b/libs/utils/VectorImpl.cpp
@@ -290,7 +290,7 @@ void VectorImpl::clear()
void* VectorImpl::editItemLocation(size_t index)
{
LOG_ASSERT(index<capacity(),
- "[%p] itemLocation: index=%d, capacity=%d, count=%d",
+ "[%p] editItemLocation: index=%d, capacity=%d, count=%d",
this, (int)index, (int)capacity(), (int)mCount);
void* buffer = editArrayImpl();
@@ -302,7 +302,7 @@ void* VectorImpl::editItemLocation(size_t index)
const void* VectorImpl::itemLocation(size_t index) const
{
LOG_ASSERT(index<capacity(),
- "[%p] editItemLocation: index=%d, capacity=%d, count=%d",
+ "[%p] itemLocation: index=%d, capacity=%d, count=%d",
this, (int)index, (int)capacity(), (int)mCount);
const void* buffer = arrayImpl();
diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk
index 87ad98e..8726a53 100644
--- a/libs/utils/tests/Android.mk
+++ b/libs/utils/tests/Android.mk
@@ -2,8 +2,6 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-ifneq ($(TARGET_SIMULATOR),true)
-
# Build the unit tests.
test_src_files := \
BlobCache_test.cpp \
@@ -43,5 +41,3 @@ $(foreach file,$(test_src_files), \
$(eval LOCAL_MODULE_TAGS := $(module_tags)) \
$(eval include $(BUILD_EXECUTABLE)) \
)
-
-endif
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 6df2f73..816d215 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -104,10 +104,9 @@ public class MediaFile {
public static final int FILE_TYPE_MS_POWERPOINT = 106;
public static final int FILE_TYPE_ZIP = 107;
- static class MediaFileType {
-
- int fileType;
- String mimeType;
+ public static class MediaFileType {
+ public final int fileType;
+ public final String mimeType;
MediaFileType(int fileType, String mimeType) {
this.fileType = fileType;
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index c55338a..e89be08 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -101,6 +101,8 @@ import java.util.Iterator;
* Java MyMediaScanner handleStringTag.
* Once MediaScanner processFile returns, an entry is inserted in to the database.
*
+ * The MediaScanner class is not thread-safe, so it should only be used in a single threaded manner.
+ *
* {@hide}
*/
public class MediaScanner
@@ -368,6 +370,34 @@ public class MediaScanner
}
}
+ private class FileInserter {
+
+ ContentValues[] mValues = new ContentValues[1000];
+ int mIndex = 0;
+
+ public Uri insert(ContentValues values) {
+ if (mIndex == mValues.length) {
+ flush();
+ }
+ mValues[mIndex++] = values;
+ // URI not needed when doing bulk inserts
+ return null;
+ }
+
+ public void flush() {
+ while (mIndex < mValues.length) {
+ mValues[mIndex++] = null;
+ }
+ try {
+ mMediaProvider.bulkInsert(mFilesUri, mValues);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in FileInserter.flush()", e);
+ }
+ mIndex = 0;
+ }
+ }
+ private FileInserter mFileInserter;
+
// hashes file path to FileCacheEntry.
// path should be lower case if mCaseInsensitivePaths is true
private HashMap<String, FileCacheEntry> mFileCache;
@@ -805,35 +835,42 @@ public class MediaScanner
}
}
+ // For inserts we always use the file URI so we can insert in bulk.
+ // For updates we compute the URI based on the media type.
Uri tableUri = mFilesUri;
- if (!mNoMedia) {
- if (MediaFile.isVideoFileType(mFileType)) {
- tableUri = mVideoUri;
- } else if (MediaFile.isImageFileType(mFileType)) {
- tableUri = mImagesUri;
- } else if (MediaFile.isAudioFileType(mFileType)) {
- tableUri = mAudioUri;
- }
- }
Uri result = null;
if (rowId == 0) {
if (mMtpObjectHandle != 0) {
values.put(MediaStore.MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, mMtpObjectHandle);
}
- if (tableUri == mFilesUri) {
- int format = entry.mFormat;
- if (format == 0) {
- format = MediaFile.getFormatCode(entry.mPath, mMimeType);
- }
- values.put(Files.FileColumns.FORMAT, format);
+ int format = entry.mFormat;
+ if (format == 0) {
+ format = MediaFile.getFormatCode(entry.mPath, mMimeType);
}
+ values.put(Files.FileColumns.FORMAT, format);
+
// new file, insert it
- result = mMediaProvider.insert(tableUri, values);
+ if (mFileInserter != null) {
+ result = mFileInserter.insert(values);
+ } else {
+ result = mMediaProvider.insert(tableUri, values);
+ }
+
if (result != null) {
rowId = ContentUris.parseId(result);
entry.mRowId = rowId;
}
} else {
+ if (!mNoMedia) {
+ if (MediaFile.isVideoFileType(mFileType)) {
+ tableUri = mVideoUri;
+ } else if (MediaFile.isImageFileType(mFileType)) {
+ tableUri = mImagesUri;
+ } else if (MediaFile.isAudioFileType(mFileType)) {
+ tableUri = mAudioUri;
+ }
+ }
+
// updated file
result = ContentUris.withAppendedId(tableUri, rowId);
// path should never change, and we want to avoid replacing mixed cased paths
@@ -854,7 +891,7 @@ public class MediaScanner
new String[] { genre }, null);
if (cursor == null || cursor.getCount() == 0) {
// genre does not exist, so create the genre in the genre table
- values.clear();
+ values = new ContentValues();
values.put(MediaStore.Audio.Genres.NAME, genre);
uri = mMediaProvider.insert(mGenresUri, values);
} else {
@@ -876,7 +913,7 @@ public class MediaScanner
if (uri != null) {
// add entry to audio_genre_map
- values.clear();
+ values = new ContentValues();
values.put(MediaStore.Audio.Genres.Members.AUDIO_ID, Long.valueOf(rowId));
mMediaProvider.insert(uri, values);
}
@@ -1152,10 +1189,6 @@ public class MediaScanner
mPlaylistsUri = Playlists.getContentUri(volumeName);
mCaseInsensitivePaths = true;
- if (!Process.supportsProcesses()) {
- // Simulator uses host file system, so it should be case sensitive.
- mCaseInsensitivePaths = false;
- }
}
}
@@ -1165,10 +1198,14 @@ public class MediaScanner
initialize(volumeName);
prescan(null, true);
long prescan = System.currentTimeMillis();
+ mFileInserter = new FileInserter();
for (int i = 0; i < directories.length; i++) {
processDirectory(directories[i], mClient);
}
+ mFileInserter.flush();
+ mFileInserter = null;
+
long scan = System.currentTimeMillis();
postscan(directories);
long end = System.currentTimeMillis();
diff --git a/media/java/android/mtp/MtpPropertyGroup.java b/media/java/android/mtp/MtpPropertyGroup.java
index b75b11a..76c8569 100644
--- a/media/java/android/mtp/MtpPropertyGroup.java
+++ b/media/java/android/mtp/MtpPropertyGroup.java
@@ -330,7 +330,6 @@ class MtpPropertyGroup {
}
int count = (c == null ? 1 : c.getCount());
- Log.d(TAG, "count: " + count);
MtpPropertyList result = new MtpPropertyList(count * mProperties.length,
MtpConstants.RESPONSE_OK);
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index 0133cf6..f561cc0 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -16,18 +16,13 @@
package android.mtp;
-import android.util.Log;
-
/**
* Java wrapper for MTP/PTP support as USB responder.
* {@hide}
*/
-public class MtpServer {
-
- private final Object mLock = new Object();
- private boolean mStarted;
+public class MtpServer implements Runnable {
- private static final String TAG = "MtpServer";
+ private int mNativeContext; // accessed by native methods
static {
System.loadLibrary("media_jni");
@@ -38,19 +33,14 @@ public class MtpServer {
}
public void start() {
- synchronized (mLock) {
- native_start();
- mStarted = true;
- }
+ Thread thread = new Thread(this, "MtpServer");
+ thread.start();
}
- public void stop() {
- synchronized (mLock) {
- if (mStarted) {
- native_stop();
- mStarted = false;
- }
- }
+ @Override
+ public void run() {
+ native_run();
+ native_cleanup();
}
public void sendObjectAdded(int handle) {
@@ -70,8 +60,8 @@ public class MtpServer {
}
private native final void native_setup(MtpDatabase database, boolean usePtp);
- private native final void native_start();
- private native final void native_stop();
+ private native final void native_run();
+ private native final void native_cleanup();
private native final void native_send_object_added(int handle);
private native final void native_send_object_removed(int handle);
private native final void native_add_storage(MtpStorage storage);
diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java
index 7932d34..da190a6 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -32,6 +32,7 @@ public class MtpStorage {
private final String mDescription;
private final long mReserveSpace;
private final boolean mRemovable;
+ private final long mMaxFileSize;
public MtpStorage(StorageVolume volume) {
mStorageId = volume.getStorageId();
@@ -39,6 +40,7 @@ public class MtpStorage {
mDescription = volume.getDescription();
mReserveSpace = volume.getMtpReserveSpace();
mRemovable = volume.isRemovable();
+ mMaxFileSize = volume.getMaxFileSize();
}
/**
@@ -98,4 +100,13 @@ public class MtpStorage {
public final boolean isRemovable() {
return mRemovable;
}
+
+ /**
+ * Returns maximum file size for the storage, or zero if it is unbounded.
+ *
+ * @return maximum file size
+ */
+ public long getMaxFileSize() {
+ return mMaxFileSize;
+ }
}
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index 9151799..d0d2d1e 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -45,7 +45,6 @@ struct fields_t {
jfieldID context;
};
static fields_t fields;
-static Mutex sLock;
class MyMediaScannerClient : public MediaScannerClient
{
@@ -159,13 +158,11 @@ static bool ExceptionCheck(void* env)
return ((JNIEnv *)env)->ExceptionCheck();
}
-// Call this method with sLock hold
static MediaScanner *getNativeScanner_l(JNIEnv* env, jobject thiz)
{
return (MediaScanner *) env->GetIntField(thiz, fields.context);
}
-// Call this method with sLock hold
static void setNativeScanner_l(JNIEnv* env, jobject thiz, MediaScanner *s)
{
env->SetIntField(thiz, fields.context, (int)s);
@@ -176,7 +173,6 @@ android_media_MediaScanner_processDirectory(
JNIEnv *env, jobject thiz, jstring path, jobject client)
{
LOGV("processDirectory");
- Mutex::Autolock l(sLock);
MediaScanner *mp = getNativeScanner_l(env, thiz);
if (mp == NULL) {
jniThrowException(env, kRunTimeException, "No scanner available");
@@ -243,7 +239,6 @@ android_media_MediaScanner_setLocale(
JNIEnv *env, jobject thiz, jstring locale)
{
LOGV("setLocale");
- Mutex::Autolock l(sLock);
MediaScanner *mp = getNativeScanner_l(env, thiz);
if (mp == NULL) {
jniThrowException(env, kRunTimeException, "No scanner available");
@@ -268,7 +263,6 @@ android_media_MediaScanner_extractAlbumArt(
JNIEnv *env, jobject thiz, jobject fileDescriptor)
{
LOGV("extractAlbumArt");
- Mutex::Autolock l(sLock);
MediaScanner *mp = getNativeScanner_l(env, thiz);
if (mp == NULL) {
jniThrowException(env, kRunTimeException, "No scanner available");
@@ -339,7 +333,6 @@ static void
android_media_MediaScanner_native_finalize(JNIEnv *env, jobject thiz)
{
LOGV("native_finalize");
- Mutex::Autolock l(sLock);
MediaScanner *mp = getNativeScanner_l(env, thiz);
if (mp == 0) {
return;
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index aaf85c3..107db08 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -22,13 +22,8 @@
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
-#include <sys/ioctl.h>
#include <utils/threads.h>
-#ifdef HAVE_ANDROID_OS
-#include <linux/usb/f_mtp.h>
-#endif
-
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
@@ -39,8 +34,8 @@
using namespace android;
-// MtpStorage class
-jclass clazz_MtpStorage;
+// MtpServer fields
+static jfieldID field_MtpServer_nativeContext;
// MtpStorage fields
static jfieldID field_MtpStorage_storageId;
@@ -48,6 +43,7 @@ static jfieldID field_MtpStorage_path;
static jfieldID field_MtpStorage_description;
static jfieldID field_MtpStorage_reserveSpace;
static jfieldID field_MtpStorage_removable;
+static jfieldID field_MtpStorage_maxFileSize;
static Mutex sMutex;
@@ -56,185 +52,92 @@ static Mutex sMutex;
// in android_mtp_MtpDatabase.cpp
extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
-// ----------------------------------------------------------------------------
-
-#ifdef HAVE_ANDROID_OS
-
-static bool ExceptionCheck(void* env)
-{
- return ((JNIEnv *)env)->ExceptionCheck();
+static inline MtpServer* getMtpServer(JNIEnv *env, jobject thiz) {
+ return (MtpServer*)env->GetIntField(thiz, field_MtpServer_nativeContext);
}
-class MtpThread : public Thread {
-private:
- MtpDatabase* mDatabase;
- bool mPtp;
- MtpServer* mServer;
- MtpStorageList mStorageList;
- int mFd;
-
-public:
- MtpThread(MtpDatabase* database, bool usePtp)
- : mDatabase(database),
- mPtp(usePtp),
- mServer(NULL),
- mFd(-1)
- {
- }
-
- virtual ~MtpThread() {
- }
-
- void addStorage(MtpStorage *storage) {
- mStorageList.push(storage);
- if (mServer)
- mServer->addStorage(storage);
- }
-
- void removeStorage(MtpStorageID id) {
- MtpStorage* storage = mServer->getStorage(id);
- if (storage) {
- for (size_t i = 0; i < mStorageList.size(); i++) {
- if (mStorageList[i] == storage) {
- mStorageList.removeAt(i);
- break;
- }
- }
- if (mServer)
- mServer->removeStorage(storage);
- delete storage;
- }
- }
-
- void start() {
- run("MtpThread");
- }
-
- virtual bool threadLoop() {
- sMutex.lock();
-
- mFd = open("/dev/mtp_usb", O_RDWR);
- if (mFd >= 0) {
- mServer = new MtpServer(mFd, mDatabase, mPtp, AID_MEDIA_RW, 0664, 0775);
- for (size_t i = 0; i < mStorageList.size(); i++) {
- mServer->addStorage(mStorageList[i]);
- }
- } else {
- LOGE("could not open MTP driver, errno: %d", errno);
- }
-
- sMutex.unlock();
- mServer->run();
- sMutex.lock();
-
- close(mFd);
- mFd = -1;
- delete mServer;
- mServer = NULL;
-
- sMutex.unlock();
- // delay a bit before retrying to avoid excessive spin
- if (!exitPending()) {
- sleep(1);
- }
-
- return true;
- }
-
- void sendObjectAdded(MtpObjectHandle handle) {
- if (mServer)
- mServer->sendObjectAdded(handle);
- }
-
- void sendObjectRemoved(MtpObjectHandle handle) {
- if (mServer)
- mServer->sendObjectRemoved(handle);
- }
-};
-
-// This smart pointer is necessary for preventing MtpThread from exiting too early
-static sp<MtpThread> sThread;
-
-#endif // HAVE_ANDROID_OS
-
static void
android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jboolean usePtp)
{
-#ifdef HAVE_ANDROID_OS
- // create the thread and assign it to the smart pointer
- sThread = new MtpThread(getMtpDatabase(env, javaDatabase), usePtp);
-#endif
+ int fd = open("/dev/mtp_usb", O_RDWR);
+ if (fd >= 0) {
+ MtpServer* server = new MtpServer(fd, getMtpDatabase(env, javaDatabase),
+ usePtp, AID_MEDIA_RW, 0664, 0775);
+ env->SetIntField(thiz, field_MtpServer_nativeContext, (int)server);
+ } else {
+ LOGE("could not open MTP driver, errno: %d", errno);
+ }
}
static void
-android_mtp_MtpServer_start(JNIEnv *env, jobject thiz)
+android_mtp_MtpServer_run(JNIEnv *env, jobject thiz)
{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread)
- thread->start();
- sMutex.unlock();
-#endif // HAVE_ANDROID_OS
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server)
+ server->run();
+ else
+ LOGE("server is null in run");
}
static void
-android_mtp_MtpServer_stop(JNIEnv *env, jobject thiz)
+android_mtp_MtpServer_cleanup(JNIEnv *env, jobject thiz)
{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread) {
- thread->requestExitAndWait();
- sThread = NULL;
+ Mutex::Autolock autoLock(sMutex);
+
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server) {
+ delete server;
+ env->SetIntField(thiz, field_MtpServer_nativeContext, 0);
+ } else {
+ LOGE("server is null in cleanup");
}
- sMutex.unlock();
-#endif
}
static void
android_mtp_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread)
- thread->sendObjectAdded(handle);
- sMutex.unlock();
-#endif
+ Mutex::Autolock autoLock(sMutex);
+
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server)
+ server->sendObjectAdded(handle);
+ else
+ LOGE("server is null in send_object_added");
}
static void
android_mtp_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread)
- thread->sendObjectRemoved(handle);
- sMutex.unlock();
-#endif
+ Mutex::Autolock autoLock(sMutex);
+
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server)
+ server->sendObjectRemoved(handle);
+ else
+ LOGE("server is null in send_object_removed");
}
static void
android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage)
{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread) {
+ Mutex::Autolock autoLock(sMutex);
+
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server) {
jint storageID = env->GetIntField(jstorage, field_MtpStorage_storageId);
jstring path = (jstring)env->GetObjectField(jstorage, field_MtpStorage_path);
jstring description = (jstring)env->GetObjectField(jstorage, field_MtpStorage_description);
jlong reserveSpace = env->GetLongField(jstorage, field_MtpStorage_reserveSpace);
jboolean removable = env->GetBooleanField(jstorage, field_MtpStorage_removable);
+ jlong maxFileSize = env->GetLongField(jstorage, field_MtpStorage_maxFileSize);
const char *pathStr = env->GetStringUTFChars(path, NULL);
if (pathStr != NULL) {
const char *descriptionStr = env->GetStringUTFChars(description, NULL);
if (descriptionStr != NULL) {
- MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr, reserveSpace, removable);
- thread->addStorage(storage);
+ MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr,
+ reserveSpace, removable, maxFileSize);
+ server->addStorage(storage);
env->ReleaseStringUTFChars(path, pathStr);
env->ReleaseStringUTFChars(description, descriptionStr);
} else {
@@ -242,24 +145,24 @@ android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage)
}
}
} else {
- LOGE("MtpThread is null in add_storage");
+ LOGE("server is null in add_storage");
}
- sMutex.unlock();
-#endif
}
static void
android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId)
{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread)
- thread->removeStorage(storageId);
- else
- LOGE("MtpThread is null in remove_storage");
- sMutex.unlock();
-#endif
+ Mutex::Autolock autoLock(sMutex);
+
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server) {
+ MtpStorage* storage = server->getStorage(storageId);
+ if (storage) {
+ server->removeStorage(storage);
+ delete storage;
+ }
+ } else
+ LOGE("server is null in remove_storage");
}
// ----------------------------------------------------------------------------
@@ -267,8 +170,8 @@ android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId)
static JNINativeMethod gMethods[] = {
{"native_setup", "(Landroid/mtp/MtpDatabase;Z)V",
(void *)android_mtp_MtpServer_setup},
- {"native_start", "()V", (void *)android_mtp_MtpServer_start},
- {"native_stop", "()V", (void *)android_mtp_MtpServer_stop},
+ {"native_run", "()V", (void *)android_mtp_MtpServer_run},
+ {"native_cleanup", "()V", (void *)android_mtp_MtpServer_cleanup},
{"native_send_object_added", "(I)V", (void *)android_mtp_MtpServer_send_object_added},
{"native_send_object_removed", "(I)V", (void *)android_mtp_MtpServer_send_object_removed},
{"native_add_storage", "(Landroid/mtp/MtpStorage;)V",
@@ -312,13 +215,22 @@ int register_android_mtp_MtpServer(JNIEnv *env)
LOGE("Can't find MtpStorage.mRemovable");
return -1;
}
- clazz_MtpStorage = (jclass)env->NewGlobalRef(clazz);
+ field_MtpStorage_maxFileSize = env->GetFieldID(clazz, "mMaxFileSize", "J");
+ if (field_MtpStorage_maxFileSize == NULL) {
+ LOGE("Can't find MtpStorage.mMaxFileSize");
+ return -1;
+ }
clazz = env->FindClass("android/mtp/MtpServer");
if (clazz == NULL) {
LOGE("Can't find android/mtp/MtpServer");
return -1;
}
+ field_MtpServer_nativeContext = env->GetFieldID(clazz, "mNativeContext", "I");
+ if (field_MtpServer_nativeContext == NULL) {
+ LOGE("Can't find MtpServer.mNativeContext");
+ return -1;
+ }
return AndroidRuntime::registerNativeMethods(env,
"android/mtp/MtpServer", gMethods, NELEM(gMethods));
diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk
index 20f58e5..26265ae 100644
--- a/media/libeffects/factory/Android.mk
+++ b/media/libeffects/factory/Android.mk
@@ -12,14 +12,6 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_MODULE:= libeffects
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-LOCAL_LDLIBS += -ldl
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
LOCAL_SHARED_LIBRARIES += libdl
-endif
-
-LOCAL_C_INCLUDES := \
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index a3e76d9..a9689bc 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -130,10 +130,43 @@ int Effect_GetDescriptor(effect_handle_t self,
return ret;
}
+int Effect_ProcessReverse(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+ int ret = init();
+ if (ret < 0) {
+ return ret;
+ }
+ effect_entry_t *fx = (effect_entry_t *)self;
+ pthread_mutex_lock(&gLibLock);
+ if (fx->lib == NULL) {
+ pthread_mutex_unlock(&gLibLock);
+ return -EPIPE;
+ }
+ pthread_mutex_lock(&fx->lib->lock);
+ pthread_mutex_unlock(&gLibLock);
+
+ if ((*fx->subItfe)->process_reverse != NULL) {
+ ret = (*fx->subItfe)->process_reverse(fx->subItfe, inBuffer, outBuffer);
+ } else {
+ ret = -ENOSYS;
+ }
+ pthread_mutex_unlock(&fx->lib->lock);
+ return ret;
+}
+
+
const struct effect_interface_s gInterface = {
Effect_Process,
Effect_Command,
- Effect_GetDescriptor
+ Effect_GetDescriptor,
+ NULL
+};
+
+const struct effect_interface_s gInterfaceWithReverse = {
+ Effect_Process,
+ Effect_Command,
+ Effect_GetDescriptor,
+ Effect_ProcessReverse
};
/////////////////////////////////////////////////
@@ -266,7 +299,13 @@ int EffectCreate(effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_ha
// add entry to effect list
fx = (effect_entry_t *)malloc(sizeof(effect_entry_t));
fx->subItfe = itfe;
- fx->itfe = (struct effect_interface_s *)&gInterface;
+ if ((*itfe)->process_reverse != NULL) {
+ fx->itfe = (struct effect_interface_s *)&gInterfaceWithReverse;
+ LOGV("EffectCreate() gInterfaceWithReverse");
+ } else {
+ fx->itfe = (struct effect_interface_s *)&gInterface;
+ LOGV("EffectCreate() gInterface");
+ }
fx->lib = l;
e = (list_elem_t *)malloc(sizeof(list_elem_t));
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
index ab13605..f097dd0 100644
--- a/media/libeffects/lvm/wrapper/Android.mk
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -19,12 +19,7 @@ LOCAL_STATIC_LIBRARIES += libmusicbundle
LOCAL_SHARED_LIBRARIES := \
libcutils \
-
-ifeq ($(TARGET_SIMULATOR),true)
-LOCAL_LDLIBS += -ldl
-else
-LOCAL_SHARED_LIBRARIES += libdl
-endif
+ libdl
LOCAL_C_INCLUDES += \
@@ -54,12 +49,7 @@ LOCAL_STATIC_LIBRARIES += libreverb
LOCAL_SHARED_LIBRARIES := \
libcutils \
-
-ifeq ($(TARGET_SIMULATOR),true)
-LOCAL_LDLIBS += -ldl
-else
-LOCAL_SHARED_LIBRARIES += libdl
-endif
+ libdl
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/Reverb \
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 21c451f..efa1c45 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -3231,7 +3231,8 @@ int Effect_getDescriptor(effect_handle_t self,
const struct effect_interface_s gLvmEffectInterface = {
Effect_process,
Effect_command,
- Effect_getDescriptor
+ Effect_getDescriptor,
+ NULL,
}; /* end gLvmEffectInterface */
audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 2727375..663f8ff 100755
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -2134,7 +2134,8 @@ int Reverb_getDescriptor(effect_handle_t self,
const struct effect_interface_s gReverbInterface = {
Reverb_process,
Reverb_command,
- Reverb_getDescriptor
+ Reverb_getDescriptor,
+ NULL,
}; /* end gReverbInterface */
audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
diff --git a/media/libeffects/testlibs/EffectEqualizer.cpp b/media/libeffects/testlibs/EffectEqualizer.cpp
index c2ffce5..b22ebec 100644
--- a/media/libeffects/testlibs/EffectEqualizer.cpp
+++ b/media/libeffects/testlibs/EffectEqualizer.cpp
@@ -736,7 +736,8 @@ extern "C" int Equalizer_getDescriptor(effect_handle_t self,
const struct effect_interface_s gEqualizerInterface = {
Equalizer_process,
Equalizer_command,
- Equalizer_getDescriptor
+ Equalizer_getDescriptor,
+ NULL
};
diff --git a/media/libeffects/testlibs/EffectReverb.c b/media/libeffects/testlibs/EffectReverb.c
index 02762c9..405f908 100644
--- a/media/libeffects/testlibs/EffectReverb.c
+++ b/media/libeffects/testlibs/EffectReverb.c
@@ -27,7 +27,8 @@
const struct effect_interface_s gReverbInterface = {
Reverb_Process,
Reverb_Command,
- Reverb_GetDescriptor
+ Reverb_GetDescriptor,
+ NULL
};
// Google auxiliary environmental reverb UUID: 1f0ae2e0-4ef7-11df-bc09-0002a5d5c51b
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index dff585f..2160177 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -9,19 +9,12 @@ LOCAL_SRC_FILES:= \
LOCAL_CFLAGS+= -O2
LOCAL_SHARED_LIBRARIES := \
- libcutils
+ libcutils \
+ libdl
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
LOCAL_MODULE:= libvisualizer
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-LOCAL_LDLIBS += -ldl
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
-
LOCAL_C_INCLUDES := \
$(call include-path-for, graphics corecg) \
system/media/audio_effects/include
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index aeebd4d..3c3af8f 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -450,7 +450,8 @@ int Visualizer_getDescriptor(effect_handle_t self,
const struct effect_interface_s gVisualizerInterface = {
Visualizer_process,
Visualizer_command,
- Visualizer_getDescriptor
+ Visualizer_getDescriptor,
+ NULL,
};
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index f7c54fa..7af4a87 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -49,20 +49,12 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES := \
libui libcutils libutils libbinder libsonivox libicuuc libexpat \
libcamera_client libstagefright_foundation \
- libgui
+ libgui libdl
LOCAL_WHOLE_STATIC_LIBRARY := libmedia_helper
LOCAL_MODULE:= libmedia
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-LOCAL_LDLIBS += -ldl -lpthread
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
-
LOCAL_C_INCLUDES := \
$(JNI_H_INCLUDE) \
$(call include-path-for, graphics corecg) \
diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp
index c14ee82..b311f35 100644
--- a/media/libmedia/IStreamSource.cpp
+++ b/media/libmedia/IStreamSource.cpp
@@ -29,6 +29,9 @@ namespace android {
// static
const char *const IStreamListener::kKeyResumeAtPTS = "resume-at-PTS";
+// static
+const char *const IStreamListener::kKeyFormatChange = "format-change";
+
enum {
// IStreamSource
SET_LISTENER = IBinder::FIRST_CALL_TRANSACTION,
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index fadad28..ec7d8a0 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -16,10 +16,6 @@ LOCAL_SRC_FILES:= \
StagefrightPlayer.cpp \
StagefrightRecorder.cpp
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-LOCAL_LDLIBS += -ldl -lpthread
-endif
-
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
@@ -32,16 +28,13 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright \
libstagefright_omx \
libstagefright_foundation \
- libgui
+ libgui \
+ libdl
LOCAL_STATIC_LIBRARIES := \
libstagefright_rtsp \
libstagefright_nuplayer \
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
-
LOCAL_C_INCLUDES := \
$(JNI_H_INCLUDE) \
$(call include-path-for, graphics corecg) \
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index b003476..223e0be 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1136,10 +1136,69 @@ status_t StagefrightRecorder::checkVideoEncoderCapabilities() {
clipVideoFrameRate();
clipVideoFrameWidth();
clipVideoFrameHeight();
+ setDefaultProfileIfNecessary();
}
return OK;
}
+// Set to use AVC baseline profile if the encoding parameters matches
+// CAMCORDER_QUALITY_LOW profile; this is for the sake of MMS service.
+void StagefrightRecorder::setDefaultProfileIfNecessary() {
+ LOGV("setDefaultProfileIfNecessary");
+
+ camcorder_quality quality = CAMCORDER_QUALITY_LOW;
+
+ int64_t durationUs = mEncoderProfiles->getCamcorderProfileParamByName(
+ "duration", mCameraId, quality) * 1000000LL;
+
+ int fileFormat = mEncoderProfiles->getCamcorderProfileParamByName(
+ "file.format", mCameraId, quality);
+
+ int videoCodec = mEncoderProfiles->getCamcorderProfileParamByName(
+ "vid.codec", mCameraId, quality);
+
+ int videoBitRate = mEncoderProfiles->getCamcorderProfileParamByName(
+ "vid.bps", mCameraId, quality);
+
+ int videoFrameRate = mEncoderProfiles->getCamcorderProfileParamByName(
+ "vid.fps", mCameraId, quality);
+
+ int videoFrameWidth = mEncoderProfiles->getCamcorderProfileParamByName(
+ "vid.width", mCameraId, quality);
+
+ int videoFrameHeight = mEncoderProfiles->getCamcorderProfileParamByName(
+ "vid.height", mCameraId, quality);
+
+ int audioCodec = mEncoderProfiles->getCamcorderProfileParamByName(
+ "aud.codec", mCameraId, quality);
+
+ int audioBitRate = mEncoderProfiles->getCamcorderProfileParamByName(
+ "aud.bps", mCameraId, quality);
+
+ int audioSampleRate = mEncoderProfiles->getCamcorderProfileParamByName(
+ "aud.hz", mCameraId, quality);
+
+ int audioChannels = mEncoderProfiles->getCamcorderProfileParamByName(
+ "aud.ch", mCameraId, quality);
+
+ if (durationUs == mMaxFileDurationUs &&
+ fileFormat == mOutputFormat &&
+ videoCodec == mVideoEncoder &&
+ videoBitRate == mVideoBitRate &&
+ videoFrameRate == mFrameRate &&
+ videoFrameWidth == mVideoWidth &&
+ videoFrameHeight == mVideoHeight &&
+ audioCodec == mAudioEncoder &&
+ audioBitRate == mAudioBitRate &&
+ audioSampleRate == mSampleRate &&
+ audioChannels == mAudioChannels) {
+ if (videoCodec == VIDEO_ENCODER_H264) {
+ LOGI("Force to use AVC baseline profile");
+ setParamVideoEncoderProfile(OMX_VIDEO_AVCProfileBaseline);
+ }
+ }
+}
+
status_t StagefrightRecorder::checkAudioEncoderCapabilities() {
clipAudioBitRate();
clipAudioSampleRate();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index cb9c406..034b373 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -174,6 +174,7 @@ private:
void clipAudioBitRate();
void clipAudioSampleRate();
void clipNumberOfAudioChannels();
+ void setDefaultProfileIfNecessary();
StagefrightRecorder(const StagefrightRecorder &);
StagefrightRecorder &operator=(const StagefrightRecorder &);
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index bbc8a6e..a6a3a18 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -63,8 +63,17 @@ bool NuPlayer::StreamingSource::feedMoreTSData() {
mEOS = true;
break;
} else if (n == INFO_DISCONTINUITY) {
- mTSParser->signalDiscontinuity(
- ATSParser::DISCONTINUITY_SEEK, extra);
+ ATSParser::DiscontinuityType type = ATSParser::DISCONTINUITY_SEEK;
+
+ int32_t formatChange;
+ if (extra != NULL
+ && extra->findInt32(
+ IStreamListener::kKeyFormatChange, &formatChange)
+ && formatChange != 0) {
+ type = ATSParser::DISCONTINUITY_FORMATCHANGE;
+ }
+
+ mTSParser->signalDiscontinuity(type, extra);
} else if (n < 0) {
CHECK_EQ(n, -EWOULDBLOCK);
break;
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 8c4b274..0b998b9 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -3,8 +3,6 @@ include $(CLEAR_VARS)
include frameworks/base/media/libstagefright/codecs/common/Config.mk
-BUILD_WITH_SOFTWARE_DECODERS := false
-
LOCAL_SRC_FILES:= \
ACodec.cpp \
AACExtractor.cpp \
@@ -96,26 +94,6 @@ LOCAL_STATIC_LIBRARIES := \
libstagefright_id3 \
libFLAC \
-ifeq ($(BUILD_WITH_SOFTWARE_DECODERS),true)
-
-LOCAL_SRC_FILES += \
- ThreadedSource.cpp \
-
-LOCAL_STATIC_LIBRARIES += \
- libstagefright_aacdec \
- libstagefright_amrnbdec \
- libstagefright_amrwbdec \
- libstagefright_avcdec \
- libstagefright_g711dec \
- libstagefright_mp3dec \
- libstagefright_m4vh263dec \
- libstagefright_vorbisdec \
- libstagefright_vpxdec \
- libvpx \
-
-endif
-
-
################################################################################
# The following was shamelessly copied from external/webkit/Android.mk and
@@ -159,10 +137,8 @@ LOCAL_STATIC_LIBRARIES += \
libchromium_net \
libwebcore \
-ifneq ($(TARGET_SIMULATOR),true)
LOCAL_SHARED_LIBRARIES += libstlport
include external/stlport/libstlport.mk
-endif
LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1
@@ -175,27 +151,10 @@ LOCAL_SHARED_LIBRARIES += \
libstagefright_enc_common \
libstagefright_avc_common \
libstagefright_foundation \
-
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
- LOCAL_LDLIBS += -lpthread -ldl
- LOCAL_SHARED_LIBRARIES += libdvm
- LOCAL_CPPFLAGS += -DANDROID_SIMULATOR
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
-
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
- LOCAL_LDLIBS += -lpthread
-endif
+ libdl
LOCAL_CFLAGS += -Wno-multichar
-ifeq ($(BUILD_WITH_SOFTWARE_DECODERS),true)
- LOCAL_CFLAGS += -DHAVE_SOFTWARE_DECODERS
-endif
-
LOCAL_MODULE:= libstagefright
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index ed8149a..1bc2fb9 100644..100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -103,6 +103,10 @@ static int32_t getColorFormat(const char* colorFormat) {
return OMX_COLOR_Format16bitRGB565;
}
+ if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
+ return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
+ }
+
LOGE("Uknown color format (%s), please add it to "
"CameraSource::getColorFormat", colorFormat);
@@ -158,12 +162,10 @@ CameraSource::CameraSource(
mVideoSize.width = -1;
mVideoSize.height = -1;
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
mInitCheck = init(camera, proxy, cameraId,
videoSize, frameRate,
storeMetaDataInVideoBuffers);
if (mInitCheck != OK) releaseCamera();
- IPCThreadState::self()->restoreCallingIdentity(token);
}
status_t CameraSource::initCheck() const {
@@ -463,6 +465,22 @@ status_t CameraSource::init(
bool storeMetaDataInVideoBuffers) {
status_t err = OK;
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ err = initWithCameraAccess(camera, proxy, cameraId,
+ videoSize, frameRate,
+ storeMetaDataInVideoBuffers);
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ return err;
+}
+
+status_t CameraSource::initWithCameraAccess(
+ const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId,
+ Size videoSize,
+ int32_t frameRate,
+ bool storeMetaDataInVideoBuffers) {
+ status_t err = OK;
if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
LOGE("Camera connection could not be established.");
@@ -525,6 +543,11 @@ status_t CameraSource::init(
CameraSource::~CameraSource() {
if (mStarted) {
stop();
+ } else if (mInitCheck == OK) {
+ // Camera is initialized but because start() is never called,
+ // the lock on Camera is never released(). This makes sure
+ // Camera's lock is released in this case.
+ releaseCamera();
}
}
@@ -571,6 +594,7 @@ void CameraSource::stopCameraRecording() {
void CameraSource::releaseCamera() {
LOGV("releaseCamera");
if (mCamera != 0) {
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
LOGV("Camera was cold when we started, stopping preview");
mCamera->stopPreview();
@@ -580,6 +604,7 @@ void CameraSource::releaseCamera() {
mCamera->unlock();
}
mCamera.clear();
+ IPCThreadState::self()->restoreCallingIdentity(token);
}
if (mCameraRecordingProxy != 0) {
mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index f075699..8c9ff87 100644..100755
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -246,6 +246,7 @@ MPEG4Writer::MPEG4Writer(const char *filename)
mIsFileSizeLimitExplicitlyRequested(false),
mPaused(false),
mStarted(false),
+ mWriterThreadStarted(false),
mOffset(0),
mMdatOffset(0),
mEstimatedMoovBoxSize(0),
@@ -269,6 +270,7 @@ MPEG4Writer::MPEG4Writer(int fd)
mIsFileSizeLimitExplicitlyRequested(false),
mPaused(false),
mStarted(false),
+ mWriterThreadStarted(false),
mOffset(0),
mMdatOffset(0),
mEstimatedMoovBoxSize(0),
@@ -538,6 +540,9 @@ status_t MPEG4Writer::pause() {
void MPEG4Writer::stopWriterThread() {
LOGD("Stopping writer thread");
+ if (!mWriterThreadStarted) {
+ return;
+ }
{
Mutex::Autolock autolock(mLock);
@@ -548,6 +553,7 @@ void MPEG4Writer::stopWriterThread() {
void *dummy;
pthread_join(mThread, &dummy);
+ mWriterThreadStarted = false;
LOGD("Writer thread stopped");
}
@@ -603,10 +609,25 @@ void MPEG4Writer::writeCompositionMatrix(int degrees) {
writeInt32(0x40000000); // w
}
+void MPEG4Writer::release() {
+ close(mFd);
+ mFd = -1;
+ mInitCheck = NO_INIT;
+ mStarted = false;
+}
status_t MPEG4Writer::stop() {
if (mInitCheck != OK) {
return OK;
+ } else {
+ if (!mWriterThreadStarted ||
+ !mStarted) {
+ if (mWriterThreadStarted) {
+ stopWriterThread();
+ }
+ release();
+ return OK;
+ }
}
status_t err = OK;
@@ -637,10 +658,7 @@ status_t MPEG4Writer::stop() {
// Do not write out movie header on error.
if (err != OK) {
- close(mFd);
- mFd = -1;
- mInitCheck = NO_INIT;
- mStarted = false;
+ release();
return err;
}
@@ -688,11 +706,7 @@ status_t MPEG4Writer::stop() {
CHECK(mBoxes.empty());
- close(mFd);
- mFd = -1;
- mInitCheck = NO_INIT;
- mStarted = false;
-
+ release();
return err;
}
@@ -1415,6 +1429,7 @@ status_t MPEG4Writer::startWriterThread() {
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&mThread, &attr, ThreadWrapper, this);
pthread_attr_destroy(&attr);
+ mWriterThreadStarted = true;
return OK;
}
@@ -1700,7 +1715,10 @@ status_t MPEG4Writer::Track::parseAVCCodecSpecificData(
return ERROR_MALFORMED;
}
}
-
+// FIXME:
+// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
+// and remove #if 0
+#if 0
{
// Check on the profiles
// These profiles requires additional parameter set extensions
@@ -1710,7 +1728,7 @@ status_t MPEG4Writer::Track::parseAVCCodecSpecificData(
return BAD_VALUE;
}
}
-
+#endif
return OK;
}
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 1ac2c1f..b7b0dc0 100644..100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -18,20 +18,11 @@
#define LOG_TAG "OMXCodec"
#include <utils/Log.h>
-#include "include/AACDecoder.h"
#include "include/AACEncoder.h"
-#include "include/AMRNBDecoder.h"
#include "include/AMRNBEncoder.h"
-#include "include/AMRWBDecoder.h"
#include "include/AMRWBEncoder.h"
-#include "include/AVCDecoder.h"
#include "include/AVCEncoder.h"
-#include "include/G711Decoder.h"
-#include "include/M4vH263Decoder.h"
#include "include/M4vH263Encoder.h"
-#include "include/MP3Decoder.h"
-#include "include/VorbisDecoder.h"
-#include "include/VPXDecoder.h"
#include "include/ESDS.h"
@@ -53,10 +44,6 @@
#include <OMX_Audio.h>
#include <OMX_Component.h>
-#if HAVE_SOFTWARE_DECODERS
-#include "include/ThreadedSource.h"
-#endif
-
#include "include/avc_utils.h"
namespace android {
@@ -79,24 +66,6 @@ FACTORY_CREATE_ENCODER(AACEncoder)
FACTORY_CREATE_ENCODER(AVCEncoder)
FACTORY_CREATE_ENCODER(M4vH263Encoder)
-#if HAVE_SOFTWARE_DECODERS
-
-#define FACTORY_CREATE(name) \
-static sp<MediaSource> Make##name(const sp<MediaSource> &source) { \
- return new name(source); \
-}
-
-FACTORY_CREATE(AMRNBDecoder)
-FACTORY_CREATE(AMRWBDecoder)
-FACTORY_CREATE(AACDecoder)
-FACTORY_CREATE(AVCDecoder)
-FACTORY_CREATE(G711Decoder)
-FACTORY_CREATE(MP3Decoder)
-FACTORY_CREATE(M4vH263Decoder)
-FACTORY_CREATE(VorbisDecoder)
-FACTORY_CREATE(VPXDecoder)
-#endif
-
static sp<MediaSource> InstantiateSoftwareEncoder(
const char *name, const sp<MediaSource> &source,
const sp<MetaData> &meta) {
@@ -122,40 +91,6 @@ static sp<MediaSource> InstantiateSoftwareEncoder(
return NULL;
}
-static sp<MediaSource> InstantiateSoftwareCodec(
- const char *name, const sp<MediaSource> &source) {
-#if HAVE_SOFTWARE_DECODERS
- struct FactoryInfo {
- const char *name;
- sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &);
- };
-
- static const FactoryInfo kFactoryInfo[] = {
- FACTORY_REF(AMRNBDecoder)
- FACTORY_REF(AMRWBDecoder)
- FACTORY_REF(AACDecoder)
- FACTORY_REF(AVCDecoder)
- FACTORY_REF(G711Decoder)
- FACTORY_REF(MP3Decoder)
- FACTORY_REF(M4vH263Decoder)
- FACTORY_REF(VorbisDecoder)
- FACTORY_REF(VPXDecoder)
- };
- for (size_t i = 0;
- i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
- if (!strcmp(name, kFactoryInfo[i].name)) {
- if (!strcmp(name, "VPXDecoder")) {
- return new ThreadedSource(
- (*kFactoryInfo[i].CreateFunc)(source));
- }
- return (*kFactoryInfo[i].CreateFunc)(source);
- }
- }
-#endif
-
- return NULL;
-}
-
#undef FACTORY_REF
#undef FACTORY_CREATE
@@ -163,23 +98,17 @@ static const CodecInfo kDecoderInfo[] = {
{ MEDIA_MIMETYPE_IMAGE_JPEG, "OMX.TI.JPEG.decode" },
// { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
{ MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.google.mp3.decoder" },
- { MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" },
// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amr.decoder" },
{ MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.google.amrnb.decoder" },
- { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" },
// { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.Nvidia.amrwb.decoder" },
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.google.amrwb.decoder" },
- { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBDecoder" },
// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.Nvidia.aac.decoder" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "OMX.google.aac.decoder" },
- { MEDIA_MIMETYPE_AUDIO_AAC, "AACDecoder" },
{ MEDIA_MIMETYPE_AUDIO_G711_ALAW, "OMX.google.g711.alaw.decoder" },
- { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "G711Decoder" },
{ MEDIA_MIMETYPE_AUDIO_G711_MLAW, "OMX.google.g711.mlaw.decoder" },
- { MEDIA_MIMETYPE_AUDIO_G711_MLAW, "G711Decoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.DECODER" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.decode" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
@@ -187,14 +116,12 @@ static const CodecInfo kDecoderInfo[] = {
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.google.mpeg4.decoder" },
- { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.DECODER" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.decode" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.google.h263.decoder" },
- { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.DECODER" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.decode" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
@@ -203,11 +130,8 @@ static const CodecInfo kDecoderInfo[] = {
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.SEC.AVC.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.google.h264.decoder" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.google.avc.decoder" },
- { MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" },
{ MEDIA_MIMETYPE_AUDIO_VORBIS, "OMX.google.vorbis.decoder" },
- { MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" },
{ MEDIA_MIMETYPE_VIDEO_VPX, "OMX.google.vpx.decoder" },
- { MEDIA_MIMETYPE_VIDEO_VPX, "VPXDecoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG2, "OMX.Nvidia.mpeg2v.decode" },
};
@@ -218,18 +142,21 @@ static const CodecInfo kEncoderInfo[] = {
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.MPEG4E" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.encoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.encoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Encoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Encoder" },
+ { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.MPEG4E" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.encoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.encoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Encoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Encoder" },
+ { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.H264E" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.encoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
@@ -393,7 +320,17 @@ uint32_t OMXCodec::getComponentQuirks(
if (!strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.DECODER")) {
quirks |= kRequiresAllocateBufferOnInputPorts;
quirks |= kRequiresAllocateBufferOnOutputPorts;
- } else if (!strncmp(componentName, "OMX.TI.", 7)) {
+ }
+
+ // FIXME:
+ // Remove the quirks after the work is done.
+ else if (!strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.MPEG4E") ||
+ !strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.H264E")) {
+
+ quirks |= kRequiresAllocateBufferOnInputPorts;
+ quirks |= kRequiresAllocateBufferOnOutputPorts;
+ }
+ else if (!strncmp(componentName, "OMX.TI.", 7)) {
// Apparently I must not use OMX_UseBuffer on either input or
// output ports on any of the TI components or quote:
// "(I) may have unexpected problem (sic) which can be timing related
@@ -505,14 +442,15 @@ sp<MediaSource> OMXCodec::Create(
for (size_t i = 0; i < matchingCodecs.size(); ++i) {
componentName = matchingCodecs[i].string();
- sp<MediaSource> softwareCodec = createEncoder?
- InstantiateSoftwareEncoder(componentName, source, meta):
- InstantiateSoftwareCodec(componentName, source);
+ if (createEncoder) {
+ sp<MediaSource> softwareCodec =
+ InstantiateSoftwareEncoder(componentName, source, meta);
- if (softwareCodec != NULL) {
- LOGV("Successfully allocated software codec '%s'", componentName);
+ if (softwareCodec != NULL) {
+ LOGV("Successfully allocated software codec '%s'", componentName);
- return softwareCodec;
+ return softwareCodec;
+ }
}
LOGV("Attempting to allocate OMX node '%s'", componentName);
@@ -887,6 +825,7 @@ static size_t getFrameSize(
case OMX_COLOR_FormatYUV420Planar:
case OMX_COLOR_FormatYUV420SemiPlanar:
+ case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
return (width * height * 3) / 2;
default:
@@ -910,6 +849,7 @@ status_t OMXCodec::findTargetColorFormat(
}
}
+
// Check whether the target color format is supported.
return isColorFormatSupported(*colorFormat, kPortIndexInput);
}
@@ -1032,6 +972,11 @@ void OMXCodec::setVideoInputFormat(
video_def->nFrameWidth = width;
video_def->nFrameHeight = height;
video_def->xFramerate = 0; // No need for output port
+ // FIXME:
+ // Revmoe this workaround after work is done.
+ if (!strncmp(mComponentName, "OMX.TI.DUCATI1", 14)) {
+ video_def->xFramerate = (frameRate << 16);
+ }
video_def->nBitrate = bitRate; // Q16 format
video_def->eCompressionFormat = compressionFormat;
video_def->eColorFormat = OMX_COLOR_FormatUnused;
@@ -1295,13 +1240,6 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
h264type.nAllowedPictureTypes =
OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
- h264type.nSliceHeaderSpacing = 0;
- h264type.nBFrames = 0; // No B frames support yet
- h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
- if (h264type.nPFrames == 0) {
- h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
- }
-
// Check profile and level parameters
CodecProfileLevel defaultProfileLevel, profileLevel;
defaultProfileLevel.mProfile = h264type.eProfile;
@@ -1311,9 +1249,21 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile);
h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
+ // FIXME:
+ // Remove the workaround after the work in done.
+ if (!strncmp(mComponentName, "OMX.TI.DUCATI1", 14)) {
+ h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
+ }
+
if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
+ h264type.nSliceHeaderSpacing = 0;
h264type.bUseHadamard = OMX_TRUE;
h264type.nRefFrames = 1;
+ h264type.nBFrames = 0;
+ h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+ if (h264type.nPFrames == 0) {
+ h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+ }
h264type.nRefIdx10ActiveMinus1 = 0;
h264type.nRefIdx11ActiveMinus1 = 0;
h264type.bEntropyCodingCABAC = OMX_FALSE;
@@ -4405,12 +4355,9 @@ status_t QueryCodecs(
if (strncmp(componentName, "OMX.", 4)) {
// Not an OpenMax component but a software codec.
-#if HAVE_SOFTWARE_DECODERS
results->push();
CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
caps->mComponentName = componentName;
-#endif
-
continue;
}
diff --git a/media/libstagefright/ThreadedSource.cpp b/media/libstagefright/ThreadedSource.cpp
deleted file mode 100644
index 38c6e2d..0000000
--- a/media/libstagefright/ThreadedSource.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "ThreadedSource"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include "include/ThreadedSource.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-static const size_t kMaxQueueSize = 2;
-
-ThreadedSource::ThreadedSource(const sp<MediaSource> &source)
- : mSource(source),
- mReflector(new AHandlerReflector<ThreadedSource>(this)),
- mLooper(new ALooper),
- mStarted(false) {
- mLooper->registerHandler(mReflector);
-}
-
-ThreadedSource::~ThreadedSource() {
- if (mStarted) {
- stop();
- }
-}
-
-status_t ThreadedSource::start(MetaData *params) {
- CHECK(!mStarted);
-
- status_t err = mSource->start(params);
-
- if (err != OK) {
- return err;
- }
-
- mFinalResult = OK;
- mSeekTimeUs = -1;
- mDecodePending = false;
-
- Mutex::Autolock autoLock(mLock);
- postDecodeMore_l();
-
- CHECK_EQ(mLooper->start(), (status_t)OK);
-
- mStarted = true;
-
- return OK;
-}
-
-status_t ThreadedSource::stop() {
- CHECK(mStarted);
-
- CHECK_EQ(mLooper->stop(), (status_t)OK);
-
- Mutex::Autolock autoLock(mLock);
- clearQueue_l();
-
- status_t err = mSource->stop();
-
- mStarted = false;
-
- return err;
-}
-
-sp<MetaData> ThreadedSource::getFormat() {
- return mSource->getFormat();
-}
-
-status_t ThreadedSource::read(
- MediaBuffer **buffer, const ReadOptions *options) {
- *buffer = NULL;
-
- Mutex::Autolock autoLock(mLock);
-
- int64_t seekTimeUs;
- ReadOptions::SeekMode seekMode;
- if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
- int32_t seekComplete = 0;
-
- sp<AMessage> msg = new AMessage(kWhatSeek, mReflector->id());
- msg->setInt64("timeUs", seekTimeUs);
- msg->setInt32("mode", seekMode);
- msg->setPointer("complete", &seekComplete);
- msg->post();
-
- while (!seekComplete) {
- mCondition.wait(mLock);
- }
- }
-
- while (mQueue.empty() && mFinalResult == OK) {
- mCondition.wait(mLock);
- }
-
- if (!mQueue.empty()) {
- *buffer = *mQueue.begin();
- mQueue.erase(mQueue.begin());
-
- if (mFinalResult == OK) {
- postDecodeMore_l();
- }
-
- return OK;
- }
-
- return mFinalResult;
-}
-
-void ThreadedSource::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatSeek:
- {
- CHECK(msg->findInt64("timeUs", &mSeekTimeUs));
- CHECK_GE(mSeekTimeUs, 0ll);
-
- int32_t x;
- CHECK(msg->findInt32("mode", &x));
- mSeekMode = (ReadOptions::SeekMode)x;
-
- int32_t *seekComplete;
- CHECK(msg->findPointer("complete", (void **)&seekComplete));
-
- Mutex::Autolock autoLock(mLock);
- clearQueue_l();
- mFinalResult = OK;
-
- *seekComplete = 1;
- mCondition.signal();
-
- postDecodeMore_l();
- break;
- }
-
- case kWhatDecodeMore:
- {
- {
- Mutex::Autolock autoLock(mLock);
- mDecodePending = false;
-
- if (mQueue.size() == kMaxQueueSize) {
- break;
- }
- }
-
- MediaBuffer *buffer;
- ReadOptions options;
- if (mSeekTimeUs >= 0) {
- options.setSeekTo(mSeekTimeUs, mSeekMode);
- mSeekTimeUs = -1ll;
- }
- status_t err = mSource->read(&buffer, &options);
-
- Mutex::Autolock autoLock(mLock);
-
- if (err != OK) {
- mFinalResult = err;
- } else {
- mQueue.push_back(buffer);
-
- if (mQueue.size() < kMaxQueueSize) {
- postDecodeMore_l();
- }
- }
-
- mCondition.signal();
- break;
- }
-
- default:
- TRESPASS();
- break;
- }
-}
-
-void ThreadedSource::postDecodeMore_l() {
- if (mDecodePending) {
- return;
- }
-
- mDecodePending = true;
- (new AMessage(kWhatDecodeMore, mReflector->id()))->post();
-}
-
-void ThreadedSource::clearQueue_l() {
- while (!mQueue.empty()) {
- MediaBuffer *buffer = *mQueue.begin();
- mQueue.erase(mQueue.begin());
-
- buffer->release();
- buffer = NULL;
- }
-}
-
-} // namespace android
diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk
index 80b2478..6573e3c 100644
--- a/media/libstagefright/chromium_http/Android.mk
+++ b/media/libstagefright/chromium_http/Android.mk
@@ -15,10 +15,8 @@ LOCAL_C_INCLUDES:= \
LOCAL_CFLAGS += -Wno-multichar
-ifneq ($(TARGET_SIMULATOR),true)
LOCAL_SHARED_LIBRARIES += libstlport
include external/stlport/libstlport.mk
-endif
LOCAL_MODULE:= libstagefright_chromium_http
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
deleted file mode 100644
index d2e3eaa..0000000
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2009 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 "AACDecoder.h"
-#define LOG_TAG "AACDecoder"
-
-#include "../../include/ESDS.h"
-
-#include "pvmp4audiodecoder_api.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-AACDecoder::AACDecoder(const sp<MediaSource> &source)
- : mSource(source),
- mStarted(false),
- mBufferGroup(NULL),
- mConfig(new tPVMP4AudioDecoderExternal),
- mDecoderBuf(NULL),
- mAnchorTimeUs(0),
- mNumSamplesOutput(0),
- mInputBuffer(NULL) {
-
- sp<MetaData> srcFormat = mSource->getFormat();
-
- int32_t sampleRate;
- CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-
- mMeta = new MetaData;
- mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-
- // We'll always output stereo, regardless of how many channels are
- // present in the input due to decoder limitations.
- mMeta->setInt32(kKeyChannelCount, 2);
- mMeta->setInt32(kKeySampleRate, sampleRate);
-
- int64_t durationUs;
- if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
- mMeta->setInt64(kKeyDuration, durationUs);
- }
- mMeta->setCString(kKeyDecoderComponent, "AACDecoder");
-
- mInitCheck = initCheck();
-}
-
-status_t AACDecoder::initCheck() {
- memset(mConfig, 0, sizeof(tPVMP4AudioDecoderExternal));
- mConfig->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED;
- mConfig->aacPlusEnabled = 1;
-
- // The software decoder doesn't properly support mono output on
- // AACplus files. Always output stereo.
- mConfig->desiredChannels = 2;
-
- UInt32 memRequirements = PVMP4AudioDecoderGetMemRequirements();
- mDecoderBuf = malloc(memRequirements);
-
- status_t err = PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf);
- if (err != MP4AUDEC_SUCCESS) {
- LOGE("Failed to initialize MP4 audio decoder");
- return UNKNOWN_ERROR;
- }
-
- uint32_t type;
- const void *data;
- size_t size;
- sp<MetaData> meta = mSource->getFormat();
- if (meta->findData(kKeyESDS, &type, &data, &size)) {
- ESDS esds((const char *)data, size);
- CHECK_EQ(esds.InitCheck(), (status_t)OK);
-
- const void *codec_specific_data;
- size_t codec_specific_data_size;
- esds.getCodecSpecificInfo(
- &codec_specific_data, &codec_specific_data_size);
-
- mConfig->pInputBuffer = (UChar *)codec_specific_data;
- mConfig->inputBufferCurrentLength = codec_specific_data_size;
- mConfig->inputBufferMaxLength = 0;
-
- if (PVMP4AudioDecoderConfig(mConfig, mDecoderBuf)
- != MP4AUDEC_SUCCESS) {
- return ERROR_UNSUPPORTED;
- }
- }
- return OK;
-}
-
-AACDecoder::~AACDecoder() {
- if (mStarted) {
- stop();
- }
-
- delete mConfig;
- mConfig = NULL;
-}
-
-status_t AACDecoder::start(MetaData *params) {
- CHECK(!mStarted);
-
- mBufferGroup = new MediaBufferGroup;
- mBufferGroup->add_buffer(new MediaBuffer(4096 * 2));
-
- mSource->start();
-
- mAnchorTimeUs = 0;
- mNumSamplesOutput = 0;
- mStarted = true;
- mNumDecodedBuffers = 0;
- mUpsamplingFactor = 2;
-
- return OK;
-}
-
-status_t AACDecoder::stop() {
- CHECK(mStarted);
-
- if (mInputBuffer) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- free(mDecoderBuf);
- mDecoderBuf = NULL;
-
- delete mBufferGroup;
- mBufferGroup = NULL;
-
- mSource->stop();
-
- mStarted = false;
-
- return OK;
-}
-
-sp<MetaData> AACDecoder::getFormat() {
- return mMeta;
-}
-
-status_t AACDecoder::read(
- MediaBuffer **out, const ReadOptions *options) {
- status_t err;
-
- *out = NULL;
-
- int64_t seekTimeUs;
- ReadOptions::SeekMode mode;
- if (options && options->getSeekTo(&seekTimeUs, &mode)) {
- CHECK(seekTimeUs >= 0);
-
- mNumSamplesOutput = 0;
-
- if (mInputBuffer) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- // Make sure that the next buffer output does not still
- // depend on fragments from the last one decoded.
- PVMP4AudioDecoderResetBuffer(mDecoderBuf);
- } else {
- seekTimeUs = -1;
- }
-
- if (mInputBuffer == NULL) {
- err = mSource->read(&mInputBuffer, options);
-
- if (err != OK) {
- return err;
- }
-
- int64_t timeUs;
- if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- mAnchorTimeUs = timeUs;
- mNumSamplesOutput = 0;
- } else {
- // We must have a new timestamp after seeking.
- CHECK(seekTimeUs < 0);
- }
- }
-
- MediaBuffer *buffer;
- CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK);
-
- mConfig->pInputBuffer =
- (UChar *)mInputBuffer->data() + mInputBuffer->range_offset();
-
- mConfig->inputBufferCurrentLength = mInputBuffer->range_length();
- mConfig->inputBufferMaxLength = 0;
- mConfig->inputBufferUsedLength = 0;
- mConfig->remainderBits = 0;
-
- mConfig->pOutputBuffer = static_cast<Int16 *>(buffer->data());
- mConfig->pOutputBuffer_plus = &mConfig->pOutputBuffer[2048];
- mConfig->repositionFlag = false;
-
- Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);
-
- /*
- * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
- * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
- * rate system and the sampling rate in the final output is actually
- * doubled compared with the core AAC decoder sampling rate.
- *
- * Explicit signalling is done by explicitly defining SBR audio object
- * type in the bitstream. Implicit signalling is done by embedding
- * SBR content in AAC extension payload specific to SBR, and hence
- * requires an AAC decoder to perform pre-checks on actual audio frames.
- *
- * Thus, we could not say for sure whether a stream is
- * AAC+/eAAC+ until the first data frame is decoded.
- */
- if (++mNumDecodedBuffers <= 2) {
- LOGV("audio/extended audio object type: %d + %d",
- mConfig->audioObjectType, mConfig->extendedAudioObjectType);
- LOGV("aac+ upsampling factor: %d desired channels: %d",
- mConfig->aacPlusUpsamplingFactor, mConfig->desiredChannels);
-
- CHECK(mNumDecodedBuffers > 0);
-
- if (decoderErr != MP4AUDEC_SUCCESS) {
- // If decoding fails this early, the fields in mConfig may
- // not be valid and we cannot recover.
-
- LOGE("Unable to decode aac content, decoder returned error %d",
- decoderErr);
-
- buffer->release();
- buffer = NULL;
-
- mInputBuffer->release();
- mInputBuffer = NULL;
-
- return ERROR_UNSUPPORTED;
- }
-
- if (mNumDecodedBuffers == 1) {
- mUpsamplingFactor = mConfig->aacPlusUpsamplingFactor;
- // Check on the sampling rate to see whether it is changed.
- int32_t sampleRate;
- CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate));
- if (mConfig->samplingRate != sampleRate) {
- mMeta->setInt32(kKeySampleRate, mConfig->samplingRate);
- LOGW("Sample rate was %d Hz, but now is %d Hz",
- sampleRate, mConfig->samplingRate);
- buffer->release();
- mInputBuffer->release();
- mInputBuffer = NULL;
- return INFO_FORMAT_CHANGED;
- }
- } else { // mNumDecodedBuffers == 2
- if (mConfig->extendedAudioObjectType == MP4AUDIO_AAC_LC ||
- mConfig->extendedAudioObjectType == MP4AUDIO_LTP) {
- if (mUpsamplingFactor == 2) {
- // The stream turns out to be not aacPlus mode anyway
- LOGW("Disable AAC+/eAAC+ since extended audio object type is %d",
- mConfig->extendedAudioObjectType);
- mConfig->aacPlusEnabled = 0;
- }
- } else {
- if (mUpsamplingFactor == 1) {
- // aacPlus mode does not buy us anything, but to cause
- // 1. CPU load to increase, and
- // 2. a half speed of decoding
- LOGW("Disable AAC+/eAAC+ since upsampling factor is 1");
- mConfig->aacPlusEnabled = 0;
- }
- }
- }
- }
-
- size_t numOutBytes =
- mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
- if (mUpsamplingFactor == 2) {
- if (mConfig->desiredChannels == 1) {
- memcpy(&mConfig->pOutputBuffer[1024], &mConfig->pOutputBuffer[2048], numOutBytes * 2);
- }
- numOutBytes *= 2;
- }
-
- if (decoderErr != MP4AUDEC_SUCCESS) {
- LOGW("AAC decoder returned error %d, substituting silence", decoderErr);
-
- memset(buffer->data(), 0, numOutBytes);
-
- // Discard input buffer.
- mInputBuffer->release();
- mInputBuffer = NULL;
-
- // fall through
- }
-
- buffer->set_range(0, numOutBytes);
-
- if (mInputBuffer != NULL) {
- mInputBuffer->set_range(
- mInputBuffer->range_offset() + mConfig->inputBufferUsedLength,
- mInputBuffer->range_length() - mConfig->inputBufferUsedLength);
-
- if (mInputBuffer->range_length() == 0) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
- }
-
- buffer->meta_data()->setInt64(
- kKeyTime,
- mAnchorTimeUs
- + (mNumSamplesOutput * 1000000) / mConfig->samplingRate);
-
- mNumSamplesOutput += mConfig->frameLength * mUpsamplingFactor;
-
- *out = buffer;
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/codecs/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk
index 359a2ec..20c7bc0 100644
--- a/media/libstagefright/codecs/aacdec/Android.mk
+++ b/media/libstagefright/codecs/aacdec/Android.mk
@@ -143,7 +143,6 @@ LOCAL_SRC_FILES := \
unpack_idx.cpp \
window_tables_fxp.cpp \
pvmp4setaudioconfig.cpp \
- AACDecoder.cpp \
LOCAL_CFLAGS := -DAAC_PLUS -DHQ_SBR -DPARAMETRICSTEREO -DOSCL_IMPORT_REF= -DOSCL_EXPORT_REF= -DOSCL_UNUSED_ARG=
diff --git a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
deleted file mode 100644
index a11d46b..0000000
--- a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2009 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_NDEBUG 0
-#define LOG_TAG "AMRNBDecoder"
-#include <utils/Log.h>
-
-#include "AMRNBDecoder.h"
-
-#include "gsmamr_dec.h"
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-static const int32_t kNumSamplesPerFrame = 160;
-static const int32_t kSampleRate = 8000;
-
-AMRNBDecoder::AMRNBDecoder(const sp<MediaSource> &source)
- : mSource(source),
- mStarted(false),
- mBufferGroup(NULL),
- mState(NULL),
- mAnchorTimeUs(0),
- mNumSamplesOutput(0),
- mInputBuffer(NULL) {
-}
-
-AMRNBDecoder::~AMRNBDecoder() {
- if (mStarted) {
- stop();
- }
-}
-
-status_t AMRNBDecoder::start(MetaData *params) {
- CHECK(!mStarted);
-
- mBufferGroup = new MediaBufferGroup;
- mBufferGroup->add_buffer(
- new MediaBuffer(kNumSamplesPerFrame * sizeof(int16_t)));
-
- CHECK_EQ(GSMInitDecode(&mState, (Word8 *)"AMRNBDecoder"), 0);
-
- mSource->start();
-
- mAnchorTimeUs = 0;
- mNumSamplesOutput = 0;
- mStarted = true;
-
- return OK;
-}
-
-status_t AMRNBDecoder::stop() {
- CHECK(mStarted);
-
- if (mInputBuffer) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- delete mBufferGroup;
- mBufferGroup = NULL;
-
- GSMDecodeFrameExit(&mState);
-
- mSource->stop();
-
- mStarted = false;
-
- return OK;
-}
-
-sp<MetaData> AMRNBDecoder::getFormat() {
- sp<MetaData> srcFormat = mSource->getFormat();
-
- int32_t numChannels;
- int32_t sampleRate;
-
- CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
- CHECK_EQ(numChannels, 1);
-
- CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
- CHECK_EQ(sampleRate, kSampleRate);
-
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
- meta->setInt32(kKeyChannelCount, numChannels);
- meta->setInt32(kKeySampleRate, sampleRate);
-
- int64_t durationUs;
- if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
- meta->setInt64(kKeyDuration, durationUs);
- }
-
- meta->setCString(kKeyDecoderComponent, "AMRNBDecoder");
-
- return meta;
-}
-
-status_t AMRNBDecoder::read(
- MediaBuffer **out, const ReadOptions *options) {
- status_t err;
-
- *out = NULL;
-
- int64_t seekTimeUs;
- ReadOptions::SeekMode mode;
- if (options && options->getSeekTo(&seekTimeUs, &mode)) {
- CHECK(seekTimeUs >= 0);
-
- mNumSamplesOutput = 0;
-
- if (mInputBuffer) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
- } else {
- seekTimeUs = -1;
- }
-
- if (mInputBuffer == NULL) {
- err = mSource->read(&mInputBuffer, options);
-
- if (err != OK) {
- return err;
- }
-
- int64_t timeUs;
- if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- mAnchorTimeUs = timeUs;
- mNumSamplesOutput = 0;
- } else {
- // We must have a new timestamp after seeking.
- CHECK(seekTimeUs < 0);
- }
- }
-
- MediaBuffer *buffer;
- CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
-
- const uint8_t *inputPtr =
- (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
-
- int32_t numBytesRead =
- AMRDecode(mState,
- (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f),
- (UWord8 *)&inputPtr[1],
- static_cast<int16_t *>(buffer->data()),
- MIME_IETF);
-
- if (numBytesRead == -1 ) {
- LOGE("PV AMR decoder AMRDecode() call failed");
- buffer->release();
- buffer = NULL;
- return ERROR_MALFORMED;
- }
- ++numBytesRead; // Include the frame type header byte.
-
- buffer->set_range(0, kNumSamplesPerFrame * sizeof(int16_t));
-
- if (static_cast<size_t>(numBytesRead) > mInputBuffer->range_length()) {
- // This is bad, should never have happened, but did. Abort now.
-
- buffer->release();
- buffer = NULL;
-
- return ERROR_MALFORMED;
- }
-
- mInputBuffer->set_range(
- mInputBuffer->range_offset() + numBytesRead,
- mInputBuffer->range_length() - numBytesRead);
-
- if (mInputBuffer->range_length() == 0) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- buffer->meta_data()->setInt64(
- kKeyTime,
- mAnchorTimeUs
- + (mNumSamplesOutput * 1000000) / kSampleRate);
-
- mNumSamplesOutput += kNumSamplesPerFrame;
-
- *out = buffer;
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
index 5862abc..23a22ef 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.mk
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -2,7 +2,6 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
- AMRNBDecoder.cpp \
src/a_refl.cpp \
src/agc.cpp \
src/amrdecode.cpp \
diff --git a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp b/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
deleted file mode 100644
index 5b111ef..0000000
--- a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2009 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 "AMRWBDecoder.h"
-
-#include "pvamrwbdecoder.h"
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-static const int32_t kNumSamplesPerFrame = 320;
-static const int32_t kSampleRate = 16000;
-
-AMRWBDecoder::AMRWBDecoder(const sp<MediaSource> &source)
- : mSource(source),
- mStarted(false),
- mBufferGroup(NULL),
- mState(NULL),
- mDecoderBuf(NULL),
- mDecoderCookie(NULL),
- mAnchorTimeUs(0),
- mNumSamplesOutput(0),
- mInputBuffer(NULL) {
-}
-
-AMRWBDecoder::~AMRWBDecoder() {
- if (mStarted) {
- stop();
- }
-}
-
-status_t AMRWBDecoder::start(MetaData *params) {
- CHECK(!mStarted);
-
- mBufferGroup = new MediaBufferGroup;
- mBufferGroup->add_buffer(
- new MediaBuffer(kNumSamplesPerFrame * sizeof(int16_t)));
-
- int32_t memReq = pvDecoder_AmrWbMemRequirements();
- mDecoderBuf = malloc(memReq);
-
- pvDecoder_AmrWb_Init(&mState, mDecoderBuf, &mDecoderCookie);
-
- mSource->start();
-
- mAnchorTimeUs = 0;
- mNumSamplesOutput = 0;
- mStarted = true;
-
- return OK;
-}
-
-status_t AMRWBDecoder::stop() {
- CHECK(mStarted);
-
- if (mInputBuffer) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- delete mBufferGroup;
- mBufferGroup = NULL;
-
- free(mDecoderBuf);
- mDecoderBuf = NULL;
-
- mSource->stop();
-
- mStarted = false;
-
- return OK;
-}
-
-sp<MetaData> AMRWBDecoder::getFormat() {
- sp<MetaData> srcFormat = mSource->getFormat();
-
- int32_t numChannels;
- int32_t sampleRate;
-
- CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
- CHECK_EQ(numChannels, 1);
-
- CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
- CHECK_EQ(sampleRate, kSampleRate);
-
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
- meta->setInt32(kKeyChannelCount, numChannels);
- meta->setInt32(kKeySampleRate, sampleRate);
-
- int64_t durationUs;
- if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
- meta->setInt64(kKeyDuration, durationUs);
- }
-
- meta->setCString(kKeyDecoderComponent, "AMRWBDecoder");
-
- return meta;
-}
-
-static size_t getFrameSize(unsigned FT) {
- static const size_t kFrameSizeWB[9] = {
- 132, 177, 253, 285, 317, 365, 397, 461, 477
- };
-
- size_t frameSize = kFrameSizeWB[FT];
-
- // Round up bits to bytes and add 1 for the header byte.
- frameSize = (frameSize + 7) / 8 + 1;
-
- return frameSize;
-}
-
-status_t AMRWBDecoder::read(
- MediaBuffer **out, const ReadOptions *options) {
- status_t err;
-
- *out = NULL;
-
- int64_t seekTimeUs;
- ReadOptions::SeekMode seekMode;
- if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
- CHECK(seekTimeUs >= 0);
-
- mNumSamplesOutput = 0;
-
- if (mInputBuffer) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
- } else {
- seekTimeUs = -1;
- }
-
- if (mInputBuffer == NULL) {
- err = mSource->read(&mInputBuffer, options);
-
- if (err != OK) {
- return err;
- }
-
- int64_t timeUs;
- if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- mAnchorTimeUs = timeUs;
- mNumSamplesOutput = 0;
- } else {
- // We must have a new timestamp after seeking.
- CHECK(seekTimeUs < 0);
- }
- }
-
- MediaBuffer *buffer;
- CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
-
- const uint8_t *inputPtr =
- (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
-
- int16 mode = ((inputPtr[0] >> 3) & 0x0f);
- size_t frameSize = getFrameSize(mode);
- CHECK(mInputBuffer->range_length() >= frameSize);
-
- int16 frameType;
- RX_State_wb rx_state;
- mime_unsorting(
- const_cast<uint8_t *>(&inputPtr[1]),
- mInputSampleBuffer,
- &frameType, &mode, 1, &rx_state);
-
- int16_t *outPtr = (int16_t *)buffer->data();
-
- int16_t numSamplesOutput;
- pvDecoder_AmrWb(
- mode, mInputSampleBuffer,
- outPtr,
- &numSamplesOutput,
- mDecoderBuf, frameType, mDecoderCookie);
-
- CHECK_EQ(numSamplesOutput, kNumSamplesPerFrame);
-
- for (int i = 0; i < kNumSamplesPerFrame; ++i) {
- /* Delete the 2 LSBs (14-bit output) */
- outPtr[i] &= 0xfffC;
- }
-
- buffer->set_range(0, numSamplesOutput * sizeof(int16_t));
-
- mInputBuffer->set_range(
- mInputBuffer->range_offset() + frameSize,
- mInputBuffer->range_length() - frameSize);
-
- if (mInputBuffer->range_length() == 0) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- buffer->meta_data()->setInt64(
- kKeyTime,
- mAnchorTimeUs
- + (mNumSamplesOutput * 1000000) / kSampleRate);
-
- mNumSamplesOutput += kNumSamplesPerFrame;
-
- *out = buffer;
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/codecs/amrwb/Android.mk b/media/libstagefright/codecs/amrwb/Android.mk
index ab591d7..c9e1c25 100644
--- a/media/libstagefright/codecs/amrwb/Android.mk
+++ b/media/libstagefright/codecs/amrwb/Android.mk
@@ -2,7 +2,6 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
- AMRWBDecoder.cpp \
src/agc2_amr_wb.cpp \
src/band_pass_6k_7k.cpp \
src/dec_acelp_2p_in_64.cpp \
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
deleted file mode 100644
index 490129f..0000000
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * Copyright (C) 2009 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_NDEBUG 0
-#define LOG_TAG "AVCDecoder"
-#include <utils/Log.h>
-
-#include "AVCDecoder.h"
-
-#include "avcdec_api.h"
-#include "avcdec_int.h"
-
-#include <OMX_Component.h>
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-#include <media/stagefright/foundation/hexdump.h>
-
-namespace android {
-
-static const char kStartCode[4] = { 0x00, 0x00, 0x00, 0x01 };
-
-static int32_t Malloc(void *userData, int32_t size, int32_t attrs) {
- return reinterpret_cast<int32_t>(malloc(size));
-}
-
-static void Free(void *userData, int32_t ptr) {
- free(reinterpret_cast<void *>(ptr));
-}
-
-AVCDecoder::AVCDecoder(const sp<MediaSource> &source)
- : mSource(source),
- mStarted(false),
- mHandle(new tagAVCHandle),
- mInputBuffer(NULL),
- mAnchorTimeUs(0),
- mNumSamplesOutput(0),
- mPendingSeekTimeUs(-1),
- mPendingSeekMode(MediaSource::ReadOptions::SEEK_CLOSEST_SYNC),
- mTargetTimeUs(-1),
- mSPSSeen(false),
- mPPSSeen(false) {
- memset(mHandle, 0, sizeof(tagAVCHandle));
- mHandle->AVCObject = NULL;
- mHandle->userData = this;
- mHandle->CBAVC_DPBAlloc = ActivateSPSWrapper;
- mHandle->CBAVC_FrameBind = BindFrameWrapper;
- mHandle->CBAVC_FrameUnbind = UnbindFrame;
- mHandle->CBAVC_Malloc = Malloc;
- mHandle->CBAVC_Free = Free;
-
- mFormat = new MetaData;
- mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
- int32_t width, height;
- CHECK(mSource->getFormat()->findInt32(kKeyWidth, &width));
- CHECK(mSource->getFormat()->findInt32(kKeyHeight, &height));
- mFormat->setInt32(kKeyWidth, width);
- mFormat->setInt32(kKeyHeight, height);
- mFormat->setRect(kKeyCropRect, 0, 0, width - 1, height - 1);
- mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
- mFormat->setCString(kKeyDecoderComponent, "AVCDecoder");
-
- int64_t durationUs;
- if (mSource->getFormat()->findInt64(kKeyDuration, &durationUs)) {
- mFormat->setInt64(kKeyDuration, durationUs);
- }
-}
-
-AVCDecoder::~AVCDecoder() {
- if (mStarted) {
- stop();
- }
-
- PVAVCCleanUpDecoder(mHandle);
-
- delete mHandle;
- mHandle = NULL;
-}
-
-status_t AVCDecoder::start(MetaData *) {
- CHECK(!mStarted);
-
- uint32_t type;
- const void *data;
- size_t size;
- sp<MetaData> meta = mSource->getFormat();
- if (meta->findData(kKeyAVCC, &type, &data, &size)) {
- // Parse the AVCDecoderConfigurationRecord
-
- const uint8_t *ptr = (const uint8_t *)data;
-
- CHECK(size >= 7);
- CHECK_EQ(ptr[0], 1); // configurationVersion == 1
- uint8_t profile = ptr[1];
- uint8_t level = ptr[3];
-
- // There is decodable content out there that fails the following
- // assertion, let's be lenient for now...
- // CHECK((ptr[4] >> 2) == 0x3f); // reserved
-
- size_t lengthSize = 1 + (ptr[4] & 3);
-
- // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
- // violates it...
- // CHECK((ptr[5] >> 5) == 7); // reserved
-
- size_t numSeqParameterSets = ptr[5] & 31;
-
- ptr += 6;
- size -= 6;
-
- for (size_t i = 0; i < numSeqParameterSets; ++i) {
- CHECK(size >= 2);
- size_t length = U16_AT(ptr);
-
- ptr += 2;
- size -= 2;
-
- CHECK(size >= length);
-
- addCodecSpecificData(ptr, length);
-
- ptr += length;
- size -= length;
- }
-
- CHECK(size >= 1);
- size_t numPictureParameterSets = *ptr;
- ++ptr;
- --size;
-
- for (size_t i = 0; i < numPictureParameterSets; ++i) {
- CHECK(size >= 2);
- size_t length = U16_AT(ptr);
-
- ptr += 2;
- size -= 2;
-
- CHECK(size >= length);
-
- addCodecSpecificData(ptr, length);
-
- ptr += length;
- size -= length;
- }
- }
-
- mSource->start();
-
- mAnchorTimeUs = 0;
- mNumSamplesOutput = 0;
- mPendingSeekTimeUs = -1;
- mPendingSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
- mTargetTimeUs = -1;
- mSPSSeen = false;
- mPPSSeen = false;
- mStarted = true;
-
- return OK;
-}
-
-void AVCDecoder::addCodecSpecificData(const uint8_t *data, size_t size) {
- MediaBuffer *buffer = new MediaBuffer(size + 4);
- memcpy(buffer->data(), kStartCode, 4);
- memcpy((uint8_t *)buffer->data() + 4, data, size);
- buffer->set_range(0, size + 4);
-
- mCodecSpecificData.push(buffer);
-}
-
-status_t AVCDecoder::stop() {
- CHECK(mStarted);
-
- for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
- (*mCodecSpecificData.editItemAt(i)).release();
- }
- mCodecSpecificData.clear();
-
- if (mInputBuffer) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- mSource->stop();
-
- releaseFrames();
-
- mStarted = false;
-
- return OK;
-}
-
-sp<MetaData> AVCDecoder::getFormat() {
- return mFormat;
-}
-
-static void findNALFragment(
- const MediaBuffer *buffer, const uint8_t **fragPtr, size_t *fragSize) {
- const uint8_t *data =
- (const uint8_t *)buffer->data() + buffer->range_offset();
-
- size_t size = buffer->range_length();
-
- CHECK(size >= 4);
- CHECK(!memcmp(kStartCode, data, 4));
-
- size_t offset = 4;
- while (offset + 3 < size && memcmp(kStartCode, &data[offset], 4)) {
- ++offset;
- }
-
- *fragPtr = &data[4];
- if (offset + 3 >= size) {
- *fragSize = size - 4;
- } else {
- *fragSize = offset - 4;
- }
-}
-
-MediaBuffer *AVCDecoder::drainOutputBuffer() {
- int32_t index;
- int32_t Release;
- AVCFrameIO Output;
- Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
- AVCDec_Status status = PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
-
- if (status != AVCDEC_SUCCESS) {
- LOGV("PVAVCDecGetOutput returned error %d", status);
- return NULL;
- }
-
- CHECK(index >= 0);
- CHECK(index < (int32_t)mFrames.size());
-
- MediaBuffer *mbuf = mFrames.editItemAt(index);
-
- bool skipFrame = false;
-
- if (mTargetTimeUs >= 0) {
- int64_t timeUs;
- CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
- CHECK(timeUs <= mTargetTimeUs);
-
- if (timeUs < mTargetTimeUs) {
- // We're still waiting for the frame with the matching
- // timestamp and we won't return the current one.
- skipFrame = true;
-
- LOGV("skipping frame at %lld us", timeUs);
- } else {
- LOGV("found target frame at %lld us", timeUs);
-
- mTargetTimeUs = -1;
- }
- }
-
- if (!skipFrame) {
- mbuf->set_range(0, mbuf->size());
- mbuf->add_ref();
-
- return mbuf;
- }
-
- return new MediaBuffer(0);
-}
-
-status_t AVCDecoder::read(
- MediaBuffer **out, const ReadOptions *options) {
- *out = NULL;
-
- int64_t seekTimeUs;
- ReadOptions::SeekMode mode;
- if (options && options->getSeekTo(&seekTimeUs, &mode)) {
- LOGV("seek requested to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
-
- CHECK(seekTimeUs >= 0);
- mPendingSeekTimeUs = seekTimeUs;
- mPendingSeekMode = mode;
-
- if (mInputBuffer) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- PVAVCDecReset(mHandle);
- }
-
- if (mInputBuffer == NULL) {
- LOGV("fetching new input buffer.");
-
- bool seeking = false;
-
- if (!mCodecSpecificData.isEmpty()) {
- mInputBuffer = mCodecSpecificData.editItemAt(0);
- mCodecSpecificData.removeAt(0);
- } else {
- for (;;) {
- if (mPendingSeekTimeUs >= 0) {
- LOGV("reading data from timestamp %lld (%.2f secs)",
- mPendingSeekTimeUs, mPendingSeekTimeUs / 1E6);
- }
-
- ReadOptions seekOptions;
- if (mPendingSeekTimeUs >= 0) {
- seeking = true;
-
- seekOptions.setSeekTo(mPendingSeekTimeUs, mPendingSeekMode);
- mPendingSeekTimeUs = -1;
- }
- status_t err = mSource->read(&mInputBuffer, &seekOptions);
- seekOptions.clearSeekTo();
-
- if (err != OK) {
- *out = drainOutputBuffer();
- return (*out == NULL) ? err : (status_t)OK;
- }
-
- if (mInputBuffer->range_length() > 0) {
- break;
- }
-
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
- }
-
- if (seeking) {
- int64_t targetTimeUs;
- if (mInputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
- && targetTimeUs >= 0) {
- mTargetTimeUs = targetTimeUs;
- } else {
- mTargetTimeUs = -1;
- }
- }
- }
-
- const uint8_t *fragPtr;
- size_t fragSize;
- findNALFragment(mInputBuffer, &fragPtr, &fragSize);
-
- bool releaseFragment = true;
- status_t err = UNKNOWN_ERROR;
-
- int nalType;
- int nalRefIdc;
- AVCDec_Status res =
- PVAVCDecGetNALType(
- const_cast<uint8_t *>(fragPtr), fragSize,
- &nalType, &nalRefIdc);
-
- if (res != AVCDEC_SUCCESS) {
- LOGV("cannot determine nal type");
- } else if (nalType == AVC_NALTYPE_SPS || nalType == AVC_NALTYPE_PPS
- || (mSPSSeen && mPPSSeen)) {
- switch (nalType) {
- case AVC_NALTYPE_SPS:
- {
- mSPSSeen = true;
-
- res = PVAVCDecSeqParamSet(
- mHandle, const_cast<uint8_t *>(fragPtr),
- fragSize);
-
- if (res != AVCDEC_SUCCESS) {
- LOGV("PVAVCDecSeqParamSet returned error %d", res);
- break;
- }
-
- AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject;
-
- int32_t width =
- (pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16;
-
- int32_t height =
- (pDecVid->seqParams[0]->pic_height_in_map_units_minus1 + 1) * 16;
-
- int32_t crop_left, crop_right, crop_top, crop_bottom;
- if (pDecVid->seqParams[0]->frame_cropping_flag)
- {
- crop_left = 2 * pDecVid->seqParams[0]->frame_crop_left_offset;
- crop_right =
- width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1);
-
- if (pDecVid->seqParams[0]->frame_mbs_only_flag)
- {
- crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset;
- crop_bottom =
- height -
- (2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
- }
- else
- {
- crop_top = 4 * pDecVid->seqParams[0]->frame_crop_top_offset;
- crop_bottom =
- height -
- (4 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
- }
- } else {
- crop_bottom = height - 1;
- crop_right = width - 1;
- crop_top = crop_left = 0;
- }
-
- int32_t prevCropLeft, prevCropTop;
- int32_t prevCropRight, prevCropBottom;
- if (!mFormat->findRect(
- kKeyCropRect,
- &prevCropLeft, &prevCropTop,
- &prevCropRight, &prevCropBottom)) {
- prevCropLeft = prevCropTop = 0;
- prevCropRight = width - 1;
- prevCropBottom = height - 1;
- }
-
- int32_t oldWidth, oldHeight;
- CHECK(mFormat->findInt32(kKeyWidth, &oldWidth));
- CHECK(mFormat->findInt32(kKeyHeight, &oldHeight));
-
- if (oldWidth != width || oldHeight != height
- || prevCropLeft != crop_left
- || prevCropTop != crop_top
- || prevCropRight != crop_right
- || prevCropBottom != crop_bottom) {
- mFormat->setRect(
- kKeyCropRect,
- crop_left, crop_top, crop_right, crop_bottom);
-
- mFormat->setInt32(kKeyWidth, width);
- mFormat->setInt32(kKeyHeight, height);
-
- err = INFO_FORMAT_CHANGED;
- } else {
- *out = new MediaBuffer(0);
- err = OK;
- }
- break;
- }
-
- case AVC_NALTYPE_PPS:
- {
- mPPSSeen = true;
-
- res = PVAVCDecPicParamSet(
- mHandle, const_cast<uint8_t *>(fragPtr),
- fragSize);
-
- if (res != AVCDEC_SUCCESS) {
- LOGV("PVAVCDecPicParamSet returned error %d", res);
- break;
- }
-
- *out = new MediaBuffer(0);
-
- err = OK;
- break;
- }
-
- case AVC_NALTYPE_SLICE:
- case AVC_NALTYPE_IDR:
- {
- res = PVAVCDecodeSlice(
- mHandle, const_cast<uint8_t *>(fragPtr),
- fragSize);
-
- if (res == AVCDEC_PICTURE_OUTPUT_READY) {
- MediaBuffer *mbuf = drainOutputBuffer();
- if (mbuf == NULL) {
- break;
- }
-
- *out = mbuf;
-
- // Do _not_ release input buffer yet.
-
- releaseFragment = false;
- err = OK;
- break;
- }
-
- if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) {
- *out = new MediaBuffer(0);
-
- err = OK;
- } else {
- LOGV("PVAVCDecodeSlice returned error %d", res);
- }
- break;
- }
-
- case AVC_NALTYPE_SEI:
- {
- res = PVAVCDecSEI(
- mHandle, const_cast<uint8_t *>(fragPtr),
- fragSize);
-
- if (res != AVCDEC_SUCCESS) {
- break;
- }
-
- *out = new MediaBuffer(0);
-
- err = OK;
- break;
- }
-
- case AVC_NALTYPE_AUD:
- case AVC_NALTYPE_FILL:
- case AVC_NALTYPE_EOSEQ:
- {
- *out = new MediaBuffer(0);
-
- err = OK;
- break;
- }
-
- default:
- {
- LOGE("Should not be here, unknown nalType %d", nalType);
-
- err = ERROR_MALFORMED;
- break;
- }
- }
- } else {
- // We haven't seen SPS or PPS yet.
-
- *out = new MediaBuffer(0);
- err = OK;
- }
-
- if (releaseFragment) {
- size_t offset = mInputBuffer->range_offset();
- if (fragSize + 4 == mInputBuffer->range_length()) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- } else {
- mInputBuffer->set_range(
- offset + fragSize + 4,
- mInputBuffer->range_length() - fragSize - 4);
- }
- }
-
- return err;
-}
-
-// static
-int32_t AVCDecoder::ActivateSPSWrapper(
- void *userData, unsigned int sizeInMbs, unsigned int numBuffers) {
- return static_cast<AVCDecoder *>(userData)->activateSPS(sizeInMbs, numBuffers);
-}
-
-// static
-int32_t AVCDecoder::BindFrameWrapper(
- void *userData, int32_t index, uint8_t **yuv) {
- return static_cast<AVCDecoder *>(userData)->bindFrame(index, yuv);
-}
-
-// static
-void AVCDecoder::UnbindFrame(void *userData, int32_t index) {
-}
-
-int32_t AVCDecoder::activateSPS(
- unsigned int sizeInMbs, unsigned int numBuffers) {
- CHECK(mFrames.isEmpty());
-
- size_t frameSize = (sizeInMbs << 7) * 3;
- for (unsigned int i = 0; i < numBuffers; ++i) {
- MediaBuffer *buffer = new MediaBuffer(frameSize);
- buffer->setObserver(this);
-
- mFrames.push(buffer);
- }
-
- return 1;
-}
-
-int32_t AVCDecoder::bindFrame(int32_t index, uint8_t **yuv) {
- CHECK(index >= 0);
- CHECK(index < (int32_t)mFrames.size());
-
- CHECK(mInputBuffer != NULL);
- int64_t timeUs;
- CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
- mFrames[index]->meta_data()->setInt64(kKeyTime, timeUs);
-
- *yuv = (uint8_t *)mFrames[index]->data();
-
- return 1;
-}
-
-void AVCDecoder::releaseFrames() {
- for (size_t i = 0; i < mFrames.size(); ++i) {
- MediaBuffer *buffer = mFrames.editItemAt(i);
-
- buffer->setObserver(NULL);
- buffer->release();
- }
- mFrames.clear();
-}
-
-void AVCDecoder::signalBufferReturned(MediaBuffer *buffer) {
-}
-
-} // namespace android
diff --git a/media/libstagefright/codecs/avc/dec/Android.mk b/media/libstagefright/codecs/avc/dec/Android.mk
index 4d4533b..2949a04 100644
--- a/media/libstagefright/codecs/avc/dec/Android.mk
+++ b/media/libstagefright/codecs/avc/dec/Android.mk
@@ -2,7 +2,6 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
- AVCDecoder.cpp \
src/avcdec_api.cpp \
src/avc_bitstream.cpp \
src/header.cpp \
diff --git a/media/libstagefright/codecs/g711/dec/Android.mk b/media/libstagefright/codecs/g711/dec/Android.mk
index 6e98559..6692533 100644
--- a/media/libstagefright/codecs/g711/dec/Android.mk
+++ b/media/libstagefright/codecs/g711/dec/Android.mk
@@ -2,20 +2,6 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
- G711Decoder.cpp
-
-LOCAL_C_INCLUDES := \
- frameworks/base/media/libstagefright/include \
-
-LOCAL_MODULE := libstagefright_g711dec
-
-include $(BUILD_STATIC_LIBRARY)
-
-################################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
SoftG711.cpp
LOCAL_C_INCLUDES := \
diff --git a/media/libstagefright/codecs/g711/dec/G711Decoder.cpp b/media/libstagefright/codecs/g711/dec/G711Decoder.cpp
deleted file mode 100644
index 4414e4e..0000000
--- a/media/libstagefright/codecs/g711/dec/G711Decoder.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "G711Decoder"
-#include <utils/Log.h>
-
-#include "G711Decoder.h"
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-
-static const size_t kMaxNumSamplesPerFrame = 16384;
-
-namespace android {
-
-G711Decoder::G711Decoder(const sp<MediaSource> &source)
- : mSource(source),
- mStarted(false),
- mBufferGroup(NULL) {
-}
-
-G711Decoder::~G711Decoder() {
- if (mStarted) {
- stop();
- }
-}
-
-status_t G711Decoder::start(MetaData *params) {
- CHECK(!mStarted);
-
- const char *mime;
- CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
-
- mIsMLaw = false;
- if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
- mIsMLaw = true;
- } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)) {
- return ERROR_UNSUPPORTED;
- }
-
- mBufferGroup = new MediaBufferGroup;
- mBufferGroup->add_buffer(
- new MediaBuffer(kMaxNumSamplesPerFrame * sizeof(int16_t)));
-
- mSource->start();
-
- mStarted = true;
-
- return OK;
-}
-
-status_t G711Decoder::stop() {
- CHECK(mStarted);
-
- delete mBufferGroup;
- mBufferGroup = NULL;
-
- mSource->stop();
-
- mStarted = false;
-
- return OK;
-}
-
-sp<MetaData> G711Decoder::getFormat() {
- sp<MetaData> srcFormat = mSource->getFormat();
-
- int32_t numChannels;
- int32_t sampleRate;
-
- CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
- CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
- meta->setInt32(kKeyChannelCount, numChannels);
- meta->setInt32(kKeySampleRate, sampleRate);
-
- int64_t durationUs;
- if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
- meta->setInt64(kKeyDuration, durationUs);
- }
-
- meta->setCString(kKeyDecoderComponent, "G711Decoder");
-
- return meta;
-}
-
-status_t G711Decoder::read(
- MediaBuffer **out, const ReadOptions *options) {
- status_t err;
-
- *out = NULL;
-
- int64_t seekTimeUs;
- ReadOptions::SeekMode mode;
- if (options && options->getSeekTo(&seekTimeUs, &mode)) {
- CHECK(seekTimeUs >= 0);
- } else {
- seekTimeUs = -1;
- }
-
- MediaBuffer *inBuffer;
- err = mSource->read(&inBuffer, options);
-
- if (err != OK) {
- return err;
- }
-
- if (inBuffer->range_length() > kMaxNumSamplesPerFrame) {
- LOGE("input buffer too large (%d).", inBuffer->range_length());
-
- inBuffer->release();
- inBuffer = NULL;
-
- return ERROR_UNSUPPORTED;
- }
-
- int64_t timeUs;
- CHECK(inBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
-
- const uint8_t *inputPtr =
- (const uint8_t *)inBuffer->data() + inBuffer->range_offset();
-
- MediaBuffer *outBuffer;
- CHECK_EQ(mBufferGroup->acquire_buffer(&outBuffer), OK);
-
- if (mIsMLaw) {
- DecodeMLaw(
- static_cast<int16_t *>(outBuffer->data()),
- inputPtr, inBuffer->range_length());
- } else {
- DecodeALaw(
- static_cast<int16_t *>(outBuffer->data()),
- inputPtr, inBuffer->range_length());
- }
-
- // Each 8-bit byte is converted into a 16-bit sample.
- outBuffer->set_range(0, inBuffer->range_length() * 2);
-
- outBuffer->meta_data()->setInt64(kKeyTime, timeUs);
-
- inBuffer->release();
- inBuffer = NULL;
-
- *out = outBuffer;
-
- return OK;
-}
-
-// static
-void G711Decoder::DecodeALaw(
- int16_t *out, const uint8_t *in, size_t inSize) {
- while (inSize-- > 0) {
- int32_t x = *in++;
-
- int32_t ix = x ^ 0x55;
- ix &= 0x7f;
-
- int32_t iexp = ix >> 4;
- int32_t mant = ix & 0x0f;
-
- if (iexp > 0) {
- mant += 16;
- }
-
- mant = (mant << 4) + 8;
-
- if (iexp > 1) {
- mant = mant << (iexp - 1);
- }
-
- *out++ = (x > 127) ? mant : -mant;
- }
-}
-
-// static
-void G711Decoder::DecodeMLaw(
- int16_t *out, const uint8_t *in, size_t inSize) {
- while (inSize-- > 0) {
- int32_t x = *in++;
-
- int32_t mantissa = ~x;
- int32_t exponent = (mantissa >> 4) & 7;
- int32_t segment = exponent + 1;
- mantissa &= 0x0f;
-
- int32_t step = 4 << segment;
-
- int32_t abs = (0x80l << exponent) + step * mantissa + step / 2 - 4 * 33;
-
- *out++ = (x < 0x80) ? -abs : abs;
- }
-}
-
-} // namespace android
diff --git a/media/libstagefright/codecs/m4v_h263/dec/Android.mk b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
index f1bec08..2ffa5f2 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
@@ -2,7 +2,6 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
- M4vH263Decoder.cpp \
src/adaptive_smooth_no_mmx.cpp \
src/bitstream.cpp \
src/block_idct.cpp \
diff --git a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
deleted file mode 100644
index 2bdb3ef..0000000
--- a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2009 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_NDEBUG 0
-#define LOG_TAG "M4vH263Decoder"
-#include <utils/Log.h>
-#include <stdlib.h> // for free
-#include "ESDS.h"
-#include "M4vH263Decoder.h"
-
-#include "mp4dec_api.h"
-
-#include <OMX_Component.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-namespace android {
-
-M4vH263Decoder::M4vH263Decoder(const sp<MediaSource> &source)
- : mSource(source),
- mStarted(false),
- mHandle(new tagvideoDecControls),
- mInputBuffer(NULL),
- mNumSamplesOutput(0),
- mTargetTimeUs(-1) {
-
- LOGV("M4vH263Decoder");
- memset(mHandle, 0, sizeof(tagvideoDecControls));
- mFormat = new MetaData;
- mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
-
- // CHECK(mSource->getFormat()->findInt32(kKeyWidth, &mWidth));
- // CHECK(mSource->getFormat()->findInt32(kKeyHeight, &mHeight));
-
- // We'll ignore the dimension advertised by the source, the decoder
- // appears to require us to always start with the default dimensions
- // of 352 x 288 to operate correctly and later react to changes in
- // the dimensions as needed.
- mWidth = 352;
- mHeight = 288;
-
- mFormat->setInt32(kKeyWidth, mWidth);
- mFormat->setInt32(kKeyHeight, mHeight);
- mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
- mFormat->setCString(kKeyDecoderComponent, "M4vH263Decoder");
-}
-
-M4vH263Decoder::~M4vH263Decoder() {
- if (mStarted) {
- stop();
- }
-
- delete mHandle;
- mHandle = NULL;
-}
-
-void M4vH263Decoder::allocateFrames(int32_t width, int32_t height) {
- size_t frameSize =
- (((width + 15) & - 16) * ((height + 15) & - 16) * 3) / 2;
-
- for (uint32_t i = 0; i < 2; ++i) {
- mFrames[i] = new MediaBuffer(frameSize);
- mFrames[i]->setObserver(this);
- }
-
- PVSetReferenceYUV(
- mHandle,
- (uint8_t *)mFrames[1]->data());
-}
-
-status_t M4vH263Decoder::start(MetaData *) {
- CHECK(!mStarted);
-
- const char *mime = NULL;
- sp<MetaData> meta = mSource->getFormat();
- CHECK(meta->findCString(kKeyMIMEType, &mime));
-
- MP4DecodingMode mode;
- if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
- mode = MPEG4_MODE;
- } else {
- CHECK(!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime));
- mode = H263_MODE;
- }
-
- uint32_t type;
- const void *data = NULL;
- size_t size = 0;
- uint8_t *vol_data[1] = {0};
- int32_t vol_size = 0;
- if (meta->findData(kKeyESDS, &type, &data, &size)) {
- ESDS esds((const uint8_t *)data, size);
- CHECK_EQ(esds.InitCheck(), (status_t)OK);
-
- const void *codec_specific_data;
- size_t codec_specific_data_size;
- esds.getCodecSpecificInfo(
- &codec_specific_data, &codec_specific_data_size);
-
- vol_data[0] = (uint8_t *) malloc(codec_specific_data_size);
- memcpy(vol_data[0], codec_specific_data, codec_specific_data_size);
- vol_size = codec_specific_data_size;
- } else {
- vol_data[0] = NULL;
- vol_size = 0;
-
- }
-
- Bool success = PVInitVideoDecoder(
- mHandle, vol_data, &vol_size, 1, mWidth, mHeight, mode);
- if (vol_data[0]) free(vol_data[0]);
-
- if (success != PV_TRUE) {
- LOGW("PVInitVideoDecoder failed. Unsupported content?");
- return ERROR_UNSUPPORTED;
- }
-
- MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle);
- if (mode != actualMode) {
- PVCleanUpVideoDecoder(mHandle);
- return UNKNOWN_ERROR;
- }
-
- PVSetPostProcType((VideoDecControls *) mHandle, 0);
-
- int32_t width, height;
- PVGetVideoDimensions(mHandle, &width, &height);
- if (mode == H263_MODE && (width == 0 || height == 0)) {
- width = 352;
- height = 288;
- }
- allocateFrames(width, height);
-
- mSource->start();
-
- mNumSamplesOutput = 0;
- mTargetTimeUs = -1;
- mStarted = true;
-
- return OK;
-}
-
-status_t M4vH263Decoder::stop() {
- CHECK(mStarted);
-
- if (mInputBuffer) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- mSource->stop();
-
- releaseFrames();
-
- mStarted = false;
- return (PVCleanUpVideoDecoder(mHandle) == PV_TRUE)? OK: UNKNOWN_ERROR;
-}
-
-sp<MetaData> M4vH263Decoder::getFormat() {
- return mFormat;
-}
-
-status_t M4vH263Decoder::read(
- MediaBuffer **out, const ReadOptions *options) {
- *out = NULL;
-
- bool seeking = false;
- int64_t seekTimeUs;
- ReadOptions::SeekMode mode;
- if (options && options->getSeekTo(&seekTimeUs, &mode)) {
- seeking = true;
- CHECK_EQ((int)PVResetVideoDecoder(mHandle), PV_TRUE);
- }
-
- MediaBuffer *inputBuffer = NULL;
- status_t err = mSource->read(&inputBuffer, options);
- if (err != OK) {
- return err;
- }
-
- if (seeking) {
- int64_t targetTimeUs;
- if (inputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
- && targetTimeUs >= 0) {
- mTargetTimeUs = targetTimeUs;
- } else {
- mTargetTimeUs = -1;
- }
- }
-
- uint8_t *bitstream =
- (uint8_t *) inputBuffer->data() + inputBuffer->range_offset();
-
- uint32_t timestamp = 0xFFFFFFFF;
- int32_t bufferSize = inputBuffer->range_length();
- uint32_t useExtTimestamp = 0;
- if (PVDecodeVideoFrame(
- mHandle, &bitstream, &timestamp, &bufferSize,
- &useExtTimestamp,
- (uint8_t *)mFrames[mNumSamplesOutput & 0x01]->data())
- != PV_TRUE) {
- LOGE("failed to decode video frame.");
-
- inputBuffer->release();
- inputBuffer = NULL;
-
- return UNKNOWN_ERROR;
- }
-
- int32_t disp_width, disp_height;
- PVGetVideoDimensions(mHandle, &disp_width, &disp_height);
-
- int32_t buf_width, buf_height;
- PVGetBufferDimensions(mHandle, &buf_width, &buf_height);
-
- if (buf_width != mWidth || buf_height != mHeight) {
- ++mNumSamplesOutput; // The client will never get to see this frame.
-
- inputBuffer->release();
- inputBuffer = NULL;
-
- mWidth = buf_width;
- mHeight = buf_height;
- mFormat->setInt32(kKeyWidth, mWidth);
- mFormat->setInt32(kKeyHeight, mHeight);
-
- CHECK_LE(disp_width, buf_width);
- CHECK_LE(disp_height, buf_height);
-
- mFormat->setRect(kKeyCropRect, 0, 0, disp_width - 1, disp_height - 1);
-
- return INFO_FORMAT_CHANGED;
- }
-
- int64_t timeUs;
- CHECK(inputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
-
- inputBuffer->release();
- inputBuffer = NULL;
-
- bool skipFrame = false;
-
- if (mTargetTimeUs >= 0) {
- CHECK(timeUs <= mTargetTimeUs);
-
- if (timeUs < mTargetTimeUs) {
- // We're still waiting for the frame with the matching
- // timestamp and we won't return the current one.
- skipFrame = true;
-
- LOGV("skipping frame at %lld us", timeUs);
- } else {
- LOGV("found target frame at %lld us", timeUs);
-
- mTargetTimeUs = -1;
- }
- }
-
- if (skipFrame) {
- *out = new MediaBuffer(0);
- } else {
- *out = mFrames[mNumSamplesOutput & 0x01];
- (*out)->add_ref();
- (*out)->meta_data()->setInt64(kKeyTime, timeUs);
- }
-
- ++mNumSamplesOutput;
-
- return OK;
-}
-
-void M4vH263Decoder::releaseFrames() {
- for (size_t i = 0; i < sizeof(mFrames) / sizeof(mFrames[0]); ++i) {
- MediaBuffer *buffer = mFrames[i];
-
- buffer->setObserver(NULL);
- buffer->release();
-
- mFrames[i] = NULL;
- }
-}
-
-void M4vH263Decoder::signalBufferReturned(MediaBuffer *buffer) {
- LOGV("signalBufferReturned");
-}
-
-
-} // namespace android
diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk
index 229988e..a08c9f0 100644
--- a/media/libstagefright/codecs/mp3dec/Android.mk
+++ b/media/libstagefright/codecs/mp3dec/Android.mk
@@ -2,7 +2,6 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
- MP3Decoder.cpp \
src/pvmp3_normalize.cpp \
src/pvmp3_alias_reduction.cpp \
src/pvmp3_crc.cpp \
diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
deleted file mode 100644
index 0ba42ff..0000000
--- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2009 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_NDEBUG 0
-#define LOG_TAG "MP3Decoder"
-
-#include "MP3Decoder.h"
-
-#include "include/pvmp3decoder_api.h"
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-MP3Decoder::MP3Decoder(const sp<MediaSource> &source)
- : mSource(source),
- mNumChannels(0),
- mStarted(false),
- mBufferGroup(NULL),
- mConfig(new tPVMP3DecoderExternal),
- mDecoderBuf(NULL),
- mAnchorTimeUs(0),
- mNumFramesOutput(0),
- mInputBuffer(NULL) {
- init();
-}
-
-void MP3Decoder::init() {
- sp<MetaData> srcFormat = mSource->getFormat();
-
- int32_t sampleRate;
- CHECK(srcFormat->findInt32(kKeyChannelCount, &mNumChannels));
- CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-
- mMeta = new MetaData;
- mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
- mMeta->setInt32(kKeyChannelCount, mNumChannels);
- mMeta->setInt32(kKeySampleRate, sampleRate);
-
- int64_t durationUs;
- if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
- mMeta->setInt64(kKeyDuration, durationUs);
- }
-
- mMeta->setCString(kKeyDecoderComponent, "MP3Decoder");
-}
-
-MP3Decoder::~MP3Decoder() {
- if (mStarted) {
- stop();
- }
-
- delete mConfig;
- mConfig = NULL;
-}
-
-status_t MP3Decoder::start(MetaData *params) {
- CHECK(!mStarted);
-
- mBufferGroup = new MediaBufferGroup;
- mBufferGroup->add_buffer(new MediaBuffer(4608 * 2));
-
- mConfig->equalizerType = flat;
- mConfig->crcEnabled = false;
-
- uint32_t memRequirements = pvmp3_decoderMemRequirements();
- mDecoderBuf = malloc(memRequirements);
-
- pvmp3_InitDecoder(mConfig, mDecoderBuf);
-
- mSource->start();
-
- mAnchorTimeUs = 0;
- mNumFramesOutput = 0;
- mStarted = true;
-
- return OK;
-}
-
-status_t MP3Decoder::stop() {
- CHECK(mStarted);
-
- if (mInputBuffer) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- free(mDecoderBuf);
- mDecoderBuf = NULL;
-
- delete mBufferGroup;
- mBufferGroup = NULL;
-
- mSource->stop();
-
- mStarted = false;
-
- return OK;
-}
-
-sp<MetaData> MP3Decoder::getFormat() {
- return mMeta;
-}
-
-status_t MP3Decoder::read(
- MediaBuffer **out, const ReadOptions *options) {
- status_t err;
-
- *out = NULL;
-
- int64_t seekTimeUs;
- ReadOptions::SeekMode mode;
- if (options && options->getSeekTo(&seekTimeUs, &mode)) {
- CHECK(seekTimeUs >= 0);
-
- mNumFramesOutput = 0;
-
- if (mInputBuffer) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- // Make sure that the next buffer output does not still
- // depend on fragments from the last one decoded.
- pvmp3_InitDecoder(mConfig, mDecoderBuf);
- } else {
- seekTimeUs = -1;
- }
-
- if (mInputBuffer == NULL) {
- err = mSource->read(&mInputBuffer, options);
-
- if (err != OK) {
- return err;
- }
-
- int64_t timeUs;
- if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- mAnchorTimeUs = timeUs;
- mNumFramesOutput = 0;
- } else {
- // We must have a new timestamp after seeking.
- CHECK(seekTimeUs < 0);
- }
- }
-
- MediaBuffer *buffer;
- CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
-
- mConfig->pInputBuffer =
- (uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
-
- mConfig->inputBufferCurrentLength = mInputBuffer->range_length();
- mConfig->inputBufferMaxLength = 0;
- mConfig->inputBufferUsedLength = 0;
-
- mConfig->outputFrameSize = buffer->size() / sizeof(int16_t);
- mConfig->pOutputBuffer = static_cast<int16_t *>(buffer->data());
-
- ERROR_CODE decoderErr;
- if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf))
- != NO_DECODING_ERROR) {
- LOGV("mp3 decoder returned error %d", decoderErr);
-
- if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR ||
- mConfig->outputFrameSize == 0) {
-
- if (mConfig->outputFrameSize == 0) {
- LOGE("Output frame size is 0");
- }
- buffer->release();
- buffer = NULL;
-
- mInputBuffer->release();
- mInputBuffer = NULL;
-
- return UNKNOWN_ERROR;
- }
-
- // This is recoverable, just ignore the current frame and
- // play silence instead.
- memset(buffer->data(), 0, mConfig->outputFrameSize * sizeof(int16_t));
- mConfig->inputBufferUsedLength = mInputBuffer->range_length();
- }
-
- buffer->set_range(
- 0, mConfig->outputFrameSize * sizeof(int16_t));
-
- mInputBuffer->set_range(
- mInputBuffer->range_offset() + mConfig->inputBufferUsedLength,
- mInputBuffer->range_length() - mConfig->inputBufferUsedLength);
-
- if (mInputBuffer->range_length() == 0) {
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
-
- buffer->meta_data()->setInt64(
- kKeyTime,
- mAnchorTimeUs
- + (mNumFramesOutput * 1000000) / mConfig->samplingRate);
-
- mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
-
- *out = buffer;
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk
index 832b885..32bbd6b 100644
--- a/media/libstagefright/codecs/on2/dec/Android.mk
+++ b/media/libstagefright/codecs/on2/dec/Android.mk
@@ -2,24 +2,6 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
- VPXDecoder.cpp \
-
-LOCAL_MODULE := libstagefright_vpxdec
-
-LOCAL_C_INCLUDES := \
- $(TOP)/frameworks/base/media/libstagefright/include \
- frameworks/base/include/media/stagefright/openmax \
- $(TOP)/external/libvpx \
- $(TOP)/external/libvpx/vpx_codec \
- $(TOP)/external/libvpx/vpx_ports
-
-include $(BUILD_STATIC_LIBRARY)
-
-################################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
SoftVPX.cpp
LOCAL_C_INCLUDES := \
@@ -30,7 +12,6 @@ LOCAL_C_INCLUDES := \
frameworks/base/include/media/stagefright/openmax \
LOCAL_STATIC_LIBRARIES := \
- libstagefright_vpxdec \
libvpx
LOCAL_SHARED_LIBRARIES := \
diff --git a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
deleted file mode 100644
index 489e5ad..0000000
--- a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "VPXDecoder"
-#include <utils/Log.h>
-
-#include "VPXDecoder.h"
-
-#include <OMX_Component.h>
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-#include "vpx/vpx_decoder.h"
-#include "vpx/vpx_codec.h"
-#include "vpx/vp8dx.h"
-
-namespace android {
-
-VPXDecoder::VPXDecoder(const sp<MediaSource> &source)
- : mSource(source),
- mStarted(false),
- mBufferSize(0),
- mCtx(NULL),
- mBufferGroup(NULL),
- mTargetTimeUs(-1) {
- sp<MetaData> inputFormat = source->getFormat();
- const char *mime;
- CHECK(inputFormat->findCString(kKeyMIMEType, &mime));
- CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_VPX));
-
- CHECK(inputFormat->findInt32(kKeyWidth, &mWidth));
- CHECK(inputFormat->findInt32(kKeyHeight, &mHeight));
-
- mBufferSize = (mWidth * mHeight * 3) / 2;
-
- mFormat = new MetaData;
- mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
- mFormat->setInt32(kKeyWidth, mWidth);
- mFormat->setInt32(kKeyHeight, mHeight);
- mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
- mFormat->setCString(kKeyDecoderComponent, "VPXDecoder");
-
- int64_t durationUs;
- if (inputFormat->findInt64(kKeyDuration, &durationUs)) {
- mFormat->setInt64(kKeyDuration, durationUs);
- }
-}
-
-VPXDecoder::~VPXDecoder() {
- if (mStarted) {
- stop();
- }
-}
-
-status_t VPXDecoder::start(MetaData *) {
- if (mStarted) {
- return UNKNOWN_ERROR;
- }
-
- status_t err = mSource->start();
-
- if (err != OK) {
- return err;
- }
-
- mCtx = new vpx_codec_ctx_t;
- vpx_codec_err_t vpx_err;
- if ((vpx_err = vpx_codec_dec_init(
- (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, NULL, 0))) {
- LOGE("on2 decoder failed to initialize. (%d)", vpx_err);
-
- mSource->stop();
-
- return UNKNOWN_ERROR;
- }
-
- mBufferGroup = new MediaBufferGroup;
- mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
- mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
-
- mTargetTimeUs = -1;
-
- mStarted = true;
-
- return OK;
-}
-
-status_t VPXDecoder::stop() {
- if (!mStarted) {
- return UNKNOWN_ERROR;
- }
-
- delete mBufferGroup;
- mBufferGroup = NULL;
-
- vpx_codec_destroy((vpx_codec_ctx_t *)mCtx);
- delete (vpx_codec_ctx_t *)mCtx;
- mCtx = NULL;
-
- mSource->stop();
-
- mStarted = false;
-
- return OK;
-}
-
-sp<MetaData> VPXDecoder::getFormat() {
- return mFormat;
-}
-
-status_t VPXDecoder::read(
- MediaBuffer **out, const ReadOptions *options) {
- *out = NULL;
-
- bool seeking = false;
- int64_t seekTimeUs;
- ReadOptions::SeekMode seekMode;
- if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
- seeking = true;
- }
-
- MediaBuffer *input;
- status_t err = mSource->read(&input, options);
-
- if (err != OK) {
- return err;
- }
-
- LOGV("read %d bytes from source\n", input->range_length());
-
- if (seeking) {
- int64_t targetTimeUs;
- if (input->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
- && targetTimeUs >= 0) {
- mTargetTimeUs = targetTimeUs;
- } else {
- mTargetTimeUs = -1;
- }
- }
-
- if (vpx_codec_decode(
- (vpx_codec_ctx_t *)mCtx,
- (uint8_t *)input->data() + input->range_offset(),
- input->range_length(),
- NULL,
- 0)) {
- LOGE("on2 decoder failed to decode frame.");
- input->release();
- input = NULL;
-
- return UNKNOWN_ERROR;
- }
-
- LOGV("successfully decoded 1 or more frames.");
-
- int64_t timeUs;
- CHECK(input->meta_data()->findInt64(kKeyTime, &timeUs));
-
- input->release();
- input = NULL;
-
- bool skipFrame = false;
-
- if (mTargetTimeUs >= 0) {
- CHECK(timeUs <= mTargetTimeUs);
-
- if (timeUs < mTargetTimeUs) {
- // We're still waiting for the frame with the matching
- // timestamp and we won't return the current one.
- skipFrame = true;
-
- LOGV("skipping frame at %lld us", timeUs);
- } else {
- LOGV("found target frame at %lld us", timeUs);
-
- mTargetTimeUs = -1;
- }
- }
-
- if (skipFrame) {
- *out = new MediaBuffer(0);
- return OK;
- }
-
- vpx_codec_iter_t iter = NULL;
- vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
-
- if (img == NULL) {
- // The VPX format supports "internal-only" frames that are
- // referenced by future content but never actually displayed, so
- // this is a perfectly valid scenario.
-
- *out = new MediaBuffer(0);
- return OK;
- }
-
- CHECK_EQ(img->fmt, IMG_FMT_I420);
-
- int32_t width = img->d_w;
- int32_t height = img->d_h;
-
- if (width != mWidth || height != mHeight) {
- LOGI("Image dimensions changed, width = %d, height = %d",
- width, height);
-
- mWidth = width;
- mHeight = height;
- mFormat->setInt32(kKeyWidth, width);
- mFormat->setInt32(kKeyHeight, height);
-
- mBufferSize = (mWidth * mHeight * 3) / 2;
- delete mBufferGroup;
- mBufferGroup = new MediaBufferGroup;
- mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
- mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
-
- return INFO_FORMAT_CHANGED;
- }
-
- MediaBuffer *output;
- CHECK_EQ(mBufferGroup->acquire_buffer(&output), OK);
-
- const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y];
- uint8_t *dst = (uint8_t *)output->data();
- for (size_t i = 0; i < img->d_h; ++i) {
- memcpy(dst, srcLine, img->d_w);
-
- srcLine += img->stride[PLANE_Y];
- dst += img->d_w;
- }
-
- srcLine = (const uint8_t *)img->planes[PLANE_U];
- for (size_t i = 0; i < img->d_h / 2; ++i) {
- memcpy(dst, srcLine, img->d_w / 2);
-
- srcLine += img->stride[PLANE_U];
- dst += img->d_w / 2;
- }
-
- srcLine = (const uint8_t *)img->planes[PLANE_V];
- for (size_t i = 0; i < img->d_h / 2; ++i) {
- memcpy(dst, srcLine, img->d_w / 2);
-
- srcLine += img->stride[PLANE_V];
- dst += img->d_w / 2;
- }
-
- output->set_range(0, (width * height * 3) / 2);
-
- output->meta_data()->setInt64(kKeyTime, timeUs);
-
- *out = output;
-
- return OK;
-}
-
-} // namespace android
-
diff --git a/media/libstagefright/codecs/vorbis/dec/Android.mk b/media/libstagefright/codecs/vorbis/dec/Android.mk
index 9251229..f33f3ac 100644
--- a/media/libstagefright/codecs/vorbis/dec/Android.mk
+++ b/media/libstagefright/codecs/vorbis/dec/Android.mk
@@ -2,21 +2,6 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
- VorbisDecoder.cpp \
-
-LOCAL_C_INCLUDES := \
- frameworks/base/media/libstagefright/include \
- external/tremolo \
-
-LOCAL_MODULE := libstagefright_vorbisdec
-
-include $(BUILD_STATIC_LIBRARY)
-
-################################################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
SoftVorbis.cpp
LOCAL_C_INCLUDES := \
@@ -24,9 +9,6 @@ LOCAL_C_INCLUDES := \
frameworks/base/media/libstagefright/include \
frameworks/base/include/media/stagefright/openmax \
-LOCAL_STATIC_LIBRARIES := \
- libstagefright_vorbisdec
-
LOCAL_SHARED_LIBRARIES := \
libvorbisidec libstagefright libstagefright_omx \
libstagefright_foundation libutils
diff --git a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
deleted file mode 100644
index e14fb95..0000000
--- a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "VorbisDecoder"
-#include <utils/Log.h>
-
-#include "VorbisDecoder.h"
-
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-
-extern "C" {
- #include <Tremolo/codec_internal.h>
-
- int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
- int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
- int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
-}
-
-namespace android {
-
-VorbisDecoder::VorbisDecoder(const sp<MediaSource> &source)
- : mSource(source),
- mStarted(false),
- mBufferGroup(NULL),
- mAnchorTimeUs(0),
- mNumFramesOutput(0),
- mState(NULL),
- mVi(NULL) {
- sp<MetaData> srcFormat = mSource->getFormat();
- CHECK(srcFormat->findInt32(kKeyChannelCount, &mNumChannels));
- CHECK(srcFormat->findInt32(kKeySampleRate, &mSampleRate));
-}
-
-VorbisDecoder::~VorbisDecoder() {
- if (mStarted) {
- stop();
- }
-}
-
-static void makeBitReader(
- const void *data, size_t size,
- ogg_buffer *buf, ogg_reference *ref, oggpack_buffer *bits) {
- buf->data = (uint8_t *)data;
- buf->size = size;
- buf->refcount = 1;
- buf->ptr.owner = NULL;
-
- ref->buffer = buf;
- ref->begin = 0;
- ref->length = size;
- ref->next = NULL;
-
- oggpack_readinit(bits, ref);
-}
-
-status_t VorbisDecoder::start(MetaData *params) {
- CHECK(!mStarted);
-
- mBufferGroup = new MediaBufferGroup;
- mBufferGroup->add_buffer(
- new MediaBuffer(kMaxNumSamplesPerBuffer * sizeof(int16_t)));
-
- mSource->start();
-
- sp<MetaData> meta = mSource->getFormat();
-
- mVi = new vorbis_info;
- vorbis_info_init(mVi);
-
- ///////////////////////////////////////////////////////////////////////////
-
- uint32_t type;
- const void *data;
- size_t size;
- CHECK(meta->findData(kKeyVorbisInfo, &type, &data, &size));
-
- ogg_buffer buf;
- ogg_reference ref;
- oggpack_buffer bits;
- makeBitReader((const uint8_t *)data + 7, size - 7, &buf, &ref, &bits);
- CHECK_EQ(0, _vorbis_unpack_info(mVi, &bits));
-
- ///////////////////////////////////////////////////////////////////////////
-
- CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
-
- makeBitReader((const uint8_t *)data + 7, size - 7, &buf, &ref, &bits);
- CHECK_EQ(0, _vorbis_unpack_books(mVi, &bits));
-
- ///////////////////////////////////////////////////////////////////////////
-
- mState = new vorbis_dsp_state;
- CHECK_EQ(0, vorbis_dsp_init(mState, mVi));
-
- mAnchorTimeUs = 0;
- mNumFramesOutput = 0;
-
- // If the source never limits the number of valid frames contained
- // in the input data, we'll assume that all of the decoded frames are
- // valid.
- mNumFramesLeftOnPage = -1;
-
- mStarted = true;
-
- return OK;
-}
-
-status_t VorbisDecoder::stop() {
- CHECK(mStarted);
-
- vorbis_dsp_clear(mState);
- delete mState;
- mState = NULL;
-
- vorbis_info_clear(mVi);
- delete mVi;
- mVi = NULL;
-
- delete mBufferGroup;
- mBufferGroup = NULL;
-
- mSource->stop();
-
- mStarted = false;
-
- return OK;
-}
-
-sp<MetaData> VorbisDecoder::getFormat() {
- sp<MetaData> srcFormat = mSource->getFormat();
-
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
- meta->setInt32(kKeyChannelCount, mNumChannels);
- meta->setInt32(kKeySampleRate, mSampleRate);
-
- int64_t durationUs;
- if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
- meta->setInt64(kKeyDuration, durationUs);
- }
-
- meta->setCString(kKeyDecoderComponent, "VorbisDecoder");
-
- return meta;
-}
-
-int VorbisDecoder::decodePacket(MediaBuffer *packet, MediaBuffer *out) {
- ogg_buffer buf;
- buf.data = (uint8_t *)packet->data() + packet->range_offset();
- buf.size = packet->range_length();
- buf.refcount = 1;
- buf.ptr.owner = NULL;
-
- ogg_reference ref;
- ref.buffer = &buf;
- ref.begin = 0;
- ref.length = packet->range_length();
- ref.next = NULL;
-
- ogg_packet pack;
- pack.packet = &ref;
- pack.bytes = packet->range_length();
- pack.b_o_s = 0;
- pack.e_o_s = 0;
- pack.granulepos = 0;
- pack.packetno = 0;
-
- int numFrames = 0;
-
- int err = vorbis_dsp_synthesis(mState, &pack, 1);
- if (err != 0) {
- LOGW("vorbis_dsp_synthesis returned %d", err);
- } else {
- numFrames = vorbis_dsp_pcmout(
- mState, (int16_t *)out->data(), kMaxNumSamplesPerBuffer);
-
- if (numFrames < 0) {
- LOGE("vorbis_dsp_pcmout returned %d", numFrames);
- numFrames = 0;
- }
- }
-
- if (mNumFramesLeftOnPage >= 0) {
- if (numFrames > mNumFramesLeftOnPage) {
- LOGV("discarding %d frames at end of page",
- numFrames - mNumFramesLeftOnPage);
- numFrames = mNumFramesLeftOnPage;
- }
- mNumFramesLeftOnPage -= numFrames;
- }
-
- out->set_range(0, numFrames * sizeof(int16_t) * mNumChannels);
-
- return numFrames;
-}
-
-status_t VorbisDecoder::read(
- MediaBuffer **out, const ReadOptions *options) {
- status_t err;
-
- *out = NULL;
-
- int64_t seekTimeUs;
- ReadOptions::SeekMode mode;
- if (options && options->getSeekTo(&seekTimeUs, &mode)) {
- CHECK(seekTimeUs >= 0);
-
- mNumFramesOutput = 0;
- vorbis_dsp_restart(mState);
- } else {
- seekTimeUs = -1;
- }
-
- MediaBuffer *inputBuffer;
- err = mSource->read(&inputBuffer, options);
-
- if (err != OK) {
- return ERROR_END_OF_STREAM;
- }
-
- int64_t timeUs;
- if (inputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- mAnchorTimeUs = timeUs;
- mNumFramesOutput = 0;
- } else {
- // We must have a new timestamp after seeking.
- CHECK(seekTimeUs < 0);
- }
-
- int32_t numPageSamples;
- if (inputBuffer->meta_data()->findInt32(
- kKeyValidSamples, &numPageSamples)) {
- CHECK(numPageSamples >= 0);
- mNumFramesLeftOnPage = numPageSamples;
- }
-
- MediaBuffer *outputBuffer;
- CHECK_EQ(mBufferGroup->acquire_buffer(&outputBuffer), OK);
-
- int numFrames = decodePacket(inputBuffer, outputBuffer);
-
- inputBuffer->release();
- inputBuffer = NULL;
-
- outputBuffer->meta_data()->setInt64(
- kKeyTime,
- mAnchorTimeUs
- + (mNumFramesOutput * 1000000ll) / mSampleRate);
-
- mNumFramesOutput += numFrames;
-
- *out = outputBuffer;
-
- return OK;
-}
-
-} // namespace android
diff --git a/media/libstagefright/include/ThreadedSource.h b/media/libstagefright/include/ThreadedSource.h
deleted file mode 100644
index c67295c..0000000
--- a/media/libstagefright/include/ThreadedSource.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef THREADED_SOURCE_H_
-
-#define THREADED_SOURCE_H_
-
-#include <media/stagefright/foundation/ABase.h>
-#include <media/stagefright/foundation/AHandlerReflector.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/MediaSource.h>
-#include <utils/threads.h>
-
-namespace android {
-
-struct ThreadedSource : public MediaSource {
- ThreadedSource(const sp<MediaSource> &source);
-
- virtual status_t start(MetaData *params);
- virtual status_t stop();
-
- virtual sp<MetaData> getFormat();
-
- virtual status_t read(
- MediaBuffer **buffer, const ReadOptions *options);
-
- virtual void onMessageReceived(const sp<AMessage> &msg);
-
-protected:
- virtual ~ThreadedSource();
-
-private:
- enum {
- kWhatDecodeMore = 'deco',
- kWhatSeek = 'seek',
- };
-
- sp<MediaSource> mSource;
- sp<AHandlerReflector<ThreadedSource> > mReflector;
- sp<ALooper> mLooper;
-
- Mutex mLock;
- Condition mCondition;
- List<MediaBuffer *> mQueue;
- status_t mFinalResult;
- bool mDecodePending;
- bool mStarted;
-
- int64_t mSeekTimeUs;
- ReadOptions::SeekMode mSeekMode;
-
- void postDecodeMore_l();
- void clearQueue_l();
-
- DISALLOW_EVIL_CONSTRUCTORS(ThreadedSource);
-};
-
-} // namespace android
-
-#endif // THREADED_SOURCE_H_
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 08ad6f3..d844f3d 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -23,14 +23,7 @@ LOCAL_SHARED_LIBRARIES := \
libui \
libcutils \
libstagefright_foundation \
-
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
- LOCAL_LDLIBS += -lpthread -ldl
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
+ libdl
LOCAL_MODULE:= libstagefright_omx
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index c25285e..e590bab 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -16,8 +16,6 @@
LOCAL_PATH:= $(call my-dir)
-ifneq ($(TARGET_SIMULATOR),true)
-
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
@@ -45,8 +43,6 @@ LOCAL_SHARED_LIBRARIES := libutils libcutils libusbhost libbinder
include $(BUILD_SHARED_LIBRARY)
-endif
-
ifeq ($(HOST_OS),linux)
include $(CLEAR_VARS)
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index bc04e8c..4047e2e 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -237,6 +237,8 @@ void MtpServer::run() {
if (mSessionOpen)
mDatabase->sessionEnded();
+ close(fd);
+ mFD = -1;
}
void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
@@ -871,6 +873,14 @@ MtpResponseCode MtpServer::doSendObjectInfo() {
// check space first
if (mSendObjectFileSize > storage->getFreeSpace())
return MTP_RESPONSE_STORAGE_FULL;
+ uint64_t maxFileSize = storage->getMaxFileSize();
+ // check storage max file size
+ if (maxFileSize != 0) {
+ // if mSendObjectFileSize is 0xFFFFFFFF, then all we know is the file size
+ // is >= 0xFFFFFFFF
+ if (mSendObjectFileSize > maxFileSize || mSendObjectFileSize == 0xFFFFFFFF)
+ return MTP_RESPONSE_OBJECT_TOO_LARGE;
+ }
LOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID);
MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path,
diff --git a/media/mtp/MtpStorage.cpp b/media/mtp/MtpStorage.cpp
index fef8066..941e303 100644
--- a/media/mtp/MtpStorage.cpp
+++ b/media/mtp/MtpStorage.cpp
@@ -33,11 +33,13 @@
namespace android {
MtpStorage::MtpStorage(MtpStorageID id, const char* filePath,
- const char* description, uint64_t reserveSpace, bool removable)
+ const char* description, uint64_t reserveSpace,
+ bool removable, uint64_t maxFileSize)
: mStorageID(id),
mFilePath(filePath),
mDescription(description),
mMaxCapacity(0),
+ mMaxFileSize(maxFileSize),
mReserveSpace(reserveSpace),
mRemovable(removable)
{
diff --git a/media/mtp/MtpStorage.h b/media/mtp/MtpStorage.h
index 3e4f40d..e5a2e57 100644
--- a/media/mtp/MtpStorage.h
+++ b/media/mtp/MtpStorage.h
@@ -31,6 +31,7 @@ private:
MtpString mFilePath;
MtpString mDescription;
uint64_t mMaxCapacity;
+ uint64_t mMaxFileSize;
// amount of free space to leave unallocated
uint64_t mReserveSpace;
bool mRemovable;
@@ -38,7 +39,7 @@ private:
public:
MtpStorage(MtpStorageID id, const char* filePath,
const char* description, uint64_t reserveSpace,
- bool removable);
+ bool removable, uint64_t maxFileSize);
virtual ~MtpStorage();
inline MtpStorageID getStorageID() const { return mStorageID; }
@@ -50,6 +51,7 @@ public:
const char* getDescription() const;
inline const char* getPath() const { return (const char *)mFilePath; }
inline bool isRemovable() const { return mRemovable; }
+ inline uint64_t getMaxFileSize() const { return mMaxFileSize; }
};
}; // namespace android
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
index 5120694..afe2001 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
@@ -1335,16 +1335,19 @@ public class VideoEditorAPITest extends
@LargeTest
public void testEffectKenBurn() throws Exception {
// Test ken burn effect using a JPEG file.
- testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.jpg");
+ testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.jpg",
+ "mediaImageItem1");
// Test ken burn effect using a PNG file
- testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.png");
+ testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.png",
+ "mediaImageItem2");
}
- private void testEffectKenBurn(final String imageItemFileName) throws Exception {
+ private void testEffectKenBurn(final String imageItemFileName,
+ final String MediaId) throws Exception {
final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
final MediaImageItem mediaImageItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
+ mVideoEditorHelper.createMediaItem(mVideoEditor, MediaId,
imageItemFileName, 5000, imageItemRenderingMode);
mVideoEditor.addMediaItem(mediaImageItem);
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 32d1a23..3f547fd 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -88,7 +88,7 @@ import android.view.SurfaceView;
* well as how many bits are allocated to each channel. Therefore, the first thing
* GLSurfaceView has to do when starting to render is choose what EGLConfig to use.
* <p>
- * By default GLSurfaceView chooses a EGLConfig that has an RGB_656 pixel format,
+ * By default GLSurfaceView chooses a EGLConfig that has an RGB_565 pixel format,
* with at least a 16-bit depth buffer and no stencil.
* <p>
* If you would prefer a different EGLConfig
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index b5c018f..15e58f2 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -38,15 +38,13 @@ ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
-ifneq ($(TARGET_SIMULATOR),true)
- # we need to access the private Bionic header <bionic_tls.h>
- # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
- # behavior from the bionic Android.mk file
- ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
- endif
- LOCAL_C_INCLUDES += bionic/libc/private
+# we need to access the private Bionic header <bionic_tls.h>
+# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
+# behavior from the bionic Android.mk file
+ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
+ LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
+LOCAL_C_INCLUDES += bionic/libc/private
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
LOCAL_MODULE:= libGLES_android
diff --git a/opengl/libagl2/Android.mk b/opengl/libagl2/Android.mk
index 564932f..b442a2d 100644
--- a/opengl/libagl2/Android.mk
+++ b/opengl/libagl2/Android.mk
@@ -39,15 +39,13 @@ ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
-ifneq ($(TARGET_SIMULATOR),true)
- # we need to access the private Bionic header <bionic_tls.h>
- # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
- # behavior from the bionic Android.mk file
- ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
- endif
- LOCAL_C_INCLUDES += bionic/libc/private
+# we need to access the private Bionic header <bionic_tls.h>
+# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
+# behavior from the bionic Android.mk file
+ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
+ LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
+LOCAL_C_INCLUDES += bionic/libc/private
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
#replace libagl for now
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index ff45edc..3e66a13 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -21,18 +21,14 @@ LOCAL_SHARED_LIBRARIES += libcutils libutils libGLESv2_dbg
LOCAL_LDLIBS := -lpthread -ldl
LOCAL_MODULE:= libEGL
LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL
-# needed on sim build because of weird logging issues
-ifeq ($(TARGET_SIMULATOR),true)
-else
- LOCAL_SHARED_LIBRARIES += libdl
- # Bionic's private TLS header relies on the ARCH_ARM_HAVE_TLS_REGISTER to
- # select the appropriate TLS codepath
- ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
- endif
- # we need to access the private Bionic header <bionic_tls.h>
- LOCAL_C_INCLUDES += bionic/libc/private
+LOCAL_SHARED_LIBRARIES += libdl
+# Bionic's private TLS header relies on the ARCH_ARM_HAVE_TLS_REGISTER to
+# select the appropriate TLS codepath
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+ LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
+# we need to access the private Bionic header <bionic_tls.h>
+LOCAL_C_INCLUDES += bionic/libc/private
LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
@@ -81,16 +77,12 @@ LOCAL_SHARED_LIBRARIES += libcutils libEGL
LOCAL_LDLIBS := -lpthread -ldl
LOCAL_MODULE:= libGLESv1_CM
-# needed on sim build because of weird logging issues
-ifeq ($(TARGET_SIMULATOR),true)
-else
- LOCAL_SHARED_LIBRARIES += libdl
- # we need to access the private Bionic header <bionic_tls.h>
- ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
- endif
- LOCAL_C_INCLUDES += bionic/libc/private
+LOCAL_SHARED_LIBRARIES += libdl
+# we need to access the private Bionic header <bionic_tls.h>
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+ LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
+LOCAL_C_INCLUDES += bionic/libc/private
LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv1\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
@@ -117,16 +109,12 @@ LOCAL_SHARED_LIBRARIES += libcutils libEGL
LOCAL_LDLIBS := -lpthread -ldl
LOCAL_MODULE:= libGLESv2
-# needed on sim build because of weird logging issues
-ifeq ($(TARGET_SIMULATOR),true)
-else
- LOCAL_SHARED_LIBRARIES += libdl
- # we need to access the private Bionic header <bionic_tls.h>
- ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
- endif
- LOCAL_C_INCLUDES += bionic/libc/private
+LOCAL_SHARED_LIBRARIES += libdl
+# we need to access the private Bionic header <bionic_tls.h>
+ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
+ LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
+LOCAL_C_INCLUDES += bionic/libc/private
LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv2\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index b11db32..ddad2d3 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -31,6 +31,7 @@
#include <cutils/properties.h>
#include <cutils/memory.h>
+#include <utils/CallStack.h>
#include <utils/String8.h>
#include "egldefs.h"
@@ -147,6 +148,10 @@ static int gl_no_context() {
if (egl_tls_t::logNoContextCall()) {
LOGE("call to OpenGL ES API with no current context "
"(logged once per thread)");
+ LOGE("call stack before error:");
+ CallStack stack;
+ stack.update();
+ stack.dump();
}
return 0;
}
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 7d5d010..ba5d29a 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -367,7 +367,12 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
if (cnx->egl.eglGetConfigAttrib(iDpy,
iConfig, EGL_NATIVE_VISUAL_ID, &format)) {
if (format != 0) {
- native_window_set_buffers_geometry(window, 0, 0, format);
+ int err = native_window_set_buffers_format(window, format);
+ if (err != 0) {
+ LOGE("error setting native window pixel format: %s (%d)",
+ strerror(-err), err);
+ return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+ }
}
}
diff --git a/opengl/libs/GLES2_dbg/Android.mk b/opengl/libs/GLES2_dbg/Android.mk
index 9f6e68c..c2b1142 100644
--- a/opengl/libs/GLES2_dbg/Android.mk
+++ b/opengl/libs/GLES2_dbg/Android.mk
@@ -31,15 +31,13 @@ ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
-ifneq ($(TARGET_SIMULATOR),true)
- # we need to access the private Bionic header <bionic_tls.h>
- # on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
- # behavior from the bionic Android.mk file
- ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
- endif
- LOCAL_C_INCLUDES += bionic/libc/private
+# we need to access the private Bionic header <bionic_tls.h>
+# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
+# behavior from the bionic Android.mk file
+ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
+ LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
+LOCAL_C_INCLUDES += bionic/libc/private
LOCAL_MODULE:= libGLESv2_dbg
LOCAL_MODULE_TAGS := optional
diff --git a/opengl/libs/GLES2_dbg/test/Android.mk b/opengl/libs/GLES2_dbg/test/Android.mk
index 14a84b4..8708d43 100644
--- a/opengl/libs/GLES2_dbg/test/Android.mk
+++ b/opengl/libs/GLES2_dbg/test/Android.mk
@@ -27,9 +27,7 @@ LOCAL_MODULE:= libGLESv2_dbg_test
ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
-ifneq ($(TARGET_SIMULATOR),true)
- LOCAL_C_INCLUDES += bionic/libc/private
-endif
+LOCAL_C_INCLUDES += bionic/libc/private
LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
diff --git a/opengl/specs/EGL_ANDROID_blob_cache.txt b/opengl/specs/EGL_ANDROID_blob_cache.txt
new file mode 100644
index 0000000..55dc900
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_blob_cache.txt
@@ -0,0 +1,208 @@
+Name
+
+ ANDROID_blob_cache
+
+Name Strings
+
+ EGL_ANDROID_blob_cache
+
+Contributors
+
+ Jamie Gennis
+
+Contact
+
+ Jamie Gennis, Google Inc. (jgennis 'at' google.com)
+
+Status
+
+ Draft.
+
+Version
+
+ Version 1, April 22, 2011
+
+Number
+
+ EGL Extension #XXX
+
+Dependencies
+
+ Requires EGL 1.0
+
+ This extension is written against the wording of the EGL 1.4 Specification
+
+Overview
+
+ Shader compilation and optimization has been a troublesome aspect of OpenGL
+ programming for a long time. It can consume seconds of CPU cycles during
+ application start-up. Additionally, state-based re-compiles done
+ internally by the drivers add an unpredictable element to application
+ performance tuning, often leading to occasional pauses in otherwise smooth
+ animations.
+
+ This extension provides a mechanism through which client API
+ implementations may cache shader binaries after they are compiled. It may
+ then retrieve those cached shaders during subsequent executions of the same
+ program. The management of the cache is handled by the application (or
+ middleware), allowing it to be tuned to a particular platform or
+ environment.
+
+ While the focus of this extension is on providing a persistent cache for
+ shader binaries, it may also be useful for caching other data. This is
+ perfectly acceptable, but the guarantees provided (or lack thereof) were
+ designed around the shader use case.
+
+ Note that although this extension is written as if the application
+ implements the caching functionality, on the Android OS it is implemented
+ as part of the Android EGL module. This extension is not exposed to
+ applications on Android, but will be used automatically in every
+ application that uses EGL if it is supported by the underlying
+ device-specific EGL implementation.
+
+New Types
+
+ /*
+ * EGLsizei is a signed integer type for representing the size of a memory
+ * buffer.
+ */
+ #include <khrplatform.h>
+ typedef khronos_ssize_t EGLsizei;
+
+ /*
+ * EGLSetBlobFunc is a pointer to an application-provided function that a
+ * client API implementation may use to insert a key/value pair into the
+ * cache.
+ */
+ typedef void (*EGLSetBlobFunc) (const void* key, EGLsizei keySize,
+ const void* value, EGLsizei valueSize)
+
+ /*
+ * EGLGetBlobFunc is a pointer to an application-provided function that a
+ * client API implementation may use to retrieve a cached value from the
+ * cache.
+ */
+ typedef EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize,
+ void* value, EGLsizei valueSize)
+
+New Procedures and Functions
+
+ void eglSetBlobCacheFuncs(EGLDisplay dpy,
+ EGLSetBlobFunc set,
+ EGLGetBlobFunc get);
+
+New Tokens
+
+ None.
+
+Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
+
+ Add a new subsection after Section 3.8, page 50
+ (Synchronization Primitives)
+
+ "3.9 Persistent Caching
+
+ In order to facilitate persistent caching of internal client API state that
+ is slow to compute or collect, the application may specify callback
+ function pointers through which the client APIs can request data be cached
+ and retrieved. The command
+
+ void eglSetBlobCacheFuncs(EGLDisplay dpy,
+ EGLSetBlobFunc set, EGLGetBlobFunc get);
+
+ sets the callback function pointers that client APIs associated with
+ display <dpy> can use to interact with caching functionality provided by
+ the application. <set> points to a function that inserts a new value into
+ the cache and associates it with the given key. <get> points to a function
+ that retrieves from the cache the value associated with a given key. The
+ semantics of these callback functions are described in Section 3.9.1 (Cache
+ Operations).
+
+ Cache functions may only be specified once during the lifetime of an
+ EGLDisplay. The <set> and <get> functions may be called at any time and
+ from any thread from the time at which eglSetBlobCacheFuncs is called until
+ the time that the last resource associated with <dpy> is deleted and <dpy>
+ itself is terminated. Concurrent calls to these functions from different
+ threads is also allowed.
+
+ If eglSetBlobCacheFuncs generates an error then all client APIs must behave
+ as though eglSetBlobCacheFuncs was not called for the display <dpy>. If
+ <set> or <get> is NULL then an EGL_BAD_PARAMETER error is generated. If a
+ successful eglSetBlobCacheFuncs call was already made for <dpy> and the
+ display has not since been terminated then an EGL_BAD_PARAMETER error is
+ generated.
+
+ 3.9.1 Cache Operations
+
+ To insert a new binary value into the cache and associate it with a given
+ key, a client API implementation can call the application-provided callback
+ function
+
+ void (*set) (const void* key, EGLsizei keySize, const void* value,
+ EGLsizei valueSize)
+
+ <key> and <value> are pointers to the beginning of the key and value,
+ respectively, that are to be inserted. <keySize> and <valueSize> specify
+ the size in bytes of the data pointed to by <key> and <value>,
+ respectively.
+
+ No guarantees are made as to whether a given key/value pair is present in
+ the cache after the set call. If a different value has been associated
+ with the given key in the past then it is undefined which value, if any, is
+ associated with the key after the set call. Note that while there are no
+ guarantees, the cache implementation should attempt to cache the most
+ recently set value for a given key.
+
+ To retrieve the binary value associated with a given key from the cache, a
+ client API implementation can call the application-provided callback
+ function
+
+ EGLsizei (*get) (const void* key, EGLsizei keySize, void* value,
+ EGLsizei valueSize)
+
+ <key> is a pointer to the beginning of the key. <keySize> specifies the
+ size in bytes of the binary key pointed to by <key>. If the cache contains
+ a value associated with the given key then the size of that binary value in
+ bytes is returned. Otherwise 0 is returned.
+
+ If the cache contains a value for the given key and its size in bytes is
+ less than or equal to <valueSize> then the value is written to the memory
+ pointed to by <value>. Otherwise nothing is written to the memory pointed
+ to by <value>.
+
+Issues
+
+ 1. How should errors be handled in the callback functions?
+
+ RESOLVED: No guarantees are made about the presence of values in the cache,
+ so there should not be a need to return error information to the client API
+ implementation. The cache implementation can simply drop a value if it
+ encounters an error during the 'set' callback. Similarly, it can simply
+ return 0 if it encouters an error in a 'get' callback.
+
+ 2. When a client API driver gets updated, that may need to invalidate
+ previously cached entries. How can the driver handle this situation?
+
+ RESPONSE: There are a number of ways the driver can handle this situation.
+ The recommended way is to include the driver version in all cache keys.
+ That way each driver version will use a set of cache keys that are unique
+ to that version, and conflicts should never occur. Updating the driver
+ could then leave a number of values in the cache that will never be
+ requested again. If needed, the cache implementation can handle those
+ values in some way, but the driver does not need to take any special
+ action.
+
+ 3. How much data can be stored in the cache?
+
+ RESPONSE: This is entirely dependent upon the cache implementation.
+ Presumably it will be tuned to store enough data to be useful, but not
+ enough to become problematic. :)
+
+Revision History
+
+#2 (Jamie Gennis, April 25, 2011)
+ - Swapped the order of the size and pointer arguments to the get and set
+ functions.
+
+#1 (Jamie Gennis, April 22, 2011)
+ - Initial draft.
diff --git a/opengl/specs/EGL_ANDROID_recordable.txt b/opengl/specs/EGL_ANDROID_recordable.txt
new file mode 100644
index 0000000..cf44465
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_recordable.txt
@@ -0,0 +1,113 @@
+Name
+
+ ANDROID_recordable
+
+Name Strings
+
+ EGL_ANDROID_recordable
+
+Contributors
+
+ Jamie Gennis
+
+Contact
+
+ Jamie Gennis, Google Inc. (jgennis 'at' google.com)
+
+Status
+
+ Draft.
+
+Version
+
+ Version 1, July 8, 2011
+
+Number
+
+ EGL Extension #XXX
+
+Dependencies
+
+ Requires EGL 1.0
+
+ This extension is written against the wording of the EGL 1.4 Specification
+
+Overview
+
+ Android supports a number of different ANativeWindow implementations that
+ can be used to create an EGLSurface. One implementation, which records the
+ rendered image as a video each time eglSwapBuffers gets called, may have
+ some device-specific restrictions. Because of this, some EGLConfigs may be
+ incompatible with these ANativeWindows. This extension introduces a new
+ boolean EGLConfig attribute that indicates whether the EGLConfig supports
+ rendering to an ANativeWindow that records images to a video.
+
+New Types
+
+ None.
+
+New Procedures and Functions
+
+ None.
+
+New Tokens
+
+ Accepted by the <attribute> parameter of eglGetConfigAttrib and
+ the <attrib_list> parameter of eglChooseConfig:
+
+ EGL_RECORDABLE_ANDROID 0xXXXX
+
+Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
+
+ Section 3.4, Configuration Management, add a row to Table 3.1.
+
+ Attribute Type Notes
+ ---------------------- ------- --------------------------
+ EGL_RECORDABLE_ANDROID boolean whether video recording is
+ supported
+
+ Section 3.4, Configuration Management, add a row to Table 3.4.
+
+ Attribute Default Selection Sort Sort
+ Criteria Order Priority
+ ---------------------- ------------- --------- ----- --------
+ EGL_RECORDABLE_ANDROID EGL_DONT_CARE Exact None
+
+ Section 3.4, Configuration Management, add a paragraph at the end of the
+ subsection titled Other EGLConfig Attribute Descriptions.
+
+ EGL_RECORDABLE_ANDROID is a boolean indicating whether the config may
+ be used to create an EGLSurface from an ANativeWindow that is a video
+ recorder as indicated by the NATIVE_WINDOW_IS_VIDEO_RECORDER query on
+ the ANativeWindow.
+
+ Section 3.4.1, Querying Configurations, change the last paragraph as follow
+
+ EGLConfigs are not sorted with respect to the parameters
+ EGL_BIND_TO_TEXTURE_RGB, EGL_BIND_TO_TEXTURE_RGBA, EGL_CONFORMANT,
+ EGL_LEVEL, EGL_NATIVE_RENDERABLE, EGL_MAX_SWAP_INTERVAL,
+ EGL_MIN_SWAP_INTERVAL, EGL_RENDERABLE_TYPE, EGL_SURFACE_TYPE,
+ EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RED_VALUE,
+ EGL_TRANSPARENT_GREEN_VALUE, EGL_TRANSPARENT_BLUE_VALUE, and
+ EGL_RECORDABLE_ANDROID.
+
+Issues
+
+ 1. Should this functionality be exposed as a new attribute or as a bit in
+ the EGL_SURFACE_TYPE bitfield?
+
+ RESOLVED: It should be a new attribute. It does not make sense to use up a
+ bit in the limit-size bitfield for a platform-specific extension.
+
+ 2. How should the new attribute affect the sorting of EGLConfigs?
+
+ RESOLVED: It should not affect sorting. Some implementations may not have
+ any drawback associated with using a recordable EGLConfig. Such
+ implementations should not have to double-up some of their configs to one sort earlier than .
+ Implementations that do have drawbacks can use the existing caveat
+ mechanism to report this drawback to the client.
+
+Revision History
+
+#1 (Jamie Gennis, July 8, 2011)
+ - Initial draft.
diff --git a/opengl/specs/README b/opengl/specs/README
new file mode 100644
index 0000000..2fa2587
--- /dev/null
+++ b/opengl/specs/README
@@ -0,0 +1,12 @@
+This directory contains OpenGL ES and EGL extension specifications that have
+been or are being defined for Android.
+
+The table below tracks usage of EGL enumerant values that have been reserved
+for use by Android extensions.
+
+ Value Extension
+---------------- ----------------------------------
+0x3140 EGL_ANDROID_image_native_buffer
+0x3141 (unused)
+0x3142 EGL_ANDROID_recordable
+0x3143 - 0x314F (unused)
diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk
new file mode 100644
index 0000000..92d7eb1
--- /dev/null
+++ b/opengl/tests/EGLTest/Android.mk
@@ -0,0 +1,37 @@
+# Build the unit tests.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := EGL_test
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+ EGL_test.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libEGL \
+ libcutils \
+ libstlport \
+ libutils \
+
+LOCAL_STATIC_LIBRARIES := \
+ libgtest \
+ libgtest_main \
+
+LOCAL_C_INCLUDES := \
+ bionic \
+ bionic/libstdc++/include \
+ external/gtest/include \
+ external/stlport/stlport \
+
+include $(BUILD_EXECUTABLE)
+
+# Include subdirectory makefiles
+# ============================================================
+
+# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
+# team really wants is to build the stuff defined by this makefile.
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
new file mode 100644
index 0000000..337ad33
--- /dev/null
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <utils/String8.h>
+
+#include <EGL/egl.h>
+
+namespace android {
+
+class EGLTest : public ::testing::Test {
+protected:
+ EGLDisplay mEglDisplay;
+
+protected:
+ EGLTest() :
+ mEglDisplay(EGL_NO_DISPLAY) {
+ }
+
+ virtual void SetUp() {
+ mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ EGLint majorVersion;
+ EGLint minorVersion;
+ EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ RecordProperty("EglVersionMajor", majorVersion);
+ RecordProperty("EglVersionMajor", minorVersion);
+ }
+
+ virtual void TearDown() {
+ EGLBoolean success = eglTerminate(mEglDisplay);
+ ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ }
+};
+
+TEST_F(EGLTest, DISABLED_EGLConfigEightBitFirst) {
+
+ EGLint numConfigs;
+ EGLConfig config;
+ EGLBoolean success;
+ EGLint attrs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NONE
+ };
+
+ success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+ ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_GE(numConfigs, 1);
+
+ EGLint components[3];
+
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+ ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+ ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+ ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ EXPECT_GE(components[0], 8);
+ EXPECT_GE(components[1], 8);
+ EXPECT_GE(components[2], 8);
+}
+
+TEST_F(EGLTest, EGLConfigRGBA8888First) {
+
+ EGLint numConfigs;
+ EGLConfig config;
+ EGLBoolean success;
+ EGLint attrs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_NONE
+ };
+
+ success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+ ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_GE(numConfigs, 1);
+
+ EGLint components[4];
+
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+ ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+ ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+ ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+ ASSERT_EQ(EGL_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ EXPECT_GE(components[0], 8);
+ EXPECT_GE(components[1], 8);
+ EXPECT_GE(components[2], 8);
+ EXPECT_GE(components[3], 8);
+}
+
+
+}
diff --git a/opengl/tests/gl2_jni/Android.mk b/opengl/tests/gl2_jni/Android.mk
index e8b6c57..5d90ff6 100644
--- a/opengl/tests/gl2_jni/Android.mk
+++ b/opengl/tests/gl2_jni/Android.mk
@@ -2,8 +2,6 @@
# OpenGL ES JNI sample
# This makefile builds both an activity and a shared library.
#########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
TOP_LOCAL_PATH:= $(call my-dir)
# Build activity
@@ -47,5 +45,3 @@ LOCAL_MODULE := libgl2jni
include $(BUILD_SHARED_LIBRARY)
-
-endif # TARGET_SIMULATOR
diff --git a/opengl/tests/gl_jni/Android.mk b/opengl/tests/gl_jni/Android.mk
index 4acd91f..3d20e72 100644
--- a/opengl/tests/gl_jni/Android.mk
+++ b/opengl/tests/gl_jni/Android.mk
@@ -2,8 +2,6 @@
# OpenGL ES JNI sample
# This makefile builds both an activity and a shared library.
#########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
TOP_LOCAL_PATH:= $(call my-dir)
# Build activity
@@ -49,5 +47,3 @@ LOCAL_ARM_MODE := arm
include $(BUILD_SHARED_LIBRARY)
-
-endif # TARGET_SIMULATOR
diff --git a/opengl/tests/gl_perfapp/Android.mk b/opengl/tests/gl_perfapp/Android.mk
index 4b79569..65e50e9 100644
--- a/opengl/tests/gl_perfapp/Android.mk
+++ b/opengl/tests/gl_perfapp/Android.mk
@@ -2,8 +2,6 @@
# OpenGL ES Perf App
# This makefile builds both an activity and a shared library.
#########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
TOP_LOCAL_PATH:= $(call my-dir)
# Build activity
@@ -50,5 +48,3 @@ LOCAL_MODULE := libglperf
include $(BUILD_SHARED_LIBRARY)
-
-endif # TARGET_SIMULATOR
diff --git a/opengl/tests/gldual/Android.mk b/opengl/tests/gldual/Android.mk
index f1a998a..b4b378e 100644
--- a/opengl/tests/gldual/Android.mk
+++ b/opengl/tests/gldual/Android.mk
@@ -2,8 +2,6 @@
# OpenGL ES JNI sample
# This makefile builds both an activity and a shared library.
#########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
TOP_LOCAL_PATH:= $(call my-dir)
# Build activity
@@ -47,5 +45,3 @@ LOCAL_MODULE := libgldualjni
include $(BUILD_SHARED_LIBRARY)
-
-endif # TARGET_SIMULATOR
diff --git a/opengl/tests/testPauseResume/Android.mk b/opengl/tests/testPauseResume/Android.mk
index 450473a..cf8bdc3 100644
--- a/opengl/tests/testPauseResume/Android.mk
+++ b/opengl/tests/testPauseResume/Android.mk
@@ -2,8 +2,6 @@
# OpenGL ES JNI sample
# This makefile builds both an activity and a shared library.
#########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
TOP_LOCAL_PATH:= $(call my-dir)
# Build activity
@@ -18,5 +16,3 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := TestEGL
include $(BUILD_PACKAGE)
-
-endif # TARGET_SIMULATOR
diff --git a/opengl/tests/testViewport/Android.mk b/opengl/tests/testViewport/Android.mk
index ab37809..9980e7d 100644
--- a/opengl/tests/testViewport/Android.mk
+++ b/opengl/tests/testViewport/Android.mk
@@ -2,8 +2,6 @@
# OpenGL ES JNI sample
# This makefile builds both an activity and a shared library.
#########################################################################
-ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean
-
TOP_LOCAL_PATH:= $(call my-dir)
# Build activity
@@ -22,5 +20,3 @@ LOCAL_PACKAGE_NAME := TestViewport
LOCAL_SDK_VERSION := 8
include $(BUILD_PACKAGE)
-
-endif # TARGET_SIMULATOR
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 47ab150..afe4246 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -16,17 +16,6 @@
package com.android.providers.settings;
-import com.android.internal.content.PackageHelper;
-import com.android.internal.telephony.BaseCommands;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.util.XmlUtils;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternView;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
@@ -47,6 +36,17 @@ import android.provider.Settings.Secure;
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.content.PackageHelper;
+import com.android.internal.telephony.BaseCommands;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.util.XmlUtils;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
@@ -63,7 +63,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 65;
+ private static final int DATABASE_VERSION = 66;
private Context mContext;
@@ -839,6 +839,28 @@ public class DatabaseHelper extends SQLiteOpenHelper {
upgradeVersion = 65;
}
+ if (upgradeVersion == 65) {
+ /*
+ * Animations are removed from Settings. Turned on by default
+ */
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ db.execSQL("DELETE FROM system WHERE name='"
+ + Settings.System.WINDOW_ANIMATION_SCALE + "'");
+ db.execSQL("DELETE FROM system WHERE name='"
+ + Settings.System.TRANSITION_ANIMATION_SCALE + "'");
+ stmt = db.compileStatement("INSERT INTO system(name,value)"
+ + " VALUES(?,?);");
+ loadDefaultAnimationSettings(stmt);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ upgradeVersion = 66;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
index 386182d..28ef239 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
@@ -29,21 +29,17 @@
android:background="@drawable/status_bar_recents_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_alignParentBottom="true"
- android:paddingBottom="@*android:dimen/status_bar_height"
- android:clipToPadding="false"
- android:clipChildren="false">
+ android:layout_alignParentBottom="true">
<LinearLayout android:id="@+id/recents_glow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginBottom="0dp"
android:layout_gravity="bottom"
android:orientation="horizontal"
- android:clipToPadding="false"
android:clipChildren="false"
- >
- <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container"
+ android:layout_marginTop="@*android:dimen/status_bar_height">
+ <com.android.systemui.recent.RecentsVerticalScrollView
+ android:id="@+id/recents_container"
android:layout_width="@dimen/status_bar_recents_width"
android:layout_height="wrap_content"
android:layout_marginRight="0dp"
@@ -51,7 +47,7 @@
android:stackFromBottom="true"
android:fadingEdge="vertical"
android:scrollbars="none"
- android:fadingEdgeLength="20dip"
+ android:fadingEdgeLength="@*android:dimen/status_bar_height"
android:listSelector="@drawable/recents_thumbnail_bg_selector"
android:layout_gravity="bottom|left"
android:clipToPadding="false"
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Constants.java b/packages/SystemUI/src/com/android/systemui/recent/Constants.java
index 66f9292..8252a9f 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Constants.java
@@ -18,7 +18,8 @@ package com.android.systemui.recent;
public class Constants {
static final int MAX_ESCAPE_ANIMATION_DURATION = 500; // in ms
- static final float FADE_CONSTANT = 0.5f; // unitless
static final int SNAP_BACK_DURATION = 250; // in ms
static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it in dp/s
+ public static float ALPHA_FADE_START = 0.8f; // fraction of thumbnail width where fade starts
+ static final float ALPHA_FADE_END = 0.5f; // fraction of thumbnail width beyond which alpha->0
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index fb7a0a7..f984aac 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -118,12 +118,12 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView
}
private float getAlphaForOffset(View view, float thumbHeight) {
- final float fadeHeight = Constants.FADE_CONSTANT * thumbHeight;
+ final float fadeHeight = Constants.ALPHA_FADE_END * thumbHeight;
float result = 1.0f;
- if (view.getY() >= thumbHeight) {
- result = 1.0f - (view.getY() - thumbHeight) / fadeHeight;
- } else if (view.getY() < 0.0f) {
- result = 1.0f + (thumbHeight + view.getY()) / fadeHeight;
+ if (view.getY() >= thumbHeight * Constants.ALPHA_FADE_START) {
+ result = 1.0f - (view.getY() - thumbHeight * Constants.ALPHA_FADE_START) / fadeHeight;
+ } else if (view.getY() < thumbHeight * (1.0f - Constants.ALPHA_FADE_START)) {
+ result = 1.0f + (thumbHeight * Constants.ALPHA_FADE_START + view.getY()) / fadeHeight;
}
if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result);
return result;
@@ -269,7 +269,7 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView
// This has to happen post-layout, so run it "in the future"
post(new Runnable() {
public void run() {
- scrollTo(0, mLastScrollPosition);
+ scrollTo(mLastScrollPosition, 0);
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index 711ffa3..27bb0b5 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -118,12 +118,12 @@ public class RecentsVerticalScrollView extends ScrollView
}
private float getAlphaForOffset(View view, float thumbWidth) {
- final float fadeWidth = Constants.FADE_CONSTANT * thumbWidth;
+ final float fadeWidth = Constants.ALPHA_FADE_END * thumbWidth;
float result = 1.0f;
- if (view.getX() >= thumbWidth) {
- result = 1.0f - (view.getX() - thumbWidth) / fadeWidth;
- } else if (view.getX() < 0.0f) {
- result = 1.0f + (thumbWidth + view.getX()) / fadeWidth;
+ if (view.getX() >= thumbWidth*Constants.ALPHA_FADE_START) {
+ result = 1.0f - (view.getX() - thumbWidth*Constants.ALPHA_FADE_START) / fadeWidth;
+ } else if (view.getX() < thumbWidth* (1.0f - Constants.ALPHA_FADE_START)) {
+ result = 1.0f + (thumbWidth*Constants.ALPHA_FADE_START + view.getX()) / fadeWidth;
}
if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result);
return result;
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 5eacad7..b50fd81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -307,7 +307,7 @@ public class PhoneStatusBar extends StatusBar {
mDateView.setVisibility(View.INVISIBLE);
// Recents Panel
- initializeRecentsPanel();
+ updateRecentsPanel();
// receive broadcasts
IntentFilter filter = new IntentFilter();
@@ -338,7 +338,7 @@ public class PhoneStatusBar extends StatusBar {
return lp;
}
- protected void initializeRecentsPanel() {
+ protected void updateRecentsPanel() {
// Recents Panel
boolean visible = false;
if (mRecentsPanel != null) {
@@ -385,9 +385,9 @@ public class PhoneStatusBar extends StatusBar {
// For small-screen devices (read: phones) that lack hardware navigation buttons
private void addNavigationBar() {
if (mNavigationBarView == null) return;
-
+
mNavigationBarView.reorient();
-
+
mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
WindowManagerImpl.getDefault().addView(
@@ -396,7 +396,7 @@ public class PhoneStatusBar extends StatusBar {
private void repositionNavigationBar() {
if (mNavigationBarView == null) return;
-
+
mNavigationBarView.reorient();
mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
@@ -656,7 +656,7 @@ public class PhoneStatusBar extends StatusBar {
@Override
protected void onConfigurationChanged(Configuration newConfig) {
- initializeRecentsPanel();
+ updateRecentsPanel();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 826ac92..dedbe5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -785,7 +785,7 @@ public class PhoneStatusBarPolicy {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
mBluetoothEnabled = state == BluetoothAdapter.STATE_ON;
} else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
- int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
+ int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
BluetoothAdapter.STATE_DISCONNECTED);
if (state == BluetoothAdapter.STATE_CONNECTED) {
iconId = R.drawable.stat_sys_data_bluetooth_connected;
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index f862d01..75e799c 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -29,7 +29,9 @@ import android.os.CountDownTimer;
import android.os.SystemClock;
import android.security.KeyStore;
import android.telephony.TelephonyManager;
+import android.text.Editable;
import android.text.InputType;
+import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import android.text.method.TextKeyListener;
import android.util.Log;
@@ -120,15 +122,6 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
}
});
- // We don't currently use the IME for PIN mode, but this will make it work if we ever do...
- if (!mIsAlpha) {
- mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
- | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
- } else {
- mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
- | InputType.TYPE_TEXT_VARIATION_PASSWORD);
- }
-
mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
mEmergencyCallButton.setOnClickListener(this);
mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
@@ -151,14 +144,17 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
mPasswordEntry.requestFocus();
- // This allows keyboards with overlapping qwerty/numeric keys to choose just the
- // numeric keys.
+ // This allows keyboards with overlapping qwerty/numeric keys to choose just numeric keys.
if (mIsAlpha) {
mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
+ mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
+ | InputType.TYPE_TEXT_VARIATION_PASSWORD);
// mStatusView.setHelpMessage(R.string.keyguard_password_enter_password_code,
// StatusView.LOCK_ICON);
} else {
mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
+ mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
+ | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
//mStatusView.setHelpMessage(R.string.keyguard_password_enter_pin_code,
// StatusView.LOCK_ICON);
}
@@ -179,6 +175,19 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
//mUpdateMonitor.registerSimStateCallback(this);
resetStatusInfo();
+
+ // Poke the wakelock any time the text is modified
+ mPasswordEntry.addTextChangedListener(new TextWatcher() {
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ public void afterTextChanged(Editable s) {
+ mCallback.pokeWakelock();
+ }
+ });
}
@Override
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 7f6327d..dff0556 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -1555,9 +1555,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// We restore the panel if it was last open; we skip it if it
// now is open, to avoid a race condition if the user immediately
// opens it when we are resuming.
- if ((st != null) && !st.isOpen && st.wasLastOpen) {
- st.isInExpandedMode = st.wasLastExpanded;
- openPanel(st, null);
+ if (st != null) {
+ st.applyFrozenState();
+ if (!st.isOpen && st.wasLastOpen) {
+ st.isInExpandedMode = st.wasLastExpanded;
+ openPanel(st, null);
+ }
}
}
}
@@ -2235,6 +2238,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
mActionModePopup = null;
}
+
+ PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+ if (st != null && st.menu != null) {
+ st.menu.close();
+ }
}
@Override
@@ -3046,46 +3054,33 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
getIconMenuView(cb); // Need this initialized to know where our offset goes
- boolean init = false;
if (expandedMenuPresenter == null) {
expandedMenuPresenter = new ListMenuPresenter(
com.android.internal.R.layout.list_menu_item_layout,
com.android.internal.R.style.Theme_ExpandedMenu);
expandedMenuPresenter.setCallback(cb);
+ expandedMenuPresenter.setId(com.android.internal.R.id.list_menu_presenter);
menu.addMenuPresenter(expandedMenuPresenter);
- init = true;
}
expandedMenuPresenter.setItemIndexOffset(iconMenuPresenter.getNumActualItemsShown());
MenuView result = expandedMenuPresenter.getMenuView(decorView);
- if (init && frozenMenuState != null) {
- expandedMenuPresenter.restoreHierarchyState(frozenMenuState);
- // Once we initialize the expanded menu we're done with the frozen state
- // since we will have also restored any icon menu state.
- frozenMenuState = null;
- }
-
return result;
}
MenuView getIconMenuView(MenuPresenter.Callback cb) {
if (menu == null) return null;
- boolean init = false;
if (iconMenuPresenter == null) {
iconMenuPresenter = new IconMenuPresenter();
iconMenuPresenter.setCallback(cb);
+ iconMenuPresenter.setId(com.android.internal.R.id.icon_menu_presenter);
menu.addMenuPresenter(iconMenuPresenter);
- init = true;
}
MenuView result = iconMenuPresenter.getMenuView(decorView);
- if (init && frozenMenuState != null) {
- iconMenuPresenter.restoreHierarchyState(frozenMenuState);
- }
-
return result;
}
@@ -3097,12 +3092,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (menu != null) {
savedState.menuState = new Bundle();
- if (iconMenuPresenter != null) {
- iconMenuPresenter.saveHierarchyState(savedState.menuState);
- }
- if (expandedMenuPresenter != null) {
- expandedMenuPresenter.saveHierarchyState(savedState.menuState);
- }
+ menu.savePresenterStates(savedState.menuState);
}
return savedState;
@@ -3127,6 +3117,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
decorView = null;
}
+ void applyFrozenState() {
+ if (menu != null && frozenMenuState != null) {
+ menu.restorePresenterStates(frozenMenuState);
+ frozenMenuState = null;
+ }
+ }
+
private static class SavedState implements Parcelable {
int featureId;
boolean isOpen;
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 75d24a1..6bb1f56 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -20,23 +20,12 @@ LOCAL_SHARED_LIBRARIES := \
libmedia \
libhardware \
libhardware_legacy \
- libeffects
+ libeffects \
+ libdl
LOCAL_STATIC_LIBRARIES := \
libmedia_helper
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -ldl
-else
- LOCAL_SHARED_LIBRARIES += libdl
-endif
-
LOCAL_MODULE:= libaudioflinger
-ifeq ($(TARGET_SIMULATOR),true)
- ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt -lpthread
- endif
-endif
-
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp
index 1d247bd..4d721f6 100644
--- a/services/audioflinger/AudioResamplerCubic.cpp
+++ b/services/audioflinger/AudioResamplerCubic.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "AudioSRC"
+
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
@@ -22,8 +24,6 @@
#include "AudioResampler.h"
#include "AudioResamplerCubic.h"
-#define LOG_TAG "AudioSRC"
-
namespace android {
// ----------------------------------------------------------------------------
diff --git a/services/camera/libcameraservice/CameraHardwareStub.h b/services/camera/libcameraservice/CameraHardwareStub.h
index 9b66a76..c6d8756 100644
--- a/services/camera/libcameraservice/CameraHardwareStub.h
+++ b/services/camera/libcameraservice/CameraHardwareStub.h
@@ -73,14 +73,7 @@ private:
CameraHardwareStub* mHardware;
public:
PreviewThread(CameraHardwareStub* hw) :
-#ifdef SINGLE_PROCESS
- // In single process mode this thread needs to be a java thread,
- // since we won't be calling through the binder.
- Thread(true),
-#else
- Thread(false),
-#endif
- mHardware(hw) { }
+ Thread(false), mHardware(hw) { }
virtual void onFirstRef() {
run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
}
diff --git a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
index f86ca47..e390ae2 100644
--- a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
+++ b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
@@ -29,7 +29,6 @@
#include <camera/ICamera.h>
#include <camera/ICameraClient.h>
#include <camera/ICameraService.h>
-#include <ui/Overlay.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
@@ -311,8 +310,6 @@ public:
virtual status_t registerBuffers(const BufferHeap& buffers);
virtual void postBuffer(ssize_t offset);
virtual void unregisterBuffers();
- virtual sp<OverlayRef> createOverlay(
- uint32_t w, uint32_t h, int32_t format, int32_t orientation);
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage);
virtual status_t setBufferCount(int bufferCount);
@@ -381,13 +378,6 @@ void MSurface::waitUntil(int c0, int c1, int c2) {
}
}
-sp<OverlayRef> MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format,
- int32_t orientation) {
- // Not implemented.
- ASSERT(0);
- return NULL;
-}
-
//
// Utilities to use the Holder service
//
diff --git a/services/input/Android.mk b/services/input/Android.mk
index 836c081..e36507a 100644
--- a/services/input/Android.mk
+++ b/services/input/Android.mk
@@ -41,10 +41,6 @@ LOCAL_MODULE:= libinput
LOCAL_MODULE_TAGS := optional
-ifeq ($(TARGET_SIMULATOR),true)
- LOCAL_LDLIBS += -lpthread
-endif
-
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/input/tests/Android.mk b/services/input/tests/Android.mk
index cabbccb..d92fc74 100644
--- a/services/input/tests/Android.mk
+++ b/services/input/tests/Android.mk
@@ -2,8 +2,6 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-ifneq ($(TARGET_SIMULATOR),true)
-
# Build the unit tests.
test_src_files := \
InputReader_test.cpp \
@@ -45,5 +43,3 @@ $(foreach file,$(test_src_files), \
# Build the manual test programs.
include $(call all-subdir-makefiles)
-
-endif \ No newline at end of file
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 158c778..0b15221 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -1072,7 +1072,7 @@ class AppWidgetService extends IAppWidgetService.Stub
throw new IllegalArgumentException("packageName and uid don't match packageName="
+ packageName);
}
- if (callingUid != packageUid && Process.supportsProcesses()) {
+ if (callingUid != packageUid) {
throw new IllegalArgumentException("packageName and uid don't match packageName="
+ packageName);
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 786f2fa..168b894 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -76,6 +76,7 @@ import com.android.internal.backup.IBackupTransport;
import com.android.internal.backup.LocalTransport;
import com.android.server.PackageManagerBackupAgent.Metadata;
+import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileDescriptor;
@@ -96,6 +97,10 @@ import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
class BackupManagerService extends IBackupManager.Stub {
private static final String TAG = "BackupManagerService";
@@ -1679,6 +1684,7 @@ class BackupManagerService extends IBackupManager.Stub {
class PerformFullBackupTask implements Runnable {
ParcelFileDescriptor mOutputFile;
+ DeflaterOutputStream mDeflater;
IFullBackupRestoreObserver mObserver;
boolean mIncludeApks;
boolean mIncludeShared;
@@ -1688,6 +1694,55 @@ class BackupManagerService extends IBackupManager.Stub {
File mFilesDir;
File mManifestFile;
+ class FullBackupRunner implements Runnable {
+ PackageInfo mPackage;
+ IBackupAgent mAgent;
+ ParcelFileDescriptor mPipe;
+ int mToken;
+ boolean mSendApk;
+
+ FullBackupRunner(PackageInfo pack, IBackupAgent agent, ParcelFileDescriptor pipe,
+ int token, boolean sendApk) throws IOException {
+ mPackage = pack;
+ mAgent = agent;
+ mPipe = ParcelFileDescriptor.dup(pipe.getFileDescriptor());
+ mToken = token;
+ mSendApk = sendApk;
+ }
+
+ @Override
+ public void run() {
+ try {
+ BackupDataOutput output = new BackupDataOutput(
+ mPipe.getFileDescriptor());
+
+ if (DEBUG) Slog.d(TAG, "Writing manifest for " + mPackage.packageName);
+ writeAppManifest(mPackage, mManifestFile, mSendApk);
+ FullBackup.backupToTar(mPackage.packageName, null, null,
+ mFilesDir.getAbsolutePath(),
+ mManifestFile.getAbsolutePath(),
+ output);
+
+ if (mSendApk) {
+ writeApkToBackup(mPackage, output);
+ }
+
+ if (DEBUG) Slog.d(TAG, "Calling doFullBackup()");
+ prepareOperationTimeout(mToken, TIMEOUT_FULL_BACKUP_INTERVAL);
+ mAgent.doFullBackup(mPipe, mToken, mBackupManagerBinder);
+ } catch (IOException e) {
+ Slog.e(TAG, "Error running full backup for " + mPackage.packageName);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote agent vanished during full backup of "
+ + mPackage.packageName);
+ } finally {
+ try {
+ mPipe.close();
+ } catch (IOException e) {}
+ }
+ }
+ }
+
PerformFullBackupTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer,
boolean includeApks, boolean includeShared,
boolean doAllApps, String[] packages, AtomicBoolean latch) {
@@ -1736,13 +1791,21 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
+ // Set up the compression stage
+ FileOutputStream ofstream = new FileOutputStream(mOutputFile.getFileDescriptor());
+ Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
+ DeflaterOutputStream out = new DeflaterOutputStream(ofstream, deflater, true);
+
+ // !!! TODO: if using encryption, set up the encryption stage
+ // and emit the tar header stating the password salt.
+
PackageInfo pkg = null;
try {
// Now back up the app data via the agent mechanism
int N = packagesToBackup.size();
for (int i = 0; i < N; i++) {
pkg = packagesToBackup.get(i);
- backupOnePackage(pkg);
+ backupOnePackage(pkg, out);
}
// Finally, shared storage if requested
@@ -1754,6 +1817,7 @@ class BackupManagerService extends IBackupManager.Stub {
} finally {
tearDown(pkg);
try {
+ out.close();
mOutputFile.close();
} catch (IOException e) {
/* nothing we can do about this */
@@ -1771,13 +1835,17 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
- private void backupOnePackage(PackageInfo pkg) throws RemoteException {
+ private void backupOnePackage(PackageInfo pkg, DeflaterOutputStream out)
+ throws RemoteException {
Slog.d(TAG, "Binding to full backup agent : " + pkg.packageName);
IBackupAgent agent = bindToAgentSynchronous(pkg.applicationInfo,
IApplicationThread.BACKUP_MODE_FULL);
if (agent != null) {
+ ParcelFileDescriptor[] pipes = null;
try {
+ pipes = ParcelFileDescriptor.createPipe();
+
ApplicationInfo app = pkg.applicationInfo;
final boolean sendApk = mIncludeApks
&& ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0)
@@ -1786,31 +1854,54 @@ class BackupManagerService extends IBackupManager.Stub {
sendOnBackupPackage(pkg.packageName);
- BackupDataOutput output = new BackupDataOutput(
- mOutputFile.getFileDescriptor());
-
- if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName);
- writeAppManifest(pkg, mManifestFile, sendApk);
- FullBackup.backupToTar(pkg.packageName, null, null,
- mFilesDir.getAbsolutePath(),
- mManifestFile.getAbsolutePath(),
- output);
-
- if (sendApk) {
- writeApkToBackup(pkg, output);
+ final int token = generateToken();
+ FullBackupRunner runner = new FullBackupRunner(pkg, agent, pipes[1],
+ token, sendApk);
+ pipes[1].close(); // the runner has dup'd it
+ pipes[1] = null;
+ Thread t = new Thread(runner);
+ t.start();
+
+ // Now pull data from the app and stuff it into the compressor
+ try {
+ FileInputStream raw = new FileInputStream(pipes[0].getFileDescriptor());
+ DataInputStream in = new DataInputStream(raw);
+
+ byte[] buffer = new byte[16 * 1024];
+ int chunkTotal;
+ while ((chunkTotal = in.readInt()) > 0) {
+ while (chunkTotal > 0) {
+ int toRead = (chunkTotal > buffer.length)
+ ? buffer.length : chunkTotal;
+ int nRead = in.read(buffer, 0, toRead);
+ out.write(buffer, 0, nRead);
+ chunkTotal -= nRead;
+ }
+ }
+ } catch (IOException e) {
+ Slog.i(TAG, "Caught exception reading from agent", e);
}
- if (DEBUG) Slog.d(TAG, "Calling doFullBackup()");
- final int token = generateToken();
- prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL);
- agent.doFullBackup(mOutputFile, token, mBackupManagerBinder);
if (!waitUntilOperationComplete(token)) {
Slog.e(TAG, "Full backup failed on package " + pkg.packageName);
} else {
- if (DEBUG) Slog.d(TAG, "Full backup success: " + pkg.packageName);
+ if (DEBUG) Slog.d(TAG, "Full package backup success: " + pkg.packageName);
}
+
} catch (IOException e) {
Slog.e(TAG, "Error backing up " + pkg.packageName, e);
+ } finally {
+ try {
+ if (pipes != null) {
+ if (pipes[0] != null) pipes[0].close();
+ if (pipes[1] != null) pipes[1].close();
+ }
+
+ // Apply a full sync/flush after each application's data
+ out.flush();
+ } catch (IOException e) {
+ Slog.w(TAG, "Error bringing down backup stack");
+ }
}
} else {
Slog.w(TAG, "Unable to bind to full agent for " + pkg.packageName);
@@ -2084,11 +2175,12 @@ class BackupManagerService extends IBackupManager.Stub {
try {
mBytes = 0;
byte[] buffer = new byte[32 * 1024];
- FileInputStream instream = new FileInputStream(mInputFile.getFileDescriptor());
+ FileInputStream rawInStream = new FileInputStream(mInputFile.getFileDescriptor());
+ InflaterInputStream in = new InflaterInputStream(rawInStream);
boolean didRestore;
do {
- didRestore = restoreOneFile(instream, buffer);
+ didRestore = restoreOneFile(in, buffer);
} while (didRestore);
if (DEBUG) Slog.v(TAG, "Done consuming input tarfile, total bytes=" + mBytes);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index b98d2a2..41450d2 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1602,8 +1602,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (linkProperties != null) {
String iface = linkProperties.getInterfaceName();
if (TextUtils.isEmpty(iface) == false) {
- if (DBG) log("resetConnections(" + iface + ")");
- NetworkUtils.resetConnections(iface);
+ if (DBG) {
+ log("resetConnections(" + iface + ", NetworkUtils.RESET_ALL_ADDRESSES)");
+ }
+ NetworkUtils.resetConnections(iface, NetworkUtils.RESET_ALL_ADDRESSES);
}
}
}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 2d55433..18d393f 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -531,10 +531,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mImeSwitcherNotification.sound = null;
mImeSwitcherNotification.vibrate = null;
Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
- | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- mImeSwitchPendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+ mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
com.android.internal.R.bool.show_ongoing_ime_switcher);
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 54e5432..94465fd 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -1075,18 +1075,22 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
com.android.internal.R.styleable.Storage_mtpReserve, 0);
boolean allowMassStorage = a.getBoolean(
com.android.internal.R.styleable.Storage_allowMassStorage, false);
+ // resource parser does not support longs, so XML value is in megabytes
+ long maxFileSize = a.getInt(
+ com.android.internal.R.styleable.Storage_maxFileSize, 0) * 1024L * 1024L;
Slog.d(TAG, "got storage path: " + path + " description: " + description +
" primary: " + primary + " removable: " + removable +
" emulated: " + emulated + " mtpReserve: " + mtpReserve +
- " allowMassStorage: " + allowMassStorage);
+ " allowMassStorage: " + allowMassStorage +
+ " maxFileSize: " + maxFileSize);
if (path == null || description == null) {
Slog.e(TAG, "path or description is null in readStorageList");
} else {
String pathString = path.toString();
StorageVolume volume = new StorageVolume(pathString,
description.toString(), removable, emulated,
- mtpReserve, allowMassStorage);
+ mtpReserve, allowMassStorage, maxFileSize);
if (primary) {
if (mPrimaryVolume == null) {
mPrimaryVolume = volume;
@@ -2357,6 +2361,19 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
pw.print(" -> "); pw.println(e.getValue().toString());
}
}
+
+ pw.println("");
+
+ synchronized (mVolumes) {
+ pw.println(" mVolumes:");
+
+ final int N = mVolumes.size();
+ for (int i = 0; i < N; i++) {
+ final StorageVolume v = mVolumes.get(i);
+ pw.print(" ");
+ pw.println(v.toString());
+ }
+ }
}
}
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index da1bf83..41e8a31 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -77,11 +77,15 @@ class NetworkManagementService extends INetworkManagementService.Stub {
/** Path to {@code /proc/uid_stat}. */
@Deprecated
- private final File mProcStatsUidstat;
+ private final File mStatsUid;
+ /** Path to {@code /proc/net/dev}. */
+ private final File mStatsIface;
/** Path to {@code /proc/net/xt_qtaguid/stats}. */
- private final File mProcStatsNetfilter;
+ private final File mStatsXtUid;
+ /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */
+ private final File mStatsXtIface;
- /** {@link #mProcStatsNetfilter} headers. */
+ /** {@link #mStatsXtUid} headers. */
private static final String KEY_IFACE = "iface";
private static final String KEY_TAG_HEX = "acct_tag_hex";
private static final String KEY_UID = "uid_tag_int";
@@ -137,8 +141,10 @@ class NetworkManagementService extends INetworkManagementService.Stub {
mContext = context;
mObservers = new ArrayList<INetworkManagementEventObserver>();
- mProcStatsUidstat = new File(procRoot, "uid_stat");
- mProcStatsNetfilter = new File(procRoot, "net/xt_qtaguid/stats");
+ mStatsUid = new File(procRoot, "uid_stat");
+ mStatsIface = new File(procRoot, "net/dev");
+ mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
+ mStatsXtIface = new File(procRoot, "net/xt_qtaguid/iface_stat");
if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
return;
@@ -161,9 +167,12 @@ class NetworkManagementService extends INetworkManagementService.Stub {
}
// @VisibleForTesting
- public static NetworkManagementService createForTest(Context context, File procRoot) {
+ public static NetworkManagementService createForTest(
+ Context context, File procRoot, boolean bandwidthControlEnabled) {
// TODO: eventually connect with mock netd
- return new NetworkManagementService(context, procRoot);
+ final NetworkManagementService service = new NetworkManagementService(context, procRoot);
+ service.mBandwidthControlEnabled = bandwidthControlEnabled;
+ return service;
}
public void systemReady() {
@@ -187,6 +196,9 @@ class NetworkManagementService extends INetworkManagementService.Stub {
} else {
Slog.d(TAG, "not enabling bandwidth control");
}
+
+ SystemProperties.set(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED,
+ mBandwidthControlEnabled ? "1" : "0");
}
public void registerObserver(INetworkManagementEventObserver obs) {
@@ -930,13 +942,68 @@ class NetworkManagementService extends INetworkManagementService.Stub {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
- final String[] ifaces = listInterfaces();
- final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), ifaces.length);
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+
+ final HashSet<String> activeIfaces = Sets.newHashSet();
+ final ArrayList<String> values = Lists.newArrayList();
+
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(mStatsIface));
+
+ // skip first two header lines
+ reader.readLine();
+ reader.readLine();
- for (String iface : ifaces) {
- final long rx = getInterfaceCounter(iface, true);
- final long tx = getInterfaceCounter(iface, false);
- stats.addEntry(iface, UID_ALL, TAG_NONE, rx, tx);
+ // parse remaining lines
+ String line;
+ while ((line = reader.readLine()) != null) {
+ splitLine(line, values);
+
+ try {
+ entry.iface = values.get(0);
+ entry.uid = UID_ALL;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = Long.parseLong(values.get(1));
+ entry.rxPackets = Long.parseLong(values.get(2));
+ entry.txBytes = Long.parseLong(values.get(9));
+ entry.txPackets = Long.parseLong(values.get(10));
+
+ activeIfaces.add(entry.iface);
+ stats.addValues(entry);
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
+ }
+ }
+ } catch (IOException e) {
+ Slog.w(TAG, "problem parsing stats: " + e);
+ } finally {
+ IoUtils.closeQuietly(reader);
+ }
+
+ if (DBG) Slog.d(TAG, "recorded active stats from " + activeIfaces);
+
+ // splice in stats from any disabled ifaces
+ if (mBandwidthControlEnabled) {
+ final HashSet<String> xtIfaces = Sets.newHashSet(fileListWithoutNull(mStatsXtIface));
+ xtIfaces.removeAll(activeIfaces);
+
+ for (String iface : xtIfaces) {
+ final File ifacePath = new File(mStatsXtIface, iface);
+
+ entry.iface = iface;
+ entry.uid = UID_ALL;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
+ entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
+ entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes"));
+ entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets"));
+
+ stats.addValues(entry);
+ }
+
+ if (DBG) Slog.d(TAG, "recorded stale stats from " + xtIfaces);
}
return stats;
@@ -1063,13 +1130,15 @@ class NetworkManagementService extends INetworkManagementService.Stub {
*/
private NetworkStats getNetworkStatsDetailNetfilter(int limitUid) {
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24);
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+
final ArrayList<String> keys = Lists.newArrayList();
final ArrayList<String> values = Lists.newArrayList();
final HashMap<String, String> parsed = Maps.newHashMap();
BufferedReader reader = null;
try {
- reader = new BufferedReader(new FileReader(mProcStatsNetfilter));
+ reader = new BufferedReader(new FileReader(mStatsXtUid));
// parse first line as header
String line = reader.readLine();
@@ -1081,15 +1150,16 @@ class NetworkManagementService extends INetworkManagementService.Stub {
parseLine(keys, values, parsed);
try {
- final String iface = parsed.get(KEY_IFACE);
- final int tag = NetworkManagementSocketTagger.kernelToTag(
+ // TODO: add rxPackets/txPackets once kernel exports
+ entry.iface = parsed.get(KEY_IFACE);
+ entry.tag = NetworkManagementSocketTagger.kernelToTag(
parsed.get(KEY_TAG_HEX));
- final int uid = Integer.parseInt(parsed.get(KEY_UID));
- final long rx = Long.parseLong(parsed.get(KEY_RX));
- final long tx = Long.parseLong(parsed.get(KEY_TX));
+ entry.uid = Integer.parseInt(parsed.get(KEY_UID));
+ entry.rxBytes = Long.parseLong(parsed.get(KEY_RX));
+ entry.txBytes = Long.parseLong(parsed.get(KEY_TX));
- if (limitUid == UID_ALL || limitUid == uid) {
- stats.addEntry(iface, uid, tag, rx, tx);
+ if (limitUid == UID_ALL || limitUid == entry.uid) {
+ stats.addValues(entry);
}
} catch (NumberFormatException e) {
Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
@@ -1114,19 +1184,27 @@ class NetworkManagementService extends INetworkManagementService.Stub {
private NetworkStats getNetworkStatsDetailUidstat(int limitUid) {
final String[] knownUids;
if (limitUid == UID_ALL) {
- knownUids = mProcStatsUidstat.list();
+ knownUids = fileListWithoutNull(mStatsUid);
} else {
knownUids = new String[] { String.valueOf(limitUid) };
}
final NetworkStats stats = new NetworkStats(
SystemClock.elapsedRealtime(), knownUids.length);
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
for (String uid : knownUids) {
final int uidInt = Integer.parseInt(uid);
- final File uidPath = new File(mProcStatsUidstat, uid);
- final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv"));
- final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd"));
- stats.addEntry(IFACE_ALL, uidInt, TAG_NONE, rx, tx);
+ final File uidPath = new File(mStatsUid, uid);
+
+ entry.iface = IFACE_ALL;
+ entry.uid = uidInt;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = readSingleLongFromFile(new File(uidPath, "tcp_rcv"));
+ entry.rxPackets = readSingleLongFromFile(new File(uidPath, "tcp_rcv_pkt"));
+ entry.txBytes = readSingleLongFromFile(new File(uidPath, "tcp_snd"));
+ entry.txPackets = readSingleLongFromFile(new File(uidPath, "tcp_snd_pkt"));
+
+ stats.addValues(entry);
}
return stats;
@@ -1197,7 +1275,7 @@ class NetworkManagementService extends INetworkManagementService.Stub {
private static void splitLine(String line, ArrayList<String> outSplit) {
outSplit.clear();
- final StringTokenizer t = new StringTokenizer(line);
+ final StringTokenizer t = new StringTokenizer(line, " \t\n\r\f:");
while (t.hasMoreTokens()) {
outSplit.add(t.nextToken());
}
@@ -1232,6 +1310,15 @@ class NetworkManagementService extends INetworkManagementService.Stub {
}
}
+ /**
+ * Wrapper for {@link File#list()} that returns empty array instead of
+ * {@code null}.
+ */
+ private static String[] fileListWithoutNull(File file) {
+ final String[] list = file.list();
+ return list != null ? list : new String[0];
+ }
+
public void setDefaultInterfaceForDns(String iface) throws IllegalStateException {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
diff --git a/services/java/com/android/server/NetworkTimeUpdateService.java b/services/java/com/android/server/NetworkTimeUpdateService.java
index 15f22c0..f7fe39e 100644
--- a/services/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/java/com/android/server/NetworkTimeUpdateService.java
@@ -16,8 +16,6 @@
package com.android.server;
-import com.android.internal.telephony.TelephonyIntents;
-
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -28,7 +26,6 @@ import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
-import android.net.SntpClient;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -36,12 +33,10 @@ import android.os.Message;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
-import android.util.Slog;
+import android.util.NtpTrustedTime;
+import android.util.TrustedTime;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Properties;
+import com.android.internal.telephony.TelephonyIntents;
/**
* Monitors the network time and updates the system time if it is out of sync
@@ -68,14 +63,11 @@ public class NetworkTimeUpdateService {
private static final long POLLING_INTERVAL_SHORTER_MS = 60 * 1000L; // 60 seconds
/** Number of times to try again */
private static final int TRY_AGAIN_TIMES_MAX = 3;
- /** How long to wait for the NTP server to respond. */
- private static final int MAX_NTP_FETCH_WAIT_MS = 20 * 1000;
/** If the time difference is greater than this threshold, then update the time. */
private static final int TIME_ERROR_THRESHOLD_MS = 5 * 1000;
private static final String ACTION_POLL =
"com.android.server.NetworkTimeUpdateService.action.POLL";
- private static final String PROPERTIES_FILE = "/etc/gps.conf";
private static int POLL_REQUEST = 0;
private static final long NOT_SET = -1;
@@ -84,14 +76,14 @@ public class NetworkTimeUpdateService {
private long mNitzZoneSetTime = NOT_SET;
private Context mContext;
+ private TrustedTime mTime;
+
// NTP lookup is done on this thread and handler
private Handler mHandler;
private HandlerThread mThread;
private AlarmManager mAlarmManager;
private PendingIntent mPendingPollIntent;
private SettingsObserver mSettingsObserver;
- // Address of the NTP server
- private String mNtpServer;
// The last time that we successfully fetched the NTP time.
private long mLastNtpFetchTime = NOT_SET;
// Keeps track of how many quick attempts were made to fetch NTP time.
@@ -101,6 +93,7 @@ public class NetworkTimeUpdateService {
public NetworkTimeUpdateService(Context context) {
mContext = context;
+ mTime = NtpTrustedTime.getInstance(context);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
Intent pollIntent = new Intent(ACTION_POLL, null);
mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
@@ -108,12 +101,6 @@ public class NetworkTimeUpdateService {
/** Initialize the receivers and initiate the first NTP request */
public void systemReady() {
- mNtpServer = getNtpServerAddress();
- if (mNtpServer == null) {
- Slog.e(TAG, "NTP server address not found, not syncing to NTP time");
- return;
- }
-
registerForTelephonyIntents();
registerForAlarms();
registerForConnectivityIntents();
@@ -128,27 +115,6 @@ public class NetworkTimeUpdateService {
mSettingsObserver.observe(mContext);
}
- private String getNtpServerAddress() {
- String serverAddress = null;
- FileInputStream stream = null;
- try {
- Properties properties = new Properties();
- File file = new File(PROPERTIES_FILE);
- stream = new FileInputStream(file);
- properties.load(stream);
- serverAddress = properties.getProperty("NTP_SERVER", null);
- } catch (IOException e) {
- Slog.e(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
- } finally {
- if (stream != null) {
- try {
- stream.close();
- } catch (Exception e) {}
- }
- }
- return serverAddress;
- }
-
private void registerForTelephonyIntents() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME);
@@ -189,9 +155,15 @@ public class NetworkTimeUpdateService {
if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + POLLING_INTERVAL_MS
|| event == EVENT_AUTO_TIME_CHANGED) {
if (DBG) Log.d(TAG, "Before Ntp fetch");
- long ntp = getNtpTime();
- if (DBG) Log.d(TAG, "Ntp = " + ntp);
- if (ntp > 0) {
+
+ // force refresh NTP cache when outdated
+ if (mTime.getCacheAge() >= POLLING_INTERVAL_MS) {
+ mTime.forceRefresh();
+ }
+
+ // only update when NTP time is fresh
+ if (mTime.getCacheAge() < POLLING_INTERVAL_MS) {
+ final long ntp = mTime.currentTimeMillis();
mTryAgainCounter = 0;
mLastNtpFetchTime = SystemClock.elapsedRealtime();
if (Math.abs(ntp - currentTime) > TIME_ERROR_THRESHOLD_MS) {
@@ -232,15 +204,6 @@ public class NetworkTimeUpdateService {
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
}
- private long getNtpTime() {
- SntpClient client = new SntpClient();
- if (client.requestTime(mNtpServer, MAX_NTP_FETCH_WAIT_MS)) {
- return client.getNtpTime();
- } else {
- return 0;
- }
- }
-
/**
* Checks if the user prefers to automatically set the time.
*/
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index d81dfdb..b8890aa 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -16,9 +16,6 @@
package com.android.server;
-import com.android.internal.R;
-import com.android.internal.telephony.TelephonyProperties;
-
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -54,6 +51,9 @@ import android.util.NtpTrustedTime;
import android.util.Slog;
import android.util.TrustedTime;
+import com.android.internal.R;
+import com.android.internal.telephony.TelephonyProperties;
+
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileDescriptor;
@@ -63,7 +63,6 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.GregorianCalendar;
-import java.util.Properties;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@@ -87,7 +86,6 @@ public class ThrottleService extends IThrottleManager.Stub {
private static final long TESTING_THRESHOLD = 1 * 1024 * 1024;
private static final long MAX_NTP_CACHE_AGE = 24 * 60 * 60 * 1000;
- private static final long MAX_NTP_FETCH_WAIT = 20 * 1000;
private long mMaxNtpCacheAge = MAX_NTP_CACHE_AGE;
@@ -127,8 +125,6 @@ public class ThrottleService extends IThrottleManager.Stub {
private static final int THROTTLE_INDEX_UNINITIALIZED = -1;
private static final int THROTTLE_INDEX_UNTHROTTLED = 0;
- private static final String PROPERTIES_FILE = "/etc/gps.conf";
-
private Intent mPollStickyBroadcast;
private TrustedTime mTime;
@@ -139,8 +135,7 @@ public class ThrottleService extends IThrottleManager.Stub {
}
public ThrottleService(Context context) {
- // TODO: move to using cached NtpTrustedTime
- this(context, getNetworkManagementService(), new NtpTrustedTime(),
+ this(context, getNetworkManagementService(), NtpTrustedTime.getInstance(context),
context.getResources().getString(R.string.config_datause_iface));
}
@@ -341,26 +336,6 @@ public class ThrottleService extends IThrottleManager.Stub {
}
}, new IntentFilter(ACTION_RESET));
- FileInputStream stream = null;
- try {
- Properties properties = new Properties();
- File file = new File(PROPERTIES_FILE);
- stream = new FileInputStream(file);
- properties.load(stream);
- final String ntpServer = properties.getProperty("NTP_SERVER", null);
- if (mTime instanceof NtpTrustedTime) {
- ((NtpTrustedTime) mTime).setNtpServer(ntpServer, MAX_NTP_FETCH_WAIT);
- }
- } catch (IOException e) {
- Slog.e(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
- } finally {
- if (stream != null) {
- try {
- stream.close();
- } catch (Exception e) {}
- }
- }
-
// use a new thread as we don't want to stall the system for file writes
mThread = new HandlerThread(TAG);
mThread.start();
@@ -540,8 +515,9 @@ public class ThrottleService extends IThrottleManager.Stub {
mIface, NetworkStats.UID_ALL, NetworkStats.TAG_NONE);
if (index != -1) {
- incRead = stats.rx[index] - mLastRead;
- incWrite = stats.tx[index] - mLastWrite;
+ final NetworkStats.Entry entry = stats.getValues(index, null);
+ incRead = entry.rxBytes - mLastRead;
+ incWrite = entry.txBytes - mLastWrite;
} else {
// missing iface, assume stats are 0
Slog.w(TAG, "unable to find stats for iface " + mIface);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 29cccb6..8501163 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -208,6 +208,12 @@ public final class ActivityManagerService extends ActivityManagerNative
// before we decide it's never going to come up for real.
static final int PROC_START_TIMEOUT = 10*1000;
+ // How long we wait for a launched process to attach to the activity manager
+ // before we decide it's never going to come up for real, when the process was
+ // started with a wrapper for instrumentation (such as Valgrind) because it
+ // could take much longer than usual.
+ static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000;
+
// How long to wait after going idle before forcing apps to GC.
static final int GC_TIMEOUT = 5*1000;
@@ -502,15 +508,6 @@ public final class ActivityManagerService extends ActivityManagerNative
= new ArrayList<ProcessRecord>();
/**
- * List of records for processes that we have started and are waiting
- * for them to call back. This is really only needed when running in
- * single processes mode, in which case we do not have a unique pid for
- * each process.
- */
- final ArrayList<ProcessRecord> mStartingProcesses
- = new ArrayList<ProcessRecord>();
-
- /**
* List of persistent applications that are in the process
* of being started.
*/
@@ -1959,8 +1956,13 @@ public final class ActivityManagerService extends ActivityManagerNative
if ("1".equals(SystemProperties.get("debug.assert"))) {
debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
}
- int pid = Process.start("android.app.ActivityThread",
- app.processName, uid, uid, gids, debugFlags, null);
+
+ // Start the process. It will either succeed and return a result containing
+ // the PID of the new process, or else throw a RuntimeException.
+ Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
+ app.processName, uid, uid, gids, debugFlags,
+ app.info.targetSdkVersion, null);
+
BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
synchronized (bs) {
if (bs.isOnBattery()) {
@@ -1968,12 +1970,12 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
+ EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,
app.processName, hostingType,
hostingNameStr != null ? hostingNameStr : "");
if (app.persistent) {
- Watchdog.getInstance().processStarted(app.processName, pid);
+ Watchdog.getInstance().processStarted(app.processName, startResult.pid);
}
StringBuilder buf = mStringBuilder;
@@ -1987,7 +1989,7 @@ public final class ActivityManagerService extends ActivityManagerNative
buf.append(hostingNameStr);
}
buf.append(": pid=");
- buf.append(pid);
+ buf.append(startResult.pid);
buf.append(" uid=");
buf.append(uid);
buf.append(" gids={");
@@ -2000,26 +2002,15 @@ public final class ActivityManagerService extends ActivityManagerNative
}
buf.append("}");
Slog.i(TAG, buf.toString());
- if (pid == 0 || pid == MY_PID) {
- // Processes are being emulated with threads.
- app.pid = MY_PID;
- app.removed = false;
- mStartingProcesses.add(app);
- } else if (pid > 0) {
- app.pid = pid;
- app.removed = false;
- synchronized (mPidsSelfLocked) {
- this.mPidsSelfLocked.put(pid, app);
- Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
- msg.obj = app;
- mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
- }
- } else {
- app.pid = 0;
- RuntimeException e = new RuntimeException(
- "Failure starting process " + app.processName
- + ": returned pid=" + pid);
- Slog.e(TAG, e.getMessage(), e);
+ app.pid = startResult.pid;
+ app.usingWrapper = startResult.usingWrapper;
+ app.removed = false;
+ synchronized (mPidsSelfLocked) {
+ this.mPidsSelfLocked.put(startResult.pid, app);
+ Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
+ msg.obj = app;
+ mHandler.sendMessageDelayed(msg, startResult.usingWrapper
+ ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
} catch (RuntimeException e) {
// XXX do better error recovery.
@@ -3605,9 +3596,6 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
- } else if (mStartingProcesses.size() > 0) {
- app = mStartingProcesses.remove(0);
- app.setPid(pid);
} else {
app = null;
}
@@ -4041,8 +4029,7 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized(this) {
int callingUid = Binder.getCallingUid();
try {
- if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
- Process.supportsProcesses()) {
+ if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
int uid = AppGlobals.getPackageManager()
.getPackageUid(packageName);
if (uid != Binder.getCallingUid()) {
@@ -4301,8 +4288,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
// Root, system server and our own process get to do everything.
- if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
- !Process.supportsProcesses()) {
+ if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
return PackageManager.PERMISSION_GRANTED;
}
// If there is a uid that owns whatever is being accessed, it has
@@ -4446,7 +4432,7 @@ public final class ActivityManagerService extends ActivityManagerNative
private final boolean checkUriPermissionLocked(Uri uri, int uid,
int modeFlags) {
// Root gets to do everything.
- if (uid == 0 || !Process.supportsProcesses()) {
+ if (uid == 0) {
return true;
}
HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
@@ -5527,8 +5513,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// CONTENT PROVIDERS
// =========================================================
- private final List generateApplicationProvidersLocked(ProcessRecord app) {
- List providers = null;
+ private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
+ List<ProviderInfo> providers = null;
try {
providers = AppGlobals.getPackageManager().
queryContentProviders(app.processName, app.info.uid,
@@ -5966,7 +5952,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
public static final void installSystemProviders() {
- List providers;
+ List<ProviderInfo> providers;
synchronized (mSelf) {
ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
providers = mSelf.generateApplicationProvidersLocked(app);
@@ -6584,13 +6570,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
public void systemReady(final Runnable goingCallback) {
- // In the simulator, startRunning will never have been called, which
- // normally sets a few crucial variables. Do it here instead.
- if (!Process.supportsProcesses()) {
- mStartRunning = true;
- mTopAction = Intent.ACTION_MAIN;
- }
-
synchronized(this) {
if (mSystemReady) {
if (goingCallback != null) goingCallback.run();
@@ -7954,14 +7933,6 @@ public final class ActivityManagerService extends ActivityManagerNative
"Starting Norm", "Restarting PERS");
}
- if (mStartingProcesses.size() > 0) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" Processes that are starting:");
- dumpProcessList(pw, this, mStartingProcesses, " ",
- "Starting Norm", "Starting PERS");
- }
-
if (mRemovedProcesses.size() > 0) {
if (needSep) pw.println(" ");
needSep = true;
@@ -13127,74 +13098,72 @@ public final class ActivityManagerService extends ActivityManagerNative
int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
- if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
- if (app.curRawAdj != app.setRawAdj) {
- if (app.curRawAdj > FOREGROUND_APP_ADJ
- && app.setRawAdj <= FOREGROUND_APP_ADJ) {
- // If this app is transitioning from foreground to
- // non-foreground, have it do a gc.
- scheduleAppGcLocked(app);
- } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
- && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
- // Likewise do a gc when an app is moving in to the
- // background (such as a service stopping).
- scheduleAppGcLocked(app);
- }
-
- if (wasKeeping && !app.keeping) {
- // This app is no longer something we want to keep. Note
- // its current wake lock time to later know to kill it if
- // it is not behaving well.
- BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
- synchronized (stats) {
- app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
- app.pid, SystemClock.elapsedRealtime());
- }
- app.lastCpuTime = app.curCpuTime;
+ if (app.curRawAdj != app.setRawAdj) {
+ if (app.curRawAdj > FOREGROUND_APP_ADJ
+ && app.setRawAdj <= FOREGROUND_APP_ADJ) {
+ // If this app is transitioning from foreground to
+ // non-foreground, have it do a gc.
+ scheduleAppGcLocked(app);
+ } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
+ && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
+ // Likewise do a gc when an app is moving in to the
+ // background (such as a service stopping).
+ scheduleAppGcLocked(app);
+ }
+
+ if (wasKeeping && !app.keeping) {
+ // This app is no longer something we want to keep. Note
+ // its current wake lock time to later know to kill it if
+ // it is not behaving well.
+ BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+ synchronized (stats) {
+ app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
+ app.pid, SystemClock.elapsedRealtime());
}
+ app.lastCpuTime = app.curCpuTime;
+ }
- app.setRawAdj = app.curRawAdj;
+ app.setRawAdj = app.curRawAdj;
+ }
+ if (adj != app.setAdj) {
+ if (Process.setOomAdj(app.pid, adj)) {
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
+ TAG, "Set app " + app.processName +
+ " oom adj to " + adj);
+ app.setAdj = adj;
+ } else {
+ success = false;
}
- if (adj != app.setAdj) {
- if (Process.setOomAdj(app.pid, adj)) {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
- TAG, "Set app " + app.processName +
- " oom adj to " + adj);
- app.setAdj = adj;
- } else {
- success = false;
+ }
+ if (app.setSchedGroup != app.curSchedGroup) {
+ app.setSchedGroup = app.curSchedGroup;
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
+ "Setting process group of " + app.processName
+ + " to " + app.curSchedGroup);
+ if (app.waitingToKill != null &&
+ app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
+ Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
+ EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+ app.processName, app.setAdj, app.waitingToKill);
+ Process.killProcessQuiet(app.pid);
+ } else {
+ if (true) {
+ long oldId = Binder.clearCallingIdentity();
+ try {
+ Process.setProcessGroup(app.pid, app.curSchedGroup);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed setting process group of " + app.pid
+ + " to " + app.curSchedGroup);
+ e.printStackTrace();
+ } finally {
+ Binder.restoreCallingIdentity(oldId);
+ }
}
- }
- if (app.setSchedGroup != app.curSchedGroup) {
- app.setSchedGroup = app.curSchedGroup;
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
- "Setting process group of " + app.processName
- + " to " + app.curSchedGroup);
- if (app.waitingToKill != null &&
- app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
- Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
- EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
- app.processName, app.setAdj, app.waitingToKill);
- Process.killProcessQuiet(app.pid);
- } else {
- if (true) {
- long oldId = Binder.clearCallingIdentity();
+ if (false) {
+ if (app.thread != null) {
try {
- Process.setProcessGroup(app.pid, app.curSchedGroup);
- } catch (Exception e) {
- Slog.w(TAG, "Failed setting process group of " + app.pid
- + " to " + app.curSchedGroup);
- e.printStackTrace();
- } finally {
- Binder.restoreCallingIdentity(oldId);
- }
- }
- if (false) {
- if (app.thread != null) {
- try {
- app.thread.setSchedulingGroup(app.curSchedGroup);
- } catch (RemoteException e) {
- }
+ app.thread.setSchedulingGroup(app.curSchedGroup);
+ } catch (RemoteException e) {
}
}
}
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 090e26b..73ffafb 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -658,12 +658,12 @@ final class ActivityRecord extends IApplicationToken.Stub {
public long getKeyDispatchingTimeout() {
synchronized(service) {
ActivityRecord r = getWaitingHistoryRecordLocked();
- if (r == null || r.app == null
- || r.app.instrumentationClass == null) {
- return ActivityManagerService.KEY_DISPATCHING_TIMEOUT;
+ if (r != null && r.app != null
+ && (r.app.instrumentationClass != null || r.app.usingWrapper)) {
+ return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT;
}
-
- return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT;
+
+ return ActivityManagerService.KEY_DISPATCHING_TIMEOUT;
}
}
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 3968f66..da83e7d 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -78,6 +78,7 @@ class ProcessRecord {
IInstrumentationWatcher instrumentationWatcher; // who is waiting
Bundle instrumentationArguments;// as given to us
ComponentName instrumentationResultClass;// copy of instrumentationClass
+ boolean usingWrapper; // Set to true when process was launched with a wrapper attached
BroadcastRecord curReceiver;// receiver currently running in the app
long lastWakeTime; // How long proc held wake lock at last check
long lastCpuTime; // How long proc has run CPU at last check
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
index 6e8f248..12c8ccf 100644
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -63,7 +63,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
private static final String TAG = "UsageStats";
// Current on-disk Parcel version
- private static final int VERSION = 1005;
+ private static final int VERSION = 1006;
private static final int CHECKIN_VERSION = 4;
@@ -145,6 +145,8 @@ public final class UsageStatsService extends IUsageStats.Stub {
final HashMap<String, TimeStats> mLaunchTimes
= new HashMap<String, TimeStats>();
int mLaunchCount;
+ final HashMap<String, Long> mLastResumeTimes
+ = new HashMap<String, Long>();
long mUsageTime;
long mPausedTime;
long mResumedTime;
@@ -160,20 +162,28 @@ public final class UsageStatsService extends IUsageStats.Stub {
if (localLOGV) Slog.v(TAG, "Launch count: " + mLaunchCount
+ ", Usage time:" + mUsageTime);
- final int N = in.readInt();
- if (localLOGV) Slog.v(TAG, "Reading comps: " + N);
- for (int i=0; i<N; i++) {
+ final int numTimeStats = in.readInt();
+ if (localLOGV) Slog.v(TAG, "Reading comps: " + numTimeStats);
+ for (int i=0; i<numTimeStats; i++) {
String comp = in.readString();
if (localLOGV) Slog.v(TAG, "Component: " + comp);
TimeStats times = new TimeStats(in);
mLaunchTimes.put(comp, times);
}
+ final int numResumeTimes = in.readInt();
+ if (localLOGV) Slog.v(TAG, "Reading last resume times: " + numResumeTimes);
+ for (int i=0; i<numResumeTimes; i++) {
+ String comp = in.readString();
+ if (localLOGV) Slog.v(TAG, "Component: " + comp);
+ mLastResumeTimes.put(comp, in.readLong());
+ }
}
-
- void updateResume(boolean launched) {
+
+ void updateResume(String comp, boolean launched) {
if (launched) {
mLaunchCount ++;
}
+ mLastResumeTimes.put(comp, System.currentTimeMillis());
mResumedTime = SystemClock.elapsedRealtime();
}
@@ -203,20 +213,29 @@ public final class UsageStatsService extends IUsageStats.Stub {
void writeToParcel(Parcel out) {
out.writeInt(mLaunchCount);
out.writeLong(mUsageTime);
- final int N = mLaunchTimes.size();
- out.writeInt(N);
- if (N > 0) {
+ final int numTimeStats = mLaunchTimes.size();
+ out.writeInt(numTimeStats);
+ if (numTimeStats > 0) {
for (Map.Entry<String, TimeStats> ent : mLaunchTimes.entrySet()) {
out.writeString(ent.getKey());
TimeStats times = ent.getValue();
times.writeToParcel(out);
}
}
+ final int numResumeTimes = mLastResumeTimes.size();
+ out.writeInt(numResumeTimes);
+ if (numResumeTimes > 0) {
+ for (Map.Entry<String, Long> ent : mLastResumeTimes.entrySet()) {
+ out.writeString(ent.getKey());
+ out.writeLong(ent.getValue());
+ }
+ }
}
void clear() {
mLaunchTimes.clear();
mLaunchCount = 0;
+ mLastResumeTimes.clear();
mUsageTime = 0;
}
}
@@ -546,7 +565,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
pus = new PkgUsageStatsExtended();
mStats.put(pkgName, pus);
}
- pus.updateResume(!samePackage);
+ pus.updateResume(mLastResumedComp, !samePackage);
if (!sameComp) {
pus.addLaunchCount(mLastResumedComp);
}
@@ -624,7 +643,8 @@ public final class UsageStatsService extends IUsageStats.Stub {
if (pus == null) {
return null;
}
- return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime);
+ return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime,
+ pus.mLastResumeTimes);
}
}
@@ -641,7 +661,8 @@ public final class UsageStatsService extends IUsageStats.Stub {
int i = 0;
for (String key: keys) {
PkgUsageStatsExtended pus = mStats.get(key);
- retArr[i] = new PkgUsageStats(key, pus.mLaunchCount, pus.mUsageTime);
+ retArr[i] = new PkgUsageStats(key, pus.mLaunchCount, pus.mUsageTime,
+ pus.mLastResumeTimes);
i++;
}
return retArr;
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 6bb7949..d7d4b03 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -221,8 +221,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
}
public void interfaceLinkStateChanged(String iface, boolean up) {
- if (DEBUG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
- interfaceStatusChanged(iface, up);
}
private boolean isUsb(String iface) {
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 4fa3bda..c813d37 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -32,7 +32,6 @@ import android.location.LocationManager;
import android.location.LocationProvider;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
-import android.net.SntpClient;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -51,6 +50,7 @@ import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
+import android.util.NtpTrustedTime;
import android.util.SparseIntArray;
import com.android.internal.app.IBatteryStats;
@@ -61,7 +61,7 @@ import com.android.internal.telephony.Phone;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.io.StringBufferInputStream;
+import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map.Entry;
@@ -235,13 +235,13 @@ public class GpsLocationProvider implements LocationProviderInterface {
// properties loaded from PROPERTIES_FILE
private Properties mProperties;
- private String mNtpServer;
private String mSuplServerHost;
private int mSuplServerPort;
private String mC2KServerHost;
private int mC2KServerPort;
private final Context mContext;
+ private final NtpTrustedTime mNtpTime;
private final ILocationManager mLocationManager;
private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
private Bundle mLocationExtras = new Bundle();
@@ -286,10 +286,6 @@ public class GpsLocationProvider implements LocationProviderInterface {
// current setting - 5 minutes
private static final long RETRY_INTERVAL = 5*60*1000;
- // to avoid injecting bad NTP time, we reject any time fixes that differ from system time
- // by more than 5 minutes.
- private static final long MAX_NTP_SYSTEM_TIME_OFFSET = 5*60*1000;
-
private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
if (listener == null) {
@@ -378,6 +374,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
public GpsLocationProvider(Context context, ILocationManager locationManager) {
mContext = context;
+ mNtpTime = NtpTrustedTime.getInstance(context);
mLocationManager = locationManager;
mNIHandler = new GpsNetInitiatedHandler(context);
@@ -418,7 +415,6 @@ public class GpsLocationProvider implements LocationProviderInterface {
FileInputStream stream = new FileInputStream(file);
mProperties.load(stream);
stream.close();
- mNtpServer = mProperties.getProperty("NTP_SERVER", null);
mSuplServerHost = mProperties.getProperty("SUPL_HOST");
String portString = mProperties.getProperty("SUPL_PORT");
@@ -530,13 +526,18 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
mInjectNtpTimePending = false;
- SntpClient client = new SntpClient();
long delay;
- if (client.requestTime(mNtpServer, 10000)) {
- long time = client.getNtpTime();
- long timeReference = client.getNtpTimeReference();
- int certainty = (int)(client.getRoundTripTime()/2);
+ // force refresh NTP cache when outdated
+ if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
+ mNtpTime.forceRefresh();
+ }
+
+ // only update when NTP time is fresh
+ if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
+ long time = mNtpTime.getCachedNtpTime();
+ long timeReference = mNtpTime.getCachedNtpTimeReference();
+ long certainty = mNtpTime.getCacheCertainty();
long now = System.currentTimeMillis();
Log.d(TAG, "NTP server returned: "
@@ -545,7 +546,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
+ " certainty: " + certainty
+ " system time offset: " + (time - now));
- native_inject_time(time, timeReference, certainty);
+ native_inject_time(time, timeReference, (int) certainty);
delay = NTP_INTERVAL;
} else {
if (DEBUG) Log.d(TAG, "requestTime failed");
@@ -1395,7 +1396,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
Properties extraProp = new Properties();
try {
- extraProp.load(new StringBufferInputStream(extras));
+ extraProp.load(new StringReader(extras));
}
catch (IOException e)
{
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 2a17cbe..d30b66b 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -204,9 +204,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
IPowerManager powerManager, INetworkStatsService networkStats,
INetworkManagementService networkManagement) {
- // TODO: move to using cached NtpTrustedTime
this(context, activityManager, powerManager, networkStats, networkManagement,
- new NtpTrustedTime(), getSystemDir());
+ NtpTrustedTime.getInstance(context), getSystemDir());
}
private static File getSystemDir() {
@@ -406,7 +405,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
try {
final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
policy.template, start, end);
- total = stats.rx[0] + stats.tx[0];
+ final NetworkStats.Entry entry = stats.getValues(0, null);
+ total = entry.rxBytes + entry.txBytes;
} catch (RemoteException e) {
Slog.w(TAG, "problem reading summary for template " + policy.template);
continue;
@@ -606,7 +606,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final long total;
try {
stats = mNetworkStats.getSummaryForNetwork(policy.template, start, end);
- total = stats.rx[0] + stats.tx[0];
+ final NetworkStats.Entry entry = stats.getValues(0, null);
+ total = entry.rxBytes + entry.txBytes;
} catch (RemoteException e) {
Slog.w(TAG, "problem reading summary for template " + policy.template);
continue;
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index b4bd176..54e94db 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -27,7 +27,6 @@ import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_REMOVED;
-import static android.provider.Settings.Secure.NETSTATS_ENABLED;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
@@ -71,7 +70,6 @@ import android.util.Slog;
import android.util.TrustedTime;
import com.android.internal.os.AtomicFile;
-import com.android.server.NativeDaemonConnectorException;
import com.google.android.collect.Maps;
import com.google.android.collect.Sets;
@@ -175,9 +173,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
public NetworkStatsService(
Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
- // TODO: move to using cached NtpTrustedTime
- this(context, networkManager, alarmManager, new NtpTrustedTime(), getSystemDir(),
- new DefaultNetworkStatsSettings(context));
+ this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
+ getSystemDir(), new DefaultNetworkStatsSettings(context));
}
private static File getSystemDir() {
@@ -316,22 +313,29 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
synchronized (mStatsLock) {
- long rx = 0;
- long tx = 0;
- long[] networkTotal = new long[2];
+ // use system clock to be externally consistent
+ final long now = System.currentTimeMillis();
+
+ final NetworkStats stats = new NetworkStats(end - start, 1);
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+ NetworkStatsHistory.Entry historyEntry = null;
// combine total from all interfaces that match template
for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
if (templateMatches(template, ident)) {
final NetworkStatsHistory history = mNetworkStats.get(ident);
- networkTotal = history.getTotalData(start, end, networkTotal);
- rx += networkTotal[0];
- tx += networkTotal[1];
+ historyEntry = history.getValues(start, end, now, historyEntry);
+
+ entry.iface = IFACE_ALL;
+ entry.uid = UID_ALL;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = historyEntry.rxBytes;
+ entry.txBytes = historyEntry.txBytes;
+
+ stats.combineValues(entry);
}
}
- final NetworkStats stats = new NetworkStats(end - start, 1);
- stats.addEntry(IFACE_ALL, UID_ALL, TAG_NONE, rx, tx);
return stats;
}
}
@@ -344,8 +348,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
synchronized (mStatsLock) {
ensureUidStatsLoadedLocked();
+ // use system clock to be externally consistent
+ final long now = System.currentTimeMillis();
+
final NetworkStats stats = new NetworkStats(end - start, 24);
- long[] total = new long[2];
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+ NetworkStatsHistory.Entry historyEntry = null;
for (NetworkIdentitySet ident : mUidStats.keySet()) {
if (templateMatches(template, ident)) {
@@ -359,11 +367,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// other tags when requested.
if (tag == TAG_NONE || includeTags) {
final NetworkStatsHistory history = uidStats.valueAt(i);
- total = history.getTotalData(start, end, total);
- final long rx = total[0];
- final long tx = total[1];
- if (rx > 0 || tx > 0) {
- stats.combineEntry(IFACE_ALL, uid, tag, rx, tx);
+ historyEntry = history.getValues(start, end, now, historyEntry);
+
+ entry.iface = IFACE_ALL;
+ entry.uid = uid;
+ entry.tag = tag;
+ entry.rxBytes = historyEntry.rxBytes;
+ entry.txBytes = historyEntry.txBytes;
+
+ if (entry.rxBytes > 0 || entry.txBytes > 0) {
+ stats.combineValues(entry);
}
}
}
@@ -418,6 +431,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// broadcast.
final int uid = intent.getIntExtra(EXTRA_UID, 0);
synchronized (mStatsLock) {
+ // TODO: perform one last stats poll for UID
removeUidLocked(uid);
}
}
@@ -515,10 +529,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final NetworkStats persistDelta = computeStatsDelta(
mLastPersistNetworkSnapshot, networkSnapshot);
final long persistThreshold = mSettings.getPersistThreshold();
+
+ NetworkStats.Entry entry = null;
for (String iface : persistDelta.getUniqueIfaces()) {
final int index = persistDelta.findIndex(iface, UID_ALL, TAG_NONE);
- if (forcePersist || persistDelta.rx[index] > persistThreshold
- || persistDelta.tx[index] > persistThreshold) {
+ entry = persistDelta.getValues(index, entry);
+ if (forcePersist || entry.rxBytes > persistThreshold
+ || entry.txBytes > persistThreshold) {
writeNetworkStatsLocked();
if (mUidStatsLoaded) {
writeUidStatsLocked();
@@ -541,20 +558,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final HashSet<String> unknownIface = Sets.newHashSet();
final NetworkStats delta = computeStatsDelta(mLastNetworkSnapshot, networkSnapshot);
- final long timeStart = currentTime - delta.elapsedRealtime;
- for (int i = 0; i < delta.size; i++) {
- final String iface = delta.iface[i];
- final NetworkIdentitySet ident = mActiveIfaces.get(iface);
+ final long timeStart = currentTime - delta.getElapsedRealtime();
+
+ NetworkStats.Entry entry = null;
+ for (int i = 0; i < delta.size(); i++) {
+ entry = delta.getValues(i, entry);
+ final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
if (ident == null) {
- unknownIface.add(iface);
+ unknownIface.add(entry.iface);
continue;
}
- final long rx = delta.rx[i];
- final long tx = delta.tx[i];
-
final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident);
- history.recordData(timeStart, currentTime, rx, tx);
+ history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes);
}
// trim any history beyond max
@@ -577,22 +593,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
ensureUidStatsLoadedLocked();
final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot);
- final long timeStart = currentTime - delta.elapsedRealtime;
+ final long timeStart = currentTime - delta.getElapsedRealtime();
- for (int i = 0; i < delta.size; i++) {
- final String iface = delta.iface[i];
- final NetworkIdentitySet ident = mActiveIfaces.get(iface);
+ NetworkStats.Entry entry = null;
+ for (int i = 0; i < delta.size(); i++) {
+ entry = delta.getValues(i, entry);
+ final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
if (ident == null) {
continue;
}
- final int uid = delta.uid[i];
- final int tag = delta.tag[i];
- final long rx = delta.rx[i];
- final long tx = delta.tx[i];
-
- final NetworkStatsHistory history = findOrCreateUidStatsLocked(ident, uid, tag);
- history.recordData(timeStart, currentTime, rx, tx);
+ final NetworkStatsHistory history = findOrCreateUidStatsLocked(
+ ident, entry.uid, entry.tag);
+ history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes);
}
// trim any history beyond max
@@ -654,7 +667,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
NetworkStatsHistory updated = null;
if (existing == null) {
updated = new NetworkStatsHistory(bucketDuration, 10);
- } else if (existing.bucketDuration != bucketDuration) {
+ } else if (existing.getBucketDuration() != bucketDuration) {
updated = new NetworkStatsHistory(
bucketDuration, estimateResizeBuckets(existing, bucketDuration));
updated.recordEntireHistory(existing);
@@ -686,7 +699,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
NetworkStatsHistory updated = null;
if (existing == null) {
updated = new NetworkStatsHistory(bucketDuration, 10);
- } else if (existing.bucketDuration != bucketDuration) {
+ } else if (existing.getBucketDuration() != bucketDuration) {
updated = new NetworkStatsHistory(
bucketDuration, estimateResizeBuckets(existing, bucketDuration));
updated.recordEntireHistory(existing);
@@ -1006,7 +1019,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
private static int estimateResizeBuckets(NetworkStatsHistory existing, long newBucketDuration) {
- return (int) (existing.bucketCount * existing.bucketDuration / newBucketDuration);
+ return (int) (existing.size() * existing.getBucketDuration() / newBucketDuration);
}
// @VisibleForTesting
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index ea5d26b..d6a15e6 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -778,16 +778,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mSeparateProcesses = null;
}
- Installer installer = new Installer();
- // Little hacky thing to check if installd is here, to determine
- // whether we are running on the simulator and thus need to take
- // care of building the /data file structure ourself.
- // (apparently the sim now has a working installer)
- if (installer.ping() && Process.supportsProcesses()) {
- mInstaller = installer;
- } else {
- mInstaller = null;
- }
+ mInstaller = new Installer();
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Display d = wm.getDefaultDisplay();
@@ -806,17 +797,6 @@ public class PackageManagerService extends IPackageManager.Stub {
mUserManager = new UserManager(mInstaller, mUserAppDataDir);
- if (mInstaller == null) {
- // Make sure these dirs exist, when we are running in
- // the simulator.
- // Make a wide-open directory for random misc stuff.
- File miscDir = new File(dataDir, "misc");
- miscDir.mkdirs();
- mAppDataDir.mkdirs();
- mUserAppDataDir.mkdirs();
- mDrmAppPrivateInstallDir.mkdirs();
- }
-
readPermissions();
mRestoredSettings = mSettings.readLPw();
@@ -838,104 +818,102 @@ public class PackageManagerService extends IPackageManager.Stub {
mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
mDalvikCacheDir = new File(dataDir, "dalvik-cache");
- if (mInstaller != null) {
- boolean didDexOpt = false;
-
- /**
- * Out of paranoia, ensure that everything in the boot class
- * path has been dexed.
- */
- String bootClassPath = System.getProperty("java.boot.class.path");
- if (bootClassPath != null) {
- String[] paths = splitString(bootClassPath, ':');
- for (int i=0; i<paths.length; i++) {
- try {
- if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
- libFiles.add(paths[i]);
- mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
- didDexOpt = true;
- }
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "Boot class path not found: " + paths[i]);
- } catch (IOException e) {
- Slog.w(TAG, "Exception reading boot class path: " + paths[i], e);
+ boolean didDexOpt = false;
+
+ /**
+ * Out of paranoia, ensure that everything in the boot class
+ * path has been dexed.
+ */
+ String bootClassPath = System.getProperty("java.boot.class.path");
+ if (bootClassPath != null) {
+ String[] paths = splitString(bootClassPath, ':');
+ for (int i=0; i<paths.length; i++) {
+ try {
+ if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
+ libFiles.add(paths[i]);
+ mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
+ didDexOpt = true;
}
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "Boot class path not found: " + paths[i]);
+ } catch (IOException e) {
+ Slog.w(TAG, "Exception reading boot class path: " + paths[i], e);
}
- } else {
- Slog.w(TAG, "No BOOTCLASSPATH found!");
}
+ } else {
+ Slog.w(TAG, "No BOOTCLASSPATH found!");
+ }
- /**
- * Also ensure all external libraries have had dexopt run on them.
- */
- if (mSharedLibraries.size() > 0) {
- Iterator<String> libs = mSharedLibraries.values().iterator();
- while (libs.hasNext()) {
- String lib = libs.next();
- try {
- if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
- libFiles.add(lib);
- mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
- didDexOpt = true;
- }
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "Library not found: " + lib);
- } catch (IOException e) {
- Slog.w(TAG, "Exception reading library: " + lib, e);
+ /**
+ * Also ensure all external libraries have had dexopt run on them.
+ */
+ if (mSharedLibraries.size() > 0) {
+ Iterator<String> libs = mSharedLibraries.values().iterator();
+ while (libs.hasNext()) {
+ String lib = libs.next();
+ try {
+ if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
+ libFiles.add(lib);
+ mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
+ didDexOpt = true;
}
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "Library not found: " + lib);
+ } catch (IOException e) {
+ Slog.w(TAG, "Exception reading library: " + lib, e);
}
}
+ }
- // Gross hack for now: we know this file doesn't contain any
- // code, so don't dexopt it to avoid the resulting log spew.
- libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
-
- /**
- * And there are a number of commands implemented in Java, which
- * we currently need to do the dexopt on so that they can be
- * run from a non-root shell.
- */
- String[] frameworkFiles = mFrameworkDir.list();
- if (frameworkFiles != null) {
- for (int i=0; i<frameworkFiles.length; i++) {
- File libPath = new File(mFrameworkDir, frameworkFiles[i]);
- String path = libPath.getPath();
- // Skip the file if we alrady did it.
- if (libFiles.contains(path)) {
- continue;
- }
- // Skip the file if it is not a type we want to dexopt.
- if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
- continue;
- }
- try {
- if (dalvik.system.DexFile.isDexOptNeeded(path)) {
- mInstaller.dexopt(path, Process.SYSTEM_UID, true);
- didDexOpt = true;
- }
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "Jar not found: " + path);
- } catch (IOException e) {
- Slog.w(TAG, "Exception reading jar: " + path, e);
+ // Gross hack for now: we know this file doesn't contain any
+ // code, so don't dexopt it to avoid the resulting log spew.
+ libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
+
+ /**
+ * And there are a number of commands implemented in Java, which
+ * we currently need to do the dexopt on so that they can be
+ * run from a non-root shell.
+ */
+ String[] frameworkFiles = mFrameworkDir.list();
+ if (frameworkFiles != null) {
+ for (int i=0; i<frameworkFiles.length; i++) {
+ File libPath = new File(mFrameworkDir, frameworkFiles[i]);
+ String path = libPath.getPath();
+ // Skip the file if we alrady did it.
+ if (libFiles.contains(path)) {
+ continue;
+ }
+ // Skip the file if it is not a type we want to dexopt.
+ if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
+ continue;
+ }
+ try {
+ if (dalvik.system.DexFile.isDexOptNeeded(path)) {
+ mInstaller.dexopt(path, Process.SYSTEM_UID, true);
+ didDexOpt = true;
}
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "Jar not found: " + path);
+ } catch (IOException e) {
+ Slog.w(TAG, "Exception reading jar: " + path, e);
}
}
+ }
- if (didDexOpt) {
- // If we had to do a dexopt of one of the previous
- // things, then something on the system has changed.
- // Consider this significant, and wipe away all other
- // existing dexopt files to ensure we don't leave any
- // dangling around.
- String[] files = mDalvikCacheDir.list();
- if (files != null) {
- for (int i=0; i<files.length; i++) {
- String fn = files[i];
- if (fn.startsWith("data@app@")
- || fn.startsWith("data@app-private@")) {
- Slog.i(TAG, "Pruning dalvik file: " + fn);
- (new File(mDalvikCacheDir, fn)).delete();
- }
+ if (didDexOpt) {
+ // If we had to do a dexopt of one of the previous
+ // things, then something on the system has changed.
+ // Consider this significant, and wipe away all other
+ // existing dexopt files to ensure we don't leave any
+ // dangling around.
+ String[] files = mDalvikCacheDir.list();
+ if (files != null) {
+ for (int i=0; i<files.length; i++) {
+ String fn = files[i];
+ if (fn.startsWith("data@app@")
+ || fn.startsWith("data@app-private@")) {
+ Slog.i(TAG, "Pruning dalvik file: " + fn);
+ (new File(mDalvikCacheDir, fn)).delete();
}
}
}
@@ -965,11 +943,9 @@ public class PackageManagerService extends IPackageManager.Stub {
scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
- if (mInstaller != null) {
- if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
- mInstaller.moveFiles();
- }
-
+ if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
+ mInstaller.moveFiles();
+
// Prune any system packages that no longer exist.
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
@@ -981,19 +957,12 @@ public class PackageManagerService extends IPackageManager.Stub {
String msg = "System package " + ps.name
+ " no longer exists; wiping its data";
reportSettingsProblem(Log.WARN, msg);
- if (mInstaller != null) {
- mInstaller.remove(ps.name, 0);
- mUserManager.removePackageForAllUsers(ps.name);
- }
+ mInstaller.remove(ps.name, 0);
+ mUserManager.removePackageForAllUsers(ps.name);
}
}
mAppInstallDir = new File(dataDir, "app");
- if (mInstaller == null) {
- // Make sure these dirs exist, when we are running in
- // the simulator.
- mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
- }
//look for any incomplete package installations
ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
//clean up list
@@ -1067,19 +1036,12 @@ public class PackageManagerService extends IPackageManager.Stub {
void cleanupInstallFailedPackage(PackageSetting ps) {
Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
- if (mInstaller != null) {
- int retCode = mInstaller.remove(ps.name, 0);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove app data directory for package: "
- + ps.name + ", retcode=" + retCode);
- } else {
- mUserManager.removePackageForAllUsers(ps.name);
- }
+ int retCode = mInstaller.remove(ps.name, 0);
+ if (retCode < 0) {
+ Slog.w(TAG, "Couldn't remove app data directory for package: "
+ + ps.name + ", retcode=" + retCode);
} else {
- //for emulator
- PackageParser.Package pkg = mPackages.get(ps.name);
- File dataDir = new File(pkg.applicationInfo.dataDir);
- dataDir.delete();
+ mUserManager.removePackageForAllUsers(ps.name);
}
if (ps.codePath != null) {
if (!ps.codePath.delete()) {
@@ -1562,12 +1524,10 @@ public class PackageManagerService extends IPackageManager.Stub {
public void run() {
mHandler.removeCallbacks(this);
int retCode = -1;
- if (mInstaller != null) {
- retCode = mInstaller.freeCache(freeStorageSize);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't clear application caches");
- }
- } //end if mInstaller
+ retCode = mInstaller.freeCache(freeStorageSize);
+ if (retCode < 0) {
+ Slog.w(TAG, "Couldn't clear application caches");
+ }
if (observer != null) {
try {
observer.onRemoveCompleted(null, (retCode >= 0));
@@ -1587,11 +1547,9 @@ public class PackageManagerService extends IPackageManager.Stub {
public void run() {
mHandler.removeCallbacks(this);
int retCode = -1;
- if (mInstaller != null) {
- retCode = mInstaller.freeCache(freeStorageSize);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't clear application caches");
- }
+ retCode = mInstaller.freeCache(freeStorageSize);
+ if (retCode < 0) {
+ Slog.w(TAG, "Couldn't clear application caches");
}
if(pi != null) {
try {
@@ -2850,7 +2808,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
boolean performed = false;
- if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
+ if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
String path = pkg.mScanPath;
int ret = 0;
try {
@@ -3235,42 +3193,39 @@ public class PackageManagerService extends IPackageManager.Stub {
mOutPermissions[1] = 0;
FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
- // If we have mismatched owners for the data path, we have a
- // problem (unless we're running in the simulator.)
- if (mOutPermissions[1] != pkg.applicationInfo.uid && Process.supportsProcesses()) {
+ // If we have mismatched owners for the data path, we have a problem.
+ if (mOutPermissions[1] != pkg.applicationInfo.uid) {
boolean recovered = false;
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
// If this is a system app, we can at least delete its
// current data so the application will still work.
- if (mInstaller != null) {
- int ret = mInstaller.remove(pkgName, 0);
- if (ret >= 0) {
- // TODO: Kill the processes first
- // Remove the data directories for all users
- mUserManager.removePackageForAllUsers(pkgName);
- // Old data gone!
- String msg = "System package " + pkg.packageName
- + " has changed from uid: "
- + mOutPermissions[1] + " to "
- + pkg.applicationInfo.uid + "; old data erased";
+ int ret = mInstaller.remove(pkgName, 0);
+ if (ret >= 0) {
+ // TODO: Kill the processes first
+ // Remove the data directories for all users
+ mUserManager.removePackageForAllUsers(pkgName);
+ // Old data gone!
+ String msg = "System package " + pkg.packageName
+ + " has changed from uid: "
+ + mOutPermissions[1] + " to "
+ + pkg.applicationInfo.uid + "; old data erased";
+ reportSettingsProblem(Log.WARN, msg);
+ recovered = true;
+
+ // And now re-install the app.
+ ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
+ pkg.applicationInfo.uid);
+ if (ret == -1) {
+ // Ack should not happen!
+ msg = "System package " + pkg.packageName
+ + " could not have data directory re-created after delete.";
reportSettingsProblem(Log.WARN, msg);
- recovered = true;
-
- // And now re-install the app.
- ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
- pkg.applicationInfo.uid);
- if (ret == -1) {
- // Ack should not happen!
- msg = "System package " + pkg.packageName
- + " could not have data directory re-created after delete.";
- reportSettingsProblem(Log.WARN, msg);
- mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- return null;
- }
- // Create data directories for all users
- mUserManager.installPackageForAllUsers(pkgName,
- pkg.applicationInfo.uid);
+ mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ return null;
}
+ // Create data directories for all users
+ mUserManager.installPackageForAllUsers(pkgName,
+ pkg.applicationInfo.uid);
}
if (!recovered) {
mHasSystemUidErrors = true;
@@ -3303,25 +3258,16 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.v(TAG, "Want this data dir: " + dataPath);
}
//invoke installer to do the actual installation
- if (mInstaller != null) {
- int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
- pkg.applicationInfo.uid);
- if (ret < 0) {
- // Error from installer
- mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- return null;
- }
- // Create data directories for all users
- mUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
- } else {
- dataPath.mkdirs();
- if (dataPath.exists()) {
- FileUtils.setPermissions(
- dataPath.toString(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- pkg.applicationInfo.uid, pkg.applicationInfo.uid);
- }
+ int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
+ pkg.applicationInfo.uid);
+ if (ret < 0) {
+ // Error from installer
+ mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ return null;
}
+ // Create data directories for all users
+ mUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
+
if (dataPath.exists()) {
pkg.applicationInfo.dataDir = dataPath.getPath();
} else {
@@ -3352,65 +3298,62 @@ public class PackageManagerService extends IPackageManager.Stub {
pkgSetting.uidError = uidError;
}
- // If we're running in the simulator, we don't need to unpack anything.
- if (mInstaller != null) {
- String path = scanFile.getPath();
- /* Note: We don't want to unpack the native binaries for
- * system applications, unless they have been updated
- * (the binaries are already under /system/lib).
- * Also, don't unpack libs for apps on the external card
- * since they should have their libraries in the ASEC
- * container already.
- *
- * In other words, we're going to unpack the binaries
- * only for non-system apps and system app upgrades.
- */
- if (pkg.applicationInfo.nativeLibraryDir != null) {
- try {
- final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
- final String dataPathString = dataPath.getCanonicalFile().getPath();
+ String path = scanFile.getPath();
+ /* Note: We don't want to unpack the native binaries for
+ * system applications, unless they have been updated
+ * (the binaries are already under /system/lib).
+ * Also, don't unpack libs for apps on the external card
+ * since they should have their libraries in the ASEC
+ * container already.
+ *
+ * In other words, we're going to unpack the binaries
+ * only for non-system apps and system app upgrades.
+ */
+ if (pkg.applicationInfo.nativeLibraryDir != null) {
+ try {
+ final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
+ final String dataPathString = dataPath.getCanonicalFile().getPath();
- if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
- /*
- * Upgrading from a previous version of the OS sometimes
- * leaves native libraries in the /data/data/<app>/lib
- * directory for system apps even when they shouldn't be.
- * Recent changes in the JNI library search path
- * necessitates we remove those to match previous behavior.
- */
- if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
- Log.i(TAG, "removed obsolete native libraries for system package "
- + path);
- }
- } else if (nativeLibraryDir.getCanonicalFile().getParent()
- .equals(dataPathString)) {
- /*
- * If this is an internal application or our
- * nativeLibraryPath points to our data directory, unpack
- * the libraries. The native library path pointing to the
- * data directory for an application in an ASEC container
- * can happen for older apps that existed before an OTA to
- * Gingerbread.
- */
- Slog.i(TAG, "Unpacking native libraries for " + path);
- mInstaller.unlinkNativeLibraryDirectory(dataPathString);
- NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir);
- } else {
- Slog.i(TAG, "Linking native library dir for " + path);
- mInstaller.linkNativeLibraryDirectory(dataPathString,
- pkg.applicationInfo.nativeLibraryDir);
+ if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
+ /*
+ * Upgrading from a previous version of the OS sometimes
+ * leaves native libraries in the /data/data/<app>/lib
+ * directory for system apps even when they shouldn't be.
+ * Recent changes in the JNI library search path
+ * necessitates we remove those to match previous behavior.
+ */
+ if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
+ Log.i(TAG, "removed obsolete native libraries for system package "
+ + path);
}
- } catch (IOException ioe) {
- Log.e(TAG, "Unable to get canonical file " + ioe.toString());
+ } else if (nativeLibraryDir.getCanonicalFile().getParent()
+ .equals(dataPathString)) {
+ /*
+ * If this is an internal application or our
+ * nativeLibraryPath points to our data directory, unpack
+ * the libraries. The native library path pointing to the
+ * data directory for an application in an ASEC container
+ * can happen for older apps that existed before an OTA to
+ * Gingerbread.
+ */
+ Slog.i(TAG, "Unpacking native libraries for " + path);
+ mInstaller.unlinkNativeLibraryDirectory(dataPathString);
+ NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir);
+ } else {
+ Slog.i(TAG, "Linking native library dir for " + path);
+ mInstaller.linkNativeLibraryDirectory(dataPathString,
+ pkg.applicationInfo.nativeLibraryDir);
}
+ } catch (IOException ioe) {
+ Log.e(TAG, "Unable to get canonical file " + ioe.toString());
}
- pkg.mScanPath = path;
+ }
+ pkg.mScanPath = path;
- if ((scanMode&SCAN_NO_DEX) == 0) {
- if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
- mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
- return null;
- }
+ if ((scanMode&SCAN_NO_DEX) == 0) {
+ if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
+ mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
+ return null;
}
}
@@ -5434,7 +5377,7 @@ public class PackageManagerService extends IPackageManager.Stub {
void cleanUpResourcesLI() {
String sourceDir = getCodePath();
- if (cleanUp() && mInstaller != null) {
+ if (cleanUp()) {
int retCode = mInstaller.rmdex(sourceDir);
if (retCode < 0) {
Slog.w(TAG, "Couldn't remove dex file for package: "
@@ -5662,14 +5605,12 @@ public class PackageManagerService extends IPackageManager.Stub {
void cleanUpResourcesLI() {
String sourceFile = getCodePath();
// Remove dex file
- if (mInstaller != null) {
- int retCode = mInstaller.rmdex(sourceFile);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove dex file for package: "
- + " at location "
- + sourceFile.toString() + ", retcode=" + retCode);
- // we don't consider this to be a failure of the core package deletion
- }
+ int retCode = mInstaller.rmdex(sourceFile);
+ if (retCode < 0) {
+ Slog.w(TAG, "Couldn't remove dex file for package: "
+ + " at location "
+ + sourceFile.toString() + ", retcode=" + retCode);
+ // we don't consider this to be a failure of the core package deletion
}
cleanUp();
}
@@ -6077,9 +6018,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if((res.returnCode = setPermissionsLI(newPackage))
!= PackageManager.INSTALL_SUCCEEDED) {
- if (mInstaller != null) {
- mInstaller.rmdex(newPackage.mScanPath);
- }
+ mInstaller.rmdex(newPackage.mScanPath);
return;
} else {
Log.d(TAG, "New package installed in " + newPackage.mPath);
@@ -6207,15 +6146,8 @@ public class PackageManagerService extends IPackageManager.Stub {
} finally {
//TODO clean up the extracted public files
}
- if (mInstaller != null) {
- retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
- newPackage.applicationInfo.uid);
- } else {
- final int filePermissions =
- FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
- retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
- newPackage.applicationInfo.uid);
- }
+ retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
+ newPackage.applicationInfo.uid);
} else {
// The permissions on the resource file was set when it was copied for
// non forward locked apps and apps on sdcard
@@ -6478,25 +6410,14 @@ public class PackageManagerService extends IPackageManager.Stub {
deletedPs = mSettings.mPackages.get(packageName);
}
if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
- if (mInstaller != null) {
- int retCode = mInstaller.remove(packageName, 0);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
- + packageName + ", retcode=" + retCode);
- // we don't consider this to be a failure of the core package deletion
- } else {
- // TODO: Kill the processes first
- mUserManager.removePackageForAllUsers(packageName);
- }
+ int retCode = mInstaller.remove(packageName, 0);
+ if (retCode < 0) {
+ Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
+ + packageName + ", retcode=" + retCode);
+ // we don't consider this to be a failure of the core package deletion
} else {
- // for simulator
- File dataDir;
- // reader
- synchronized (mPackages) {
- PackageParser.Package pkg = mPackages.get(packageName);
- dataDir = new File(pkg.applicationInfo.dataDir);
- }
- dataDir.delete();
+ // TODO: Kill the processes first
+ mUserManager.removePackageForAllUsers(packageName);
}
schedulePackageCleaning(packageName);
}
@@ -6745,13 +6666,11 @@ public class PackageManagerService extends IPackageManager.Stub {
return false;
}
}
- if (mInstaller != null) {
- int retCode = mInstaller.clearUserData(packageName, 0); // TODO - correct userId
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove cache files for package: "
- + packageName);
- return false;
- }
+ int retCode = mInstaller.clearUserData(packageName, 0); // TODO - correct userId
+ if (retCode < 0) {
+ Slog.w(TAG, "Couldn't remove cache files for package: "
+ + packageName);
+ return false;
}
return true;
}
@@ -6797,13 +6716,11 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
return false;
}
- if (mInstaller != null) {
- int retCode = mInstaller.deleteCacheFiles(packageName);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove cache files for package: "
- + packageName);
- return false;
- }
+ int retCode = mInstaller.deleteCacheFiles(packageName);
+ if (retCode < 0) {
+ Slog.w(TAG, "Couldn't remove cache files for package: "
+ + packageName);
+ return false;
}
return true;
}
@@ -6867,14 +6784,10 @@ public class PackageManagerService extends IPackageManager.Stub {
publicSrcDir = applicationInfo.publicSourceDir;
}
}
- if (mInstaller != null) {
- int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
- asecPath, pStats);
- if (res < 0) {
- return false;
- } else {
- return true;
- }
+ int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
+ asecPath, pStats);
+ if (res < 0) {
+ return false;
}
return true;
}
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index d645160..3139798 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -138,12 +138,9 @@ public class UsbDeviceManager {
// create a thread for our Handler
HandlerThread thread = new HandlerThread("UsbDeviceManager",
- Process.THREAD_PRIORITY_BACKGROUND) {
- protected void onLooperPrepared() {
- mHandler = new UsbHandler();
- }
- };
+ Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
+ mHandler = new UsbHandler(thread.getLooper());
}
public void systemReady() {
@@ -249,21 +246,21 @@ public class UsbDeviceManager {
private static final int NOTIFICATION_INSTALLER = 3;
private static final int NOTIFICATION_ADB = 4;
- public UsbHandler() {
+ public UsbHandler(Looper looper) {
+ super(looper);
try {
+ // persist.sys.usb.config should never be unset. But if it is, set it to "adb"
+ // so we have a chance of debugging what happened.
+ mDefaultFunctions = SystemProperties.get("persist.sys.usb.config", "adb");
// sanity check the sys.usb.config system property
// this may be necessary if we crashed while switching USB configurations
String config = SystemProperties.get("sys.usb.config", "none");
- if (config.equals("none")) {
- String persistConfig = SystemProperties.get("persist.sys.usb.config", "none");
- Slog.w(TAG, "resetting config to persistent property: " + persistConfig);
- SystemProperties.set("sys.usb.config", persistConfig);
+ if (!config.equals(mDefaultFunctions)) {
+ Slog.w(TAG, "resetting config to persistent property: " + mDefaultFunctions);
+ SystemProperties.set("sys.usb.config", mDefaultFunctions);
}
- // Read initial USB state
- mCurrentFunctions = FileUtils.readTextFile(
- new File(FUNCTIONS_PATH), 0, null).trim();
- mDefaultFunctions = mCurrentFunctions;
+ mCurrentFunctions = mDefaultFunctions;
String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
updateState(state);
mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
@@ -621,6 +618,16 @@ public class UsbDeviceManager {
pw.println(" mConnected: " + mConnected);
pw.println(" mConfigured: " + mConfigured);
pw.println(" mCurrentAccessory: " + mCurrentAccessory);
+ try {
+ pw.println(" Kernel state: "
+ + FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim());
+ pw.println(" Kernel function list: "
+ + FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim());
+ pw.println(" Mass storage backing file: "
+ + FileUtils.readTextFile(new File(MASS_STORAGE_FILE_PATH), 0, null).trim());
+ } catch (IOException e) {
+ pw.println("IOException: " + e);
+ }
}
}
@@ -630,20 +637,20 @@ public class UsbDeviceManager {
}
/* opens the currently attached USB accessory */
- public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
- UsbAccessory currentAccessory = mHandler.getCurrentAccessory();
- if (currentAccessory == null) {
- throw new IllegalArgumentException("no accessory attached");
- }
- if (!currentAccessory.equals(accessory)) {
- String error = accessory.toString()
- + " does not match current accessory "
- + currentAccessory;
- throw new IllegalArgumentException(error);
- }
- mSettingsManager.checkPermission(accessory);
- return nativeOpenAccessory();
+ public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
+ UsbAccessory currentAccessory = mHandler.getCurrentAccessory();
+ if (currentAccessory == null) {
+ throw new IllegalArgumentException("no accessory attached");
+ }
+ if (!currentAccessory.equals(accessory)) {
+ String error = accessory.toString()
+ + " does not match current accessory "
+ + currentAccessory;
+ throw new IllegalArgumentException(error);
}
+ mSettingsManager.checkPermission(accessory);
+ return nativeOpenAccessory();
+ }
public void setCurrentFunction(String function, boolean makeDefault) {
if (DEBUG) Slog.d(TAG, "setCurrentFunction(" + function + ") default: " + makeDefault);
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index f33920d..e1c7305 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -39,14 +39,6 @@ LOCAL_SHARED_LIBRARIES := \
libgui \
libusbhost
-ifeq ($(TARGET_SIMULATOR),true)
-ifeq ($(TARGET_OS),linux)
-ifeq ($(TARGET_ARCH),x86)
-LOCAL_LDLIBS += -lpthread -ldl -lrt
-endif
-endif
-endif
-
ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
endif
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index ba3e6e5..6a302c0 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -16,13 +16,6 @@ LOCAL_SRC_FILES:= \
LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
-# need "-lrt" on Linux simulator to pick up clock_gettime
-ifeq ($(TARGET_SIMULATOR),true)
- ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt -lpthread
- endif
-endif
-
LOCAL_SHARED_LIBRARIES := \
libcutils \
libhardware \
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index c618263..f67c82e 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -26,13 +26,6 @@ ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
endif
-# need "-lrt" on Linux simulator to pick up clock_gettime
-ifeq ($(TARGET_SIMULATOR),true)
- ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt -lpthread
- endif
-endif
-
LOCAL_SHARED_LIBRARIES := \
libcutils \
libhardware \
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 33125c4..7bf3e0a 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -99,6 +99,31 @@ uint32_t DisplayHardware::getMaxViewportDims() const {
mMaxViewportDims[0] : mMaxViewportDims[1];
}
+static status_t selectConfigForPixelFormat(
+ EGLDisplay dpy,
+ EGLint const* attrs,
+ PixelFormat format,
+ EGLConfig* outConfig)
+{
+ EGLConfig config = NULL;
+ EGLint numConfigs = -1, n=0;
+ eglGetConfigs(dpy, NULL, 0, &numConfigs);
+ EGLConfig* const configs = new EGLConfig[numConfigs];
+ eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
+ for (int i=0 ; i<n ; i++) {
+ EGLint nativeVisualId = 0;
+ eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
+ if (nativeVisualId>0 && format == nativeVisualId) {
+ *outConfig = configs[i];
+ delete [] configs;
+ return NO_ERROR;
+ }
+ }
+ delete [] configs;
+ return NAME_NOT_FOUND;
+}
+
+
void DisplayHardware::init(uint32_t dpy)
{
mNativeWindow = new FramebufferNativeWindow();
@@ -108,6 +133,9 @@ void DisplayHardware::init(uint32_t dpy)
exit(0);
}
+ int format;
+ ANativeWindow const * const window = mNativeWindow.get();
+ window->query(window, NATIVE_WINDOW_FORMAT, &format);
mDpiX = mNativeWindow->xdpi;
mDpiY = mNativeWindow->ydpi;
mRefreshRate = fbDev->fps;
@@ -116,11 +144,13 @@ void DisplayHardware::init(uint32_t dpy)
EGLint numConfigs=0;
EGLSurface surface;
EGLContext context;
+ EGLBoolean result;
+ status_t err;
// initialize EGL
EGLint attribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_NONE, 0,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_NONE, 0,
EGL_NONE
};
@@ -141,9 +171,8 @@ void DisplayHardware::init(uint32_t dpy)
eglInitialize(display, NULL, NULL);
eglGetConfigs(display, NULL, 0, &numConfigs);
- EGLConfig config;
- status_t err = EGLUtils::selectConfigForNativeWindow(
- display, attribs, mNativeWindow.get(), &config);
+ EGLConfig config = NULL;
+ err = selectConfigForPixelFormat(display, attribs, format, &config);
LOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
EGLint r,g,b,a;
@@ -224,7 +253,11 @@ void DisplayHardware::init(uint32_t dpy)
* Gather OpenGL ES extensions
*/
- eglMakeCurrent(display, surface, surface, context);
+ result = eglMakeCurrent(display, surface, surface, context);
+ if (!result) {
+ LOGE("Couldn't create a working GLES context. check logs. exiting...");
+ exit(0);
+ }
GLExtensions& extensions(GLExtensions::getInstance());
extensions.initWithGLStrings(
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 35e29a6..f3b6c4d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -188,22 +188,37 @@ void Layer::setGeometry(hwc_layer_t* hwcl)
return;
}
+ /*
+ * Transformations are applied in this order:
+ * 1) buffer orientation/flip/mirror
+ * 2) state transformation (window manager)
+ * 3) layer orientation (screen orientation)
+ * (NOTE: the matrices are multiplied in reverse order)
+ */
+
+ const Transform bufferOrientation(mCurrentTransform);
+ const Transform& stateTransform(s.transform);
+ const Transform layerOrientation(mOrientation);
+
+ const Transform tr(layerOrientation * stateTransform * bufferOrientation);
+
+ // this gives us only the "orientation" component of the transform
+ const uint32_t finalTransform = tr.getOrientation();
+
// we can only handle simple transformation
- if (mOrientation & Transform::ROT_INVALID) {
+ if (finalTransform & Transform::ROT_INVALID) {
hwcl->flags = HWC_SKIP_LAYER;
return;
}
- // FIXME: shouldn't we take the state's transform into account here?
-
- Transform tr(Transform(mOrientation) * Transform(mCurrentTransform));
- hwcl->transform = tr.getOrientation();
+ hwcl->transform = finalTransform;
if (!isOpaque()) {
hwcl->blending = mPremultipliedAlpha ?
HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
}
+ // scaling is already applied in mTransformedBounds
hwcl->displayFrame.left = mTransformedBounds.left;
hwcl->displayFrame.top = mTransformedBounds.top;
hwcl->displayFrame.right = mTransformedBounds.right;
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index bcd8c83..c86c659 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -228,13 +228,18 @@ void LayerBase::validateVisibility(const Transform& planeTransform)
const Layer::State& s(drawingState());
const Transform tr(planeTransform * s.transform);
const bool transformed = tr.transformed();
-
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ const uint32_t hw_h = hw.getHeight();
+
uint32_t w = s.w;
uint32_t h = s.h;
tr.transform(mVertices[0], 0, 0);
tr.transform(mVertices[1], 0, h);
tr.transform(mVertices[2], w, h);
tr.transform(mVertices[3], w, 0);
+ for (size_t i=0 ; i<4 ; i++)
+ mVertices[i][1] = hw_h - mVertices[i][1];
+
if (UNLIKELY(transformed)) {
// NOTE: here we could also punt if we have too many rectangles
// in the transparent region
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index cccab4a..b0881a4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -276,7 +276,8 @@ status_t SurfaceFlinger::readyToRun()
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
- glOrthof(0, w, h, 0, 0, 1);
+ // put the origin in the left-bottom corner
+ glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
mReadyToRunBarrier.open();
@@ -1791,7 +1792,7 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
}
GLfloat vtx[8];
- const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
+ const GLfloat texCoords[4][2] = { {0,1}, {0,1-v}, {u,1-v}, {u,1} };
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);
@@ -1800,6 +1801,22 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vtx);
+ /*
+ * Texture coordinate mapping
+ *
+ * u
+ * 1 +----------+---+
+ * | | | | image is inverted
+ * | V | | w.r.t. the texture
+ * 1-v +----------+ | coordinates
+ * | |
+ * | |
+ * | |
+ * 0 +--------------+
+ * 0 1
+ *
+ */
+
class s_curve_interpolator {
const float nbFrames, s, v;
public:
@@ -1824,10 +1841,10 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
const GLfloat h = hw_h - (hw_h * v);
const GLfloat x = (hw_w - w) * 0.5f;
const GLfloat y = (hw_h - h) * 0.5f;
- vtx[0] = x; vtx[1] = y + h;
- vtx[2] = x; vtx[3] = y;
- vtx[4] = x + w; vtx[5] = y;
- vtx[6] = x + w; vtx[7] = y + h;
+ vtx[0] = x; vtx[1] = y;
+ vtx[2] = x; vtx[3] = y + h;
+ vtx[4] = x + w; vtx[5] = y + h;
+ vtx[6] = x + w; vtx[7] = y;
}
};
@@ -1842,15 +1859,20 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
const GLfloat h = 1.0f;
const GLfloat x = (hw_w - w) * 0.5f;
const GLfloat y = (hw_h - h) * 0.5f;
- vtx[0] = x; vtx[1] = y + h;
- vtx[2] = x; vtx[3] = y;
- vtx[4] = x + w; vtx[5] = y;
- vtx[6] = x + w; vtx[7] = y + h;
+ vtx[0] = x; vtx[1] = y;
+ vtx[2] = x; vtx[3] = y + h;
+ vtx[4] = x + w; vtx[5] = y + h;
+ vtx[6] = x + w; vtx[7] = y;
}
};
// the full animation is 24 frames
- const int nbFrames = 12;
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.sf.electron_frames", value, "24");
+ int nbFrames = (atoi(value) + 1) >> 1;
+ if (nbFrames <= 0) // just in case
+ nbFrames = 24;
+
s_curve_interpolator itr(nbFrames, 7.5f);
s_curve_interpolator itg(nbFrames, 8.0f);
s_curve_interpolator itb(nbFrames, 8.5f);
@@ -2225,10 +2247,11 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
// invert everything, b/c glReadPixel() below will invert the FB
glViewport(0, 0, sw, sh);
glScissor(0, 0, sw, sh);
+ glEnable(GL_SCISSOR_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
- glOrthof(0, hw_w, 0, hw_h, 0, 1);
+ glOrthof(0, hw_w, hw_h, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
// redraw the screen entirely...
@@ -2244,6 +2267,7 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
}
// XXX: this is needed on tegra
+ glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, sw, sh);
// check for errors and return screen capture
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index 0467a14..4cedcbf 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -308,6 +308,7 @@ uint32_t Transform::type() const
scale = true;
}
} else {
+ // there is a skew component and/or a non 90 degrees rotation
flags = ROT_INVALID;
}
diff --git a/services/tests/servicestests/res/raw/net_dev_typical b/services/tests/servicestests/res/raw/net_dev_typical
new file mode 100644
index 0000000..290bf03
--- /dev/null
+++ b/services/tests/servicestests/res/raw/net_dev_typical
@@ -0,0 +1,8 @@
+Inter-| Receive | Transmit
+ face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
+ lo: 8308 116 0 0 0 0 0 0 8308 116 0 0 0 0 0 0
+rmnet0: 1507570 2205 0 0 0 0 0 0 489339 2237 0 0 0 0 0 0
+ ifb0: 52454 151 0 151 0 0 0 0 0 0 0 0 0 0 0 0
+ ifb1: 52454 151 0 151 0 0 0 0 0 0 0 0 0 0 0 0
+ sit0: 0 0 0 0 0 0 0 0 0 0 148 0 0 0 0 0
+ip6tnl0: 0 0 0 0 0 0 0 0 0 0 151 151 0 0 0 0
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
index ac7cb5a..56ef995 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStats.UID_ALL;
import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
import static com.android.server.NetworkManagementSocketTagger.tagToKernel;
@@ -25,9 +27,11 @@ import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import com.android.frameworks.servicestests.R;
+import com.google.common.io.Files;
import java.io.File;
import java.io.FileOutputStream;
+import java.io.FileWriter;
import java.io.InputStream;
import java.io.OutputStream;
@@ -46,14 +50,23 @@ public class NetworkManagementServiceTest extends AndroidTestCase {
public void setUp() throws Exception {
super.setUp();
- mTestProc = getContext().getFilesDir();
- mService = NetworkManagementService.createForTest(mContext, mTestProc);
+ final File canonicalFilesDir = getContext().getFilesDir().getCanonicalFile();
+ mTestProc = new File(canonicalFilesDir, "proc");
+ if (mTestProc.exists()) {
+ Files.deleteRecursively(mTestProc);
+ }
+
+ mService = NetworkManagementService.createForTest(mContext, mTestProc, true);
}
@Override
public void tearDown() throws Exception {
mService = null;
+ if (mTestProc.exists()) {
+ Files.deleteRecursively(mTestProc);
+ }
+
super.tearDown();
}
@@ -61,7 +74,7 @@ public class NetworkManagementServiceTest extends AndroidTestCase {
stageFile(R.raw.xt_qtaguid_typical, new File(mTestProc, "net/xt_qtaguid/stats"));
final NetworkStats stats = mService.getNetworkStatsDetail();
- assertEquals(31, stats.size);
+ assertEquals(31, stats.size());
assertStatsEntry(stats, "wlan0", 0, 0, 14615L, 4270L);
assertStatsEntry(stats, "wlan0", 10004, 0, 333821L, 53558L);
assertStatsEntry(stats, "wlan0", 10004, 1947740890, 18725L, 1066L);
@@ -73,11 +86,37 @@ public class NetworkManagementServiceTest extends AndroidTestCase {
stageFile(R.raw.xt_qtaguid_extended, new File(mTestProc, "net/xt_qtaguid/stats"));
final NetworkStats stats = mService.getNetworkStatsDetail();
- assertEquals(2, stats.size);
+ assertEquals(2, stats.size());
assertStatsEntry(stats, "test0", 1000, 0, 1024L, 2048L);
assertStatsEntry(stats, "test0", 1000, 0xF00D, 512L, 512L);
}
+ public void testNetworkStatsSummary() throws Exception {
+ stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev"));
+
+ final NetworkStats stats = mService.getNetworkStatsSummary();
+ assertEquals(6, stats.size());
+ assertStatsEntry(stats, "lo", UID_ALL, TAG_NONE, 8308L, 8308L);
+ assertStatsEntry(stats, "rmnet0", UID_ALL, TAG_NONE, 1507570L, 489339L);
+ assertStatsEntry(stats, "ifb0", UID_ALL, TAG_NONE, 52454L, 0L);
+ assertStatsEntry(stats, "ifb1", UID_ALL, TAG_NONE, 52454L, 0L);
+ assertStatsEntry(stats, "sit0", UID_ALL, TAG_NONE, 0L, 0L);
+ assertStatsEntry(stats, "ip6tnl0", UID_ALL, TAG_NONE, 0L, 0L);
+ }
+
+ public void testNetworkStatsSummaryDown() throws Exception {
+ stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev"));
+ stageLong(1024L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/rx_bytes"));
+ stageLong(128L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/rx_packets"));
+ stageLong(2048L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/tx_bytes"));
+ stageLong(256L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/tx_packets"));
+
+ final NetworkStats stats = mService.getNetworkStatsSummary();
+ assertEquals(7, stats.size());
+ assertStatsEntry(stats, "rmnet0", UID_ALL, TAG_NONE, 1507570L, 489339L);
+ assertStatsEntry(stats, "wlan0", UID_ALL, TAG_NONE, 1024L, 2048L);
+ }
+
public void testKernelTags() throws Exception {
assertEquals("0", tagToKernel(0x0));
assertEquals("214748364800", tagToKernel(0x32));
@@ -90,7 +129,6 @@ public class NetworkManagementServiceTest extends AndroidTestCase {
assertEquals(2147483647, kernelToTag("0x7fffffff00000000"));
assertEquals(0, kernelToTag("0x0000000000000000"));
assertEquals(2147483136, kernelToTag("0x7FFFFE0000000000"));
-
}
/**
@@ -111,11 +149,23 @@ public class NetworkManagementServiceTest extends AndroidTestCase {
}
}
+ private void stageLong(long value, File file) throws Exception {
+ new File(file.getParent()).mkdirs();
+ FileWriter out = null;
+ try {
+ out = new FileWriter(file);
+ out.write(Long.toString(value));
+ } finally {
+ IoUtils.closeQuietly(out);
+ }
+ }
+
private static void assertStatsEntry(
- NetworkStats stats, String iface, int uid, int tag, long rx, long tx) {
+ NetworkStats stats, String iface, int uid, int tag, long rxBytes, long txBytes) {
final int i = stats.findIndex(iface, uid, tag);
- assertEquals(rx, stats.rx[i]);
- assertEquals(tx, stats.tx[i]);
+ final NetworkStats.Entry entry = stats.getValues(i, null);
+ assertEquals(rxBytes, entry.rxBytes);
+ assertEquals(txBytes, entry.txBytes);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index b4ac987..33fd355 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -447,7 +447,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
// pretend that 512 bytes total have happened
stats = new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 256L);
+ .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 2L, 256L, 2L);
expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
.andReturn(stats).atLeastOnce();
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index f2c28bb..ac74063 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -168,7 +168,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectTime(TEST_START + elapsedRealtime);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 2048L));
+ .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 1L, 2048L, 2L));
expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
replay();
@@ -184,7 +184,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectTime(TEST_START + elapsedRealtime);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 4096L, 8192L));
+ .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4096L, 4L, 8192L, 8L));
expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
replay();
@@ -219,10 +219,10 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectTime(TEST_START + elapsedRealtime);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 2048L));
+ .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 8L, 2048L, 16L));
expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 2)
- .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 512L, 256L)
- .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 128L));
+ .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L)
+ .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 128L, 1L));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -264,7 +264,6 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
public void testStatsBucketResize() throws Exception {
long elapsedRealtime = 0;
NetworkStatsHistory history = null;
- long[] total = null;
assertStatsFilesExist(false);
@@ -284,7 +283,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectTime(TEST_START + elapsedRealtime);
expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 512L, 512L));
+ .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 512L, 4L, 512L, 4L));
expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
replay();
@@ -292,11 +291,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
// verify service recorded history
history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
- total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
- assertEquals(512L, total[0]);
- assertEquals(512L, total[1]);
- assertEquals(HOUR_IN_MILLIS, history.bucketDuration);
- assertEquals(2, history.bucketCount);
+ assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L);
+ assertEquals(HOUR_IN_MILLIS, history.getBucketDuration());
+ assertEquals(2, history.size());
verifyAndReset();
// now change bucket duration setting and trigger another poll with
@@ -311,11 +308,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
// verify identical stats, but spread across 4 buckets now
history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
- total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
- assertEquals(512L, total[0]);
- assertEquals(512L, total[1]);
- assertEquals(30 * MINUTE_IN_MILLIS, history.bucketDuration);
- assertEquals(4, history.bucketCount);
+ assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L);
+ assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration());
+ assertEquals(4, history.size());
verifyAndReset();
}
@@ -338,11 +333,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectTime(TEST_START + elapsedRealtime);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 2048L, 512L));
+ .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 2048L, 16L, 512L, 4L));
expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 3)
- .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 1536L, 512L)
- .addEntry(TEST_IFACE, UID_RED, 0xF00D, 512L, 512L)
- .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 512L, 0L));
+ .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1536L, 12L, 512L, 4L)
+ .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L)
+ .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 512L, 4L, 0L, 0L));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -373,9 +368,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectTime(TEST_START + elapsedRealtime);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 128L, 1024L));
+ .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 128L, 1L, 1024L, 8L));
expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1024L));
+ .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 1024L, 8L));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -412,11 +407,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectTime(TEST_START + elapsedRealtime);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 4128L, 544L));
+ .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4128L, 258L, 544L, 34L));
expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 16L, 16L)
- .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 4096L, 512L)
- .addEntry(TEST_IFACE, UID_GREEN, TAG_NONE, 16L, 16L));
+ .addValues(TEST_IFACE, UID_RED, TAG_NONE, 16L, 1L, 16L, 1L)
+ .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 4096L, 258L, 512L, 32L)
+ .addValues(TEST_IFACE, UID_GREEN, TAG_NONE, 16L, 1L, 16L, 1L));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -468,8 +463,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 1024L, 1024L)
- .addEntry(TEST_IFACE, UID_RED, 0xF00D, 512L, 512L));
+ .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1024L, 8L, 1024L, 8L)
+ .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -497,7 +492,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 512L, 256L));
+ .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -548,9 +543,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 50L, 50L)
- .addEntry(TEST_IFACE, UID_RED, 0xF00D, 10L, 10L)
- .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 1024L, 512L));
+ .addValues(TEST_IFACE, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L)
+ .addValues(TEST_IFACE, UID_RED, 0xF00D, 10L, 1L, 10L, 1L)
+ .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -566,7 +561,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 2048L, 1024L));
+ .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -574,33 +569,29 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
// first verify entire history present
NetworkStats stats = mService.getSummaryForAllUid(
sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
- assertEquals(3, stats.size);
- assertStatsEntry(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 50L);
- assertStatsEntry(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 10L);
- assertStatsEntry(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 1024L);
+ assertEquals(3, stats.size());
+ assertValues(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L);
+ assertValues(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L);
+ assertValues(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L);
// now verify that recent history only contains one uid
final long currentTime = TEST_START + elapsedRealtime;
stats = mService.getSummaryForAllUid(
sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true);
- assertEquals(1, stats.size);
- assertStatsEntry(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 512L);
+ assertEquals(1, stats.size());
+ assertValues(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L);
verifyAndReset();
}
- private void assertNetworkTotal(NetworkTemplate template, long rx, long tx) {
+ private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long txBytes) {
final NetworkStatsHistory history = mService.getHistoryForNetwork(template);
- final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
- assertEquals(rx, total[0]);
- assertEquals(tx, total[1]);
+ assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes);
}
- private void assertUidTotal(NetworkTemplate template, int uid, long rx, long tx) {
+ private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long txBytes) {
final NetworkStatsHistory history = mService.getHistoryForUid(template, uid, TAG_NONE);
- final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
- assertEquals(rx, total[0]);
- assertEquals(tx, total[1]);
+ assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes);
}
private void expectSystemReady() throws Exception {
@@ -660,13 +651,24 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
}
}
- private static void assertStatsEntry(
- NetworkStats stats, int i, String iface, int uid, int tag, long rx, long tx) {
- assertEquals(iface, stats.iface[i]);
- assertEquals(uid, stats.uid[i]);
- assertEquals(tag, stats.tag[i]);
- assertEquals(rx, stats.rx[i]);
- assertEquals(tx, stats.tx[i]);
+ private static void assertValues(NetworkStats stats, int i, String iface, int uid, int tag,
+ long rxBytes, long rxPackets, long txBytes, long txPackets) {
+ final NetworkStats.Entry entry = stats.getValues(i, null);
+ assertEquals(iface, entry.iface);
+ assertEquals(uid, entry.uid);
+ assertEquals(tag, entry.tag);
+ assertEquals(rxBytes, entry.rxBytes);
+ // TODO: enable testing packet counts once stored in history
+// assertEquals(rxPackets, entry.rxPackets);
+ assertEquals(txBytes, entry.txBytes);
+// assertEquals(txPackets, entry.txPackets);
+ }
+
+ private static void assertValues(
+ NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) {
+ final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null);
+ assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
+ assertEquals("unexpected txBytes", txBytes, entry.txBytes);
}
private static NetworkState buildWifiState() {
diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
index 2f275c3..50c18f0 100644
--- a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
@@ -289,7 +289,7 @@ public class ThrottleServiceTest extends AndroidTestCase {
public void expectGetInterfaceCounter(long rx, long tx) throws Exception {
// TODO: provide elapsedRealtime mock to match TimeAuthority
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
- stats.addEntry(TEST_IFACE, NetworkStats.UID_ALL, NetworkStats.TAG_NONE, rx, tx);
+ stats.addValues(TEST_IFACE, NetworkStats.UID_ALL, NetworkStats.TAG_NONE, rx, 0L, tx, 0L);
expect(mMockNMService.getNetworkStatsSummary()).andReturn(stats).atLeastOnce();
}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 977b412..4f8b525 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -18,10 +18,12 @@ package com.android.internal.telephony;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.database.ContentObserver;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkInfo;
@@ -334,6 +336,31 @@ public abstract class DataConnectionTracker extends Handler {
}
};
+ private final DataRoamingSettingObserver mDataRoamingSettingObserver;
+
+ private class DataRoamingSettingObserver extends ContentObserver {
+ public DataRoamingSettingObserver(Handler handler) {
+ super(handler);
+ }
+
+ public void register(Context context) {
+ final ContentResolver resolver = context.getContentResolver();
+ resolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.DATA_ROAMING), false, this);
+ }
+
+ public void unregister(Context context) {
+ final ContentResolver resolver = context.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ // already running on mPhone handler thread
+ handleDataOnRoamingChange();
+ }
+ }
+
protected boolean isDataSetupCompleteOk(AsyncResult ar) {
if (ar.exception != null) {
if (DBG) log("isDataSetupCompleteOk return false, ar.result=" + ar.result);
@@ -398,6 +425,10 @@ public abstract class DataConnectionTracker extends Handler {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
mAutoAttachOnCreation = sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
+
+ // watch for changes to Settings.Secure.DATA_ROAMING
+ mDataRoamingSettingObserver = new DataRoamingSettingObserver(mPhone);
+ mDataRoamingSettingObserver.register(mPhone.getContext());
}
public void dispose() {
@@ -407,6 +438,7 @@ public abstract class DataConnectionTracker extends Handler {
mDataConnectionAsyncChannels.clear();
mIsDisposed = true;
mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
+ mDataRoamingSettingObserver.unregister(mPhone.getContext());
}
protected void broadcastMessenger() {
@@ -461,32 +493,38 @@ public abstract class DataConnectionTracker extends Handler {
return result;
}
- //The data roaming setting is now located in the shared preferences.
- // See if the requested preference value is the same as that stored in
- // the shared values. If it is not, then update it.
+ /**
+ * Modify {@link Settings.Secure#DATA_ROAMING} value.
+ */
public void setDataOnRoamingEnabled(boolean enabled) {
if (getDataOnRoamingEnabled() != enabled) {
- Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
- Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
- if (mPhone.getServiceState().getRoaming()) {
- if (enabled) {
- resetAllRetryCounts();
- }
- sendMessage(obtainMessage(EVENT_ROAMING_ON));
- }
+ final ContentResolver resolver = mPhone.getContext().getContentResolver();
+ Settings.Secure.putInt(resolver, Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
+ // will trigger handleDataOnRoamingChange() through observer
}
}
- // Retrieve the data roaming setting from the shared preferences.
+ /**
+ * Return current {@link Settings.Secure#DATA_ROAMING} value.
+ */
public boolean getDataOnRoamingEnabled() {
try {
- return Settings.Secure.getInt(
- mPhone.getContext().getContentResolver(), Settings.Secure.DATA_ROAMING) > 0;
+ final ContentResolver resolver = mPhone.getContext().getContentResolver();
+ return Settings.Secure.getInt(resolver, Settings.Secure.DATA_ROAMING) != 0;
} catch (SettingNotFoundException snfe) {
return false;
}
}
+ private void handleDataOnRoamingChange() {
+ if (mPhone.getServiceState().getRoaming()) {
+ if (getDataOnRoamingEnabled()) {
+ resetAllRetryCounts();
+ }
+ sendMessage(obtainMessage(EVENT_ROAMING_ON));
+ }
+ }
+
// abstract methods
protected abstract String getActionIntentReconnectAlarm();
protected abstract void startNetStatPoll();
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 4309309..60cf9b7 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -166,4 +166,11 @@ public interface TelephonyProperties
* the value of config_sms_capable
*/
static final String PROPERTY_SMS_SEND = "telephony.sms.send";
+
+ /**
+ * Set to true to indicate a test CSIM card is used in the device.
+ * This property is for testing purpose only. This should not be defined
+ * in commercial configuration.
+ */
+ static final String PROPERTY_TEST_CSIM = "persist.radio.test-csim";
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index 459cf87..0d551aa 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -39,7 +39,6 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
CDMALTEPhone mCdmaLtePhone;
private ServiceState mLteSS; // The last LTE state from Voice Registration
- private String mCurrentSpn = null;
public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
super(phone);
@@ -345,6 +344,18 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
ss.setOperatorAlphaLong(eriText);
}
+ if (cm.getSimState().isSIMReady()) {
+ // SIM is found on the device. If ERI roaming is OFF, use operator name
+ // from CSIM record.
+ boolean showSpn =
+ ((CdmaLteUiccRecords)phone.mIccRecords).getCsimSpnDisplayCondition();
+ int iconIndex = ss.getCdmaEriIconIndex();
+
+ if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF)) {
+ ss.setOperatorAlphaLong(phone.mIccRecords.getServiceProviderName());
+ }
+ }
+
String operatorNumeric;
phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
@@ -468,43 +479,6 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
}
@Override
- protected void updateSpnDisplay() {
- // mOperatorAlphaLong contains the ERI text
- String plmn = ss.getOperatorAlphaLong();
-
- boolean showSpn = false;
- String spn = null;
- if (cm.getSimState().isSIMReady()) {
- // SIM is found on the device. Read the operator name from the card.
- showSpn = ((CdmaLteUiccRecords)phone.mIccRecords).getCsimSpnDisplayCondition();
- spn = phone.mIccRecords.getServiceProviderName();
-
- // double check we are not printing identicall test
- if (TextUtils.equals(plmn, spn)) showSpn = false;
- }
-
- if (!TextUtils.equals(plmn, mCurPlmn) ||
- !TextUtils.equals(spn, mCurrentSpn)) {
- boolean showPlmn = plmn != null;
- if (DBG) {
- log(String.format("updateSpnDisplay: changed sending intent" +
- " showPlmn='%b' plmn='%s' showSpn='%b' spn='%s'",
- showPlmn, plmn, showSpn, spn));
- }
- Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn);
- intent.putExtra(Intents.EXTRA_SPN, spn);
- intent.putExtra(Intents.EXTRA_SHOW_PLMN, showPlmn);
- intent.putExtra(Intents.EXTRA_PLMN, plmn);
- phone.getContext().sendStickyBroadcast(intent);
- }
-
- mCurPlmn = plmn;
- mCurrentSpn = spn;
- }
-
- @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 10515f7..fc6abad 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.cdma;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_TEST_CSIM;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.IccCardApplication.AppType;
import com.android.internal.telephony.IccFileHandler;
@@ -447,6 +448,12 @@ public final class CdmaLteUiccRecords extends SIMRecords {
// to determine if the SIM is provisioned. Otherwise,
// consider the SIM is provisioned. (for case of ordinal
// USIM only UICC.)
+ // If PROPERTY_TEST_CSIM is defined, bypess provision check
+ // and consider the SIM is provisioned.
+ if (SystemProperties.getBoolean(PROPERTY_TEST_CSIM, false)) {
+ return true;
+ }
+
if (phone.mIccCard.isApplicationOnIcc(AppType.APPTYPE_CSIM) &&
((mMdn == null) || (mMin == null))) {
return false;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index fe57d0d..df5898b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -1055,10 +1055,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
}
if (!found) {
- // ApnContext does not have dcan reorted in data call list.
+ // ApnContext does not have dcac reported in data call list.
+ // Fetch all the ApnContexts that map to this dcac which are in
+ // INITING state too.
if (DBG) log("onDataStateChanged(ar): Connected apn not found in the list (" +
apnContext.toString() + ")");
- list.add(apnContext);
+ if (apnContext.getDataConnectionAc() != null) {
+ list.addAll(apnContext.getDataConnectionAc().getApnListSync());
+ } else {
+ list.add(apnContext);
+ }
}
}
}
@@ -1110,10 +1116,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
Collection<ApnContext> apns = dcac.getApnListSync();
- // filter out ApnContext with "Connected" state.
+ // filter out ApnContext with "Connected/Connecting" state.
ArrayList<ApnContext> connectedApns = new ArrayList<ApnContext>();
for (ApnContext apnContext : apns) {
- if (apnContext.getState() == State.CONNECTED) {
+ if (apnContext.getState() == State.CONNECTED ||
+ apnContext.getState() == State.CONNECTING ||
+ apnContext.getState() == State.INITING) {
connectedApns.add(apnContext);
}
}
diff --git a/tests/BiDiTests/res/layout/textview_drawables_ltr.xml b/tests/BiDiTests/res/layout/textview_drawables_ltr.xml
new file mode 100644
index 0000000..88b13b7
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_drawables_ltr.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/textview_drawables_ltr"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layoutDirection="ltr">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableStart="@drawable/start"
+ android:drawableEnd="@drawable/end"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableLeft="@drawable/end"
+ android:drawableStart="@drawable/start"
+ android:drawableEnd="@drawable/end"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableRight="@drawable/start"
+ android:drawableStart="@drawable/start"
+ android:drawableEnd="@drawable/end"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableLeft="@drawable/end"
+ android:drawableRight="@drawable/start"
+ android:drawableStart="@drawable/start"
+ android:drawableEnd="@drawable/end"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableRight="@drawable/end"
+ android:drawableStart="@drawable/start"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableLeft="@drawable/start"
+ android:drawableEnd="@drawable/end"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:id="@+id/textview_error"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawablePadding="3dip"
+ />
+
+ </LinearLayout>
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/textview_drawables_rtl.xml b/tests/BiDiTests/res/layout/textview_drawables_rtl.xml
new file mode 100644
index 0000000..7f47d5d
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_drawables_rtl.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/textview_drawables_rtl"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layoutDirection="rtl">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableLeft="@drawable/end"
+ android:drawableRight="@drawable/start"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableStart="@drawable/start"
+ android:drawableEnd="@drawable/end"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableLeft="@drawable/start"
+ android:drawableStart="@drawable/start"
+ android:drawableEnd="@drawable/end"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableRight="@drawable/end"
+ android:drawableStart="@drawable/start"
+ android:drawableEnd="@drawable/end"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:drawableStart="@drawable/start"
+ android:drawableEnd="@drawable/end"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableLeft="@drawable/end"
+ android:drawableStart="@drawable/start"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawableRight="@drawable/start"
+ android:drawableEnd="@drawable/end"
+ android:drawablePadding="3dip"
+ />
+
+ <TextView android:id="@+id/textview_error"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:drawablePadding="3dip"
+ />
+
+ </LinearLayout>
+
+</FrameLayout>
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index c033879..7002c41 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -134,6 +134,9 @@ public class BiDiTestActivity extends Activity {
addItem(result, "TextDirection LTR", BiDiTestTextViewDirectionLtr.class, R.id.textview_direction_ltr);
addItem(result, "TextDirection RTL", BiDiTestTextViewDirectionRtl.class, R.id.textview_direction_rtl);
+ addItem(result, "TextView Drawables LTR", BiDiTestTextViewDrawablesLtr.class, R.id.textview_drawables_ltr);
+ addItem(result, "TextView Drawables RTL", BiDiTestTextViewDrawablesRtl.class, R.id.textview_drawables_rtl);
+
return result;
}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesLtr.java
new file mode 100644
index 0000000..a65d92d
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesLtr.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class BiDiTestTextViewDrawablesLtr extends Fragment {
+
+ private View currentView;
+ private TextView textViewError;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ currentView = inflater.inflate(R.layout.textview_drawables_ltr, container, false);
+ return currentView;
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ textViewError = (TextView) currentView.findViewById(R.id.textview_error);
+ textViewError.setError("Error!!");
+ }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesRtl.java
new file mode 100644
index 0000000..7b7e812
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesRtl.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class BiDiTestTextViewDrawablesRtl extends Fragment {
+
+ private View currentView;
+ private TextView textViewError;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ currentView = inflater.inflate(R.layout.textview_drawables_rtl, container, false);
+ return currentView;
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ textViewError = (TextView) currentView.findViewById(R.id.textview_error);
+ textViewError.setError("Error!!");
+ }
+}
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index cb8084d..32a6a65 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -382,6 +382,15 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+
+ <activity
+ android:name="MoreNinePatchesActivity"
+ android:label="_9patch2">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
<activity
android:name="QuickRejectActivity"
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_bg_holo_dark.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_bg_holo_dark.9.png
new file mode 100644
index 0000000..089704e
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_bg_holo_dark.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_primary_holo_dark.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_primary_holo_dark.9.png
new file mode 100644
index 0000000..385dbc4
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_primary_holo_dark.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_secondary_holo_dark.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_secondary_holo_dark.9.png
new file mode 100644
index 0000000..f1510b2
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/progress_vertical_secondary_holo_dark.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_primary_holo.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_primary_holo.9.png
new file mode 100644
index 0000000..4208c6f
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_primary_holo.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_secondary_holo.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_secondary_holo.9.png
new file mode 100644
index 0000000..b25fb2f
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_secondary_holo.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_dark.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_dark.9.png
new file mode 100644
index 0000000..25129c6
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_dark.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_light.9.png b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_light.9.png
new file mode 100644
index 0000000..1505e0e
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-nodpi/scrubber_vertical_track_holo_light.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable/progress_vertical_holo_dark.xml b/tests/HwAccelerationTest/res/drawable/progress_vertical_holo_dark.xml
new file mode 100644
index 0000000..9eb54b7
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable/progress_vertical_holo_dark.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:id="@android:id/background"
+ android:drawable="@drawable/progress_vertical_bg_holo_dark" />
+
+ <item android:id="@android:id/secondaryProgress">
+ <scale android:scaleHeight="100%" android:scaleGravity="bottom"
+ android:drawable="@drawable/progress_vertical_secondary_holo_dark" />
+ </item>
+
+ <item android:id="@android:id/progress">
+ <scale android:scaleHeight="100%" android:scaleGravity="bottom"
+ android:drawable="@drawable/progress_vertical_primary_holo_dark" />
+ </item>
+
+</layer-list>
diff --git a/tests/HwAccelerationTest/res/drawable/scrubber_progress_vertical_holo_dark.xml b/tests/HwAccelerationTest/res/drawable/scrubber_progress_vertical_holo_dark.xml
new file mode 100644
index 0000000..0cc56bf
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable/scrubber_progress_vertical_holo_dark.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@android:id/background"
+ android:drawable="@drawable/scrubber_vertical_track_holo_dark" />
+ <item android:id="@android:id/secondaryProgress">
+ <scale android:scaleHeight="100%" android:scaleGravity="bottom"
+ android:drawable="@drawable/scrubber_vertical_secondary_holo" />
+ </item>
+ <item android:id="@android:id/progress">
+ <scale android:scaleHeight="100%" android:scaleGravity="bottom"
+ android:drawable="@drawable/scrubber_vertical_primary_holo" />
+ </item>
+</layer-list>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MoreNinePatchesActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MoreNinePatchesActivity.java
new file mode 100644
index 0000000..0c42387
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MoreNinePatchesActivity.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class MoreNinePatchesActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ FrameLayout layout = new FrameLayout(this);
+ PatchView b = new PatchView (this);
+ b.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.MATCH_PARENT, Gravity.CENTER));
+ layout.addView(b);
+ layout.setBackgroundColor(0xffffffff);
+
+ setContentView(layout);
+ }
+
+ private class PatchView extends View {
+ private final Drawable mDrawable1;
+ private final Drawable mDrawable2;
+ private final Drawable mDrawable3;
+
+ private PatchView(Context context) {
+ super(context);
+ Resources res = context.getResources();
+ mDrawable1 = res.getDrawable(R.drawable.progress_vertical_holo_dark);
+ mDrawable2 = res.getDrawable(R.drawable.scrubber_progress_vertical_holo_dark);
+ mDrawable3 = res.getDrawable(R.drawable.scrubber_vertical_primary_holo);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ canvas.translate(100, 100);
+ mDrawable1.setBounds(0, 0, 33, 120);
+ mDrawable1.setLevel(5000);
+ mDrawable1.draw(canvas);
+
+ canvas.translate(20, 0);
+ mDrawable2.setBounds(0, 0, 33, 120);
+ mDrawable2.setLevel(5000);
+ mDrawable2.draw(canvas);
+
+ canvas.translate(20, 0);
+ mDrawable3.setBounds(0, 0, 33, 120);
+ mDrawable3.draw(canvas);
+ }
+ }
+}
diff --git a/tests/RenderScriptTests/FBOTest/Android.mk b/tests/RenderScriptTests/FBOTest/Android.mk
index 55525c4..1df7b26 100644
--- a/tests/RenderScriptTests/FBOTest/Android.mk
+++ b/tests/RenderScriptTests/FBOTest/Android.mk
@@ -14,8 +14,6 @@
# limitations under the License.
#
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@@ -26,5 +24,3 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-fil
LOCAL_PACKAGE_NAME := FBOTest
include $(BUILD_PACKAGE)
-
-endif
diff --git a/tests/RenderScriptTests/ImageProcessing/Android.mk b/tests/RenderScriptTests/ImageProcessing/Android.mk
index 7fa30d0..507cc92 100644
--- a/tests/RenderScriptTests/ImageProcessing/Android.mk
+++ b/tests/RenderScriptTests/ImageProcessing/Android.mk
@@ -14,8 +14,6 @@
# limitations under the License.
#
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@@ -28,5 +26,3 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) \
LOCAL_PACKAGE_NAME := ImageProcessing
include $(BUILD_PACKAGE)
-
-endif
diff --git a/tests/RenderScriptTests/ModelViewer/Android.mk b/tests/RenderScriptTests/ModelViewer/Android.mk
index efe77d7..1d9bacf 100644
--- a/tests/RenderScriptTests/ModelViewer/Android.mk
+++ b/tests/RenderScriptTests/ModelViewer/Android.mk
@@ -14,8 +14,6 @@
# limitations under the License.
#
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@@ -27,5 +25,3 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-fil
LOCAL_PACKAGE_NAME := ModelViewer
include $(BUILD_PACKAGE)
-
-endif
diff --git a/tests/RenderScriptTests/PerfTest/Android.mk b/tests/RenderScriptTests/PerfTest/Android.mk
index 757b3b1..0d1e7d2 100644
--- a/tests/RenderScriptTests/PerfTest/Android.mk
+++ b/tests/RenderScriptTests/PerfTest/Android.mk
@@ -14,8 +14,6 @@
# limitations under the License.
#
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@@ -29,5 +27,3 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-fil
LOCAL_PACKAGE_NAME := PerfTest
include $(BUILD_PACKAGE)
-
-endif
diff --git a/tests/RenderScriptTests/tests/Android.mk b/tests/RenderScriptTests/tests/Android.mk
index 6c992d5..880b80f 100644
--- a/tests/RenderScriptTests/tests/Android.mk
+++ b/tests/RenderScriptTests/tests/Android.mk
@@ -14,8 +14,6 @@
# limitations under the License.
#
-ifneq ($(TARGET_SIMULATOR),true)
-
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@@ -26,5 +24,3 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-fil
LOCAL_PACKAGE_NAME := RSTest
include $(BUILD_PACKAGE)
-
-endif
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png
new file mode 100644
index 0000000..ac5a97b
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png
new file mode 100644
index 0000000..a90dc9b
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png
new file mode 100644
index 0000000..cb3c433
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
index 4bcd2be..5ab09f0 100644
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
index cfeba3e..62ca427 100644
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
index 1d97e05..ff698fb 100644
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png
new file mode 100644
index 0000000..4cb305d
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png
new file mode 100644
index 0000000..31d35c8
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png
new file mode 100644
index 0000000..f0cc341
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
new file mode 100644
index 0000000..83f9cc2
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import com.android.layoutlib.bridge.android.BridgeWindowManager;
+import com.android.layoutlib.bridge.impl.RenderAction;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.os.RemoteException;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link Display}
+ *
+ * Through the layoutlib_create tool, the original methods of Display have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class Display_Delegate {
+
+ // ---- Overridden methods ----
+
+ @LayoutlibDelegate
+ public static IWindowManager getWindowManager() {
+ return RenderAction.getCurrentContext().getIWindowManager();
+ }
+
+ // ---- Native methods ----
+
+ @LayoutlibDelegate
+ /*package*/ static int getDisplayCount() {
+ return 1;
+ }
+
+ @LayoutlibDelegate
+ /** @hide Returns the actual screen size, not including any decor. */
+ /*package*/ static int getRealWidth(Display theDisplay) {
+ // always dynamically query for the current window manager
+ return RenderAction.getCurrentContext().getIWindowManager().getMetrics().widthPixels;
+ }
+
+ @LayoutlibDelegate
+ /** @hide Returns the actual screen size, not including any decor. */
+ /*package*/ static int getRealHeight(Display theDisplay) {
+ // always dynamically query for the current window manager
+ return RenderAction.getCurrentContext().getIWindowManager().getMetrics().heightPixels;
+ }
+
+ @LayoutlibDelegate
+ /** @hide special for when we are faking the screen size. */
+ /*package*/ static int getRawWidth(Display theDisplay) {
+ // same as real since we're not faking compatibility mode.
+ return getRealWidth(theDisplay);
+ }
+
+ @LayoutlibDelegate
+ /** @hide special for when we are faking the screen size. */
+ /*package*/ static int getRawHeight(Display theDisplay) {
+ // same as real since we're not faking compatibility mode.
+ return getRealHeight(theDisplay);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static int getOrientation(Display theDisplay) {
+ try {
+ // always dynamically query for the current window manager
+ return getWindowManager().getRotation();
+ } catch (RemoteException e) {
+ // this will never been thrown since this is not a true RPC.
+ }
+
+ return Surface.ROTATION_0;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nativeClassInit() {
+ // not needed for now.
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void init(Display theDisplay, int display) {
+ // always dynamically query for the current window manager
+ BridgeWindowManager wm = RenderAction.getCurrentContext().getIWindowManager();
+ theDisplay.mDensity = wm.getMetrics().density;
+ theDisplay.mDpiX = wm.getMetrics().xdpi;
+ theDisplay.mDpiY = wm.getMetrics().ydpi;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java
index 251c053..1fd7836 100644
--- a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java
+++ b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java
@@ -16,8 +16,11 @@
package android.view.accessibility;
+import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.content.pm.ServiceInfo;
+import android.view.IWindow;
+import android.view.View;
import java.util.Collections;
import java.util.List;
@@ -38,6 +41,19 @@ public final class AccessibilityManager {
private static AccessibilityManager sInstance = new AccessibilityManager();
/**
+ * Listener for the accessibility state.
+ */
+ public interface AccessibilityStateChangeListener {
+
+ /**
+ * Called back on change in the accessibility state.
+ *
+ * @param enabled Whether accessibility is enabled.
+ */
+ public void onAccessibilityStateChanged(boolean enabled);
+ }
+
+ /**
* Get an AccessibilityManager instance (create one if necessary).
*
* @hide
@@ -92,4 +108,30 @@ public final class AccessibilityManager {
List<ServiceInfo> services = null;
return Collections.unmodifiableList(services);
}
+
+ public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
+ // normal implementation does this in some case, so let's do the same
+ // (unmodifiableList wrapped around null).
+ List<AccessibilityServiceInfo> services = null;
+ return Collections.unmodifiableList(services);
+ }
+
+ public boolean addAccessibilityStateChangeListener(
+ AccessibilityStateChangeListener listener) {
+ return true;
+ }
+
+ public boolean removeAccessibilityStateChangeListener(
+ AccessibilityStateChangeListener listener) {
+ return true;
+ }
+
+ public int addAccessibilityInteractionConnection(IWindow windowToken,
+ IAccessibilityInteractionConnection connection) {
+ return View.NO_ID;
+ }
+
+ public void removeAccessibilityInteractionConnection(IWindow windowToken) {
+ }
+
}
diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
new file mode 100644
index 0000000..ec7a67e
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+import com.android.layoutlib.bridge.android.BridgeIInputMethodManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.os.Looper;
+
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link InputMethodManager}
+ *
+ * Through the layoutlib_create tool, the original methods of InputMethodManager have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class InputMethodManager_Delegate {
+
+ // ---- Overridden methods ----
+
+ @LayoutlibDelegate
+ /*package*/ static InputMethodManager getInstance(Looper mainLooper) {
+ synchronized (InputMethodManager.mInstanceSync) {
+ if (InputMethodManager.mInstance != null) {
+ return InputMethodManager.mInstance;
+ }
+
+ InputMethodManager.mInstance = new InputMethodManager(new BridgeIInputMethodManager(),
+ mainLooper);
+ }
+ return InputMethodManager.mInstance;
+
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 47fa68e..69e0de9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -64,6 +64,7 @@ import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.LayoutInflater;
+import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
@@ -91,7 +92,11 @@ public final class BridgeContext extends Activity {
private final Object mProjectKey;
private final DisplayMetrics mMetrics;
private final RenderResources mRenderResources;
+ private final Configuration mConfig;
private final ApplicationInfo mApplicationInfo;
+ private final IProjectCallback mProjectCallback;
+
+ private final BridgeWindowManager mIWindowManager;
private final Map<Object, Map<String, String>> mDefaultPropMaps =
new IdentityHashMap<Object, Map<String,String>>();
@@ -105,7 +110,6 @@ public final class BridgeContext extends Activity {
private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache;
private BridgeInflater mBridgeInflater;
- private final IProjectCallback mProjectCallback;
private BridgeContentResolver mContentResolver;
private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>();
@@ -113,28 +117,25 @@ public final class BridgeContext extends Activity {
/**
* @param projectKey An Object identifying the project. This is used for the cache mechanism.
* @param metrics the {@link DisplayMetrics}.
- * @param themeName The name of the theme to use.
- * @param projectResources the resources of the project. The map contains (String, map) pairs
- * where the string is the type of the resource reference used in the layout file, and the
- * map contains (String, {@link }) pairs where the key is the resource name,
- * and the value is the resource value.
- * @param frameworkResources the framework resources. The map contains (String, map) pairs
- * where the string is the type of the resource reference used in the layout file, and the map
- * contains (String, {@link ResourceValue}) pairs where the key is the resource name, and the
- * value is the resource value.
- * @param styleInheritanceMap
+ * @param renderResources the configured resources (both framework and projects) for this
+ * render.
* @param projectCallback
+ * @param config the Configuration object for this render.
* @param targetSdkVersion the targetSdkVersion of the application.
*/
public BridgeContext(Object projectKey, DisplayMetrics metrics,
RenderResources renderResources,
IProjectCallback projectCallback,
+ Configuration config,
int targetSdkVersion) {
mProjectKey = projectKey;
mMetrics = metrics;
mProjectCallback = projectCallback;
mRenderResources = renderResources;
+ mConfig = config;
+
+ mIWindowManager = new BridgeWindowManager(mConfig, metrics, Surface.ROTATION_0);
mFragments.mCurState = Fragment.CREATED;
mFragments.mActivity = this;
@@ -151,13 +152,12 @@ public final class BridgeContext extends Activity {
*/
public void initResources() {
AssetManager assetManager = AssetManager.getSystem();
- Configuration config = new Configuration();
mSystemResources = BridgeResources.initSystem(
this,
assetManager,
mMetrics,
- config,
+ mConfig,
mProjectCallback);
mTheme = mSystemResources.newTheme();
}
@@ -197,6 +197,10 @@ public final class BridgeContext extends Activity {
return mRenderResources;
}
+ public BridgeWindowManager getIWindowManager() {
+ return mIWindowManager;
+ }
+
public Map<String, String> getDefaultPropMap(Object key) {
return mDefaultPropMaps.get(key);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
new file mode 100644
index 0000000..1394c32
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.android;
+
+import com.android.internal.view.IInputContext;
+import com.android.internal.view.IInputMethodClient;
+import com.android.internal.view.IInputMethodManager;
+import com.android.internal.view.InputBindResult;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.text.style.SuggestionSpan;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import java.util.List;
+
+/**
+ * Basic implementation of IInputMethodManager that does nothing.
+ *
+ */
+public class BridgeIInputMethodManager implements IInputMethodManager {
+
+ public void addClient(IInputMethodClient arg0, IInputContext arg1, int arg2, int arg3)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void finishInput(IInputMethodClient arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public InputMethodSubtype getCurrentInputMethodSubtype() throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public List<InputMethodInfo> getEnabledInputMethodList() throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo arg0,
+ boolean arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public List<InputMethodInfo> getInputMethodList() throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public InputMethodSubtype getLastInputMethodSubtype() throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public List getShortcutInputMethodsAndSubtypes() throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void hideMySoftInput(IBinder arg0, int arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean hideSoftInput(IInputMethodClient arg0, int arg1, ResultReceiver arg2)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean notifySuggestionPicked(SuggestionSpan arg0, String arg1, int arg2)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void registerSuggestionSpansForNotification(SuggestionSpan[] arg0)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void removeClient(IInputMethodClient arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean setAdditionalInputMethodSubtypes(IBinder arg0, InputMethodSubtype[] arg1)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean setCurrentInputMethodSubtype(InputMethodSubtype arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void setImeWindowStatus(IBinder arg0, int arg1, int arg2) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setInputMethod(IBinder arg0, String arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setInputMethodAndSubtype(IBinder arg0, String arg1, InputMethodSubtype arg2)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean setInputMethodEnabled(String arg0, boolean arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void showInputMethodAndSubtypeEnablerFromClient(IInputMethodClient arg0, String arg1)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void showInputMethodPickerFromClient(IInputMethodClient arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void showMySoftInput(IBinder arg0, int arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean showSoftInput(IInputMethodClient arg0, int arg1, ResultReceiver arg2)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public InputBindResult startInput(IInputMethodClient arg0, IInputContext arg1, EditorInfo arg2,
+ boolean arg3, boolean arg4) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean switchToLastInputMethod(IBinder arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void updateStatusIcon(IBinder arg0, String arg1, int arg2) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void windowGainedFocus(IInputMethodClient arg0, IBinder arg1, boolean arg2,
+ boolean arg3, int arg4, boolean arg5, int arg6) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public IBinder asBinder() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index 260cdc8..fc2f2f8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -131,6 +131,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public CharSequence getText(int index) {
+ if (index < 0 || index >= mResourceData.length) {
+ return null;
+ }
+
if (mResourceData[index] != null) {
// FIXME: handle styled strings!
return mResourceData[index].getValue();
@@ -149,6 +153,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public String getString(int index) {
+ if (index < 0 || index >= mResourceData.length) {
+ return null;
+ }
+
if (mResourceData[index] != null) {
return mResourceData[index].getValue();
}
@@ -166,6 +174,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public boolean getBoolean(int index, boolean defValue) {
+ if (index < 0 || index >= mResourceData.length) {
+ return defValue;
+ }
+
if (mResourceData[index] == null) {
return defValue;
}
@@ -188,6 +200,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public int getInt(int index, int defValue) {
+ if (index < 0 || index >= mResourceData.length) {
+ return defValue;
+ }
+
if (mResourceData[index] == null) {
return defValue;
}
@@ -252,6 +268,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public float getFloat(int index, float defValue) {
+ if (index < 0 || index >= mResourceData.length) {
+ return defValue;
+ }
+
if (mResourceData[index] == null) {
return defValue;
}
@@ -287,6 +307,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public int getColor(int index, int defValue) {
+ if (index < 0 || index >= mResourceData.length) {
+ return defValue;
+ }
+
if (mResourceData[index] == null) {
return defValue;
}
@@ -311,6 +335,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public ColorStateList getColorStateList(int index) {
+ if (index < 0 || index >= mResourceData.length) {
+ return null;
+ }
+
if (mResourceData[index] == null) {
return null;
}
@@ -395,6 +423,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public float getDimension(int index, float defValue) {
+ if (index < 0 || index >= mResourceData.length) {
+ return defValue;
+ }
+
if (mResourceData[index] == null) {
return defValue;
}
@@ -568,6 +600,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public float getFraction(int index, int base, int pbase, float defValue) {
+ if (index < 0 || index >= mResourceData.length) {
+ return defValue;
+ }
+
if (mResourceData[index] == null) {
return defValue;
}
@@ -607,6 +643,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public int getResourceId(int index, int defValue) {
+ if (index < 0 || index >= mResourceData.length) {
+ return defValue;
+ }
+
// get the Resource for this index
ResourceValue resValue = mResourceData[index];
@@ -718,6 +758,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public Drawable getDrawable(int index) {
+ if (index < 0 || index >= mResourceData.length) {
+ return null;
+ }
+
if (mResourceData[index] == null) {
return null;
}
@@ -744,6 +788,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public CharSequence[] getTextArray(int index) {
+ if (index < 0 || index >= mResourceData.length) {
+ return null;
+ }
+
if (mResourceData[index] == null) {
return null;
}
@@ -776,6 +824,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public boolean getValue(int index, TypedValue outValue) {
+ if (index < 0 || index >= mResourceData.length) {
+ return false;
+ }
+
if (mResourceData[index] == null) {
return false;
}
@@ -795,6 +847,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public boolean hasValue(int index) {
+ if (index < 0 || index >= mResourceData.length) {
+ return false;
+ }
+
return mResourceData[index] != null;
}
@@ -811,6 +867,10 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public TypedValue peekValue(int index) {
+ if (index < 0 || index >= mResourceData.length) {
+ return null;
+ }
+
if (getValue(index, mValue)) {
return mValue;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
new file mode 100644
index 0000000..13cd9ec
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.android;
+
+import com.android.internal.view.IInputContext;
+import com.android.internal.view.IInputMethodClient;
+
+import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.Display_Delegate;
+import android.view.IApplicationToken;
+import android.view.IOnKeyguardExitResult;
+import android.view.IRotationWatcher;
+import android.view.IWindowManager;
+import android.view.IWindowSession;
+import android.view.InputChannel;
+import android.view.InputDevice;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import java.util.List;
+
+/**
+ * Basic implementation of {@link IWindowManager} so that {@link Display} (and
+ * {@link Display_Delegate}) can return a valid instance.
+ */
+public class BridgeWindowManager implements IWindowManager {
+
+ private final Configuration mConfig;
+ private final DisplayMetrics mMetrics;
+ private final int mRotation;
+
+ public BridgeWindowManager(Configuration config, DisplayMetrics metrics, int rotation) {
+ mConfig = config;
+ mMetrics = metrics;
+ mRotation = rotation;
+ }
+
+ // custom API.
+
+ public DisplayMetrics getMetrics() {
+ return mMetrics;
+ }
+
+ // ---- implementation of IWindowManager that we care about ----
+
+ public int getRotation() throws RemoteException {
+ return mRotation;
+ }
+
+ public int getMaximumSizeDimension() throws RemoteException {
+ return 0;
+ }
+
+ public void getDisplaySize(Point arg0) throws RemoteException {
+ }
+
+ // ---- unused implementation of IWindowManager ----
+
+ public boolean canStatusBarHide() throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, boolean arg4)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void addWindowToken(IBinder arg0, int arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void clearForcedDisplaySize() throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void closeSystemDialogs(String arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void disableKeyguard(IBinder arg0, String arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void executeAppTransition() throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void exitKeyguardSecurely(IOnKeyguardExitResult arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void freezeRotation() throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public float getAnimationScale(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public float[] getAnimationScales() throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int getAppOrientation(IApplicationToken arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getDPadKeycodeState(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getDPadScancodeState(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+
+ public InputDevice getInputDevice(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int[] getInputDeviceIds() throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int getKeycodeState(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getKeycodeStateForDevice(int arg0, int arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+
+ public int getPendingAppTransition() throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+
+ public int getScancodeState(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getScancodeStateForDevice(int arg0, int arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getSwitchState(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getSwitchStateForDevice(int arg0, int arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getTrackballKeycodeState(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getTrackballScancodeState(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public boolean hasKeys(int[] arg0, boolean[] arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean inKeyguardRestrictedInputMode() throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean injectInputEventNoWait(InputEvent arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean injectKeyEvent(KeyEvent arg0, boolean arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean injectPointerEvent(MotionEvent arg0, boolean arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean injectTrackballEvent(MotionEvent arg0, boolean arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean inputMethodClientHasFocus(IInputMethodClient arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isKeyguardLocked() throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isKeyguardSecure() throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isViewServerRunning() throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public InputChannel monitorInput(String arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void moveAppToken(int arg0, IBinder arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void moveAppTokensToBottom(List<IBinder> arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void moveAppTokensToTop(List<IBinder> arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public IWindowSession openSession(IInputMethodClient arg0, IInputContext arg1)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void overridePendingAppTransition(String arg0, int arg1, int arg2)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void prepareAppTransition(int arg0, boolean arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void reenableKeyguard(IBinder arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void removeAppToken(IBinder arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void removeWindowToken(IBinder arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void resumeKeyDispatching(IBinder arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public Bitmap screenshotApplications(IBinder arg0, int arg1, int arg2) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setAnimationScale(int arg0, float arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setAnimationScales(float[] arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setAppGroupId(IBinder arg0, int arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setAppOrientation(IApplicationToken arg0, int arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3,
+ CharSequence arg4, int arg5, int arg6, int arg7, IBinder arg8, boolean arg9)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setAppVisibility(IBinder arg0, boolean arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setAppWillBeHidden(IBinder arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setEventDispatching(boolean arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setFocusedApp(IBinder arg0, boolean arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setForcedDisplaySize(int arg0, int arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setInTouchMode(boolean arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setNewConfiguration(Configuration arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setPointerSpeed(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setRotation(int arg0, boolean arg1, int arg2) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setStrictModeVisualIndicatorPreference(String arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void showStrictModeViolation(boolean arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void startAppFreezingScreen(IBinder arg0, int arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean startViewServer(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void statusBarVisibilityChanged(int arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void stopAppFreezingScreen(IBinder arg0, boolean arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean stopViewServer() throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void thawRotation() throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public Configuration updateOrientationFromAppTokens(Configuration arg0, IBinder arg1)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int watchRotation(IRotationWatcher arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public IBinder asBinder() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index 6194f5d..d40222f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -27,10 +27,16 @@ import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.resources.Density;
import com.android.resources.ResourceType;
+import com.android.resources.ScreenSize;
+import android.content.res.Configuration;
import android.os.HandlerThread_Delegate;
+import android.os.Looper;
import android.util.DisplayMetrics;
+import android.view.ViewConfiguration;
+import android.view.inputmethod.InputMethodManager;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
@@ -94,24 +100,29 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
// setup the display Metrics.
DisplayMetrics metrics = new DisplayMetrics();
metrics.densityDpi = mParams.getDensity().getDpiValue();
- metrics.density = metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
- metrics.scaledDensity = metrics.density;
- metrics.widthPixels = mParams.getScreenWidth();
- metrics.heightPixels = mParams.getScreenHeight();
- metrics.xdpi = mParams.getXdpi();
- metrics.ydpi = mParams.getYdpi();
+
+ metrics.density = metrics.noncompatDensity =
+ metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
+
+ metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density;
+
+ metrics.widthPixels = metrics.noncompatWidthPixels = mParams.getScreenWidth();
+ metrics.heightPixels = metrics.noncompatHeightPixels = mParams.getScreenHeight();
+ metrics.xdpi = metrics.noncompatXdpi = mParams.getXdpi();
+ metrics.ydpi = metrics.noncompatYdpi = mParams.getYdpi();
RenderResources resources = mParams.getResources();
// build the context
mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
- mParams.getProjectCallback(), mParams.getTargetSdkVersion());
+ mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion());
setUp();
return SUCCESS.createResult();
}
+
/**
* Prepares the scene for action.
* <p>
@@ -215,6 +226,9 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
mContext.initResources();
sCurrentContext = mContext;
+ // create an InputMethodManager
+ InputMethodManager.getInstance(Looper.myLooper());
+
LayoutLog currentLog = mParams.getLog();
Bridge.setLog(currentLog);
mContext.getRenderResources().setFrameworkResourceIdProvider(this);
@@ -233,6 +247,12 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
// quit HandlerThread created during this session.
HandlerThread_Delegate.cleanUp(sCurrentContext);
+ // clear the stored ViewConfiguration since the map is per density and not per context.
+ ViewConfiguration.sConfigurations.clear();
+
+ // remove the InputMethodManager
+ InputMethodManager.mInstance = null;
+
sCurrentContext = null;
Bridge.setLog(null);
@@ -281,6 +301,50 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
}
}
+ private Configuration getConfiguration() {
+ Configuration config = new Configuration();
+
+ ScreenSize screenSize = mParams.getConfigScreenSize();
+ if (screenSize != null) {
+ switch (screenSize) {
+ case SMALL:
+ config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_SMALL;
+ break;
+ case NORMAL:
+ config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_NORMAL;
+ break;
+ case LARGE:
+ config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_LARGE;
+ break;
+ case XLARGE:
+ config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_XLARGE;
+ break;
+ }
+ }
+
+ Density density = mParams.getDensity();
+ if (density == null) {
+ density = Density.MEDIUM;
+ }
+
+ config.screenWidthDp = mParams.getScreenWidth() / density.getDpiValue();
+ config.screenHeightDp = mParams.getScreenHeight() / density.getDpiValue();
+ if (config.screenHeightDp < config.screenWidthDp) {
+ config.smallestScreenWidthDp = config.screenHeightDp;
+ } else {
+ config.smallestScreenWidthDp = config.screenWidthDp;
+ }
+
+ // never run in compat mode:
+ config.compatScreenWidthDp = config.screenWidthDp;
+ config.compatScreenHeightDp = config.screenHeightDp;
+
+ // TODO: fill in more config info.
+
+ return config;
+ }
+
+
// --- FrameworkResourceIdProvider methods
@Override
diff --git a/tools/layoutlib/bridge/tests/.classpath b/tools/layoutlib/bridge/tests/.classpath
index 9cc2433..027bc67 100644
--- a/tools/layoutlib/bridge/tests/.classpath
+++ b/tools/layoutlib/bridge/tests/.classpath
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="res"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/layoutlib_bridge"/>
<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/>
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 233f72e..df7e04f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -103,9 +103,11 @@ public final class CreateInfo implements ICreateInfo {
"android.os.Handler#sendMessageAtTime",
"android.os.HandlerThread#run",
"android.os.Build#getString",
+ "android.view.Display#getWindowManager",
"android.view.LayoutInflater#rInflate",
"android.view.LayoutInflater#parseInclude",
"android.view.View#isInEditMode",
+ "android.view.inputmethod.InputMethodManager#getInstance",
"com.android.internal.util.XmlUtils#convertValueToInt",
// TODO: comment out once DelegateClass is working
};
@@ -154,6 +156,7 @@ public final class CreateInfo implements ICreateInfo {
"android.graphics.Xfermode",
"android.os.SystemClock",
"android.util.FloatMath",
+ "android.view.Display",
"libcore.icu.ICU",
};
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index c1affa6..fcdbd2c 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -57,6 +57,7 @@ public class SipAudioCall {
private static final boolean RELEASE_SOCKET = true;
private static final boolean DONT_RELEASE_SOCKET = false;
private static final int SESSION_TIMEOUT = 5; // in seconds
+ private static final int TRANSFER_TIMEOUT = 15; // in seconds
/** Listener for events relating to a SIP call, such as when a call is being
* recieved ("on ringing") or a call is outgoing ("on calling").
@@ -537,10 +538,14 @@ public class SipAudioCall {
Log.v(TAG, "onCallTransferring mSipSession:"
+ mSipSession + " newSession:" + newSession);
mTransferringSession = newSession;
- // session changing request
try {
- String answer = createAnswer(sessionDescription).encode();
- newSession.answerCall(answer, SESSION_TIMEOUT);
+ if (sessionDescription == null) {
+ newSession.makeCall(newSession.getPeerProfile(),
+ createOffer().encode(), TRANSFER_TIMEOUT);
+ } else {
+ String answer = createAnswer(sessionDescription).encode();
+ newSession.answerCall(answer, SESSION_TIMEOUT);
+ }
} catch (Throwable e) {
Log.e(TAG, "onCallTransferring()", e);
newSession.endCall();
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index c031bc1..dc628e0 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -19,6 +19,9 @@ package com.android.server.sip;
import gov.nist.javax.sip.SipStackExt;
import gov.nist.javax.sip.clientauthutils.AccountManager;
import gov.nist.javax.sip.clientauthutils.AuthenticationHelper;
+import gov.nist.javax.sip.header.extensions.ReferencesHeader;
+import gov.nist.javax.sip.header.extensions.ReferredByHeader;
+import gov.nist.javax.sip.header.extensions.ReplacesHeader;
import android.net.sip.SipProfile;
import android.util.Log;
@@ -284,14 +287,18 @@ class SipHelper {
}
public ClientTransaction sendInvite(SipProfile caller, SipProfile callee,
- String sessionDescription, String tag)
- throws SipException {
+ String sessionDescription, String tag, ReferredByHeader referredBy,
+ String replaces) throws SipException {
try {
Request request = createRequest(Request.INVITE, caller, callee, tag);
+ if (referredBy != null) request.addHeader(referredBy);
+ if (replaces != null) {
+ request.addHeader(mHeaderFactory.createHeader(
+ ReplacesHeader.NAME, replaces));
+ }
request.setContent(sessionDescription,
mHeaderFactory.createContentTypeHeader(
"application", "sdp"));
-
ClientTransaction clientTransaction =
mSipProvider.getNewClientTransaction(request);
if (DEBUG) Log.d(TAG, "send INVITE: " + request);
@@ -455,6 +462,25 @@ class SipHelper {
}
}
+ public void sendReferNotify(Dialog dialog, String content)
+ throws SipException {
+ try {
+ Request request = dialog.createRequest(Request.NOTIFY);
+ request.addHeader(mHeaderFactory.createSubscriptionStateHeader(
+ "active;expires=60"));
+ // set content here
+ request.setContent(content,
+ mHeaderFactory.createContentTypeHeader(
+ "message", "sipfrag"));
+ request.addHeader(mHeaderFactory.createEventHeader(
+ ReferencesHeader.REFER));
+ if (DEBUG) Log.d(TAG, "send NOTIFY: " + request);
+ dialog.sendRequest(mSipProvider.getNewClientTransaction(request));
+ } catch (ParseException e) {
+ throw new SipException("sendReferNotify()", e);
+ }
+ }
+
public void sendInviteRequestTerminated(Request inviteRequest,
ServerTransaction inviteTransaction) throws SipException {
try {
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 4e44402..48d9b17 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -18,12 +18,15 @@ package com.android.server.sip;
import gov.nist.javax.sip.clientauthutils.AccountManager;
import gov.nist.javax.sip.clientauthutils.UserCredentials;
-import gov.nist.javax.sip.header.SIPHeaderNames;
import gov.nist.javax.sip.header.ProxyAuthenticate;
+import gov.nist.javax.sip.header.ReferTo;
+import gov.nist.javax.sip.header.SIPHeaderNames;
+import gov.nist.javax.sip.header.StatusLine;
import gov.nist.javax.sip.header.WWWAuthenticate;
import gov.nist.javax.sip.header.extensions.ReferredByHeader;
import gov.nist.javax.sip.header.extensions.ReplacesHeader;
import gov.nist.javax.sip.message.SIPMessage;
+import gov.nist.javax.sip.message.SIPResponse;
import android.net.sip.ISipSession;
import android.net.sip.ISipSessionListener;
@@ -71,12 +74,15 @@ import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.ExpiresHeader;
import javax.sip.header.FromHeader;
+import javax.sip.header.HeaderAddress;
import javax.sip.header.MinExpiresHeader;
+import javax.sip.header.ReferToHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Message;
import javax.sip.message.Request;
import javax.sip.message.Response;
+
/**
* Manages {@link ISipSession}'s for a SIP account.
*/
@@ -390,25 +396,26 @@ class SipSessionGroup implements SipListener {
}
}
+ private SipSessionImpl createNewSession(RequestEvent event,
+ ISipSessionListener listener, ServerTransaction transaction,
+ int newState) throws SipException {
+ SipSessionImpl newSession = new SipSessionImpl(listener);
+ newSession.mServerTransaction = transaction;
+ newSession.mState = newState;
+ newSession.mDialog = newSession.mServerTransaction.getDialog();
+ newSession.mInviteReceived = event;
+ newSession.mPeerProfile = createPeerProfile((HeaderAddress)
+ event.getRequest().getHeader(FromHeader.NAME));
+ newSession.mPeerSessionDescription =
+ extractContent(event.getRequest());
+ return newSession;
+ }
+
private class SipSessionCallReceiverImpl extends SipSessionImpl {
public SipSessionCallReceiverImpl(ISipSessionListener listener) {
super(listener);
}
- private SipSessionImpl createNewSession(RequestEvent event,
- ISipSessionListener listener, ServerTransaction transaction)
- throws SipException {
- SipSessionImpl newSession = new SipSessionImpl(listener);
- newSession.mServerTransaction = transaction;
- newSession.mState = SipSession.State.INCOMING_CALL;
- newSession.mDialog = newSession.mServerTransaction.getDialog();
- newSession.mInviteReceived = event;
- newSession.mPeerProfile = createPeerProfile(event.getRequest());
- newSession.mPeerSessionDescription =
- extractContent(event.getRequest());
- return newSession;
- }
-
private int processInviteWithReplaces(RequestEvent event,
ReplacesHeader replaces) {
String callId = replaces.getCallId();
@@ -452,7 +459,8 @@ class SipSessionGroup implements SipListener {
// got INVITE w/ replaces request.
newSession = createNewSession(event,
replacedSession.mProxy.getListener(),
- mSipHelper.getServerTransaction(event));
+ mSipHelper.getServerTransaction(event),
+ SipSession.State.INCOMING_CALL);
newSession.mProxy.onCallTransferring(newSession,
newSession.mPeerSessionDescription);
} else {
@@ -461,7 +469,8 @@ class SipSessionGroup implements SipListener {
} else {
// New Incoming call.
newSession = createNewSession(event, mProxy,
- mSipHelper.sendRinging(event, generateTag()));
+ mSipHelper.sendRinging(event, generateTag()),
+ SipSession.State.INCOMING_CALL);
mProxy.onRinging(newSession, newSession.mPeerProfile,
newSession.mPeerSessionDescription);
}
@@ -507,6 +516,11 @@ class SipSessionGroup implements SipListener {
private SipSessionImpl mKeepAliveSession;
+ // the following three members are used for handling refer request.
+ SipSessionImpl mReferSession;
+ ReferredByHeader mReferredBy;
+ String mReplaces;
+
// lightweight timer
class SessionTimer {
private boolean mRunning = true;
@@ -556,6 +570,9 @@ class SipSessionGroup implements SipListener {
mInviteReceived = null;
mPeerSessionDescription = null;
mAuthenticationRetryCount = 0;
+ mReferSession = null;
+ mReferredBy = null;
+ mReplaces = null;
if (mDialog != null) mDialog.delete();
mDialog = null;
@@ -969,15 +986,26 @@ class SipSessionGroup implements SipListener {
return (proxyAuth == null) ? null : proxyAuth.getNonce();
}
+ private String getResponseString(int statusCode) {
+ StatusLine statusLine = new StatusLine();
+ statusLine.setStatusCode(statusCode);
+ statusLine.setReasonPhrase(SIPResponse.getReasonPhrase(statusCode));
+ return statusLine.encode();
+ }
+
private boolean readyForCall(EventObject evt) throws SipException {
// expect MakeCallCommand, RegisterCommand, DEREGISTER
if (evt instanceof MakeCallCommand) {
mState = SipSession.State.OUTGOING_CALL;
MakeCallCommand cmd = (MakeCallCommand) evt;
mPeerProfile = cmd.getPeerProfile();
- mClientTransaction = mSipHelper.sendInvite(mLocalProfile,
- mPeerProfile, cmd.getSessionDescription(),
- generateTag());
+ if (mReferSession != null) {
+ mSipHelper.sendReferNotify(mReferSession.mDialog,
+ getResponseString(Response.TRYING));
+ }
+ mClientTransaction = mSipHelper.sendInvite(
+ mLocalProfile, mPeerProfile, cmd.getSessionDescription(),
+ generateTag(), mReferredBy, mReplaces);
mDialog = mClientTransaction.getDialog();
addSipSession(this);
startSessionTimer(cmd.getTimeout());
@@ -1072,6 +1100,12 @@ class SipSessionGroup implements SipListener {
}
return true;
case Response.OK:
+ if (mReferSession != null) {
+ mSipHelper.sendReferNotify(mReferSession.mDialog,
+ getResponseString(Response.OK));
+ // since we don't need to remember the session anymore.
+ mReferSession = null;
+ }
mSipHelper.sendInviteAck(event, mDialog);
mPeerSessionDescription = extractContent(response);
establishCall(true);
@@ -1087,6 +1121,10 @@ class SipSessionGroup implements SipListener {
// rfc3261#section-14.1; re-schedule invite
return true;
default:
+ if (mReferSession != null) {
+ mSipHelper.sendReferNotify(mReferSession.mDialog,
+ getResponseString(Response.SERVICE_UNAVAILABLE));
+ }
if (statusCode >= 400) {
// error: an ack is sent automatically by the stack
onError(response);
@@ -1155,6 +1193,38 @@ class SipSessionGroup implements SipListener {
return false;
}
+ private boolean processReferRequest(RequestEvent event)
+ throws SipException {
+ try {
+ ReferToHeader referto = (ReferToHeader) event.getRequest()
+ .getHeader(ReferTo.NAME);
+ Address address = referto.getAddress();
+ SipURI uri = (SipURI) address.getURI();
+ String replacesHeader = uri.getHeader(ReplacesHeader.NAME);
+ String username = uri.getUser();
+ if (username == null) {
+ mSipHelper.sendResponse(event, Response.BAD_REQUEST);
+ return false;
+ }
+ // send notify accepted
+ mSipHelper.sendResponse(event, Response.ACCEPTED);
+ SipSessionImpl newSession = createNewSession(event,
+ this.mProxy.getListener(),
+ mSipHelper.getServerTransaction(event),
+ SipSession.State.READY_TO_CALL);
+ newSession.mReferSession = this;
+ newSession.mReferredBy = (ReferredByHeader) event.getRequest()
+ .getHeader(ReferredByHeader.NAME);
+ newSession.mReplaces = replacesHeader;
+ newSession.mPeerProfile = createPeerProfile(referto);
+ newSession.mProxy.onCallTransferring(newSession,
+ null);
+ return true;
+ } catch (IllegalArgumentException e) {
+ throw new SipException("createPeerProfile()", e);
+ }
+ }
+
private boolean inCall(EventObject evt) throws SipException {
// expect END_CALL cmd, BYE request, hold call (MakeCallCommand)
// OK retransmission is handled in SipStack
@@ -1175,6 +1245,8 @@ class SipSessionGroup implements SipListener {
mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
endCallNormally();
return true;
+ } else if (isRequestEvent(Request.REFER, evt)) {
+ return processReferRequest((RequestEvent) evt);
} else if (evt instanceof MakeCallCommand) {
// to change call
mState = SipSession.State.OUTGOING_CALL;
@@ -1182,6 +1254,8 @@ class SipSessionGroup implements SipListener {
((MakeCallCommand) evt).getSessionDescription());
startSessionTimer(((MakeCallCommand) evt).getTimeout());
return true;
+ } else if (evt instanceof ResponseEvent) {
+ if (expectResponse(Request.NOTIFY, evt)) return true;
}
return false;
}
@@ -1558,12 +1632,10 @@ class SipSessionGroup implements SipListener {
return false;
}
- private static SipProfile createPeerProfile(Request request)
+ private static SipProfile createPeerProfile(HeaderAddress header)
throws SipException {
try {
- FromHeader fromHeader =
- (FromHeader) request.getHeader(FromHeader.NAME);
- Address address = fromHeader.getAddress();
+ Address address = header.getAddress();
SipURI uri = (SipURI) address.getURI();
String username = uri.getUser();
if (username == null) username = ANONYMOUS;