summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt274
-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/bmgr/src/com/android/commands/bmgr/Bmgr.java32
-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/system_server/library/system_init.cpp31
-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/IRestoreSession.aidl19
-rw-r--r--core/java/android/app/backup/RestoreSession.java34
-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.java135
-rw-r--r--core/java/android/net/NetworkUtils.java18
-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.java24
-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.java119
-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.java10
-rw-r--r--core/java/android/speech/tts/AudioPlaybackHandler.java7
-rw-r--r--core/java/android/speech/tts/EventLogTags.logtags6
-rw-r--r--core/java/android/speech/tts/EventLogger.java175
-rw-r--r--core/java/android/speech/tts/PlaybackSynthesisCallback.java33
-rw-r--r--core/java/android/speech/tts/SynthesisMessageParams.java4
-rw-r--r--core/java/android/speech/tts/TextToSpeechService.java13
-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/HardwareRenderer.java88
-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.java9
-rw-r--r--core/java/android/webkit/L10nUtils.java14
-rw-r--r--core/java/android/webkit/WebViewCore.java4
-rw-r--r--core/java/android/webkit/ZoomManager.java7
-rw-r--r--core/java/android/widget/TextView.java56
-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/util/Protocol.java5
-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.java57
-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/jni/android_net_NetUtils.cpp13
-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.xml6
-rw-r--r--core/res/res/layout/activity_chooser_list_header.xml4
-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.xml17
-rw-r--r--core/res/res/values/colors.xml31
-rwxr-xr-xcore/res/res/values/config.xml5
-rw-r--r--core/res/res/values/ids.xml5
-rw-r--r--core/res/res/values/public.xml17
-rwxr-xr-xcore/res/res/values/strings.xml46
-rw-r--r--core/res/res/values/styles.xml4
-rw-r--r--core/res/res/values/themes.xml18
-rw-r--r--core/tests/coretests/AndroidManifest.xml7
-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/net/NetworkStatsTest.java6
-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/index.jd19
-rw-r--r--docs/html/sdk/eclipse-adt.jd2
-rw-r--r--docs/html/sdk/tools-notes.jd2
-rw-r--r--graphics/java/android/graphics/Path.java28
-rw-r--r--graphics/java/android/renderscript/Allocation.java68
-rw-r--r--graphics/java/android/renderscript/AllocationAdapter.java3
-rw-r--r--graphics/java/android/renderscript/ScriptC.java2
-rw-r--r--include/binder/ProcessState.h4
-rw-r--r--include/gui/SurfaceTextureClient.h5
-rw-r--r--include/media/stagefright/CameraSource.h6
-rw-r--r--include/media/stagefright/MPEG4Writer.h4
-rw-r--r--libs/binder/ProcessState.cpp51
-rw-r--r--libs/gui/SurfaceTextureClient.cpp43
-rw-r--r--libs/hwui/OpenGLRenderer.cpp8
-rw-r--r--libs/hwui/ShapeCache.h2
-rw-r--r--libs/rs/driver/rsdBcc.cpp69
-rw-r--r--libs/rs/driver/rsdGL.cpp80
-rw-r--r--libs/ui/EGLUtils.cpp58
-rw-r--r--libs/ui/FramebufferNativeWindow.cpp1
-rw-r--r--libs/utils/VectorImpl.cpp4
-rw-r--r--media/java/android/media/MediaFile.java7
-rw-r--r--media/java/android/media/MediaScanner.java78
-rw-r--r--media/java/android/mtp/MtpPropertyGroup.java1
-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.cpp10
-rw-r--r--media/libeffects/factory/EffectsFactory.c43
-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/EffectVisualizer.cpp3
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp59
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h1
-rw-r--r--media/libstagefright/CameraSource.cpp25
-rw-r--r--media/libstagefright/MPEG4Writer.cpp33
-rw-r--r--media/libstagefright/OMXCodec.cpp13
-rw-r--r--media/mtp/MtpServer.cpp8
-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/libs/EGL/egl.cpp5
-rw-r--r--opengl/libs/EGL/eglApi.cpp7
-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.mk41
-rw-r--r--opengl/tests/EGLTest/EGL_test.cpp129
-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.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java46
-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/AudioResamplerCubic.cpp4
-rw-r--r--services/camera/libcameraservice/CameraHardwareStub.h9
-rw-r--r--services/input/InputDispatcher.cpp7
-rw-r--r--services/java/com/android/server/AppWidgetService.java2
-rw-r--r--services/java/com/android/server/BackupManagerService.java108
-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.java8
-rw-r--r--services/java/com/android/server/NetworkManagementService.java138
-rw-r--r--services/java/com/android/server/NetworkTimeUpdateService.java67
-rw-r--r--services/java/com/android/server/ThrottleService.java33
-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.java3
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java7
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java529
-rw-r--r--services/java/com/android/server/usb/UsbDeviceManager.java51
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.cpp45
-rw-r--r--services/surfaceflinger/LayerBase.cpp7
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp48
-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--telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java34
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java16
-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
234 files changed, 3989 insertions, 5811 deletions
diff --git a/Android.mk b/Android.mk
index 9fbdde7..335fb73 100644
--- a/Android.mk
+++ b/Android.mk
@@ -36,6 +36,7 @@ LOCAL_SRC_FILES := $(call find-other-java-files,$(FRAMEWORKS_BASE_SUBDIRS))
# EventLogTags files.
LOCAL_SRC_FILES += \
core/java/android/content/EventLogTags.logtags \
+ core/java/android/speech/tts/EventLogTags.logtags \
core/java/android/webkit/EventLogTags.logtags \
telephony/java/com/android/internal/telephony/EventLogTags.logtags \
diff --git a/api/current.txt b/api/current.txt
index d507940..f3dda78 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
@@ -1121,6 +1126,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 +14392,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 +15014,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";
@@ -15741,6 +16007,7 @@ package android.provider {
protected static abstract interface ContactsContract.GroupsColumns {
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";
@@ -15868,6 +16135,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";
@@ -22474,7 +22742,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);
@@ -26151,7 +26419,7 @@ 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 resetResolvedLayoutDirection();
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/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 38d0d2a..2666b41 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -23,6 +23,8 @@ import android.app.backup.IRestoreSession;
import android.os.RemoteException;
import android.os.ServiceManager;
+import java.util.HashSet;
+
public final class Bmgr {
IBackupManager mBmgr;
IRestoreSession mRestore;
@@ -45,7 +47,6 @@ public final class Bmgr {
}
public void run(String[] args) {
- boolean validCommand = false;
if (args.length < 1) {
showUsage();
return;
@@ -329,7 +330,13 @@ public final class Bmgr {
} else {
try {
long token = Long.parseLong(arg, 16);
- doRestoreAll(token);
+ HashSet<String> filter = null;
+ while ((arg = nextArg()) != null) {
+ if (filter == null) filter = new HashSet<String>();
+ filter.add(arg);
+ }
+
+ doRestoreAll(token, filter);
} catch (NumberFormatException e) {
showUsage();
return;
@@ -364,7 +371,7 @@ public final class Bmgr {
}
}
- private void doRestoreAll(long token) {
+ private void doRestoreAll(long token, HashSet<String> filter) {
RestoreObserver observer = new RestoreObserver();
try {
@@ -383,7 +390,13 @@ public final class Bmgr {
for (RestoreSet s : sets) {
if (s.token == token) {
System.out.println("Scheduling restore: " + s.name);
- didRestore = (mRestore.restoreAll(token, observer) == 0);
+ if (filter == null) {
+ didRestore = (mRestore.restoreAll(token, observer) == 0);
+ } else {
+ String[] names = new String[filter.size()];
+ filter.toArray(names);
+ didRestore = (mRestore.restoreSome(token, observer, names) == 0);
+ }
break;
}
}
@@ -430,6 +443,7 @@ public final class Bmgr {
System.err.println(" bmgr list sets");
System.err.println(" bmgr transport WHICH");
System.err.println(" bmgr restore TOKEN");
+ System.err.println(" bmgr restore TOKEN PACKAGE...");
System.err.println(" bmgr restore PACKAGE");
System.err.println(" bmgr run");
System.err.println(" bmgr wipe PACKAGE");
@@ -457,12 +471,18 @@ public final class Bmgr {
System.err.println("The 'transport' command designates the named transport as the currently");
System.err.println("active one. This setting is persistent across reboots.");
System.err.println("");
- System.err.println("The 'restore' command when given a restore token initiates a full-system");
+ System.err.println("The 'restore' command when given just a restore token initiates a full-system");
System.err.println("restore operation from the currently active transport. It will deliver");
System.err.println("the restore set designated by the TOKEN argument to each application");
System.err.println("that had contributed data to that restore set.");
System.err.println("");
- System.err.println("The 'restore' command when given a package name intiates a restore of");
+ System.err.println("The 'restore' command when given a token and one or more package names");
+ System.err.println("initiates a restore operation of just those given packages from the restore");
+ System.err.println("set designated by the TOKEN argument. It is effectively the same as the");
+ System.err.println("'restore' operation supplying only a token, but applies a filter to the");
+ System.err.println("set of applications to be restored.");
+ System.err.println("");
+ System.err.println("The 'restore' command when given just a package name intiates a restore of");
System.err.println("just that one package according to the restore set selection algorithm");
System.err.println("used by the RestoreSession.restorePackage() method.");
System.err.println("");
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/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/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/IRestoreSession.aidl b/core/java/android/app/backup/IRestoreSession.aidl
index 1dddbb0..14731ee 100644
--- a/core/java/android/app/backup/IRestoreSession.aidl
+++ b/core/java/android/app/backup/IRestoreSession.aidl
@@ -52,6 +52,25 @@ interface IRestoreSession {
int restoreAll(long token, IRestoreObserver observer);
/**
+ * Restore select packages from the given set onto the device, replacing the
+ * current data of any app contained in the set with the data previously
+ * backed up.
+ *
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ *
+ * @return Zero on success, nonzero on error. The observer will only receive
+ * progress callbacks if this method returned zero.
+ * @param token The token from {@link getAvailableRestoreSets()} corresponding to
+ * the restore set that should be used.
+ * @param observer If non-null, this binder points to an object that will receive
+ * progress callbacks during the restore operation.
+ * @param packages The set of packages for which to attempt a restore. Regardless of
+ * the contents of the actual back-end dataset named by {@code token}, only
+ * applications mentioned in this list will have their data restored.
+ */
+ int restoreSome(long token, IRestoreObserver observer, in String[] packages);
+
+ /**
* Restore a single application from backup. The data will be restored from the
* current backup dataset if the given package has stored data there, or from
* the dataset used during the last full device setup operation if the current
diff --git a/core/java/android/app/backup/RestoreSession.java b/core/java/android/app/backup/RestoreSession.java
index 24ddb99..7181c61 100644
--- a/core/java/android/app/backup/RestoreSession.java
+++ b/core/java/android/app/backup/RestoreSession.java
@@ -87,6 +87,40 @@ public class RestoreSession {
}
/**
+ * Restore select packages from the given set onto the device, replacing the
+ * current data of any app contained in the set with the data previously
+ * backed up.
+ *
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ *
+ * @return Zero on success, nonzero on error. The observer will only receive
+ * progress callbacks if this method returned zero.
+ * @param token The token from {@link getAvailableRestoreSets()} corresponding to
+ * the restore set that should be used.
+ * @param observer If non-null, this binder points to an object that will receive
+ * progress callbacks during the restore operation.
+ * @param packages The set of packages for which to attempt a restore. Regardless of
+ * the contents of the actual back-end dataset named by {@code token}, only
+ * applications mentioned in this list will have their data restored.
+ *
+ * @hide
+ */
+ public int restoreSome(long token, RestoreObserver observer, String[] packages) {
+ int err = -1;
+ if (mObserver != null) {
+ Log.d(TAG, "restoreAll() called during active restore");
+ return -1;
+ }
+ mObserver = new RestoreObserverWrapper(mContext, observer);
+ try {
+ err = mBinder.restoreSome(token, mObserver, packages);
+ } catch (RemoteException e) {
+ Log.d(TAG, "Can't contact server to restore packages");
+ }
+ return err;
+ }
+
+ /**
* Restore a single application from backup. The data will be restored from the
* current backup dataset if the given package has stored data there, or from
* the dataset used during the last full device setup operation if the current
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..a4c66e4 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -43,17 +43,41 @@ public class NetworkStats implements Parcelable {
/** {@link #tag} value for without tag. */
public static final int TAG_NONE = 0;
+ // TODO: move public fields to Entry accessors, then undeprecate
+ // TODO: refactor rx/tx to rxBytes/txBytes
+
/**
* {@link SystemClock#elapsedRealtime()} timestamp when this data was
* generated.
*/
+ @Deprecated
public final long elapsedRealtime;
+ @Deprecated
public int size;
+ @Deprecated
public String[] iface;
+ @Deprecated
public int[] uid;
+ @Deprecated
public int[] tag;
+ @Deprecated
public long[] rx;
+ @Deprecated
+ public long[] rxPackets;
+ @Deprecated
public long[] tx;
+ @Deprecated
+ public 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 NetworkStats(long elapsedRealtime, int initialSize) {
this.elapsedRealtime = elapsedRealtime;
@@ -62,7 +86,9 @@ public class NetworkStats implements Parcelable {
this.uid = new int[initialSize];
this.tag = new int[initialSize];
this.rx = new long[initialSize];
+ this.rxPackets = new long[initialSize];
this.tx = new long[initialSize];
+ this.txPackets = new long[initialSize];
}
public NetworkStats(Parcel parcel) {
@@ -72,38 +98,82 @@ public class NetworkStats implements Parcelable {
uid = parcel.createIntArray();
tag = parcel.createIntArray();
rx = parcel.createLongArray();
+ rxPackets = parcel.createLongArray();
tx = parcel.createLongArray();
+ txPackets = parcel.createLongArray();
}
/**
* Add new stats entry with given values.
*/
public NetworkStats addEntry(String iface, int uid, int tag, long rx, long tx) {
+ final Entry entry = new Entry();
+ entry.iface = iface;
+ entry.uid = uid;
+ entry.tag = tag;
+ entry.rxBytes = rx;
+ entry.txBytes = tx;
+ return addValues(entry);
+ }
+
+ /**
+ * Add new stats entry, copying from given {@link Entry}. The {@link Entry}
+ * object can be recycled across multiple calls.
+ */
+ 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);
+ rx = Arrays.copyOf(rx, newLength);
+ rxPackets = Arrays.copyOf(rxPackets, newLength);
+ tx = Arrays.copyOf(tx, 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;
+ rx[size] = entry.rxBytes;
+ rxPackets[size] = entry.rxPackets;
+ tx[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 = rx[i];
+ entry.rxPackets = rxPackets[i];
+ entry.txBytes = tx[i];
+ entry.txPackets = txPackets[i];
+ return entry;
+ }
+
+ public long getElapsedRealtime() {
+ return elapsedRealtime;
+ }
+
+ public int size() {
+ return size;
+ }
+
+ /**
* 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) {
+ // TODO: extent to accept rxPackets/txPackets
final int i = findIndex(iface, uid, tag);
if (i == -1) {
// only create new entry when positive contribution
@@ -199,30 +269,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 = rx[i];
+ entry.rxPackets = rxPackets[i];
+ entry.txBytes = tx[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 = rx[i] - value.rx[j];
+ entry.rxPackets = rxPackets[i] - value.rxPackets[j];
+ entry.txBytes = tx[i] - value.tx[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 +316,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(rx[i]);
+ pw.print(" rxPackets="); pw.print(rxPackets[i]);
+ pw.print(" txBytes="); pw.print(tx[i]);
+ pw.print(" txPackets="); pw.println(txPackets[i]);
}
}
@@ -265,7 +348,9 @@ public class NetworkStats implements Parcelable {
dest.writeIntArray(uid);
dest.writeIntArray(tag);
dest.writeLongArray(rx);
+ dest.writeLongArray(rxPackets);
dest.writeLongArray(tx);
+ dest.writeLongArray(txPackets);
}
public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
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/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..60900e1 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) {
@@ -171,9 +185,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 +208,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..ec67683 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -135,14 +135,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 +263,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>
@@ -1881,13 +1871,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 +2204,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 +2215,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 +2226,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>
@@ -2537,7 +2553,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);
@@ -3814,27 +3829,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.
@@ -6213,6 +6207,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
@@ -6338,6 +6344,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>
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..b23e3ce 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);
}
}
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index c7603ee..8ef4295 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -384,11 +384,16 @@ class AudioPlaybackHandler {
}
count += written;
}
+
+ param.mLogger.onPlaybackStart();
}
private void handleSynthesisDone(MessageParams msg) {
final SynthesisMessageParams params = (SynthesisMessageParams) msg;
handleSynthesisDone(params);
+ // This call is delayed more than it should be, but we are
+ // certain at this point that we have all the data we want.
+ params.mLogger.onWriteData();
}
// Flush all remaining data to the audio track, stop it and release
@@ -416,6 +421,8 @@ class AudioPlaybackHandler {
final SynthesisMessageParams params = (SynthesisMessageParams) msg;
if (DBG) Log.d(TAG, "completeAudioAvailable(" + params + ")");
+ params.mLogger.onPlaybackStart();
+
// Channel config and bytes per frame are checked before
// this message is sent.
int channelConfig = AudioPlaybackHandler.getChannelConfig(params.mChannelCount);
diff --git a/core/java/android/speech/tts/EventLogTags.logtags b/core/java/android/speech/tts/EventLogTags.logtags
new file mode 100644
index 0000000..1a9f5fe
--- /dev/null
+++ b/core/java/android/speech/tts/EventLogTags.logtags
@@ -0,0 +1,6 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package android.speech.tts;
+
+76001 tts_speak_success (engine|3),(caller|3),(length|1),(locale|3),(rate|1),(pitch|1),(engine_latency|2|3),(engine_total|2|3),(audio_latency|2|3)
+76002 tts_speak_failure (engine|3),(caller|3),(length|1),(locale|3),(rate|1),(pitch|1)
diff --git a/core/java/android/speech/tts/EventLogger.java b/core/java/android/speech/tts/EventLogger.java
new file mode 100644
index 0000000..63b954b
--- /dev/null
+++ b/core/java/android/speech/tts/EventLogger.java
@@ -0,0 +1,175 @@
+/*
+ * 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.speech.tts;
+
+import android.os.SystemClock;
+import android.text.TextUtils;
+
+/**
+ * Writes data about a given speech synthesis request to the event logs.
+ * The data that is logged includes the calling app, length of the utterance,
+ * speech rate / pitch and the latency and overall time taken.
+ *
+ * Note that {@link EventLogger#onStopped()} and {@link EventLogger#onError()}
+ * might be called from any thread, but on {@link EventLogger#onPlaybackStart()} and
+ * {@link EventLogger#onComplete()} must be called from a single thread
+ * (usually the audio playback thread}
+ */
+class EventLogger {
+ private final SynthesisRequest mRequest;
+ private final String mCallingApp;
+ private final String mServiceApp;
+ private final long mReceivedTime;
+ private long mPlaybackStartTime = -1;
+ private volatile long mRequestProcessingStartTime = -1;
+ private volatile long mEngineStartTime = -1;
+ private volatile long mEngineCompleteTime = -1;
+
+ private volatile boolean mError = false;
+ private volatile boolean mStopped = false;
+ private boolean mLogWritten = false;
+
+ EventLogger(SynthesisRequest request, String callingApp,
+ String serviceApp) {
+ mRequest = request;
+ mCallingApp = callingApp;
+ mServiceApp = serviceApp;
+ mReceivedTime = SystemClock.elapsedRealtime();
+ }
+
+ /**
+ * Notifies the logger that this request has been selected from
+ * the processing queue for processing. Engine latency / total time
+ * is measured from this baseline.
+ */
+ public void onRequestProcessingStart() {
+ mRequestProcessingStartTime = SystemClock.elapsedRealtime();
+ }
+
+ /**
+ * Notifies the logger that a chunk of data has been received from
+ * the engine. Might be called multiple times.
+ */
+ public void onEngineDataReceived() {
+ if (mEngineStartTime == -1) {
+ mEngineStartTime = SystemClock.elapsedRealtime();
+ }
+ }
+
+ /**
+ * Notifies the logger that the engine has finished processing data.
+ * Will be called exactly once.
+ */
+ public void onEngineComplete() {
+ mEngineCompleteTime = SystemClock.elapsedRealtime();
+ }
+
+ /**
+ * Notifies the logger that audio playback has started for some section
+ * of the synthesis. This is normally some amount of time after the engine
+ * has synthesized data and varides depending on utterances and
+ * other audio currently in the queue.
+ */
+ public void onPlaybackStart() {
+ // For now, keep track of only the first chunk of audio
+ // that was played.
+ if (mPlaybackStartTime == -1) {
+ mPlaybackStartTime = SystemClock.elapsedRealtime();
+ }
+ }
+
+ /**
+ * Notifies the logger that the current synthesis was stopped.
+ * Latency numbers are not reported for stopped syntheses.
+ */
+ public void onStopped() {
+ mStopped = false;
+ }
+
+ /**
+ * Notifies the logger that the current synthesis resulted in
+ * an error. This is logged using {@link EventLogTags#writeTtsSpeakFailure}.
+ */
+ public void onError() {
+ mError = true;
+ }
+
+ /**
+ * Notifies the logger that the current synthesis has completed.
+ * All available data is not logged.
+ */
+ public void onWriteData() {
+ if (mLogWritten) {
+ return;
+ } else {
+ mLogWritten = true;
+ }
+
+ long completionTime = SystemClock.elapsedRealtime();
+ // onPlaybackStart() should normally always be called if an
+ // error does not occur.
+ if (mError || mPlaybackStartTime == -1 || mEngineCompleteTime == -1) {
+ EventLogTags.writeTtsSpeakFailure(mServiceApp, mCallingApp,
+ getUtteranceLength(), getLocaleString(),
+ mRequest.getSpeechRate(), mRequest.getPitch());
+ return;
+ }
+
+ // We don't report stopped syntheses because their overall
+ // total time spent will be innacurate (will not correlate with
+ // the length of the utterance).
+ if (mStopped) {
+ return;
+ }
+
+ final long audioLatency = mPlaybackStartTime - mReceivedTime;
+ final long engineLatency = mEngineStartTime - mRequestProcessingStartTime;
+ final long engineTotal = mEngineCompleteTime - mRequestProcessingStartTime;
+ EventLogTags.writeTtsSpeakSuccess(mServiceApp, mCallingApp,
+ getUtteranceLength(), getLocaleString(),
+ mRequest.getSpeechRate(), mRequest.getPitch(),
+ engineLatency, engineTotal, audioLatency);
+ }
+
+ /**
+ * @return the length of the utterance for the given synthesis, 0
+ * if the utterance was {@code null}.
+ */
+ private int getUtteranceLength() {
+ final String utterance = mRequest.getText();
+ return utterance == null ? 0 : utterance.length();
+ }
+
+ /**
+ * Returns a formatted locale string from the synthesis params of the
+ * form lang-country-variant.
+ */
+ private String getLocaleString() {
+ StringBuilder sb = new StringBuilder(mRequest.getLanguage());
+ if (!TextUtils.isEmpty(mRequest.getCountry())) {
+ sb.append('-');
+ sb.append(mRequest.getCountry());
+
+ if (!TextUtils.isEmpty(mRequest.getVariant())) {
+ sb.append('-');
+ sb.append(mRequest.getVariant());
+ }
+ }
+
+ return sb.toString();
+ }
+
+}
diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
index bdaa1b8..38030a6 100644
--- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java
+++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
@@ -65,29 +65,42 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
private final UtteranceCompletedDispatcher mDispatcher;
private final String mCallingApp;
+ private final EventLogger mLogger;
PlaybackSynthesisCallback(int streamType, float volume, float pan,
AudioPlaybackHandler audioTrackHandler, UtteranceCompletedDispatcher dispatcher,
- String callingApp) {
+ String callingApp, EventLogger logger) {
mStreamType = streamType;
mVolume = volume;
mPan = pan;
mAudioTrackHandler = audioTrackHandler;
mDispatcher = dispatcher;
mCallingApp = callingApp;
+ mLogger = logger;
}
@Override
void stop() {
if (DBG) Log.d(TAG, "stop()");
+ // Note that mLogger.mError might be true too at this point.
+ mLogger.onStopped();
+
synchronized (mStateLock) {
- if (mToken == null || mStopped) {
- Log.w(TAG, "stop() called twice, before start(), or after done()");
+ if (mStopped) {
+ Log.w(TAG, "stop() called twice");
return;
}
- mAudioTrackHandler.stop(mToken);
- mToken = null;
+ // mToken will be null if the engine encounters
+ // an error before it called start().
+ if (mToken != null) {
+ mAudioTrackHandler.stop(mToken);
+ mToken = null;
+ } else {
+ // In all other cases, mAudioTrackHandler.stop() will
+ // result in onComplete being called.
+ mLogger.onWriteData();
+ }
mStopped = true;
}
}
@@ -124,7 +137,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
}
SynthesisMessageParams params = new SynthesisMessageParams(
mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan,
- mDispatcher, mCallingApp);
+ mDispatcher, mCallingApp, mLogger);
mAudioTrackHandler.enqueueSynthesisStart(params);
mToken = params;
@@ -157,6 +170,8 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
mAudioTrackHandler.enqueueSynthesisDataAvailable(mToken);
}
+ mLogger.onEngineDataReceived();
+
return TextToSpeech.SUCCESS;
}
@@ -177,6 +192,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
}
mAudioTrackHandler.enqueueSynthesisDone(mToken);
+ mLogger.onEngineComplete();
}
return TextToSpeech.SUCCESS;
}
@@ -184,6 +200,9 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
@Override
public void error() {
if (DBG) Log.d(TAG, "error() [will call stop]");
+ // Currently, this call will not be logged if error( ) is called
+ // before start.
+ mLogger.onError();
stop();
}
@@ -208,7 +227,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
}
SynthesisMessageParams params = new SynthesisMessageParams(
mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan,
- mDispatcher, mCallingApp);
+ mDispatcher, mCallingApp, mLogger);
params.addBuffer(buffer, offset, length);
mAudioTrackHandler.enqueueSynthesisCompleteDataAvailable(params);
diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java
index 51f3d2e..caf02ef 100644
--- a/core/java/android/speech/tts/SynthesisMessageParams.java
+++ b/core/java/android/speech/tts/SynthesisMessageParams.java
@@ -30,6 +30,7 @@ final class SynthesisMessageParams extends MessageParams {
final int mChannelCount;
final float mVolume;
final float mPan;
+ final EventLogger mLogger;
public volatile AudioTrack mAudioTrack;
@@ -38,7 +39,7 @@ final class SynthesisMessageParams extends MessageParams {
SynthesisMessageParams(int streamType, int sampleRate,
int audioFormat, int channelCount,
float volume, float pan, UtteranceCompletedDispatcher dispatcher,
- String callingApp) {
+ String callingApp, EventLogger logger) {
super(dispatcher, callingApp);
mStreamType = streamType;
@@ -47,6 +48,7 @@ final class SynthesisMessageParams extends MessageParams {
mChannelCount = channelCount;
mVolume = volume;
mPan = pan;
+ mLogger = logger;
// initially null.
mAudioTrack = null;
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 7ea9373..010c155 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -82,8 +82,7 @@ public abstract class TextToSpeechService extends Service {
private AudioPlaybackHandler mAudioPlaybackHandler;
private CallbackMap mCallbacks;
-
- private int mDefaultAvailability = TextToSpeech.LANG_NOT_SUPPORTED;
+ private String mPackageName;
@Override
public void onCreate() {
@@ -99,9 +98,10 @@ public abstract class TextToSpeechService extends Service {
mCallbacks = new CallbackMap();
+ mPackageName = getApplicationInfo().packageName;
+
// Load default language
- mDefaultAvailability = onLoadLanguage(getDefaultLanguage(),
- getDefaultCountry(), getDefaultVariant());
+ onLoadLanguage(getDefaultLanguage(), getDefaultCountry(), getDefaultVariant());
}
@Override
@@ -457,12 +457,14 @@ public abstract class TextToSpeechService extends Service {
// Non null after synthesis has started, and all accesses
// guarded by 'this'.
private AbstractSynthesisCallback mSynthesisCallback;
+ private final EventLogger mEventLogger;
public SynthesisSpeechItem(String callingApp, Bundle params, String text) {
super(callingApp, params);
mText = text;
mSynthesisRequest = new SynthesisRequest(mText, mParams);
setRequestParams(mSynthesisRequest);
+ mEventLogger = new EventLogger(mSynthesisRequest, getCallingApp(), mPackageName);
}
public String getText() {
@@ -485,6 +487,7 @@ public abstract class TextToSpeechService extends Service {
@Override
protected int playImpl() {
AbstractSynthesisCallback synthesisCallback;
+ mEventLogger.onRequestProcessingStart();
synchronized (this) {
mSynthesisCallback = createSynthesisCallback();
synthesisCallback = mSynthesisCallback;
@@ -495,7 +498,7 @@ public abstract class TextToSpeechService extends Service {
protected AbstractSynthesisCallback createSynthesisCallback() {
return new PlaybackSynthesisCallback(getStreamType(), getVolume(), getPan(),
- mAudioPlaybackHandler, this, getCallingApp());
+ mAudioPlaybackHandler, this, getCallingApp(), mEventLogger);
}
private void setRequestParams(SynthesisRequest request) {
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/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/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 41412de..752fd5a 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -46,7 +46,6 @@ import com.android.internal.util.Predicate;
import java.util.ArrayList;
import java.util.HashSet;
-import java.util.Locale;
/**
* <p>
@@ -5000,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();
}
}
}
@@ -5019,7 +5018,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
@Override
protected void resolveTextDirection() {
- int resolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+ int resolvedTextDirection;
switch(mTextDirection) {
default:
case TEXT_DIRECTION_INHERIT:
diff --git a/core/java/android/webkit/L10nUtils.java b/core/java/android/webkit/L10nUtils.java
index 4c42cde..a1c6a53 100644
--- a/core/java/android/webkit/L10nUtils.java
+++ b/core/java/android/webkit/L10nUtils.java
@@ -74,7 +74,19 @@ public class L10nUtils {
com.android.internal.R.string.autofill_country_code_re, // IDS_AUTOFILL_COUNTRY_CODE_RE
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.autofill_phone_suffix_separator_re, // IDS_AUTOFILL_PHONE_SUFFIX_SEPARATOR_RE
+ 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/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 2145edd..c652e55 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2240,6 +2240,10 @@ public final class WebViewCore {
}
private void setupViewport(boolean updateViewState) {
+ if (mWebView == null || mSettings == null) {
+ // We've been destroyed or are being destroyed, return early
+ return;
+ }
// set the viewport settings from WebKit
setViewportSettingsFromNative();
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/TextView.java b/core/java/android/widget/TextView.java
index 1e63e26..766b520 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5571,8 +5571,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 +6212,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 +6239,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 +6285,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();
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/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index 2e7ec58..b754d94 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -26,6 +26,9 @@ package com.android.internal.util;
* codes with Message.what starting at Protocol.WIFI + 1 and less than or equal to Protocol.WIFI +
* Protocol.MAX_MESSAGE
*
+ * NOTE: After a value is created and source released a value shouldn't be changed to
+ * maintain backwards compatibility.
+ *
* {@hide}
*/
public class Protocol {
@@ -40,7 +43,7 @@ public class Protocol {
public static final int BASE_DHCP = 0x00030000;
public static final int BASE_DATA_CONNECTION = 0x00040000;
public static final int BASE_DATA_CONNECTION_AC = 0x00041000;
- public static final int BASE_DATA_CONNECTION_TRACKER = 0x00050000;
+ public static final int BASE_DATA_CONNECTION_TRACKER = 0x00042000;
//TODO: define all used protocols
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 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..a4edbc5 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -25,8 +25,8 @@ 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.ContextMenu.ContextMenuInfo;
import android.view.KeyCharacterMap;
@@ -38,7 +38,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 +48,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 +255,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;
}
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/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_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
index 7603a31..c05ba1a 100644
--- a/core/res/res/layout/activity_chooser_list_footer.xml
+++ b/core/res/res/layout/activity_chooser_list_footer.xml
@@ -23,13 +23,11 @@
android:gravity="center"
android:orientation="vertical">
- <ImageView
+ <View
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" />
+ android:background="@android:color/holo_blue_light" />
<TextView
android:id="@+id/title"
diff --git a/core/res/res/layout/activity_chooser_list_header.xml b/core/res/res/layout/activity_chooser_list_header.xml
index 867014b..0fb256f 100644
--- a/core/res/res/layout/activity_chooser_list_header.xml
+++ b/core/res/res/layout/activity_chooser_list_header.xml
@@ -32,12 +32,10 @@
android:duplicateParentState="true"
android:singleLine="true" />
- <ImageView
+ <View
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/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..9c2133f 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. -->
@@ -5303,6 +5318,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/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..f7701f2 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,15 @@
<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" />
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 50f8df7..70c204e 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,14 +2077,50 @@
<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>
+ <!-- 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. -->
<string name="permlab_readHistoryBookmarks">read Browser\'s history and bookmarks</string>
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/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 059503c..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 -->
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/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index 3cb64c7..82345e2 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -44,20 +44,20 @@ public class NetworkStatsTest extends TestCase {
public void testAddEntryGrow() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 2);
- assertEquals(0, stats.size);
+ assertEquals(0, stats.size());
assertEquals(2, stats.iface.length);
stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 1L, 2L);
stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L);
- assertEquals(2, stats.size);
+ assertEquals(2, stats.size());
assertEquals(2, stats.iface.length);
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);
- assertEquals(5, stats.size);
+ assertEquals(5, stats.size());
assertTrue(stats.iface.length >= 5);
assertEquals(1L, stats.rx[0]);
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/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/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/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/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/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 6254192..12e5ada 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -155,6 +155,14 @@ public class Allocation extends BaseObj {
}
}
+
+ private int getIDSafe() {
+ if (mAdaptedAllocation != null) {
+ return mAdaptedAllocation.getID();
+ }
+ return getID();
+ }
+
private void updateCacheInfo(Type t) {
mCurrentDimX = t.getX();
mCurrentDimY = t.getY();
@@ -262,7 +270,7 @@ public class Allocation extends BaseObj {
throw new RSIllegalArgumentException("Source must be exactly one usage type.");
}
mRS.validate();
- mRS.nAllocationSyncAll(getID(), srcLocation);
+ mRS.nAllocationSyncAll(getIDSafe(), srcLocation);
}
public void copyFrom(BaseObj[] d) {
@@ -480,7 +488,7 @@ public class Allocation extends BaseObj {
" does not match component size " + eSize + ".");
}
- mRS.nAllocationElementData1D(getID(), xoff, mSelectedLOD,
+ mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
component_number, data, data.length);
}
@@ -527,7 +535,7 @@ public class Allocation extends BaseObj {
public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
int dataSize = mType.mElement.getSizeBytes() * count;
data1DChecks(off, count, d.length * 4, dataSize);
- mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+ mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
}
/**
* Copy part of an allocation from an array. This variant is
@@ -541,7 +549,7 @@ public class Allocation extends BaseObj {
public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
int dataSize = mType.mElement.getSizeBytes() * count;
data1DChecks(off, count, d.length * 2, dataSize);
- mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+ mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
}
/**
* Copy part of an allocation from an array. This variant is
@@ -555,7 +563,7 @@ public class Allocation extends BaseObj {
public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
int dataSize = mType.mElement.getSizeBytes() * count;
data1DChecks(off, count, d.length, dataSize);
- mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+ mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
}
/**
* Copy part of an allocation from an array. This variant is
@@ -569,7 +577,7 @@ public class Allocation extends BaseObj {
public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
int dataSize = mType.mElement.getSizeBytes() * count;
data1DChecks(off, count, d.length * 4, dataSize);
- mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+ mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
}
/**
@@ -638,7 +646,7 @@ public class Allocation extends BaseObj {
* be copied.
*/
public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
- mRS.nAllocationData2D(getID(), off, 0,
+ mRS.nAllocationData2D(getIDSafe(), off, 0,
mSelectedLOD, mSelectedFace.mID,
count, 1, data.getID(), dataOff, 0,
data.mSelectedLOD, data.mSelectedFace.mID);
@@ -674,28 +682,28 @@ public class Allocation extends BaseObj {
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
mRS.validate();
validate2DRange(xoff, yoff, w, h);
- mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+ mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
w, h, data, data.length);
}
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
mRS.validate();
validate2DRange(xoff, yoff, w, h);
- mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+ mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
w, h, data, data.length * 2);
}
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
mRS.validate();
validate2DRange(xoff, yoff, w, h);
- mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+ mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
w, h, data, data.length * 4);
}
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
mRS.validate();
validate2DRange(xoff, yoff, w, h);
- mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+ mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
w, h, data, data.length * 4);
}
@@ -715,7 +723,7 @@ public class Allocation extends BaseObj {
Allocation data, int dataXoff, int dataYoff) {
mRS.validate();
validate2DRange(xoff, yoff, w, h);
- mRS.nAllocationData2D(getID(), xoff, yoff,
+ mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
mSelectedLOD, mSelectedFace.mID,
w, h, data.getID(), dataXoff, dataYoff,
data.mSelectedLOD, data.mSelectedFace.mID);
@@ -734,10 +742,16 @@ public class Allocation extends BaseObj {
mRS.validate();
validateBitmapFormat(data);
validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
- mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
+ mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
}
+ /**
+ * Copy from the Allocation into a Bitmap. The bitmap must
+ * match the dimensions of the Allocation.
+ *
+ * @param b The bitmap to be set from the Allocation.
+ */
public void copyTo(Bitmap b) {
mRS.validate();
validateBitmapFormat(b);
@@ -745,24 +759,52 @@ public class Allocation extends BaseObj {
mRS.nAllocationCopyToBitmap(getID(), b);
}
+ /**
+ * Copy from the Allocation into a byte array. The array must
+ * be at least as large as the Allocation. The allocation must
+ * be of an 8 bit elemental type.
+ *
+ * @param d The array to be set from the Allocation.
+ */
public void copyTo(byte[] d) {
validateIsInt8();
mRS.validate();
mRS.nAllocationRead(getID(), d);
}
+ /**
+ * Copy from the Allocation into a short array. The array must
+ * be at least as large as the Allocation. The allocation must
+ * be of an 16 bit elemental type.
+ *
+ * @param d The array to be set from the Allocation.
+ */
public void copyTo(short[] d) {
validateIsInt16();
mRS.validate();
mRS.nAllocationRead(getID(), d);
}
+ /**
+ * Copy from the Allocation into a int array. The array must be
+ * at least as large as the Allocation. The allocation must be
+ * of an 32 bit elemental type.
+ *
+ * @param d The array to be set from the Allocation.
+ */
public void copyTo(int[] d) {
validateIsInt32();
mRS.validate();
mRS.nAllocationRead(getID(), d);
}
+ /**
+ * Copy from the Allocation into a float array. The array must
+ * be at least as large as the Allocation. The allocation must
+ * be of an 32 bit float elemental type.
+ *
+ * @param d The array to be set from the Allocation.
+ */
public void copyTo(float[] d) {
validateIsFloat32();
mRS.validate();
diff --git a/graphics/java/android/renderscript/AllocationAdapter.java b/graphics/java/android/renderscript/AllocationAdapter.java
index ca5246a..d38f2df 100644
--- a/graphics/java/android/renderscript/AllocationAdapter.java
+++ b/graphics/java/android/renderscript/AllocationAdapter.java
@@ -31,7 +31,8 @@ public class AllocationAdapter extends Allocation {
}
int getID() {
- return mAdaptedAllocation.getID();
+ throw new RSInvalidStateException(
+ "This operation is not supported with adapters at this time.");
}
/**
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/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/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/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/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/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 06e3b29..a349121 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -673,11 +673,11 @@ void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap)
float x = rect.left;
float y = rect.top;
- bool simpleTransform = mSnapshot->transform->isPureTranslate();
-
- if (simpleTransform &&
+ bool simpleTransform = mSnapshot->transform->isPureTranslate() &&
layer->getWidth() == (uint32_t) rect.getWidth() &&
- layer->getHeight() == (uint32_t) rect.getHeight()) {
+ layer->getHeight() == (uint32_t) rect.getHeight();
+
+ if (simpleTransform) {
// When we're swapping, the layer is already in screen coordinates
if (!swap) {
x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
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/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp
index 8120864..62eb24e 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/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/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/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..e8ddd2d 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,37 +835,31 @@ public class MediaScanner
}
}
- 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(mFilesUri, values);
+ }
+
if (result != null) {
rowId = ContentUris.parseId(result);
entry.mRowId = rowId;
}
} else {
// updated file
- result = ContentUris.withAppendedId(tableUri, rowId);
+ result = ContentUris.withAppendedId(mFilesUri, rowId);
// path should never change, and we want to avoid replacing mixed cased paths
// with squashed lower case paths
values.remove(MediaStore.MediaColumns.DATA);
@@ -854,7 +878,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 +900,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);
}
@@ -885,19 +909,19 @@ public class MediaScanner
if (notifications && !mDefaultNotificationSet) {
if (TextUtils.isEmpty(mDefaultNotificationFilename) ||
doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) {
- setSettingIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId);
+ setSettingIfNotSet(Settings.System.NOTIFICATION_SOUND, mFilesUri, rowId);
mDefaultNotificationSet = true;
}
} else if (ringtones && !mDefaultRingtoneSet) {
if (TextUtils.isEmpty(mDefaultRingtoneFilename) ||
doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) {
- setSettingIfNotSet(Settings.System.RINGTONE, tableUri, rowId);
+ setSettingIfNotSet(Settings.System.RINGTONE, mFilesUri, rowId);
mDefaultRingtoneSet = true;
}
} else if (alarms && !mDefaultAlarmSet) {
if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) ||
doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) {
- setSettingIfNotSet(Settings.System.ALARM_ALERT, tableUri, rowId);
+ setSettingIfNotSet(Settings.System.ALARM_ALERT, mFilesUri, rowId);
mDefaultAlarmSet = true;
}
}
@@ -1152,10 +1176,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 +1185,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/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..446b630 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -48,6 +48,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;
@@ -228,12 +229,14 @@ android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage)
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);
+ MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr,
+ reserveSpace, removable, maxFileSize);
thread->addStorage(storage);
env->ReleaseStringUTFChars(path, pathStr);
env->ReleaseStringUTFChars(description, descriptionStr);
@@ -312,6 +315,11 @@ int register_android_mtp_MtpServer(JNIEnv *env)
LOGE("Can't find MtpStorage.mRemovable");
return -1;
}
+ field_MtpStorage_maxFileSize = env->GetFieldID(clazz, "mMaxFileSize", "J");
+ if (field_MtpStorage_maxFileSize == NULL) {
+ LOGE("Can't find MtpStorage.mMaxFileSize");
+ return -1;
+ }
clazz_MtpStorage = (jclass)env->NewGlobalRef(clazz);
clazz = env->FindClass("android/mtp/MtpServer");
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/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/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/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/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index ed8149a..c7e7ced 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -158,12 +158,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 +461,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 +539,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 +590,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 +600,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..eaad2c3 100644
--- 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;
}
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 1ac2c1f..06363ee 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1295,13 +1295,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;
@@ -1312,8 +1305,14 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
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;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index bc04e8c..9085f10 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -871,6 +871,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/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/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..ab5f4bd
--- /dev/null
+++ b/opengl/tests/EGLTest/Android.mk
@@ -0,0 +1,41 @@
+# Build the unit tests.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+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)
+
+endif
+
+# 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/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
new file mode 100644
index 0000000..8252a9f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/Constants.java
@@ -0,0 +1,25 @@
+/*
+ * 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.systemui.recent;
+
+public class Constants {
+ static final int MAX_ESCAPE_ANIMATION_DURATION = 500; // in ms
+ 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 3dbcc59..f984aac 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -25,6 +25,7 @@ import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
+import android.content.res.Configuration;
import android.database.DataSetObserver;
import android.graphics.RectF;
import android.util.AttributeSet;
@@ -33,6 +34,7 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.HorizontalScrollView;
@@ -42,12 +44,9 @@ import com.android.systemui.R;
public class RecentsHorizontalScrollView extends HorizontalScrollView
implements View.OnClickListener, View.OnTouchListener {
- private static final float FADE_CONSTANT = 0.5f;
- private static final int SNAP_BACK_DURATION = 250;
- private static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it
- private static final String TAG = RecentsPanelView.TAG;
- private static final float THRESHHOLD = 50;
private static final boolean DEBUG_INVALIDATE = false;
+ private static final String TAG = RecentsPanelView.TAG;
+ private static final boolean DEBUG = RecentsPanelView.DEBUG;
private LinearLayout mLinearLayout;
private ActivityDescriptionAdapter mAdapter;
private RecentsCallback mCallback;
@@ -56,6 +55,8 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView
private float mLastY;
private boolean mDragging;
private VelocityTracker mVelocityTracker;
+ private float mDensityScale;
+ private float mPagingTouchSlop;
public RecentsHorizontalScrollView(Context context) {
this(context, null);
@@ -63,6 +64,8 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView
public RecentsHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
+ mDensityScale = getResources().getDisplayMetrics().density;
+ mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
}
private int scrollPositionOfMostRecent() {
@@ -101,7 +104,8 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView
case MotionEvent.ACTION_MOVE:
float delta = ev.getY() - mLastY;
- if (Math.abs(delta) > THRESHHOLD) {
+ if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta);
+ if (Math.abs(delta) > mPagingTouchSlop) {
mDragging = true;
}
break;
@@ -114,13 +118,14 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView
}
private float getAlphaForOffset(View view, float thumbHeight) {
- final float fadeHeight = 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;
}
@@ -155,12 +160,13 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView
final float velocityY = velocityTracker.getYVelocity();
final float curY = animView.getY();
final float newY = (velocityY >= 0.0f ? 1 : -1) * animView.getHeight();
-
+ final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale;
if (Math.abs(velocityY) > Math.abs(velocityX)
- && Math.abs(velocityY) > ESCAPE_VELOCITY
+ && Math.abs(velocityY) > maxVelocity
&& (velocityY >= 0.0f) == (animView.getY() >= 0)) {
- final long duration =
+ long duration =
(long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY));
+ duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION);
anim = ObjectAnimator.ofFloat(animView, "y", curY, newY);
anim.setInterpolator(new LinearInterpolator());
final int swipeDirection = animView.getY() >= 0.0f ?
@@ -181,9 +187,10 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView
});
anim.setDuration(duration);
} else { // Animate back to position
- final long duration = Math.abs(velocityY) > 0.0f ?
+ long duration = Math.abs(velocityY) > 0.0f ?
(long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY))
- : SNAP_BACK_DURATION;
+ : Constants.SNAP_BACK_DURATION;
+ duration = Math.min(duration, Constants.SNAP_BACK_DURATION);
anim = ObjectAnimator.ofFloat(animView, "y", animView.getY(), 0.0f);
anim.setInterpolator(new DecelerateInterpolator(2.0f));
anim.setDuration(duration);
@@ -241,8 +248,15 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView
setOverScrollEffectPadding(leftPadding, 0);
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ mDensityScale = getResources().getDisplayMetrics().density;
+ mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ }
+
private void setOverScrollEffectPadding(int leftPadding, int i) {
- // TODO Add to RecentsHorizontalScrollView
+ // TODO Add to (Vertical)ScrollView
}
@Override
@@ -255,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/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 6190c9b..a55fe9c 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -417,11 +417,11 @@ public class RecentsPanelView extends RelativeLayout
mActivityDescriptions = getRecentTasks();
mListAdapter.notifyDataSetInvalidated();
if (mActivityDescriptions.size() > 0) {
- Log.v(TAG, "Showing " + mActivityDescriptions.size() + " apps");
+ if (DEBUG) Log.v(TAG, "Showing " + mActivityDescriptions.size() + " apps");
updateUiElements(getResources().getConfiguration());
} else {
// Immediately hide this panel
- Log.v(TAG, "Nothing to show");
+ if (DEBUG) Log.v(TAG, "Nothing to show");
hide(false);
}
}
@@ -436,7 +436,7 @@ public class RecentsPanelView extends RelativeLayout
paint.setAlpha(255);
final int srcWidth = thumbnail.getWidth();
final int srcHeight = thumbnail.getHeight();
- Log.v(TAG, "Source thumb: " + srcWidth + "x" + srcHeight);
+ if (DEBUG) Log.v(TAG, "Source thumb: " + srcWidth + "x" + srcHeight);
canvas.drawBitmap(thumbnail,
new Rect(0, 0, srcWidth-1, srcHeight-1),
new RectF(mGlowBitmapPaddingLeftPx, mGlowBitmapPaddingTopPx,
@@ -486,7 +486,7 @@ public class RecentsPanelView extends RelativeLayout
public void handleSwipe(View view, int direction) {
ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription;
- Log.v(TAG, "Jettison " + ad.label);
+ if (DEBUG) Log.v(TAG, "Jettison " + ad.label);
mActivityDescriptions.remove(ad);
// Handled by widget containers to enable LayoutTransitions properly
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index 6a962cb..27bb0b5 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -25,6 +25,7 @@ import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
+import android.content.res.Configuration;
import android.database.DataSetObserver;
import android.graphics.RectF;
import android.util.AttributeSet;
@@ -33,6 +34,7 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;
@@ -42,12 +44,9 @@ import com.android.systemui.R;
public class RecentsVerticalScrollView extends ScrollView
implements View.OnClickListener, View.OnTouchListener {
- private static final float FADE_CONSTANT = 0.5f;
- private static final int SNAP_BACK_DURATION = 250;
- private static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it
private static final String TAG = RecentsPanelView.TAG;
- private static final float THRESHHOLD = 50;
private static final boolean DEBUG_INVALIDATE = false;
+ private static final boolean DEBUG = RecentsPanelView.DEBUG;
private LinearLayout mLinearLayout;
private ActivityDescriptionAdapter mAdapter;
private RecentsCallback mCallback;
@@ -56,6 +55,8 @@ public class RecentsVerticalScrollView extends ScrollView
private float mLastX;
private boolean mDragging;
private VelocityTracker mVelocityTracker;
+ private float mDensityScale;
+ private float mPagingTouchSlop;
public RecentsVerticalScrollView(Context context) {
this(context, null);
@@ -63,6 +64,8 @@ public class RecentsVerticalScrollView extends ScrollView
public RecentsVerticalScrollView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
+ mDensityScale = getResources().getDisplayMetrics().density;
+ mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
}
private int scrollPositionOfMostRecent() {
@@ -101,8 +104,8 @@ public class RecentsVerticalScrollView extends ScrollView
case MotionEvent.ACTION_MOVE:
float delta = ev.getX() - mLastX;
- Log.v(TAG, "ACTION_MOVE : " + delta);
- if (Math.abs(delta) > THRESHHOLD) {
+ if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta);
+ if (Math.abs(delta) > mPagingTouchSlop) {
mDragging = true;
}
break;
@@ -115,14 +118,14 @@ public class RecentsVerticalScrollView extends ScrollView
}
private float getAlphaForOffset(View view, float thumbWidth) {
- final float fadeWidth = 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;
}
- Log.v(TAG, "FADE AMOUNT: " + result);
+ if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result);
return result;
}
@@ -157,12 +160,13 @@ public class RecentsVerticalScrollView extends ScrollView
final float velocityY = velocityTracker.getYVelocity();
final float curX = animView.getX();
final float newX = (velocityX >= 0.0f ? 1 : -1) * animView.getWidth();
-
+ final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale;
if (Math.abs(velocityX) > Math.abs(velocityY)
- && Math.abs(velocityX) > ESCAPE_VELOCITY
+ && Math.abs(velocityX) > maxVelocity
&& (velocityX > 0.0f) == (animView.getX() >= 0)) {
- final long duration =
+ long duration =
(long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX));
+ duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION);
anim = ObjectAnimator.ofFloat(animView, "x", curX, newX);
anim.setInterpolator(new LinearInterpolator());
final int swipeDirection = animView.getX() >= 0.0f ?
@@ -183,9 +187,10 @@ public class RecentsVerticalScrollView extends ScrollView
});
anim.setDuration(duration);
} else { // Animate back to position
- final long duration = Math.abs(velocityX) > 0.0f ?
+ long duration = Math.abs(velocityX) > 0.0f ?
(long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX))
- : SNAP_BACK_DURATION;
+ : Constants.SNAP_BACK_DURATION;
+ duration = Math.min(duration, Constants.SNAP_BACK_DURATION);
anim = ObjectAnimator.ofFloat(animView, "x", animView.getX(), 0.0f);
anim.setInterpolator(new DecelerateInterpolator(4.0f));
anim.setDuration(duration);
@@ -243,6 +248,13 @@ public class RecentsVerticalScrollView extends ScrollView
setOverScrollEffectPadding(leftPadding, 0);
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ mDensityScale = getResources().getDisplayMetrics().density;
+ mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ }
+
private void setOverScrollEffectPadding(int leftPadding, int i) {
// TODO Add to (Vertical)ScrollView
}
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/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/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 10b9083..da9b55c 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -3154,11 +3154,9 @@ void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
mLastHoverWindow = NULL;
}
- mWindows.clear();
-
// Loop over new windows and rebuild the necessary window pointers for
// tracking focus and touch.
- mWindows.appendVector(inputWindows);
+ mWindows = inputWindows;
size_t numWindows = mWindows.size();
for (size_t i = 0; i < numWindows; i++) {
@@ -4560,8 +4558,7 @@ void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
split = other.split;
deviceId = other.deviceId;
source = other.source;
- windows.clear();
- windows.appendVector(other.windows);
+ windows = other.windows;
}
void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
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 6afccec..786f2fa 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -224,6 +224,7 @@ class BackupManagerService extends IBackupManager.Stub {
public PackageInfo pkgInfo;
public int pmToken; // in post-install restore, the PM's token for this transaction
public boolean needFullBackup;
+ public String[] filterSet;
RestoreParams(IBackupTransport _transport, IRestoreObserver _obs,
long _token, PackageInfo _pkg, int _pmToken, boolean _needFullBackup) {
@@ -233,6 +234,7 @@ class BackupManagerService extends IBackupManager.Stub {
pkgInfo = _pkg;
pmToken = _pmToken;
needFullBackup = _needFullBackup;
+ filterSet = null;
}
RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token,
@@ -243,6 +245,18 @@ class BackupManagerService extends IBackupManager.Stub {
pkgInfo = null;
pmToken = 0;
needFullBackup = _needFullBackup;
+ filterSet = null;
+ }
+
+ RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token,
+ String[] _filterSet, boolean _needFullBackup) {
+ transport = _transport;
+ observer = _obs;
+ token = _token;
+ pkgInfo = null;
+ pmToken = 0;
+ needFullBackup = _needFullBackup;
+ filterSet = _filterSet;
}
}
@@ -404,7 +418,7 @@ class BackupManagerService extends IBackupManager.Stub {
Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
(new PerformRestoreTask(params.transport, params.observer,
params.token, params.pkgInfo, params.pmToken,
- params.needFullBackup)).run();
+ params.needFullBackup, params.filterSet)).run();
break;
}
@@ -3020,6 +3034,7 @@ class BackupManagerService extends IBackupManager.Stub {
private File mStateDir;
private int mPmToken;
private boolean mNeedFullBackup;
+ private HashSet<String> mFilterSet;
class RestoreRequest {
public PackageInfo app;
@@ -3033,7 +3048,7 @@ class BackupManagerService extends IBackupManager.Stub {
PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer,
long restoreSetToken, PackageInfo targetPackage, int pmToken,
- boolean needFullBackup) {
+ boolean needFullBackup, String[] filterSet) {
mTransport = transport;
mObserver = observer;
mToken = restoreSetToken;
@@ -3041,6 +3056,15 @@ class BackupManagerService extends IBackupManager.Stub {
mPmToken = pmToken;
mNeedFullBackup = needFullBackup;
+ if (filterSet != null) {
+ mFilterSet = new HashSet<String>();
+ for (String pkg : filterSet) {
+ mFilterSet.add(pkg);
+ }
+ } else {
+ mFilterSet = null;
+ }
+
try {
mStateDir = new File(mBaseStateDir, transport.transportDirName());
} catch (RemoteException e) {
@@ -3052,7 +3076,8 @@ class BackupManagerService extends IBackupManager.Stub {
long startRealtime = SystemClock.elapsedRealtime();
if (DEBUG) Slog.v(TAG, "Beginning restore process mTransport=" + mTransport
+ " mObserver=" + mObserver + " mToken=" + Long.toHexString(mToken)
- + " mTargetPackage=" + mTargetPackage + " mPmToken=" + mPmToken);
+ + " mTargetPackage=" + mTargetPackage + " mFilterSet=" + mFilterSet
+ + " mPmToken=" + mPmToken);
PackageManagerBackupAgent pmAgent = null;
int error = -1; // assume error
@@ -3071,6 +3096,22 @@ class BackupManagerService extends IBackupManager.Stub {
List<PackageInfo> agentPackages = allAgentPackages();
if (mTargetPackage == null) {
+ // if there's a filter set, strip out anything that isn't
+ // present before proceeding
+ if (mFilterSet != null) {
+ for (int i = agentPackages.size() - 1; i >= 0; i--) {
+ final PackageInfo pkg = agentPackages.get(i);
+ if (! mFilterSet.contains(pkg.packageName)) {
+ agentPackages.remove(i);
+ }
+ }
+ if (DEBUG) {
+ Slog.i(TAG, "Post-filter package set for restore:");
+ for (PackageInfo p : agentPackages) {
+ Slog.i(TAG, " " + p);
+ }
+ }
+ }
restorePackages.addAll(agentPackages);
} else {
// Just one package to attempt restore of
@@ -4266,6 +4307,67 @@ class BackupManagerService extends IBackupManager.Stub {
return -1;
}
+ public synchronized int restoreSome(long token, IRestoreObserver observer,
+ String[] packages) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+ "performRestore");
+
+ if (DEBUG) {
+ StringBuilder b = new StringBuilder(128);
+ b.append("restoreSome token=");
+ b.append(Long.toHexString(token));
+ b.append(" observer=");
+ b.append(observer.toString());
+ b.append(" packages=");
+ if (packages == null) {
+ b.append("null");
+ } else {
+ b.append('{');
+ boolean first = true;
+ for (String s : packages) {
+ if (!first) {
+ b.append(", ");
+ } else first = false;
+ b.append(s);
+ }
+ b.append('}');
+ }
+ Slog.d(TAG, b.toString());
+ }
+
+ if (mEnded) {
+ throw new IllegalStateException("Restore session already ended");
+ }
+
+ if (mRestoreTransport == null || mRestoreSets == null) {
+ Slog.e(TAG, "Ignoring restoreAll() with no restore set");
+ return -1;
+ }
+
+ if (mPackageName != null) {
+ Slog.e(TAG, "Ignoring restoreAll() on single-package session");
+ return -1;
+ }
+
+ synchronized (mQueueLock) {
+ for (int i = 0; i < mRestoreSets.length; i++) {
+ if (token == mRestoreSets[i].token) {
+ long oldId = Binder.clearCallingIdentity();
+ mWakelock.acquire();
+ Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
+ msg.obj = new RestoreParams(mRestoreTransport, observer, token,
+ packages, true);
+ mBackupHandler.sendMessage(msg);
+ Binder.restoreCallingIdentity(oldId);
+ return 0;
+ }
+ }
+ }
+
+ Slog.w(TAG, "Restore token " + Long.toHexString(token) + " not found");
+ return -1;
+ }
+
public synchronized int restorePackage(String packageName, IRestoreObserver observer) {
if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer);
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..2e54c99 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;
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index da1bf83..829df39 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() {
@@ -930,13 +939,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();
+
+ // 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"));
- 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);
+ stats.addValues(entry);
+ }
+
+ if (DBG) Slog.d(TAG, "recorded stale stats from " + xtIfaces);
}
return stats;
@@ -1063,13 +1127,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 +1147,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 +1181,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 +1272,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 +1307,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..24d4dd3 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();
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..d23d0f4 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() {
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index b4bd176..b6834f6 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() {
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..86b3d36 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -251,19 +251,18 @@ public class UsbDeviceManager {
public UsbHandler() {
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 +620,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 +639,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/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/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/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/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index 9695344..1f24b58 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -76,8 +76,6 @@ public class GsmDataConnection extends DataConnection {
+ "' APN: '" + mApn.apn
+ "' proxy: '" + mApn.proxy + "' port: '" + mApn.port);
- setHttpProxy (mApn.proxy, mApn.port);
-
createTime = -1;
lastFailTime = -1;
lastFailCause = FailCause.NONE;
@@ -152,38 +150,6 @@ public class GsmDataConnection extends DataConnection {
Log.d(LOG_TAG, "[" + getName() + "] " + s);
}
- private void setHttpProxy(String httpProxy, String httpPort) {
-
- if (DBG) log("set http proxy for"
- + "' APN: '" + mActiveApnType
- + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port);
- if(TextUtils.equals(mActiveApnType, Phone.APN_TYPE_DEFAULT)) {
- if (httpProxy == null || httpProxy.length() == 0) {
- phone.setSystemProperty("net.gprs.http-proxy", null);
- return;
- }
-
- if (httpPort == null || httpPort.length() == 0) {
- httpPort = "8080"; // Default to port 8080
- }
-
- phone.setSystemProperty("net.gprs.http-proxy",
- "http://" + httpProxy + ":" + httpPort + "/");
- } else {
- if (httpProxy == null || httpProxy.length() == 0) {
- phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType, null);
- return;
- }
-
- if (httpPort == null || httpPort.length() == 0) {
- httpPort = "8080"; // Default to port 8080
- }
-
- phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType,
- "http://" + httpProxy + ":" + httpPort + "/");
- }
- }
-
private boolean isIpAddress(String address) {
if (address == 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/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