summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk3
-rw-r--r--api/8.xml577
-rw-r--r--api/current.xml1352
-rw-r--r--common/java/com/android/common/HttpDateTime.java (renamed from core/java/android/webkit/HttpDateTime.java)2
-rw-r--r--common/java/com/android/common/speech/LoggingEvents.java130
-rw-r--r--common/java/com/android/common/userhappiness/UserHappinessSignals.java45
-rw-r--r--core/java/android/app/ActivityManager.java11
-rw-r--r--core/java/android/app/ActivityManagerNative.java20
-rw-r--r--core/java/android/app/ApplicationContext.java161
-rw-r--r--core/java/android/app/BackupAgent.java34
-rw-r--r--core/java/android/app/DeviceAdmin.java6
-rw-r--r--core/java/android/app/DeviceAdminInfo.java2
-rw-r--r--core/java/android/app/DevicePolicyManager.java86
-rw-r--r--core/java/android/app/IActivityManager.java3
-rw-r--r--core/java/android/app/IBackupAgent.aidl23
-rw-r--r--core/java/android/app/IDevicePolicyManager.aidl6
-rw-r--r--core/java/android/app/SearchDialog.java13
-rw-r--r--core/java/android/app/Service.java8
-rw-r--r--core/java/android/backup/IBackupManager.aidl10
-rw-r--r--core/java/android/backup/RestoreSession.java76
-rw-r--r--core/java/android/content/Context.java12
-rw-r--r--core/java/android/content/Intent.java77
-rw-r--r--core/java/android/content/pm/PackageManager.java27
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java5
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabase.java94
-rw-r--r--core/java/android/database/sqlite/SQLiteDebug.java78
-rw-r--r--core/java/android/database/sqlite/SQLiteProgram.java62
-rw-r--r--core/java/android/database/sqlite/SQLiteStatement.java13
-rw-r--r--core/java/android/database/sqlite/SqliteWrapper.java (renamed from core/java/com/google/android/mms/util/SqliteWrapper.java)22
-rw-r--r--core/java/android/ddm/DdmHandleHeap.java38
-rw-r--r--core/java/android/hardware/Camera.java69
-rw-r--r--core/java/android/net/http/CertificateChainValidator.java214
-rw-r--r--core/java/android/os/Build.java10
-rw-r--r--core/java/android/os/Debug.java12
-rw-r--r--core/java/android/os/IMountService.aidl72
-rw-r--r--core/java/android/os/IMountServiceListener.aidl66
-rw-r--r--core/java/android/os/MountServiceListener.java69
-rw-r--r--core/java/android/os/MountServiceResultCode.java34
-rw-r--r--core/java/android/provider/Browser.java23
-rw-r--r--core/java/android/provider/ContactsContract.java54
-rw-r--r--core/java/android/provider/MediaStore.java14
-rw-r--r--core/java/android/provider/Telephony.java3
-rw-r--r--core/java/android/server/search/SearchManagerService.java9
-rw-r--r--core/java/android/speech/RecognizerIntent.java21
-rw-r--r--core/java/android/speech/RecognizerResultsIntent.java129
-rw-r--r--core/java/android/storage/StorageEventListener.java57
-rw-r--r--core/java/android/storage/StorageManager.java300
-rw-r--r--core/java/android/view/GestureDetector.java83
-rw-r--r--core/java/android/view/ScaleGestureDetector.java19
-rw-r--r--core/java/android/view/View.java7
-rw-r--r--core/java/android/view/WindowManager.java6
-rw-r--r--core/java/android/view/WindowManagerPolicy.java6
-rw-r--r--core/java/android/webkit/CacheManager.java12
-rw-r--r--core/java/android/webkit/ContentLoader.java13
-rw-r--r--core/java/android/webkit/CookieManager.java2
-rw-r--r--core/java/android/webkit/DataLoader.java20
-rw-r--r--core/java/android/webkit/FileLoader.java14
-rw-r--r--core/java/android/webkit/FrameLoader.java15
-rw-r--r--core/java/android/webkit/JsResult.java5
-rw-r--r--core/java/android/webkit/StreamLoader.java5
-rw-r--r--core/java/android/webkit/WebView.java152
-rw-r--r--core/java/android/webkit/WebViewCore.java63
-rw-r--r--core/java/android/widget/AbsListView.java387
-rw-r--r--core/java/android/widget/DateTimeView.java2
-rw-r--r--core/java/android/widget/FastScroller.java11
-rw-r--r--core/java/android/widget/HorizontalScrollView.java11
-rw-r--r--core/java/android/widget/OverScroller.java11
-rw-r--r--core/java/android/widget/ScrollView.java11
-rw-r--r--core/java/com/android/internal/app/UsbStorageActivity.java121
-rw-r--r--core/java/com/android/internal/app/UsbStorageStopActivity.java123
-rw-r--r--core/java/com/android/internal/backup/IBackupTransport.aidl15
-rw-r--r--core/java/com/android/internal/backup/LocalTransport.java10
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java91
-rw-r--r--core/java/com/android/internal/widget/SlidingTab.java14
-rwxr-xr-xcore/java/com/google/android/mms/package.html5
-rwxr-xr-xcore/java/com/google/android/mms/pdu/package.html5
-rwxr-xr-xcore/java/com/google/android/mms/util/package.html5
-rw-r--r--core/jni/AndroidRuntime.cpp9
-rw-r--r--core/jni/CursorWindow.cpp17
-rw-r--r--core/jni/CursorWindow.h5
-rw-r--r--core/jni/android_hardware_Camera.cpp2
-rw-r--r--core/jni/com_google_android_gles_jni_GLImpl.cpp1032
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--core/res/res/drawable-hdpi/usb_android.pngbin0 -> 4924 bytes
-rw-r--r--core/res/res/drawable-hdpi/usb_android_connected.pngbin0 -> 4734 bytes
-rw-r--r--core/res/res/layout-land/usb_storage_activity.xml70
-rw-r--r--core/res/res/layout/contact_header.xml1
-rw-r--r--core/res/res/layout/keyguard_screen_sim_pin_landscape.xml32
-rw-r--r--core/res/res/layout/keyguard_screen_tab_unlock.xml1
-rw-r--r--core/res/res/layout/keyguard_screen_tab_unlock_land.xml1
-rw-r--r--core/res/res/layout/keyguard_screen_unlock_landscape.xml1
-rw-r--r--core/res/res/layout/keyguard_screen_unlock_portrait.xml1
-rw-r--r--core/res/res/layout/usb_storage_activity.xml61
-rw-r--r--core/res/res/values/config.xml6
-rw-r--r--core/res/res/values/strings.xml28
-rw-r--r--core/tests/coretests/Android.mk6
-rw-r--r--core/tests/coretests/AndroidManifest.xml225
-rw-r--r--core/tests/coretests/assets/text.txt (renamed from tests/AndroidTests/assets/text.txt)0
-rw-r--r--core/tests/coretests/res/layout/layout_five.xml (renamed from tests/AndroidTests/res/layout/layout_five.xml)0
-rw-r--r--core/tests/coretests/res/layout/layout_four.xml (renamed from tests/AndroidTests/res/layout/layout_four.xml)0
-rw-r--r--core/tests/coretests/res/layout/layout_one.xml (renamed from tests/AndroidTests/res/layout/layout_one.xml)2
-rw-r--r--core/tests/coretests/res/layout/layout_six.xml (renamed from tests/AndroidTests/res/layout/layout_six.xml)0
-rw-r--r--core/tests/coretests/res/layout/layout_tag.xml (renamed from tests/AndroidTests/res/layout/layout_tag.xml)2
-rw-r--r--core/tests/coretests/res/layout/layout_three.xml27
-rw-r--r--core/tests/coretests/res/layout/layout_two.xml (renamed from tests/AndroidTests/res/layout/layout_two.xml)2
-rw-r--r--core/tests/coretests/res/raw/medium.xml (renamed from tests/AndroidTests/res/raw/medium.xml)0
-rw-r--r--core/tests/coretests/res/raw/small.xml (renamed from tests/AndroidTests/res/raw/small.xml)0
-rw-r--r--core/tests/coretests/res/raw/text.txt (renamed from tests/AndroidTests/res/raw/text.txt)0
-rw-r--r--core/tests/coretests/res/raw/v21_backslash.vcf (renamed from tests/AndroidTests/res/raw/v21_backslash.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_complicated.vcf (renamed from tests/AndroidTests/res/raw/v21_complicated.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_invalid_comment_line.vcf (renamed from tests/AndroidTests/res/raw/v21_invalid_comment_line.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_japanese_1.vcf (renamed from tests/AndroidTests/res/raw/v21_japanese_1.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_japanese_2.vcf (renamed from tests/AndroidTests/res/raw/v21_japanese_2.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_multiple_entry.vcf (renamed from tests/AndroidTests/res/raw/v21_multiple_entry.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_org_before_title.vcf (renamed from tests/AndroidTests/res/raw/v21_org_before_title.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_pref_handling.vcf (renamed from tests/AndroidTests/res/raw/v21_pref_handling.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_simple_1.vcf (renamed from tests/AndroidTests/res/raw/v21_simple_1.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_simple_2.vcf (renamed from tests/AndroidTests/res/raw/v21_simple_2.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_simple_3.vcf (renamed from tests/AndroidTests/res/raw/v21_simple_3.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_title_before_org.vcf (renamed from tests/AndroidTests/res/raw/v21_title_before_org.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v21_winmo_65.vcf (renamed from tests/AndroidTests/res/raw/v21_winmo_65.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v30_comma_separated.vcf (renamed from tests/AndroidTests/res/raw/v30_comma_separated.vcf)0
-rw-r--r--core/tests/coretests/res/raw/v30_simple.vcf (renamed from tests/AndroidTests/res/raw/v30_simple.vcf)0
-rw-r--r--core/tests/coretests/res/values/strings.xml17
-rw-r--r--core/tests/coretests/res/xml/metadata.xml (renamed from tests/AndroidTests/res/xml/metadata.xml)0
-rw-r--r--core/tests/coretests/res/xml/metadata_app.xml (renamed from tests/AndroidTests/res/xml/metadata_app.xml)0
-rw-r--r--core/tests/coretests/res/xml/searchable.xml (renamed from tests/AndroidTests/res/xml/searchable.xml)0
-rw-r--r--core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java)4
-rw-r--r--core/tests/coretests/src/android/app/SearchManagerTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java)10
-rw-r--r--core/tests/coretests/src/android/app/SearchablesTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java)6
-rw-r--r--core/tests/coretests/src/android/app/SuggestionProvider.java (renamed from tests/AndroidTests/src/com/android/unit_tests/SuggestionProvider.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/AbortReceiver.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/AbortReceiver.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityManagerTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/ActivityManagerTest.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityTests.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTests.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityTestsBase.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTestsBase.java)6
-rw-r--r--core/tests/coretests/src/android/app/activity/BroadcastTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/BroadcastTest.java)32
-rw-r--r--core/tests/coretests/src/android/app/activity/ClearTop.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/ClearTop.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/IntentSenderTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/IntentSenderTest.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LaunchTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LaunchTest.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LaunchpadActivity.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadActivity.java)38
-rw-r--r--core/tests/coretests/src/android/app/activity/LaunchpadTabActivity.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadTabActivity.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LifecycleTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LifecycleTest.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LocalActivity.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LocalActivity.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LocalDeniedReceiver.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedReceiver.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LocalDeniedService.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedService.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LocalDialog.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LocalDialog.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LocalGrantedReceiver.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedReceiver.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LocalGrantedService.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedService.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LocalProvider.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LocalProvider.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LocalReceiver.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LocalReceiver.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LocalScreen.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LocalScreen.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/LocalService.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/LocalService.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/MetaDataTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/MetaDataTest.java)24
-rw-r--r--core/tests/coretests/src/android/app/activity/RemoteDeniedReceiver.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/RemoteDeniedReceiver.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/RemoteGrantedReceiver.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/RemoteGrantedReceiver.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/RemoteReceiver.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/RemoteReceiver.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/RemoteSubActivityScreen.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/ResultReceiver.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/ResultReceiver.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/SearchableActivity.java (renamed from tests/AndroidTests/src/com/android/unit_tests/SearchableActivity.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/ServiceTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/ServiceTest.java)8
-rw-r--r--core/tests/coretests/src/android/app/activity/SetTimeZonePermissionsTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/SetTimeZonePermissionsTest.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/SubActivityScreen.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityScreen.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/SubActivityTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityTest.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/TestedActivity.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/TestedActivity.java)2
-rw-r--r--core/tests/coretests/src/android/app/activity/TestedScreen.java (renamed from tests/AndroidTests/src/com/android/unit_tests/activity/TestedScreen.java)2
-rw-r--r--core/tests/coretests/src/android/content/AssetTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/content/AssetTest.java)2
-rw-r--r--core/tests/coretests/src/android/content/ContentQueryMapTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/ContentQueryMapTest.java)2
-rw-r--r--core/tests/coretests/src/android/content/ContentTests.java (renamed from tests/AndroidTests/src/com/android/unit_tests/content/ContentTests.java)2
-rw-r--r--core/tests/coretests/src/android/content/MemoryFileProvider.java (renamed from tests/AndroidTests/src/com/android/unit_tests/content/MemoryFileProvider.java)2
-rw-r--r--core/tests/coretests/src/android/content/MemoryFileProviderTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/content/MemoryFileProviderTest.java)8
-rw-r--r--core/tests/coretests/src/android/database/CursorWindowTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/CursorWindowTest.java)2
-rw-r--r--core/tests/coretests/src/android/database/DatabaseCursorTest.java630
-rw-r--r--core/tests/coretests/src/android/database/DatabaseGeneralTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java)2
-rw-r--r--core/tests/coretests/src/android/database/DatabaseLocaleTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/DatabaseLocaleTest.java)4
-rw-r--r--core/tests/coretests/src/android/database/DatabaseLockTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/DatabaseLockTest.java)2
-rw-r--r--core/tests/coretests/src/android/database/DatabasePerformanceTests.java (renamed from tests/AndroidTests/src/com/android/unit_tests/DatabasePerformanceTests.java)2
-rw-r--r--core/tests/coretests/src/android/database/DatabaseStatementTest.java324
-rw-r--r--core/tests/coretests/src/android/database/DatabaseStressTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/DatabaseStressTest.java)2
-rw-r--r--core/tests/coretests/src/android/database/sqlite/SQLiteDebugTest.java47
-rw-r--r--core/tests/coretests/src/android/net/LocalSocketTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/LocalSocketTest.java)6
-rw-r--r--core/tests/coretests/src/android/net/SSLTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/SSLTest.java)2
-rw-r--r--core/tests/coretests/src/android/net/UriMatcherTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/UriMatcherTest.java)2
-rw-r--r--core/tests/coretests/src/android/net/UriTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/UriTest.java)25
-rw-r--r--core/tests/coretests/src/android/os/AidlTest.aidl (renamed from tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.aidl)2
-rw-r--r--core/tests/coretests/src/android/os/AidlTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/BroadcasterTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/BroadcasterTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/BuildTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/BuildTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/FileObserverTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/FileUtilsTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/FileUtilsTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/HandlerTester.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/HandlerTester.java)2
-rw-r--r--core/tests/coretests/src/android/os/HandlerThreadTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/HierarchicalStateMachineTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/IAidlTest.aidl (renamed from tests/AndroidTests/src/com/android/unit_tests/os/IAidlTest.aidl)4
-rw-r--r--core/tests/coretests/src/android/os/IdleHandlerTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/IdleHandlerTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/MemoryFileTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/MessageQueueTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/MessageQueueTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/MessengerService.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/MessengerService.java)2
-rw-r--r--core/tests/coretests/src/android/os/MessengerTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/MessengerTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/OsTests.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/OsTests.java)4
-rw-r--r--core/tests/coretests/src/android/os/PerformanceCollectorTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/PerformanceCollectorTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/PowerManagerTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java)2
-rw-r--r--core/tests/coretests/src/android/os/SystemPropertiesTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/SystemPropertiesTest.java)4
-rw-r--r--core/tests/coretests/src/android/os/TestHandlerThread.java (renamed from tests/AndroidTests/src/com/android/unit_tests/os/TestHandlerThread.java)2
-rw-r--r--core/tests/coretests/src/android/os/TraceTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/TraceTest.java)2
-rw-r--r--core/tests/coretests/src/android/pim/vcard/ContentValuesBuilder.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesBuilder.java)2
-rw-r--r--core/tests/coretests/src/android/pim/vcard/ContentValuesVerifier.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesVerifier.java)4
-rw-r--r--core/tests/coretests/src/android/pim/vcard/ContentValuesVerifierElem.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesVerifierElem.java)4
-rw-r--r--core/tests/coretests/src/android/pim/vcard/ExportTestResolver.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/ExportTestResolver.java)4
-rw-r--r--core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/ImportTestResolver.java)2
-rw-r--r--core/tests/coretests/src/android/pim/vcard/LineVerifier.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/LineVerifier.java)2
-rw-r--r--core/tests/coretests/src/android/pim/vcard/LineVerifierElem.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/LineVerifierElem.java)2
-rw-r--r--core/tests/coretests/src/android/pim/vcard/PropertyNode.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNode.java)2
-rw-r--r--core/tests/coretests/src/android/pim/vcard/PropertyNodesVerifier.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java)2
-rw-r--r--core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java)4
-rw-r--r--core/tests/coretests/src/android/pim/vcard/VCardImporterTests.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java)6
-rw-r--r--core/tests/coretests/src/android/pim/vcard/VCardJapanizationTests.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/VCardJapanizationTests.java)4
-rw-r--r--core/tests/coretests/src/android/pim/vcard/VCardTestsBase.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java)2
-rw-r--r--core/tests/coretests/src/android/pim/vcard/VCardUtilsTests.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/VCardUtilsTests.java)2
-rw-r--r--core/tests/coretests/src/android/pim/vcard/VCardVerifier.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/VCardVerifier.java)2
-rw-r--r--core/tests/coretests/src/android/pim/vcard/VNode.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/VNode.java)2
-rw-r--r--core/tests/coretests/src/android/pim/vcard/VNodeBuilder.java (renamed from tests/AndroidTests/src/com/android/unit_tests/vcard/VNodeBuilder.java)2
-rw-r--r--core/tests/coretests/src/android/provider/SettingsProviderTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/SettingsProviderTest.java)2
-rw-r--r--core/tests/coretests/src/android/provider/SmsProviderTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/SmsProviderTest.java)2
-rw-r--r--core/tests/coretests/src/android/text/SpannedTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/SpannedTest.java)2
-rw-r--r--core/tests/coretests/src/android/text/TextLayoutTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/TextLayoutTest.java)2
-rw-r--r--core/tests/coretests/src/android/text/TextUtilsTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java)2
-rw-r--r--core/tests/coretests/src/android/text/format/TimeTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/TimeTest.java)2
-rw-r--r--core/tests/coretests/src/android/util/LogTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/LogTest.java)2
-rw-r--r--core/tests/coretests/src/android/util/TimeUtilsTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/TimeUtilsTest.java)2
-rw-r--r--core/tests/coretests/src/android/view/CreateViewTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/CreateViewTest.java)2
-rw-r--r--core/tests/coretests/src/android/view/InflateTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/InflateTest.java)3
-rw-r--r--core/tests/coretests/src/android/view/MenuTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/MenuTest.java)4
-rw-r--r--core/tests/coretests/src/android/webkit/WebkitTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/WebkitTest.java)2
-rw-r--r--core/tests/coretests/src/android/widget/LabelView.java (renamed from tests/AndroidTests/src/com/android/unit_tests/LabelView.java)2
-rw-r--r--core/tests/coretests/src/android/widget/TextViewPerformanceTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/TextViewPerformanceTest.java)2
-rw-r--r--core/tests/coretests/src/android/widget/TextViewTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/TextViewTest.java)2
-rw-r--r--core/tests/coretests/src/com/android/internal/util/BitwiseStreamsTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/BitwiseStreamsTest.java)2
-rw-r--r--core/tests/coretests/src/com/android/internal/util/CharSequencesTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/CharSequencesTest.java)2
-rw-r--r--core/tests/coretests/src/com/google/android/net/ParentalControlTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/ParentalControlTest.java)2
-rw-r--r--docs/html/guide/developing/debug-tasks.jd50
-rw-r--r--docs/html/guide/practices/screens_support.jd2
-rw-r--r--docs/html/guide/topics/manifest/uses-feature-element.jd98
-rw-r--r--docs/html/index.jd2
-rw-r--r--docs/html/mwc2010/index.html2
-rw-r--r--docs/html/sdk/android-2.1.jd15
-rw-r--r--graphics/java/android/renderscript/FieldPacker.java129
-rw-r--r--graphics/java/android/renderscript/Matrix2f.java58
-rw-r--r--graphics/java/android/renderscript/Matrix3f.java63
-rw-r--r--graphics/java/android/renderscript/Matrix4f.java (renamed from graphics/java/android/renderscript/Matrix.java)33
-rw-r--r--graphics/java/android/renderscript/ProgramVertex.java22
-rw-r--r--graphics/java/android/renderscript/Vector2f.java (renamed from tests/AndroidTests/src/com/android/unit_tests/DatabaseTests.java)29
-rw-r--r--graphics/java/android/renderscript/Vector3f.java38
-rw-r--r--graphics/java/android/renderscript/Vector4f.java38
-rw-r--r--graphics/tests/graphicstests/Android.mk14
-rw-r--r--graphics/tests/graphicstests/AndroidManifest.xml37
-rw-r--r--graphics/tests/graphicstests/res/drawable/test128x96.png (renamed from tests/AndroidTests/res/drawable/test128x96.png)bin21474 -> 21474 bytes
-rw-r--r--graphics/tests/graphicstests/res/drawable/test16x12.png (renamed from tests/AndroidTests/res/drawable/test16x12.png)bin707 -> 707 bytes
-rw-r--r--graphics/tests/graphicstests/res/drawable/test256x192.png (renamed from tests/AndroidTests/res/drawable/test256x192.png)bin78630 -> 78630 bytes
-rw-r--r--graphics/tests/graphicstests/res/drawable/test320x240.png (renamed from tests/AndroidTests/res/drawable/test320x240.png)bin39533 -> 39533 bytes
-rw-r--r--graphics/tests/graphicstests/res/drawable/test32x24.png (renamed from tests/AndroidTests/res/drawable/test32x24.png)bin1841 -> 1841 bytes
-rw-r--r--graphics/tests/graphicstests/res/drawable/test64x48.png (renamed from tests/AndroidTests/res/drawable/test64x48.png)bin6020 -> 6020 bytes
-rw-r--r--graphics/tests/graphicstests/src/android/graphics/BitmapTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/graphics/BitmapTest.java)2
-rw-r--r--graphics/tests/graphicstests/src/android/graphics/GraphicsPerformanceTests.java (renamed from tests/AndroidTests/src/com/android/unit_tests/GraphicsPerformanceTests.java)4
-rw-r--r--graphics/tests/graphicstests/src/android/graphics/GraphicsTests.java (renamed from tests/AndroidTests/src/com/android/unit_tests/graphics/GraphicsTests.java)2
-rw-r--r--graphics/tests/graphicstests/src/android/graphics/ThreadBitmapTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/ThreadBitmapTest.java)2
-rw-r--r--graphics/tests/graphicstests/src/android/graphics/TypefaceTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/graphics/TypefaceTest.java)2
-rw-r--r--include/binder/MemoryDealer.h215
-rw-r--r--include/binder/MemoryHeapPmem.h4
-rw-r--r--include/media/MediaProfiles.h303
-rw-r--r--include/media/stagefright/AudioPlayer.h2
-rw-r--r--include/media/stagefright/CachingDataSource.h2
-rw-r--r--include/media/stagefright/HTTPDataSource.h10
-rw-r--r--include/media/stagefright/OMXCodec.h1
-rw-r--r--include/private/opengles/gl_context.h7
-rw-r--r--include/ui/CameraParameters.h12
-rw-r--r--libs/audioflinger/AudioFlinger.cpp2
-rw-r--r--libs/audioflinger/AudioPolicyManagerBase.cpp3
-rw-r--r--libs/binder/MemoryDealer.cpp315
-rw-r--r--libs/binder/MemoryHeapPmem.cpp2
-rw-r--r--libs/ui/CameraParameters.cpp17
-rw-r--r--location/java/android/location/ILocationProvider.aidl1
-rw-r--r--location/java/android/location/LocationProviderImpl.java9
-rwxr-xr-xlocation/java/com/android/internal/location/GpsLocationProvider.java40
-rw-r--r--location/java/com/android/internal/location/LocationProviderProxy.java10
-rw-r--r--location/java/com/android/internal/location/MockProvider.java4
-rw-r--r--location/tests/locationtests/src/android/location/GeocoderTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/GeocoderTest.java)2
-rw-r--r--location/tests/locationtests/src/android/location/LocationManagerTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/LocationManagerTest.java)2
-rw-r--r--media/java/android/media/EncoderCapabilities.java164
-rw-r--r--media/java/android/media/ExifInterface.java36
-rw-r--r--media/java/android/media/MediaScanner.java2
-rw-r--r--media/java/android/media/MiniThumbFile.java1
-rw-r--r--media/java/android/media/ThumbnailUtils.java (renamed from media/java/android/media/ThumbnailUtil.java)414
-rw-r--r--media/jni/Android.mk3
-rw-r--r--media/jni/android_media_MediaPlayer.cpp6
-rw-r--r--media/jni/android_media_MediaProfiles.cpp187
-rw-r--r--media/libmedia/Android.mk14
-rw-r--r--media/libmedia/AudioRecord.cpp1
-rw-r--r--media/libmedia/AudioTrack.cpp1
-rw-r--r--media/libmedia/MediaProfiles.cpp675
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.cpp23
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.h2
-rw-r--r--media/libstagefright/AudioPlayer.cpp33
-rw-r--r--media/libstagefright/AwesomePlayer.cpp20
-rw-r--r--media/libstagefright/CachingDataSource.cpp4
-rw-r--r--media/libstagefright/HTTPDataSource.cpp97
-rw-r--r--media/libstagefright/HTTPStream.cpp31
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp215
-rw-r--r--media/libstagefright/MPEG4Writer.cpp21
-rw-r--r--media/libstagefright/OMXCodec.cpp15
-rw-r--r--media/libstagefright/WAVExtractor.cpp21
-rw-r--r--media/libstagefright/codecs/avc/dec/AVCDecoder.cpp8
-rw-r--r--media/libstagefright/colorconversion/SoftwareRenderer.cpp11
-rw-r--r--media/libstagefright/include/MPEG4Extractor.h3
-rw-r--r--media/libstagefright/omx/tests/OMXHarness.cpp2
-rw-r--r--media/sdutils/sdutil.cpp227
-rw-r--r--mms-common/Android.mk29
-rw-r--r--mms-common/java/com/android/mmscommon/CharacterSets.java (renamed from core/java/com/google/android/mms/pdu/CharacterSets.java)2
-rw-r--r--mms-common/java/com/android/mmscommon/ContentType.java (renamed from core/java/com/google/android/mms/ContentType.java)3
-rw-r--r--mms-common/java/com/android/mmscommon/EncodedStringValue.java (renamed from core/java/com/google/android/mms/pdu/EncodedStringValue.java)4
-rw-r--r--mms-common/java/com/android/mmscommon/InvalidHeaderValueException.java (renamed from core/java/com/google/android/mms/InvalidHeaderValueException.java)2
-rw-r--r--mms-common/java/com/android/mmscommon/MmsException.java (renamed from core/java/com/google/android/mms/MmsException.java)2
-rw-r--r--mms-common/java/com/android/mmscommon/PduHeaders.java (renamed from core/java/com/google/android/mms/pdu/PduHeaders.java)26
-rw-r--r--mms-common/java/com/android/mmscommon/mms/ContentType.java223
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/AcknowledgeInd.java (renamed from core/java/com/google/android/mms/pdu/AcknowledgeInd.java)5
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/Base64.java (renamed from core/java/com/google/android/mms/pdu/Base64.java)2
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/DeliveryInd.java (renamed from core/java/com/google/android/mms/pdu/DeliveryInd.java)6
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/GenericPdu.java (renamed from core/java/com/google/android/mms/pdu/GenericPdu.java)6
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/MultimediaMessagePdu.java (renamed from core/java/com/google/android/mms/pdu/MultimediaMessagePdu.java)6
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/NotificationInd.java (renamed from core/java/com/google/android/mms/pdu/NotificationInd.java)6
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/NotifyRespInd.java (renamed from core/java/com/google/android/mms/pdu/NotifyRespInd.java)5
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/PduBody.java (renamed from core/java/com/google/android/mms/pdu/PduBody.java)2
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/PduComposer.java (renamed from core/java/com/google/android/mms/pdu/PduComposer.java)5
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/PduContentTypes.java (renamed from core/java/com/google/android/mms/pdu/PduContentTypes.java)2
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/PduParser.java (renamed from core/java/com/google/android/mms/pdu/PduParser.java)13
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/PduPart.java (renamed from core/java/com/google/android/mms/pdu/PduPart.java)2
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/PduPersister.java (renamed from core/java/com/google/android/mms/pdu/PduPersister.java)43
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/QuotedPrintable.java (renamed from core/java/com/google/android/mms/pdu/QuotedPrintable.java)2
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/ReadOrigInd.java (renamed from core/java/com/google/android/mms/pdu/ReadOrigInd.java)6
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/ReadRecInd.java (renamed from core/java/com/google/android/mms/pdu/ReadRecInd.java)6
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/RetrieveConf.java (renamed from core/java/com/google/android/mms/pdu/RetrieveConf.java)6
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/SendConf.java (renamed from core/java/com/google/android/mms/pdu/SendConf.java)6
-rw-r--r--mms-common/java/com/android/mmscommon/mms/pdu/SendReq.java (renamed from core/java/com/google/android/mms/pdu/SendReq.java)6
-rw-r--r--mms-common/java/com/android/mmscommon/mms/util/AbstractCache.java (renamed from core/java/com/google/android/mms/util/AbstractCache.java)2
-rw-r--r--mms-common/java/com/android/mmscommon/mms/util/PduCache.java (renamed from core/java/com/google/android/mms/util/PduCache.java)4
-rw-r--r--mms-common/java/com/android/mmscommon/mms/util/PduCacheEntry.java (renamed from core/java/com/google/android/mms/util/PduCacheEntry.java)4
-rw-r--r--mms-common/java/com/android/mmscommon/telephony/TelephonyProvider.java1790
-rw-r--r--opengl/java/com/google/android/gles_jni/GLImpl.java22
-rw-r--r--opengl/libagl/Android.mk2
-rw-r--r--opengl/libagl/state.cpp8
-rw-r--r--opengl/libagl/texture.cpp60
-rw-r--r--opengl/tools/glgen/specs/jsr239/glspec-1.1extpack8
-rw-r--r--opengl/tools/glgen/specs/jsr239/glspec-checks48
-rw-r--r--opengl/tools/glgen/src/JniCodeEmitter.java56
-rw-r--r--opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp85
-rw-r--r--opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl6
-rw-r--r--packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java86
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java19
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java13
-rw-r--r--preloaded-classes4
-rw-r--r--sax/tests/saxtests/Android.mk14
-rw-r--r--sax/tests/saxtests/AndroidManifest.xml36
-rw-r--r--sax/tests/saxtests/res/raw/youtube.xml (renamed from tests/AndroidTests/res/raw/youtube.xml)0
-rw-r--r--sax/tests/saxtests/src/android/sax/ExpatPerformanceTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/ExpatPerformanceTest.java)4
-rw-r--r--sax/tests/saxtests/src/android/sax/SafeSaxTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/SafeSaxTest.java)4
-rw-r--r--services/java/com/android/server/AccessibilityManagerService.java5
-rw-r--r--services/java/com/android/server/AlarmManagerService.java27
-rw-r--r--services/java/com/android/server/AppWidgetService.java58
-rw-r--r--services/java/com/android/server/BackupManagerService.java419
-rw-r--r--services/java/com/android/server/ConnectivityService.java33
-rw-r--r--services/java/com/android/server/DevicePolicyManagerService.java60
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java87
-rw-r--r--services/java/com/android/server/LocationManagerService.java75
-rw-r--r--services/java/com/android/server/MountService.java1312
-rw-r--r--services/java/com/android/server/NativeDaemonConnector.java59
-rw-r--r--services/java/com/android/server/NativeDaemonConnectorException.java42
-rwxr-xr-xservices/java/com/android/server/NotificationManagerService.java29
-rw-r--r--services/java/com/android/server/PackageManagerService.java547
-rw-r--r--services/java/com/android/server/PowerManagerService.java4
-rw-r--r--services/java/com/android/server/WifiService.java2
-rw-r--r--services/java/com/android/server/WifiWatchdogService.java2
-rw-r--r--services/java/com/android/server/WindowManagerService.java3
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java99
-rw-r--r--services/java/com/android/server/status/StatusBarService.java20
-rw-r--r--services/tests/servicestests/Android.mk17
-rw-r--r--services/tests/servicestests/AndroidManifest.xml32
-rw-r--r--services/tests/servicestests/src/com/android/server/DropBoxTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/DropBoxTest.java)2
-rw-r--r--telephony/java/com/android/internal/telephony/BaseCommands.java10
-rw-r--r--telephony/java/com/android/internal/telephony/CommandsInterface.java12
-rw-r--r--telephony/java/com/android/internal/telephony/Phone.java15
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneBase.java10
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneProxy.java8
-rw-r--r--telephony/java/com/android/internal/telephony/RIL.java18
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java1
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CDMAPhone.java2
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaInformationRecords.java2
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java4
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/RuimRecords.java2
-rw-r--r--telephony/tests/telephonytests/AndroidManifest.xml1
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/GsmSmsTest.java)2
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/MccTableTest.java)2
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java79
-rw-r--r--telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java)2
-rw-r--r--test-runner/android/test/mock/MockPackageManager.java8
-rw-r--r--tests/AndroidTests/Android.mk3
-rw-r--r--tests/AndroidTests/AndroidManifest.xml201
-rw-r--r--tests/AndroidTests/res/layout/layout_three.xml27
-rw-r--r--tests/AndroidTests/res/values/strings.xml21
-rw-r--r--tests/AndroidTests/src/com/android/unit_tests/AndroidPerformanceTests.java4
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java97
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/EventSender.java10
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java2
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java7
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java173
-rw-r--r--tests/FrameworkTest/AndroidManifest.xml922
-rw-r--r--tools/aapt/Bundle.h5
-rw-r--r--tools/aapt/Main.cpp9
-rw-r--r--tools/aapt/Resource.cpp68
-rw-r--r--tools/aapt/StringPool.cpp2
-rw-r--r--tools/aapt/XMLNode.cpp13
-rw-r--r--tools/aapt/XMLNode.h2
-rw-r--r--vpn/tests/vpntests/Android.mk14
-rw-r--r--vpn/tests/vpntests/AndroidManifest.xml36
-rwxr-xr-xvpn/tests/vpntests/src/android/net/vpn/VpnTest.java (renamed from tests/AndroidTests/src/com/android/unit_tests/VpnTest.java)2
-rw-r--r--wifi/java/android/net/wifi/WifiMonitor.java63
-rw-r--r--wifi/java/android/net/wifi/WifiStateTracker.java36
425 files changed, 13719 insertions, 5987 deletions
diff --git a/Android.mk b/Android.mk
index 7cd482c95b50..682f2865d1ad 100644
--- a/Android.mk
+++ b/Android.mk
@@ -112,6 +112,7 @@ LOCAL_SRC_FILES += \
core/java/android/os/ICheckinService.aidl \
core/java/android/os/IMessenger.aidl \
core/java/android/os/IMountService.aidl \
+ core/java/android/os/IMountServiceListener.aidl \
core/java/android/os/INetworkManagementService.aidl \
core/java/android/os/INetStatService.aidl \
core/java/android/os/IParentalControlCallback.aidl \
@@ -398,7 +399,7 @@ web_docs_sample_code_flags := \
## SDK version identifiers used in the published docs
# major[.minor] version for current SDK. (full releases only)
-framework_docs_SDK_VERSION:=2.0.1
+framework_docs_SDK_VERSION:=2.1
# release version (ie "Release x") (full releases only)
framework_docs_SDK_REL_ID:=1
# name of current SDK directory (full releases only)
diff --git a/api/8.xml b/api/8.xml
index d5e5fc9df9ba..a07537cef744 100644
--- a/api/8.xml
+++ b/api/8.xml
@@ -173386,573 +173386,6 @@
</parameter>
</method>
</class>
-<class name="CallbackProxy"
- extends="android.os.Handler"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility=""
->
-<constructor name="CallbackProxy"
- type="android.webkit.CallbackProxy"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="w" type="android.webkit.WebView">
-</parameter>
-</constructor>
-<method name="addMessageToConsole"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="message" type="java.lang.String">
-</parameter>
-<parameter name="lineNumber" type="int">
-</parameter>
-<parameter name="sourceID" type="java.lang.String">
-</parameter>
-</method>
-<method name="createWindow"
- return="android.webkit.WebView"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="dialog" type="boolean">
-</parameter>
-<parameter name="userGesture" type="boolean">
-</parameter>
-</method>
-<method name="doUpdateVisitedHistory"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="isReload" type="boolean">
-</parameter>
-</method>
-<method name="getBackForwardList"
- return="android.webkit.WebBackForwardList"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getProgress"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getVisitedHistory"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="callback" type="android.webkit.ValueCallback&lt;java.lang.String[]&gt;">
-</parameter>
-</method>
-<method name="getWebChromeClient"
- return="android.webkit.WebChromeClient"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onCloseWindow"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="window" type="android.webkit.WebView">
-</parameter>
-</method>
-<method name="onDownloadStart"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="userAgent" type="java.lang.String">
-</parameter>
-<parameter name="contentDisposition" type="java.lang.String">
-</parameter>
-<parameter name="mimetype" type="java.lang.String">
-</parameter>
-<parameter name="contentLength" type="long">
-</parameter>
-</method>
-<method name="onExceededDatabaseQuota"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="databaseIdentifier" type="java.lang.String">
-</parameter>
-<parameter name="currentQuota" type="long">
-</parameter>
-<parameter name="estimatedSize" type="long">
-</parameter>
-<parameter name="totalUsedQuota" type="long">
-</parameter>
-<parameter name="quotaUpdater" type="android.webkit.WebStorage.QuotaUpdater">
-</parameter>
-</method>
-<method name="onFormResubmission"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="dontResend" type="android.os.Message">
-</parameter>
-<parameter name="resend" type="android.os.Message">
-</parameter>
-</method>
-<method name="onGeolocationPermissionsHidePrompt"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onGeolocationPermissionsShowPrompt"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="origin" type="java.lang.String">
-</parameter>
-<parameter name="callback" type="android.webkit.GeolocationPermissions.Callback">
-</parameter>
-</method>
-<method name="onJsAlert"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="message" type="java.lang.String">
-</parameter>
-</method>
-<method name="onJsBeforeUnload"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="message" type="java.lang.String">
-</parameter>
-</method>
-<method name="onJsConfirm"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="message" type="java.lang.String">
-</parameter>
-</method>
-<method name="onJsPrompt"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="message" type="java.lang.String">
-</parameter>
-<parameter name="defaultValue" type="java.lang.String">
-</parameter>
-</method>
-<method name="onJsTimeout"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onLoadResource"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-</method>
-<method name="onPageFinished"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-</method>
-<method name="onPageStarted"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="favicon" type="android.graphics.Bitmap">
-</parameter>
-</method>
-<method name="onProgressChanged"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="newProgress" type="int">
-</parameter>
-</method>
-<method name="onReachedMaxAppCacheSize"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="spaceNeeded" type="long">
-</parameter>
-<parameter name="totalUsedQuota" type="long">
-</parameter>
-<parameter name="quotaUpdater" type="android.webkit.WebStorage.QuotaUpdater">
-</parameter>
-</method>
-<method name="onReceivedError"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="errorCode" type="int">
-</parameter>
-<parameter name="description" type="java.lang.String">
-</parameter>
-<parameter name="failingUrl" type="java.lang.String">
-</parameter>
-</method>
-<method name="onReceivedHttpAuthRequest"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="handler" type="android.webkit.HttpAuthHandler">
-</parameter>
-<parameter name="hostName" type="java.lang.String">
-</parameter>
-<parameter name="realmName" type="java.lang.String">
-</parameter>
-</method>
-<method name="onReceivedIcon"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="icon" type="android.graphics.Bitmap">
-</parameter>
-</method>
-<method name="onReceivedTitle"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="title" type="java.lang.String">
-</parameter>
-</method>
-<method name="onRequestFocus"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onSavePassword"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="schemePlusHost" type="java.lang.String">
-</parameter>
-<parameter name="username" type="java.lang.String">
-</parameter>
-<parameter name="password" type="java.lang.String">
-</parameter>
-<parameter name="resumeMsg" type="android.os.Message">
-</parameter>
-</method>
-<method name="onScaleChanged"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="oldScale" type="float">
-</parameter>
-<parameter name="newScale" type="float">
-</parameter>
-</method>
-<method name="onTooManyRedirects"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="cancelMsg" type="android.os.Message">
-</parameter>
-<parameter name="continueMsg" type="android.os.Message">
-</parameter>
-</method>
-<method name="onUnhandledKeyEvent"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="setDownloadListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="client" type="android.webkit.DownloadListener">
-</parameter>
-</method>
-<method name="setWebChromeClient"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="client" type="android.webkit.WebChromeClient">
-</parameter>
-</method>
-<method name="setWebViewClient"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="client" type="android.webkit.WebViewClient">
-</parameter>
-</method>
-<method name="shouldOverrideUrlLoading"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-</method>
-<method name="uiOverrideKeyEvent"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="uiOverrideUrlLoading"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="overrideUrl" type="java.lang.String">
-</parameter>
-</method>
-</class>
<class name="CookieManager"
extends="java.lang.Object"
abstract="false"
@@ -174438,16 +173871,6 @@
visibility="protected"
>
</method>
-<field name="mProxy"
- type="android.webkit.CallbackProxy"
- transient="false"
- volatile="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="protected"
->
-</field>
<field name="mResult"
type="boolean"
transient="false"
diff --git a/api/current.xml b/api/current.xml
index b03f826e13d9..5e343229a435 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -17644,6 +17644,17 @@
<exception name="SecurityException" type="java.lang.SecurityException">
</exception>
</method>
+<method name="isUserAMonkey"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="killBackgroundProcesses"
return="void"
abstract="false"
@@ -20457,7 +20468,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="mode" type="int">
+<parameter name="quality" type="int">
</parameter>
</method>
<method name="getPasswordMinimumLength"
@@ -20473,7 +20484,7 @@
<parameter name="admin" type="android.content.ComponentName">
</parameter>
</method>
-<method name="getPasswordMode"
+<method name="getPasswordQuality"
return="int"
abstract="false"
native="false"
@@ -20592,7 +20603,7 @@
<parameter name="length" type="int">
</parameter>
</method>
-<method name="setPasswordMode"
+<method name="setPasswordQuality"
return="void"
abstract="false"
native="false"
@@ -20604,7 +20615,7 @@
>
<parameter name="admin" type="android.content.ComponentName">
</parameter>
-<parameter name="mode" type="int">
+<parameter name="quality" type="int">
</parameter>
</method>
<method name="wipeData"
@@ -20664,40 +20675,40 @@
visibility="public"
>
</field>
-<field name="PASSWORD_MODE_ALPHANUMERIC"
+<field name="PASSWORD_QUALITY_ALPHANUMERIC"
type="int"
transient="false"
volatile="false"
- value="3000"
+ value="196608"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
-<field name="PASSWORD_MODE_NUMERIC"
+<field name="PASSWORD_QUALITY_NUMERIC"
type="int"
transient="false"
volatile="false"
- value="2000"
+ value="131072"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
-<field name="PASSWORD_MODE_SOMETHING"
+<field name="PASSWORD_QUALITY_SOMETHING"
type="int"
transient="false"
volatile="false"
- value="1000"
+ value="65536"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
-<field name="PASSWORD_MODE_UNSPECIFIED"
+<field name="PASSWORD_QUALITY_UNSPECIFIED"
type="int"
transient="false"
volatile="false"
@@ -33630,6 +33641,17 @@
visibility="public"
>
</field>
+<field name="STORAGE_SERVICE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;storage&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="TELEPHONY_SERVICE"
type="java.lang.String"
transient="false"
@@ -52371,6 +52393,25 @@
<exception name="SQLException" type="android.database.SQLException">
</exception>
</method>
+<method name="insertWithOnConflict"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="table" type="java.lang.String">
+</parameter>
+<parameter name="nullColumnHack" type="java.lang.String">
+</parameter>
+<parameter name="initialValues" type="android.content.ContentValues">
+</parameter>
+<parameter name="conflictAlgorithm" type="int">
+</parameter>
+</method>
<method name="isDbLockedByCurrentThread"
return="boolean"
abstract="false"
@@ -52806,6 +52847,27 @@
<parameter name="whereArgs" type="java.lang.String[]">
</parameter>
</method>
+<method name="updateWithOnConflict"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="table" type="java.lang.String">
+</parameter>
+<parameter name="values" type="android.content.ContentValues">
+</parameter>
+<parameter name="whereClause" type="java.lang.String">
+</parameter>
+<parameter name="whereArgs" type="java.lang.String[]">
+</parameter>
+<parameter name="conflictAlgorithm" type="int">
+</parameter>
+</method>
<method name="yieldIfContended"
return="boolean"
abstract="false"
@@ -52897,6 +52959,81 @@
>
</field>
</class>
+<class name="SQLiteDatabase.ConflictAlgorithm"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="ABORT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FAIL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IGNORE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="REPLACE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ROLLBACK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<interface name="SQLiteDatabase.CursorFactory"
abstract="true"
static="true"
@@ -70067,6 +70204,17 @@
visibility="public"
>
</method>
+<method name="getFocalLength"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getFocusMode"
return="java.lang.String"
abstract="false"
@@ -70078,6 +70226,17 @@
visibility="public"
>
</method>
+<method name="getHorizontalViewAngle"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getInt"
return="int"
abstract="false"
@@ -70234,6 +70393,17 @@
visibility="public"
>
</method>
+<method name="getSupportedJpegThumbnailSizes"
+ return="java.util.List&lt;android.hardware.Camera.Size&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getSupportedPictureFormats"
return="java.util.List&lt;java.lang.Integer&gt;"
abstract="false"
@@ -70311,6 +70481,17 @@
visibility="public"
>
</method>
+<method name="getVerticalViewAngle"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getWhiteBalance"
return="java.lang.String"
abstract="false"
@@ -72158,7 +72339,7 @@
type="float"
transient="false"
volatile="false"
- value="0.001f"
+ value="0.0010f"
static="true"
final="true"
deprecated="not deprecated"
@@ -77862,17 +78043,6 @@
visibility="public"
>
</method>
-<method name="isEnabled"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
<method name="removeListener"
return="void"
abstract="true"
@@ -80754,6 +80924,17 @@
visibility="public"
>
</field>
+<field name="TAG_GPS_DATESTAMP"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;GPSDateStamp&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="TAG_GPS_LATITUDE"
type="java.lang.String"
transient="false"
@@ -80798,6 +80979,17 @@
visibility="public"
>
</field>
+<field name="TAG_GPS_TIMESTAMP"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;GPSTimeStamp&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="TAG_IMAGE_LENGTH"
type="java.lang.String"
transient="false"
@@ -83660,6 +83852,122 @@
</parameter>
</method>
</class>
+<class name="ThumbnailUtils"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ThumbnailUtils"
+ type="android.media.ThumbnailUtils"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="createImageThumbnail"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cr" type="android.content.ContentResolver">
+</parameter>
+<parameter name="filePath" type="java.lang.String">
+</parameter>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="origId" type="long">
+</parameter>
+<parameter name="kind" type="int">
+</parameter>
+<parameter name="saveMini" type="boolean">
+</parameter>
+</method>
+<method name="createVideoThumbnail"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filePath" type="java.lang.String">
+</parameter>
+</method>
+<method name="extractMiniThumb"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="recycle" type="boolean">
+</parameter>
+</method>
+<field name="MINI_THUMB_TARGET_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="96"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NO_RECYCLE_INPUT"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ value="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RECYCLE_INPUT"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ value="true"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="THUMBNAIL_TARGET_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="320"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<class name="ToneGenerator"
extends="java.lang.Object"
abstract="false"
@@ -109409,6 +109717,16 @@
visibility="public"
>
</field>
+<field name="BOOTLOADER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="BRAND"
type="java.lang.String"
transient="false"
@@ -109469,6 +109787,16 @@
visibility="public"
>
</field>
+<field name="HARDWARE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="HOST"
type="java.lang.String"
transient="false"
@@ -109519,6 +109847,16 @@
visibility="public"
>
</field>
+<field name="RADIO"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="TAGS"
type="java.lang.String"
transient="false"
@@ -109742,6 +110080,17 @@
visibility="public"
>
</field>
+<field name="FROYO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="Bundle"
extends="java.lang.Object"
@@ -135779,6 +136128,126 @@
</method>
</interface>
</package>
+<package name="android.storage"
+>
+<interface name="StorageEventListener"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onMediaInserted"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="label" type="java.lang.String">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="major" type="int">
+</parameter>
+<parameter name="minor" type="int">
+</parameter>
+</method>
+<method name="onMediaRemoved"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="label" type="java.lang.String">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="major" type="int">
+</parameter>
+<parameter name="minor" type="int">
+</parameter>
+<parameter name="clean" type="boolean">
+</parameter>
+</method>
+<method name="onShareAvailabilityChanged"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="method" type="java.lang.String">
+</parameter>
+<parameter name="available" type="boolean">
+</parameter>
+</method>
+<method name="onVolumeStateChanged"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="label" type="java.lang.String">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="oldState" type="java.lang.String">
+</parameter>
+<parameter name="newState" type="java.lang.String">
+</parameter>
+</method>
+</interface>
+<class name="StorageManager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="registerListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.storage.StorageEventListener">
+</parameter>
+</method>
+<method name="unregisterListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.storage.StorageEventListener">
+</parameter>
+</method>
+</class>
+</package>
<package name="android.telephony"
>
<class name="CellLocation"
@@ -162734,6 +163203,22 @@
<parameter name="handler" type="android.os.Handler">
</parameter>
</constructor>
+<constructor name="GestureDetector"
+ type="android.view.GestureDetector"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="listener" type="android.view.GestureDetector.OnGestureListener">
+</parameter>
+<parameter name="handler" type="android.os.Handler">
+</parameter>
+<parameter name="ignoreMultitouch" type="boolean">
+</parameter>
+</constructor>
<method name="isLongpressEnabled"
return="boolean"
abstract="false"
@@ -168108,6 +168593,233 @@
>
</field>
</class>
+<class name="ScaleGestureDetector"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ScaleGestureDetector"
+ type="android.view.ScaleGestureDetector"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="listener" type="android.view.ScaleGestureDetector.OnScaleGestureListener">
+</parameter>
+</constructor>
+<method name="getCurrentSpan"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEventTime"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFocusX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFocusY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPreviousSpan"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getScaleFactor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTimeDelta"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isInProgress"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onTouchEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+</class>
+<interface name="ScaleGestureDetector.OnScaleGestureListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onScale"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="detector" type="android.view.ScaleGestureDetector">
+</parameter>
+</method>
+<method name="onScaleBegin"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="detector" type="android.view.ScaleGestureDetector">
+</parameter>
+</method>
+<method name="onScaleEnd"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="detector" type="android.view.ScaleGestureDetector">
+</parameter>
+</method>
+</interface>
+<class name="ScaleGestureDetector.SimpleOnScaleGestureListener"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.ScaleGestureDetector.OnScaleGestureListener">
+</implements>
+<constructor name="ScaleGestureDetector.SimpleOnScaleGestureListener"
+ type="android.view.ScaleGestureDetector.SimpleOnScaleGestureListener"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="onScale"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="detector" type="android.view.ScaleGestureDetector">
+</parameter>
+</method>
+<method name="onScaleBegin"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="detector" type="android.view.ScaleGestureDetector">
+</parameter>
+</method>
+<method name="onScaleEnd"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="detector" type="android.view.ScaleGestureDetector">
+</parameter>
+</method>
+</class>
<class name="SoundEffectConstants"
extends="java.lang.Object"
abstract="false"
@@ -178437,6 +179149,17 @@
visibility="public"
>
</field>
+<field name="FLAG_ALLOW_LOCK_WHILE_SCREEN_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="FLAG_ALT_FOCUSABLE_IM"
type="int"
transient="false"
@@ -185604,573 +186327,6 @@
</parameter>
</method>
</class>
-<class name="CallbackProxy"
- extends="android.os.Handler"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility=""
->
-<constructor name="CallbackProxy"
- type="android.webkit.CallbackProxy"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="w" type="android.webkit.WebView">
-</parameter>
-</constructor>
-<method name="addMessageToConsole"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="message" type="java.lang.String">
-</parameter>
-<parameter name="lineNumber" type="int">
-</parameter>
-<parameter name="sourceID" type="java.lang.String">
-</parameter>
-</method>
-<method name="createWindow"
- return="android.webkit.WebView"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="dialog" type="boolean">
-</parameter>
-<parameter name="userGesture" type="boolean">
-</parameter>
-</method>
-<method name="doUpdateVisitedHistory"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="isReload" type="boolean">
-</parameter>
-</method>
-<method name="getBackForwardList"
- return="android.webkit.WebBackForwardList"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getProgress"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getVisitedHistory"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="callback" type="android.webkit.ValueCallback&lt;java.lang.String[]&gt;">
-</parameter>
-</method>
-<method name="getWebChromeClient"
- return="android.webkit.WebChromeClient"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onCloseWindow"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="window" type="android.webkit.WebView">
-</parameter>
-</method>
-<method name="onDownloadStart"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="userAgent" type="java.lang.String">
-</parameter>
-<parameter name="contentDisposition" type="java.lang.String">
-</parameter>
-<parameter name="mimetype" type="java.lang.String">
-</parameter>
-<parameter name="contentLength" type="long">
-</parameter>
-</method>
-<method name="onExceededDatabaseQuota"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="databaseIdentifier" type="java.lang.String">
-</parameter>
-<parameter name="currentQuota" type="long">
-</parameter>
-<parameter name="estimatedSize" type="long">
-</parameter>
-<parameter name="totalUsedQuota" type="long">
-</parameter>
-<parameter name="quotaUpdater" type="android.webkit.WebStorage.QuotaUpdater">
-</parameter>
-</method>
-<method name="onFormResubmission"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="dontResend" type="android.os.Message">
-</parameter>
-<parameter name="resend" type="android.os.Message">
-</parameter>
-</method>
-<method name="onGeolocationPermissionsHidePrompt"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onGeolocationPermissionsShowPrompt"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="origin" type="java.lang.String">
-</parameter>
-<parameter name="callback" type="android.webkit.GeolocationPermissions.Callback">
-</parameter>
-</method>
-<method name="onJsAlert"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="message" type="java.lang.String">
-</parameter>
-</method>
-<method name="onJsBeforeUnload"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="message" type="java.lang.String">
-</parameter>
-</method>
-<method name="onJsConfirm"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="message" type="java.lang.String">
-</parameter>
-</method>
-<method name="onJsPrompt"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="message" type="java.lang.String">
-</parameter>
-<parameter name="defaultValue" type="java.lang.String">
-</parameter>
-</method>
-<method name="onJsTimeout"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onLoadResource"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-</method>
-<method name="onPageFinished"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-</method>
-<method name="onPageStarted"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-<parameter name="favicon" type="android.graphics.Bitmap">
-</parameter>
-</method>
-<method name="onProgressChanged"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="newProgress" type="int">
-</parameter>
-</method>
-<method name="onReachedMaxAppCacheSize"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="spaceNeeded" type="long">
-</parameter>
-<parameter name="totalUsedQuota" type="long">
-</parameter>
-<parameter name="quotaUpdater" type="android.webkit.WebStorage.QuotaUpdater">
-</parameter>
-</method>
-<method name="onReceivedError"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="errorCode" type="int">
-</parameter>
-<parameter name="description" type="java.lang.String">
-</parameter>
-<parameter name="failingUrl" type="java.lang.String">
-</parameter>
-</method>
-<method name="onReceivedHttpAuthRequest"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="handler" type="android.webkit.HttpAuthHandler">
-</parameter>
-<parameter name="hostName" type="java.lang.String">
-</parameter>
-<parameter name="realmName" type="java.lang.String">
-</parameter>
-</method>
-<method name="onReceivedIcon"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="icon" type="android.graphics.Bitmap">
-</parameter>
-</method>
-<method name="onReceivedTitle"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="title" type="java.lang.String">
-</parameter>
-</method>
-<method name="onRequestFocus"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onSavePassword"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="schemePlusHost" type="java.lang.String">
-</parameter>
-<parameter name="username" type="java.lang.String">
-</parameter>
-<parameter name="password" type="java.lang.String">
-</parameter>
-<parameter name="resumeMsg" type="android.os.Message">
-</parameter>
-</method>
-<method name="onScaleChanged"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="oldScale" type="float">
-</parameter>
-<parameter name="newScale" type="float">
-</parameter>
-</method>
-<method name="onTooManyRedirects"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="cancelMsg" type="android.os.Message">
-</parameter>
-<parameter name="continueMsg" type="android.os.Message">
-</parameter>
-</method>
-<method name="onUnhandledKeyEvent"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="setDownloadListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="client" type="android.webkit.DownloadListener">
-</parameter>
-</method>
-<method name="setWebChromeClient"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="client" type="android.webkit.WebChromeClient">
-</parameter>
-</method>
-<method name="setWebViewClient"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="client" type="android.webkit.WebViewClient">
-</parameter>
-</method>
-<method name="shouldOverrideUrlLoading"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="url" type="java.lang.String">
-</parameter>
-</method>
-<method name="uiOverrideKeyEvent"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="uiOverrideUrlLoading"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="overrideUrl" type="java.lang.String">
-</parameter>
-</method>
-</class>
<class name="CookieManager"
extends="java.lang.Object"
abstract="false"
@@ -186656,16 +186812,6 @@
visibility="protected"
>
</method>
-<field name="mProxy"
- type="android.webkit.CallbackProxy"
- transient="false"
- volatile="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="protected"
->
-</field>
<field name="mResult"
type="boolean"
transient="false"
@@ -209680,7 +209826,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
</parameter>
</method>
</interface>
@@ -340575,7 +340721,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="f" type="java.io.File">
+<parameter name="uri" type="java.lang.String">
</parameter>
<exception name="IOException" type="java.io.IOException">
</exception>
@@ -340592,7 +340738,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="uri" type="java.lang.String">
+<parameter name="f" type="java.io.File">
</parameter>
<exception name="IOException" type="java.io.IOException">
</exception>
diff --git a/core/java/android/webkit/HttpDateTime.java b/common/java/com/android/common/HttpDateTime.java
index 042953c093ea..f4052cc2ee64 100644
--- a/core/java/android/webkit/HttpDateTime.java
+++ b/common/java/com/android/common/HttpDateTime.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.webkit;
+package com.android.common;
import android.text.format.Time;
diff --git a/common/java/com/android/common/speech/LoggingEvents.java b/common/java/com/android/common/speech/LoggingEvents.java
new file mode 100644
index 000000000000..3b3ecb85be87
--- /dev/null
+++ b/common/java/com/android/common/speech/LoggingEvents.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.common.speech;
+
+/**
+ * Logging event constants used for Voice Search and VoiceIME. These are the
+ * keys and values of extras to be specified in logging broadcast intents.
+ * This class is used by clients of the android.speech APIs to log how the
+ * user interacts with the IME settings and speech recognition result.
+ */
+public class LoggingEvents {
+ // The name of the broadcast intent for logging.
+ public static final String ACTION_LOG_EVENT = "com.android.common.speech.LOG_EVENT";
+
+ // The extra key used for the name of the app being logged.
+ public static final String EXTRA_APP_NAME = "app_name";
+
+ // The extra key used for the name of the app issuing the VoiceSearch
+ // or VoiceIME request
+ public static final String EXTRA_CALLING_APP_NAME = "";
+
+ // The extra key used for the event value. The possible event values depend
+ // on the app being logged for, and are defined in the subclasses below.
+ public static final String EXTRA_EVENT = "extra_event";
+
+ // The extra key used to log the time in milliseconds at which the EXTRA_EVENT
+ // occurred in the client.
+ public static final String EXTRA_TIMESTAMP = "timestamp";
+
+ // The extra key used (with a boolean value of 'true') as a way to trigger a
+ // flush of the log events to the server.
+ public static final String EXTRA_FLUSH = "flush";
+
+ /**
+ * Logging event constants for voice search. Below are the extra values for
+ * {@link LoggingEvents#EXTRA_EVENT}, clustered with keys to additional
+ * extras for some events that need to be included as additional fields in
+ * the event. Note that this is not representative of *all* voice search
+ * events - only the ones that need to be reported from outside the voice
+ * search app, such as from Browser.
+ */
+ public class VoiceSearch {
+ // The app name to be used for logging VoiceSearch events.
+ public static final String APP_NAME = "googlemobile";
+
+ public static final int RETRY = 0;
+
+ public static final int N_BEST_REVEAL = 1;
+
+ public static final int N_BEST_CHOOSE = 2;
+ public static final String EXTRA_N_BEST_CHOOSE_INDEX = "index"; // value should be int
+
+ public static final int QUERY_UPDATED = 3;
+ public static final String EXTRA_QUERY_UPDATED_VALUE = "value"; // value should be String
+ }
+
+ /**
+ * Logging event constants for VoiceIME. Below are the extra values for
+ * {@link LoggingEvents#EXTRA_EVENT}, clustered with keys to additional
+ * extras for some events that need to be included as additional fields in
+ * the event.
+ */
+ public class VoiceIme {
+ // The app name to be used for logging VoiceIME events.
+ public static final String APP_NAME = "voiceime";
+
+ public static final int KEYBOARD_WARNING_DIALOG_SHOWN = 0;
+
+ public static final int KEYBOARD_WARNING_DIALOG_DISMISSED = 1;
+
+ public static final int KEYBOARD_WARNING_DIALOG_OK = 2;
+
+ public static final int KEYBOARD_WARNING_DIALOG_CANCEL = 3;
+
+ public static final int SETTINGS_WARNING_DIALOG_SHOWN = 4;
+
+ public static final int SETTINGS_WARNING_DIALOG_DISMISSED = 5;
+
+ public static final int SETTINGS_WARNING_DIALOG_OK = 6;
+
+ public static final int SETTINGS_WARNING_DIALOG_CANCEL = 7;
+
+ public static final int SWIPE_HINT_DISPLAYED = 8;
+
+ public static final int PUNCTUATION_HINT_DISPLAYED = 9;
+
+ public static final int CANCEL_DURING_LISTENING = 10;
+
+ public static final int CANCEL_DURING_WORKING = 11;
+
+ public static final int CANCEL_DURING_ERROR = 12;
+
+ public static final int ERROR = 13;
+ public static final String EXTRA_ERROR_CODE = "code"; // value should be int
+
+ public static final int START = 14;
+ public static final String EXTRA_START_LOCALE = "locale"; // value should be String
+ public static final String EXTRA_START_SWIPE = "swipe"; // value should be boolean
+
+ public static final int VOICE_INPUT_DELIVERED = 15;
+
+ public static final int N_BEST_CHOOSE = 16;
+ public static final String EXTRA_N_BEST_CHOOSE_INDEX = "index"; // value should be int
+
+ public static final int TEXT_MODIFIED = 17;
+
+ public static final int INPUT_ENDED = 18;
+
+ public static final int VOICE_INPUT_SETTING_ENABLED = 19;
+
+ public static final int VOICE_INPUT_SETTING_DISABLED = 20;
+
+ public static final int IME_TEXT_ACCEPTED = 21;
+ }
+
+}
diff --git a/common/java/com/android/common/userhappiness/UserHappinessSignals.java b/common/java/com/android/common/userhappiness/UserHappinessSignals.java
new file mode 100644
index 000000000000..347bdaaf0102
--- /dev/null
+++ b/common/java/com/android/common/userhappiness/UserHappinessSignals.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.common.userhappiness;
+
+import android.content.Intent;
+import android.content.Context;
+import com.android.common.speech.LoggingEvents;
+
+/**
+ * Metrics for User Happiness are recorded here. Each app can define when to
+ * call these User Happiness metrics.
+ */
+public class UserHappinessSignals {
+
+ /**
+ * Log when a user "accepted" IME text. Each application can define what
+ * it means to "accept" text. In the case of Gmail, pressing the "Send"
+ * button indicates text acceptance. We broadcast this information to
+ * VoiceSearch LoggingEvents and use it to aggregate VoiceIME Happiness Metrics
+ */
+ public static void userAcceptedImeText(Context context) {
+ // Create a Voice IME Logging intent.
+ Intent i = new Intent(LoggingEvents.ACTION_LOG_EVENT);
+ i.putExtra(LoggingEvents.EXTRA_APP_NAME, LoggingEvents.VoiceIme.APP_NAME);
+ i.putExtra(LoggingEvents.EXTRA_EVENT, LoggingEvents.VoiceIme.IME_TEXT_ACCEPTED);
+ i.putExtra(LoggingEvents.EXTRA_CALLING_APP_NAME, context.getPackageName());
+ i.putExtra(LoggingEvents.EXTRA_TIMESTAMP, System.currentTimeMillis());
+ context.sendBroadcast(i);
+ }
+
+}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 932ad5355f10..e8ab51fd5713 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -957,4 +957,15 @@ public class ActivityManager {
return null;
}
+ /**
+ * Returns "true" if the user interface is currently being messed with
+ * by a monkey.
+ */
+ public static boolean isUserAMonkey() {
+ try {
+ return ActivityManagerNative.getDefault().isUserAMonkey();
+ } catch (RemoteException e) {
+ }
+ return false;
+ }
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 09b88ee2619c..2e39c10db744 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1178,6 +1178,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
int enterAnim = data.readInt();
int exitAnim = data.readInt();
overridePendingTransition(token, packageName, enterAnim, exitAnim);
+ reply.writeNoException();
+ return true;
+ }
+
+ case IS_USER_A_MONKEY_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ reply.writeInt(isUserAMonkey() ? 1 : 0);
+ reply.writeNoException();
return true;
}
}
@@ -2598,5 +2606,17 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
+ public boolean isUserAMonkey() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(IS_USER_A_MONKEY_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean res = reply.readInt() != 0;
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index fe05393bb467..cf6e0e727898 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -71,6 +71,7 @@ import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.DropBoxManager;
+import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
@@ -80,8 +81,10 @@ import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.StatFs;
import android.os.Vibrator;
import android.os.FileUtils.FileStatus;
+import android.storage.StorageManager;
import android.telephony.TelephonyManager;
import android.text.ClipboardManager;
import android.util.AndroidRuntimeException;
@@ -178,6 +181,7 @@ class ApplicationContext extends Context {
private Context mReceiverRestrictedContext = null;
private SearchManager mSearchManager = null;
private SensorManager mSensorManager = null;
+ private StorageManager mStorageManager = null;
private Vibrator mVibrator = null;
private LayoutInflater mLayoutInflater = null;
private StatusBarManager mStatusBarManager = null;
@@ -877,6 +881,8 @@ class ApplicationContext extends Context {
return getSearchManager();
} else if (SENSOR_SERVICE.equals(name)) {
return getSensorManager();
+ } else if (STORAGE_SERVICE.equals(name)) {
+ return getStorageManager();
} else if (VIBRATOR_SERVICE.equals(name)) {
return getVibrator();
} else if (STATUS_BAR_SERVICE.equals(name)) {
@@ -1039,6 +1045,20 @@ class ApplicationContext extends Context {
return mSensorManager;
}
+ private StorageManager getStorageManager() {
+ synchronized (mSync) {
+ if (mStorageManager == null) {
+ try {
+ mStorageManager = new StorageManager(mMainThread.getHandler().getLooper());
+ } catch (RemoteException rex) {
+ Log.e(TAG, "Failed to create StorageManager", rex);
+ mStorageManager = null;
+ }
+ }
+ }
+ return mStorageManager;
+ }
+
private Vibrator getVibrator() {
synchronized (mSync) {
if (mVibrator == null) {
@@ -2144,6 +2164,11 @@ class ApplicationContext extends Context {
filter.addDataScheme("package");
mContext.registerReceiverInternal(sPackageRemovedReceiver,
filter, null, null, null);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiverInternal(sPackageRemovedReceiver,
+ sdFilter, null, null, null);
}
}
}
@@ -2161,32 +2186,56 @@ class ApplicationContext extends Context {
private static final class PackageRemovedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- Uri data = intent.getData();
- String ssp;
- if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
+ String pkgList[] = null;
+ String action = intent.getAction();
+ boolean immediateGc = false;
+ if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ immediateGc = true;
+ } else {
+ Uri data = intent.getData();
+ if (data != null) {
+ String ssp = data.getSchemeSpecificPart();
+ if (ssp != null) {
+ pkgList = new String[] { ssp };
+ }
+ }
+ }
+ if (pkgList != null && (pkgList.length > 0)) {
boolean needCleanup = false;
- synchronized (sSync) {
- Iterator<ResourceName> it = sIconCache.keySet().iterator();
- while (it.hasNext()) {
- ResourceName nm = it.next();
- if (nm.packageName.equals(ssp)) {
- //Log.i(TAG, "Removing cached drawable for " + nm);
- it.remove();
- needCleanup = true;
+ boolean hasPkgInfo = false;
+ for (String ssp : pkgList) {
+ synchronized (sSync) {
+ Iterator<ResourceName> it = sIconCache.keySet().iterator();
+ while (it.hasNext()) {
+ ResourceName nm = it.next();
+ if (nm.packageName.equals(ssp)) {
+ //Log.i(TAG, "Removing cached drawable for " + nm);
+ it.remove();
+ needCleanup = true;
+ }
}
- }
- it = sStringCache.keySet().iterator();
- while (it.hasNext()) {
- ResourceName nm = it.next();
- if (nm.packageName.equals(ssp)) {
- //Log.i(TAG, "Removing cached string for " + nm);
- it.remove();
- needCleanup = true;
+ it = sStringCache.keySet().iterator();
+ while (it.hasNext()) {
+ ResourceName nm = it.next();
+ if (nm.packageName.equals(ssp)) {
+ //Log.i(TAG, "Removing cached string for " + nm);
+ it.remove();
+ needCleanup = true;
+ }
}
}
+ if (!hasPkgInfo) {
+ hasPkgInfo = ActivityThread.currentActivityThread().hasPackageInfo(ssp);
+ }
}
- if (needCleanup || ActivityThread.currentActivityThread().hasPackageInfo(ssp)) {
- ActivityThread.currentActivityThread().scheduleGcIdler();
+ if (needCleanup || hasPkgInfo) {
+ if (immediateGc) {
+ // Schedule an immediate gc.
+ Runtime.getRuntime().gc();
+ } else {
+ ActivityThread.currentActivityThread().scheduleGcIdler();
+ }
}
}
}
@@ -2537,6 +2586,76 @@ class ApplicationContext extends Context {
return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
}
+ // Constants related to app heuristics
+ // No-installation limit for internal flash: 10% or less space available
+ private static final double LOW_NAND_FLASH_TRESHOLD = 0.1;
+
+ // SD-to-internal app size threshold: currently set to 1 MB
+ private static final long INSTALL_ON_SD_THRESHOLD = (1024 * 1024);
+
+ @Override
+ public int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI) {
+ // Initial implementation:
+ // Package size = code size + cache size + data size
+ // If code size > 1 MB, install on SD card.
+ // Else install on internal NAND flash, unless space on NAND is less than 10%
+
+ if ((packageURI == null) || (appInfo == null)) {
+ return INSTALL_PARSE_FAILED_NOT_APK;
+ }
+
+ StatFs internalFlashStats = new StatFs(Environment.getDataDirectory().getPath());
+ StatFs sdcardStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
+
+ long totalInternalFlashSize = (long)internalFlashStats.getBlockCount() *
+ (long)internalFlashStats.getBlockSize();
+ long availInternalFlashSize = (long)internalFlashStats.getAvailableBlocks() *
+ (long)internalFlashStats.getBlockSize();
+ long availSDSize = (long)sdcardStats.getAvailableBlocks() *
+ (long)sdcardStats.getBlockSize();
+
+ double pctNandFree = (double)availInternalFlashSize / (double)totalInternalFlashSize;
+
+ final String archiveFilePath = packageURI.getPath();
+ File apkFile = new File(archiveFilePath);
+ long pkgLen = apkFile.length();
+
+ // Consider application flags preferences as well...
+ boolean installOnlyOnSD = ((appInfo.flags & PackageManager.INSTALL_ON_SDCARD) != 0);
+
+ // These are not very precise measures, but I guess it is hard to estimate sizes
+ // before installing the package.
+ // As a shortcut, I am assuming that the package fits on NAND flash if the available
+ // space is three times that of the APK size. For SD, we only worry about the APK size.
+ // Since packages are downloaded into SD, this might not even be necessary.
+ boolean fitsOnSD = (pkgLen < availSDSize) && ((2 * pkgLen) < availInternalFlashSize);
+ boolean fitsOnInternalFlash = ((pkgLen * 3) < availInternalFlashSize);
+
+ // Does not fit, recommend no installation.
+ if (!fitsOnSD && !fitsOnInternalFlash) {
+ return INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
+
+ if (pkgLen < (INSTALL_ON_SD_THRESHOLD) && fitsOnInternalFlash && !(installOnlyOnSD)) {
+ // recommend internal NAND likely
+ if (pctNandFree < LOW_NAND_FLASH_TRESHOLD) {
+ // Low space on NAND (<10%) - install on SD
+ return INSTALL_ON_SDCARD;
+ }
+ return INSTALL_ON_INTERNAL_FLASH;
+ } else {
+ if (fitsOnSD) {
+ // Recommend SD card
+ return INSTALL_ON_SDCARD;
+ } else if (fitsOnInternalFlash && (pctNandFree >= LOW_NAND_FLASH_TRESHOLD) &&
+ !(installOnlyOnSD)) {
+ return INSTALL_ON_INTERNAL_FLASH;
+ } else {
+ return INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
+ }
+ }
+
private final ApplicationContext mContext;
private final IPackageManager mPM;
diff --git a/core/java/android/app/BackupAgent.java b/core/java/android/app/BackupAgent.java
index 2a586777ddf3..35b6fed71014 100644
--- a/core/java/android/app/BackupAgent.java
+++ b/core/java/android/app/BackupAgent.java
@@ -19,6 +19,7 @@ package android.app;
import android.app.IBackupAgent;
import android.backup.BackupDataInput;
import android.backup.BackupDataOutput;
+import android.backup.IBackupManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.Binder;
@@ -94,12 +95,9 @@ public abstract class BackupAgent extends ContextWrapper {
// ----- Core implementation -----
-
- /**
- * Returns the private interface called by the backup system. Applications will
- * not typically override this.
- */
- public IBinder onBind() {
+
+ /** @hide */
+ public final IBinder onBind() {
return mBinder;
}
@@ -116,9 +114,10 @@ public abstract class BackupAgent extends ContextWrapper {
public void doBackup(ParcelFileDescriptor oldState,
ParcelFileDescriptor data,
- ParcelFileDescriptor newState) throws RemoteException {
+ ParcelFileDescriptor newState,
+ int token, IBackupManager callbackBinder) throws RemoteException {
// Ensure that we're running with the app's normal permission level
- long token = Binder.clearCallingIdentity();
+ long ident = Binder.clearCallingIdentity();
if (DEBUG) Log.v(TAG, "doBackup() invoked");
BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor());
@@ -131,14 +130,20 @@ public abstract class BackupAgent extends ContextWrapper {
Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
throw ex;
} finally {
- Binder.restoreCallingIdentity(token);
+ Binder.restoreCallingIdentity(ident);
+ try {
+ callbackBinder.opComplete(token);
+ } catch (RemoteException e) {
+ // we'll time out anyway, so we're safe
+ }
}
}
public void doRestore(ParcelFileDescriptor data, int appVersionCode,
- ParcelFileDescriptor newState) throws RemoteException {
+ ParcelFileDescriptor newState,
+ int token, IBackupManager callbackBinder) throws RemoteException {
// Ensure that we're running with the app's normal permission level
- long token = Binder.clearCallingIdentity();
+ long ident = Binder.clearCallingIdentity();
if (DEBUG) Log.v(TAG, "doRestore() invoked");
BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
@@ -151,7 +156,12 @@ public abstract class BackupAgent extends ContextWrapper {
Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
throw ex;
} finally {
- Binder.restoreCallingIdentity(token);
+ Binder.restoreCallingIdentity(ident);
+ try {
+ callbackBinder.opComplete(token);
+ } catch (RemoteException e) {
+ // we'll time out anyway, so we're safe
+ }
}
}
}
diff --git a/core/java/android/app/DeviceAdmin.java b/core/java/android/app/DeviceAdmin.java
index b9a84b7a4d37..ecbad012f829 100644
--- a/core/java/android/app/DeviceAdmin.java
+++ b/core/java/android/app/DeviceAdmin.java
@@ -34,15 +34,13 @@ import android.os.Bundle;
* {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission. A typical
* manifest entry would look like:</p>
*
- * <pre>{@include development/samples/ApiDemos/AndroidManifest.xml
- * device_admin_declaration}</pre>
+ * {@sample development/samples/ApiDemos/AndroidManifest.xml device_admin_declaration}
*
* <p>The meta-data referenced here provides addition information specific
* to the device administrator, as parsed by the {@link DeviceAdminInfo} class.
* A typical file would be:</p>
*
- * <pre>{@include development/samples/ApiDemos/res/xml/sample_device_admin.xml
- * meta_data}</pre>
+ * {@sample development/samples/ApiDemos/res/xml/sample_device_admin.xml meta_data}
*/
public class DeviceAdmin extends BroadcastReceiver {
private static String TAG = "DevicePolicy";
diff --git a/core/java/android/app/DeviceAdminInfo.java b/core/java/android/app/DeviceAdminInfo.java
index 50b342b6f337..ab9c44f15276 100644
--- a/core/java/android/app/DeviceAdminInfo.java
+++ b/core/java/android/app/DeviceAdminInfo.java
@@ -50,7 +50,7 @@ public final class DeviceAdminInfo implements Parcelable {
/**
* A type of policy that this device admin can use: limit the passwords
- * that the user can select, via {@link DevicePolicyManager#setPasswordMode}
+ * that the user can select, via {@link DevicePolicyManager#setPasswordQuality}
* and {@link DevicePolicyManager#setPasswordMinimumLength}.
*
* <p>To control this policy, the device admin must have a "limit-password"
diff --git a/core/java/android/app/DevicePolicyManager.java b/core/java/android/app/DevicePolicyManager.java
index 779db3ae2275..08cdd0511d4b 100644
--- a/core/java/android/app/DevicePolicyManager.java
+++ b/core/java/android/app/DevicePolicyManager.java
@@ -88,7 +88,7 @@ public class DevicePolicyManager {
/**
* Activity action: have the user enter a new password. This activity
- * should be launched after using {@link #setPasswordMode(ComponentName, int)}
+ * should be launched after using {@link #setPasswordQuality(ComponentName, int)}
* or {@link #setPasswordMinimumLength(ComponentName, int)} to have the
* user enter a new password that meets the current requirements. You can
* use {@link #isActivePasswordSufficient()} to determine whether you need
@@ -149,32 +149,33 @@ public class DevicePolicyManager {
}
/**
- * Constant for {@link #setPasswordMode}: the policy has no requirements
- * for the password. Note that mode constants are ordered so that higher
+ * Constant for {@link #setPasswordQuality}: the policy has no requirements
+ * for the password. Note that quality constants are ordered so that higher
* values are more restrictive.
*/
- public static final int PASSWORD_MODE_UNSPECIFIED = 0;
+ public static final int PASSWORD_QUALITY_UNSPECIFIED = 0;
/**
- * Constant for {@link #setPasswordMode}: the policy requires some kind
- * of password, but doesn't care what it is. Note that mode constants
+ * Constant for {@link #setPasswordQuality}: the policy requires some kind
+ * of password, but doesn't care what it is. Note that quality constants
* are ordered so that higher values are more restrictive.
*/
- public static final int PASSWORD_MODE_SOMETHING = 1000;
+ public static final int PASSWORD_QUALITY_SOMETHING = 0x10000;
/**
- * Constant for {@link #setPasswordMode}: the user must have at least a
- * numeric password. Note that mode constants are ordered so that higher
- * values are more restrictive.
+ * Constant for {@link #setPasswordQuality}: the user must have entered a
+ * password containing at least numeric characters. Note that quality
+ * constants are ordered so that higher values are more restrictive.
*/
- public static final int PASSWORD_MODE_NUMERIC = 2000;
+ public static final int PASSWORD_QUALITY_NUMERIC = 0x20000;
/**
- * Constant for {@link #setPasswordMode}: the user must have at least an
- * alphanumeric password. Note that mode constants are ordered so that higher
- * values are more restrictive.
+ * Constant for {@link #setPasswordQuality}: the user must have entered a
+ * password containing at least <em>both></em> numeric <em>and</em>
+ * alphabeter (or other symbol) characters. Note that quality constants are
+ * ordered so that higher values are more restrictive.
*/
- public static final int PASSWORD_MODE_ALPHANUMERIC = 3000;
+ public static final int PASSWORD_QUALITY_ALPHANUMERIC = 0x30000;
/**
* Called by an application that is administering the device to set the
@@ -185,8 +186,8 @@ public class DevicePolicyManager {
* take place immediately. To prompt the user for a new password, use
* {@link #ACTION_SET_NEW_PASSWORD} after setting this value.
*
- * <p>Mode constants are ordered so that higher values are more restrictive;
- * thus the highest requested mode constant (between the policy set here,
+ * <p>Quality constants are ordered so that higher values are more restrictive;
+ * thus the highest requested quality constant (between the policy set here,
* the user's preference, and any other considerations) is the one that
* is in effect.
*
@@ -195,14 +196,14 @@ public class DevicePolicyManager {
* this method; if it has not, a security exception will be thrown.
*
* @param admin Which {@link DeviceAdmin} this request is associated with.
- * @param mode The new desired mode. One of
- * {@link #PASSWORD_MODE_UNSPECIFIED}, {@link #PASSWORD_MODE_SOMETHING},
- * {@link #PASSWORD_MODE_NUMERIC}, or {@link #PASSWORD_MODE_ALPHANUMERIC}.
+ * @param quality The new desired quality. One of
+ * {@link #PASSWORD_QUALITY_UNSPECIFIED}, {@link #PASSWORD_QUALITY_SOMETHING},
+ * {@link #PASSWORD_QUALITY_NUMERIC}, or {@link #PASSWORD_QUALITY_ALPHANUMERIC}.
*/
- public void setPasswordMode(ComponentName admin, int mode) {
+ public void setPasswordQuality(ComponentName admin, int quality) {
if (mService != null) {
try {
- mService.setPasswordMode(admin, mode);
+ mService.setPasswordQuality(admin, quality);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -210,20 +211,20 @@ public class DevicePolicyManager {
}
/**
- * Retrieve the current minimum password mode for all admins
+ * Retrieve the current minimum password quality for all admins
* or a particular one.
* @param admin The name of the admin component to check, or null to aggregate
* all admins.
*/
- public int getPasswordMode(ComponentName admin) {
+ public int getPasswordQuality(ComponentName admin) {
if (mService != null) {
try {
- return mService.getPasswordMode(admin);
+ return mService.getPasswordQuality(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
- return PASSWORD_MODE_UNSPECIFIED;
+ return PASSWORD_QUALITY_UNSPECIFIED;
}
/**
@@ -235,8 +236,8 @@ public class DevicePolicyManager {
* take place immediately. To prompt the user for a new password, use
* {@link #ACTION_SET_NEW_PASSWORD} after setting this value. This
* constraint is only imposed if the administrator has also requested either
- * {@link #PASSWORD_MODE_NUMERIC} or {@link #PASSWORD_MODE_ALPHANUMERIC}
- * with {@link #setPasswordMode}.
+ * {@link #PASSWORD_QUALITY_NUMERIC} or {@link #PASSWORD_QUALITY_ALPHANUMERIC}
+ * with {@link #setPasswordQuality}.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
@@ -275,18 +276,18 @@ public class DevicePolicyManager {
/**
* Return the maximum password length that the device supports for a
- * particular password mode.
- * @param mode The mode being interrogated.
+ * particular password quality.
+ * @param quality The quality being interrogated.
* @return Returns the maximum length that the user can enter.
*/
- public int getPasswordMaximumLength(int mode) {
+ public int getPasswordMaximumLength(int quality) {
// Kind-of arbitrary.
return 16;
}
/**
* Determine whether the current password the user has set is sufficient
- * to meet the policy requirements (mode, minimum length) that have been
+ * to meet the policy requirements (quality, minimum length) that have been
* requested.
*
* <p>The calling device admin must have requested
@@ -368,14 +369,15 @@ public class DevicePolicyManager {
}
/**
- * Force a new password on the user. This takes effect immediately. The
- * given password must meet the current password minimum length constraint
- * or it will be rejected. The given password will be accepted regardless
- * of the current password mode, automatically adjusting the password mode
- * higher if needed to meet the requirements of all active administrators.
- * (The string you give here is acceptable for any mode;
- * if it contains only digits, that is still an acceptable alphanumeric
- * password.)
+ * Force a new password on the user. This takes effect immediately.
+ * The given password must be sufficient for the
+ * current password quality and length constraints as returned by
+ * {@link #getPasswordQuality(ComponentName)} and
+ * {@link #getPasswordMinimumLength(ComponentName)}; if it does not meet
+ * these constraints, then it will be rejected and false returned. Note
+ * that the password may be a stronger quality (containing alphanumeric
+ * characters when the requested quality is only numeric), in which case
+ * the currently active quality will be increased to match.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call
@@ -531,10 +533,10 @@ public class DevicePolicyManager {
/**
* @hide
*/
- public void setActivePasswordState(int mode, int length) {
+ public void setActivePasswordState(int quality, int length) {
if (mService != null) {
try {
- mService.setActivePasswordState(mode, length);
+ mService.setActivePasswordState(quality, length);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 016d465cea12..86f28bfa6cb3 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -288,6 +288,8 @@ public interface IActivityManager extends IInterface {
public void overridePendingTransition(IBinder token, String packageName,
int enterAnim, int exitAnim) throws RemoteException;
+ public boolean isUserAMonkey() throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -450,4 +452,5 @@ public interface IActivityManager extends IInterface {
int OVERRIDE_PENDING_TRANSITION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+100;
int HANDLE_APPLICATION_WTF_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+101;
int KILL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+102;
+ int IS_USER_A_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+103;
}
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 9b0550fce64b..0de6ad9a83e2 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -16,6 +16,7 @@
package android.app;
+import android.backup.IBackupManager;
import android.os.ParcelFileDescriptor;
/**
@@ -25,7 +26,7 @@ import android.os.ParcelFileDescriptor;
*
* {@hide}
*/
-interface IBackupAgent {
+oneway interface IBackupAgent {
/**
* Request that the app perform an incremental backup.
*
@@ -39,10 +40,18 @@ interface IBackupAgent {
*
* @param newState Read-write file, empty when onBackup() is called,
* where the new state blob is to be recorded.
+ *
+ * @param token Opaque token identifying this transaction. This must
+ * be echoed back to the backup service binder once the new
+ * data has been written to the data and newState files.
+ *
+ * @param callbackBinder Binder on which to indicate operation completion,
+ * passed here as a convenience to the agent.
*/
void doBackup(in ParcelFileDescriptor oldState,
in ParcelFileDescriptor data,
- in ParcelFileDescriptor newState);
+ in ParcelFileDescriptor newState,
+ int token, IBackupManager callbackBinder);
/**
* Restore an entire data snapshot to the application.
@@ -58,7 +67,15 @@ interface IBackupAgent {
* @param newState Read-write file, empty when onRestore() is called,
* that is to be written with the state description that holds after
* the restore has been completed.
+ *
+ * @param token Opaque token identifying this transaction. This must
+ * be echoed back to the backup service binder once the agent is
+ * finished restoring the application based on the restore data
+ * contents.
+ *
+ * @param callbackBinder Binder on which to indicate operation completion,
+ * passed here as a convenience to the agent.
*/
void doRestore(in ParcelFileDescriptor data, int appVersionCode,
- in ParcelFileDescriptor newState);
+ in ParcelFileDescriptor newState, int token, IBackupManager callbackBinder);
}
diff --git a/core/java/android/app/IDevicePolicyManager.aidl b/core/java/android/app/IDevicePolicyManager.aidl
index 8d804f98026a..ae5c4bf6fbf9 100644
--- a/core/java/android/app/IDevicePolicyManager.aidl
+++ b/core/java/android/app/IDevicePolicyManager.aidl
@@ -25,8 +25,8 @@ import android.os.RemoteCallback;
* {@hide}
*/
interface IDevicePolicyManager {
- void setPasswordMode(in ComponentName who, int mode);
- int getPasswordMode(in ComponentName who);
+ void setPasswordQuality(in ComponentName who, int quality);
+ int getPasswordQuality(in ComponentName who);
void setPasswordMinimumLength(in ComponentName who, int length);
int getPasswordMinimumLength(in ComponentName who);
@@ -52,7 +52,7 @@ interface IDevicePolicyManager {
void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result);
void removeActiveAdmin(in ComponentName policyReceiver);
- void setActivePasswordState(int mode, int length);
+ void setActivePasswordState(int quality, int length);
void reportFailedPasswordAttempt();
void reportSuccessfulPasswordAttempt();
}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 3dfbe7184f90..ec9f3b4fc56d 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -903,15 +903,14 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
if (mSearchable == null) {
return;
}
+ SearchableInfo searchable = mSearchable;
+ // First stop the existing search before starting voice search, or else we'll end
+ // up showing the search dialog again once we return to the app.
+ cancel();
try {
- // First stop the existing search before starting voice search, or else we'll end
- // up showing the search dialog again once we return to the app.
- ((SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE)).
- stopSearch();
-
- if (mSearchable.getVoiceSearchLaunchWebSearch()) {
+ if (searchable.getVoiceSearchLaunchWebSearch()) {
getContext().startActivity(mVoiceWebSearchIntent);
- } else if (mSearchable.getVoiceSearchLaunchRecognizer()) {
+ } else if (searchable.getVoiceSearchLaunchRecognizer()) {
Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent);
getContext().startActivity(appSearchIntent);
}
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index c4e187745a64..8ec5bd4196c0 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -292,8 +292,8 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
* callback in that case. The <code>handleCommand</code> method is implemented by
* you as appropriate:
*
- * <pre>{@include development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
- * start_compatibility}</pre>
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
+ * start_compatibility}
*
* @param intent The Intent supplied to {@link android.content.Context#startService},
* as given. This may be null if the service is being restarted after
@@ -474,8 +474,8 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
* level 5, you can use the following model to call the the older {@link #setForeground}
* or this modern method as appropriate:
*
- * <pre>{@include development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
- * foreground_compatibility}</pre>
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
+ * foreground_compatibility}
*
* @param id The identifier for this notification as per
* {@link NotificationManager#notify(int, Notification)
diff --git a/core/java/android/backup/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl
index 9d181bec49df..cb775f7504dc 100644
--- a/core/java/android/backup/IBackupManager.aidl
+++ b/core/java/android/backup/IBackupManager.aidl
@@ -130,4 +130,14 @@ interface IBackupManager {
* @return An interface to the restore session, or null on error.
*/
IRestoreSession beginRestoreSession(String transportID);
+
+ /**
+ * Notify the backup manager that a BackupAgent has completed the operation
+ * corresponding to the given token.
+ *
+ * @param token The transaction token passed to a BackupAgent's doBackup() or
+ * doRestore() method.
+ * {@hide}
+ */
+ void opComplete(int token);
}
diff --git a/core/java/android/backup/RestoreSession.java b/core/java/android/backup/RestoreSession.java
index 119fc52e7433..6b35fe87fdff 100644
--- a/core/java/android/backup/RestoreSession.java
+++ b/core/java/android/backup/RestoreSession.java
@@ -21,6 +21,7 @@ import android.backup.RestoreObserver;
import android.backup.RestoreSet;
import android.content.Context;
import android.os.Handler;
+import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
@@ -109,70 +110,51 @@ public class RestoreSession {
/*
* We wrap incoming binder calls with a private class implementation that
- * redirects them into main-thread actions. This accomplishes two things:
- * first, it ensures that the app's code is run on their own main thread,
- * never with system Binder identity; and second, it serializes the restore
+ * redirects them into main-thread actions. This serializes the restore
* progress callbacks nicely within the usual main-thread lifecycle pattern.
*/
private class RestoreObserverWrapper extends IRestoreObserver.Stub {
final Handler mHandler;
final RestoreObserver mAppObserver;
+ static final int MSG_RESTORE_STARTING = 1;
+ static final int MSG_UPDATE = 2;
+ static final int MSG_RESTORE_FINISHED = 3;
+
RestoreObserverWrapper(Context context, RestoreObserver appObserver) {
- mHandler = new Handler(context.getMainLooper());
+ mHandler = new Handler(context.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_RESTORE_STARTING:
+ mAppObserver.restoreStarting(msg.arg1);
+ break;
+ case MSG_UPDATE:
+ mAppObserver.onUpdate(msg.arg1);
+ break;
+ case MSG_RESTORE_FINISHED:
+ mAppObserver.restoreFinished(msg.arg1);
+ break;
+ }
+ }
+ };
mAppObserver = appObserver;
}
- // Wrap the IRestoreObserver -> RestoreObserver callthrough in Runnables
- // posted to the app's main thread looper.
- class RestoreStartingRunnable implements Runnable {
- int mNumPackages;
-
- RestoreStartingRunnable(int numPackages) {
- mNumPackages = numPackages;
- }
-
- public void run() {
- mAppObserver.restoreStarting(mNumPackages);
- }
- }
-
- class OnUpdateRunnable implements Runnable {
- int mNowRestoring;
-
- OnUpdateRunnable(int nowRestoring) {
- mNowRestoring = nowRestoring;
- }
-
- public void run() {
- mAppObserver.onUpdate(mNowRestoring);
- }
- }
-
- class RestoreFinishedRunnable implements Runnable {
- int mError;
-
- RestoreFinishedRunnable(int error) {
- mError = error;
- }
-
- public void run() {
- mAppObserver.restoreFinished(mError);
- }
- }
-
- // The actual redirection code is quite simple using just the
- // above Runnable subclasses
+ // Binder calls into this object just enqueue on the main-thread handler
public void restoreStarting(int numPackages) {
- mHandler.post(new RestoreStartingRunnable(numPackages));
+ mHandler.sendMessage(
+ mHandler.obtainMessage(MSG_RESTORE_STARTING, numPackages, 0));
}
public void onUpdate(int nowBeingRestored) {
- mHandler.post(new OnUpdateRunnable(nowBeingRestored));
+ mHandler.sendMessage(
+ mHandler.obtainMessage(MSG_UPDATE, nowBeingRestored, 0));
}
public void restoreFinished(int error) {
- mHandler.post(new RestoreFinishedRunnable(error));
+ mHandler.sendMessage(
+ mHandler.obtainMessage(MSG_RESTORE_FINISHED, error, 0));
}
}
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 321ba5c477a4..5aefe4c1bd7f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1109,6 +1109,8 @@ public abstract class Context {
* @see android.app.SearchManager
* @see #SENSOR_SERVICE
* @see android.hardware.SensorManager
+ * @see #STORAGE_SERVICE
+ * @see android.storage.StorageManager
* @see #VIBRATOR_SERVICE
* @see android.os.Vibrator
* @see #CONNECTIVITY_SERVICE
@@ -1240,6 +1242,16 @@ public abstract class Context {
public static final String SENSOR_SERVICE = "sensor";
/**
+ * Use with {@link #getSystemService} to retrieve a {@link
+ * android.storage.StorageManager} for accesssing system storage
+ * functions.
+ *
+ * @see #getSystemService
+ * @see android.storage.StorageManager
+ */
+ public static final String STORAGE_SERVICE = "storage";
+
+ /**
* Use with {@link #getSystemService} to retrieve a
* com.android.server.WallpaperService for accessing wallpapers.
*
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index bbd359bea989..e957e2019eac 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1355,6 +1355,60 @@ public class Intent implements Parcelable, Cloneable {
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_UID_REMOVED = "android.intent.action.UID_REMOVED";
+
+ /**
+ * Broadcast Action: Resources for a set of packages (which were
+ * previously unavailable) are currently
+ * available since the media on which they exist is available.
+ * The extra data {@link #EXTRA_CHANGED_PACKAGE_LIST} contains a
+ * list of packages whose availability changed.
+ * The extra data {@link #EXTRA_CHANGED_UID_LIST} contains a
+ * list of uids of packages whose availability changed.
+ * Note that the
+ * packages in this list do <em>not</em> receive this broadcast.
+ * The specified set of packages are now available on the system.
+ * <p>Includes the following extras:
+ * <ul>
+ * <li> {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages
+ * whose resources(were previously unavailable) are currently available.
+ * {@link #EXTRA_CHANGED_UID_LIST} is the set of uids of the
+ * packages whose resources(were previously unavailable)
+ * are currently available.
+ * </ul>
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_MEDIA_RESOURCES_AVAILABLE =
+ "android.intent.action.MEDIA_RESOURCES_AVAILABILE";
+
+ /**
+ * Broadcast Action: Resources for a set of packages are currently
+ * unavailable since the media on which they exist is unavailable.
+ * The extra data {@link #EXTRA_CHANGED_PACKAGE_LIST} contains a
+ * list of packages whose availability changed.
+ * The extra data {@link #EXTRA_CHANGED_UID_LIST} contains a
+ * list of uids of packages whose availability changed.
+ * The specified set of packages can no longer be
+ * launched and are practically unavailable on the system.
+ * <p>Inclues the following extras:
+ * <ul>
+ * <li> {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages
+ * whose resources are no longer available.
+ * {@link #EXTRA_CHANGED_UID_LIST} is the set of packages
+ * whose resources are no longer available.
+ * </ul>
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_MEDIA_RESOURCES_UNAVAILABLE =
+ "android.intent.action.MEDIA_RESOURCES_UNAVAILABILE";
+
/**
* Broadcast Action: The current system wallpaper has changed. See
* {@link android.app.WallpaperManager} for retrieving the new wallpaper.
@@ -2136,13 +2190,34 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.extra.changed_component_name";
/**
- * This field is part of {@link android.content.Intent#ACTION_PACKAGE_CHANGED}
+ * This field is part of {@link android.content.Intent#ACTION_PACKAGE_CHANGED},
* and contains a string array of all of the components that have changed.
*/
public static final String EXTRA_CHANGED_COMPONENT_NAME_LIST =
"android.intent.extra.changed_component_name_list";
/**
+ * This field is part of
+ * {@link android.content.Intent#ACTION_MEDIA_RESOURCES_AVAILABLE},
+ * {@link android.content.Intent#ACTION_MEDIA_RESOURCES_UNAVAILABLE}
+ * and contains a string array of all of the components that have changed.
+ * @hide
+ */
+ public static final String EXTRA_CHANGED_PACKAGE_LIST =
+ "android.intent.extra.changed_package_list";
+
+ /**
+ * This field is part of
+ * {@link android.content.Intent#ACTION_MEDIA_RESOURCES_AVAILABLE},
+ * {@link android.content.Intent#ACTION_MEDIA_RESOURCES_UNAVAILABLE}
+ * and contains an integer array of uids of all of the components
+ * that have changed.
+ * @hide
+ */
+ public static final String EXTRA_CHANGED_UID_LIST =
+ "android.intent.extra.changed_uid_list";
+
+ /**
* @hide
* Magic extra system code can use when binding, to give a label for
* who it is that has bound to a service. This is an integer giving
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index bc59c94526d6..745628a023c8 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -27,6 +27,8 @@ import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Environment;
+import android.os.StatFs;
import android.util.AndroidException;
import android.util.DisplayMetrics;
@@ -259,6 +261,13 @@ public abstract class PackageManager {
public static final int INSTALL_ON_SDCARD = 0x00000008;
/**
+ * Convenience flag parameter to indicate that this package has to be installed
+ * on internal flash.
+ * @hide
+ */
+ public static final int INSTALL_ON_INTERNAL_FLASH = 0x00000000;
+
+ /**
* Flag parameter for
* {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
* that you don't want to kill the app containing the component. Be careful when you set this
@@ -602,7 +611,23 @@ public abstract class PackageManager {
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
-
+
+ /**
+ * Determines best place to install an application: either SD or internal FLASH.
+ * Tweak the algorithm for best results.
+ * @param appInfo ApplicationInfo object of the package to install.
+ * Call utility method to obtain.
+ * @param packageURI URI identifying the package's APK file.
+ * @return {@link INSTALL_ON_INTERNAL_FLASH} if it is best to install package on internal
+ * storage, {@link INSTALL_ON_SDCARD} if it is best to install package on SD card,
+ * and {@link INSTALL_FAILED_INSUFFICIENT_STORAGE} if insufficient space to safely install
+ * the application. {@link INSTALL_PARSE_FAILED_NOT_APK} Is returned if any input
+ * parameter is <code>null</code>.
+ * This recommendation does take into account the package's own flags.
+ * @hide
+ */
+ public abstract int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI);
+
/**
* Retrieve overall information about an application package that is
* installed on the system.
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index b819fa07e0b9..7362394ee180 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -115,6 +115,11 @@ public abstract class RegisteredServicesCache<V> {
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
mContext.registerReceiver(receiver, intentFilter);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(receiver, sdFilter);
}
public void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 82490bb3e6a4..e4b0191c1446 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -65,9 +65,8 @@ public class SQLiteDatabase extends SQLiteClosable {
/**
* Algorithms used in ON CONFLICT clause
* http://www.sqlite.org/lang_conflict.html
- * @hide
*/
- public enum ConflictAlgorithm {
+ public static final class ConflictAlgorithm {
/**
* When a constraint violation occurs, an immediate ROLLBACK occurs,
* thus ending the current transaction, and the command aborts with a
@@ -75,14 +74,14 @@ public class SQLiteDatabase extends SQLiteClosable {
* (other than the implied transaction that is created on every command)
* then this algorithm works the same as ABORT.
*/
- ROLLBACK("ROLLBACK"),
+ public static final int ROLLBACK = 1;
/**
* When a constraint violation occurs,no ROLLBACK is executed
* so changes from prior commands within the same transaction
* are preserved. This is the default behavior.
*/
- ABORT("ABORT"),
+ public static final int ABORT = 2;
/**
* When a constraint violation occurs, the command aborts with a return
@@ -90,7 +89,7 @@ public class SQLiteDatabase extends SQLiteClosable {
* the command made prior to encountering the constraint violation
* are preserved and are not backed out.
*/
- FAIL("FAIL"),
+ public static final int FAIL = 3;
/**
* When a constraint violation occurs, the one row that contains
@@ -99,7 +98,7 @@ public class SQLiteDatabase extends SQLiteClosable {
* after the row that contained the constraint violation continue to be
* inserted or updated normally. No error is returned.
*/
- IGNORE("IGNORE"),
+ public static final int IGNORE = 4;
/**
* When a UNIQUE constraint violation occurs, the pre-existing rows that
@@ -114,15 +113,16 @@ public class SQLiteDatabase extends SQLiteClosable {
* it does not invoke delete triggers on those rows.
* This behavior might change in a future release.
*/
- REPLACE("REPLACE");
+ public static final int REPLACE = 5;
- private final String mValue;
- ConflictAlgorithm(String value) {
- mValue = value;
- }
- public String value() {
- return mValue;
- }
+ /**
+ * use the following when no conflict action is specified.
+ */
+ public static final int NONE = 0;
+ private static final String[] VALUES = new String[]
+ {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
+
+ private ConflictAlgorithm() {} // disable instantiation of this class
}
/**
@@ -290,6 +290,10 @@ public class SQLiteDatabase extends SQLiteClosable {
@Override
protected void onAllReferencesReleased() {
if (isOpen()) {
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ Log.d(TAG, "captured_sql|" + mPath + "|DETACH DATABASE " +
+ getDatabaseName(mPath) + ";");
+ }
if (SQLiteDebug.DEBUG_SQL_CACHE) {
mTimeClosed = getTime();
}
@@ -1334,7 +1338,7 @@ public class SQLiteDatabase extends SQLiteClosable {
*/
public long insert(String table, String nullColumnHack, ContentValues values) {
try {
- return insertWithOnConflict(table, nullColumnHack, values, null);
+ return insertWithOnConflict(table, nullColumnHack, values, ConflictAlgorithm.NONE);
} catch (SQLException e) {
Log.e(TAG, "Error inserting " + values, e);
return -1;
@@ -1356,7 +1360,7 @@ public class SQLiteDatabase extends SQLiteClosable {
*/
public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
throws SQLException {
- return insertWithOnConflict(table, nullColumnHack, values, null);
+ return insertWithOnConflict(table, nullColumnHack, values, ConflictAlgorithm.NONE);
}
/**
@@ -1408,12 +1412,14 @@ public class SQLiteDatabase extends SQLiteClosable {
* @param initialValues this map contains the initial column values for the
* row. The keys should be the column names and the values the
* column values
- * @param algorithm {@link ConflictAlgorithm} for insert conflict resolver
- * @return the row ID of the newly inserted row, or -1 if an error occurred
- * @hide
+ * @param conflictAlgorithm {@link ConflictAlgorithm} for insert conflict resolver
+ * @return the row ID of the newly inserted row
+ * OR the primary key of the existing row if the input param 'conflictAlgorithm' =
+ * {@link ConflictAlgorithm#IGNORE}
+ * OR -1 if any error
*/
public long insertWithOnConflict(String table, String nullColumnHack,
- ContentValues initialValues, ConflictAlgorithm algorithm) {
+ ContentValues initialValues, int conflictAlgorithm) {
if (!isOpen()) {
throw new IllegalStateException("database not open");
}
@@ -1421,10 +1427,7 @@ public class SQLiteDatabase extends SQLiteClosable {
// Measurements show most sql lengths <= 152
StringBuilder sql = new StringBuilder(152);
sql.append("INSERT");
- if (algorithm != null) {
- sql.append(" OR ");
- sql.append(algorithm.value());
- }
+ sql.append(ConflictAlgorithm.VALUES[conflictAlgorithm]);
sql.append(" INTO ");
sql.append(table);
// Measurements show most values lengths < 40
@@ -1548,7 +1551,7 @@ public class SQLiteDatabase extends SQLiteClosable {
* @return the number of rows affected
*/
public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
- return updateWithOnConflict(table, values, whereClause, whereArgs, null);
+ return updateWithOnConflict(table, values, whereClause, whereArgs, ConflictAlgorithm.NONE);
}
/**
@@ -1559,12 +1562,11 @@ public class SQLiteDatabase extends SQLiteClosable {
* valid value that will be translated to NULL.
* @param whereClause the optional WHERE clause to apply when updating.
* Passing null will update all rows.
- * @param algorithm {@link ConflictAlgorithm} for update conflict resolver
+ * @param conflictAlgorithm {@link ConflictAlgorithm} for update conflict resolver
* @return the number of rows affected
- * @hide
*/
public int updateWithOnConflict(String table, ContentValues values,
- String whereClause, String[] whereArgs, ConflictAlgorithm algorithm) {
+ String whereClause, String[] whereArgs, int conflictAlgorithm) {
if (!isOpen()) {
throw new IllegalStateException("database not open");
}
@@ -1575,12 +1577,7 @@ public class SQLiteDatabase extends SQLiteClosable {
StringBuilder sql = new StringBuilder(120);
sql.append("UPDATE ");
- if (algorithm != null) {
- sql.append("OR ");
- sql.append(algorithm.value());
- sql.append(" ");
- }
-
+ sql.append(ConflictAlgorithm.VALUES[conflictAlgorithm]);
sql.append(table);
sql.append(" SET ");
@@ -1655,6 +1652,9 @@ public class SQLiteDatabase extends SQLiteClosable {
*/
public void execSQL(String sql) throws SQLException {
long timeStart = Debug.threadCpuTimeNanos();
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ Log.v(TAG, SQLiteDebug.captureSql(this.getPath(), sql, null));
+ }
lock();
try {
native_execSQL(sql);
@@ -1680,7 +1680,9 @@ public class SQLiteDatabase extends SQLiteClosable {
if (bindArgs == null) {
throw new IllegalArgumentException("Empty bindArgs");
}
-
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ Log.v(TAG, SQLiteDebug.captureSql(this.getPath(), sql, bindArgs));
+ }
long timeStart = Debug.threadCpuTimeNanos();
lock();
SQLiteStatement statement = null;
@@ -1739,6 +1741,10 @@ public class SQLiteDatabase extends SQLiteClosable {
mLeakedException = new IllegalStateException(path +
" SQLiteDatabase created and never closed");
mFactory = factory;
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ Log.d(TAG, "captured_sql|" + mPath + "|ATTACH DATABASE '" + mPath +
+ "' as " + getDatabaseName(mPath) + ";");
+ }
dbopen(mPath, mFlags);
if (SQLiteDebug.DEBUG_SQL_CACHE) {
mTimeOpened = getTime();
@@ -1748,6 +1754,10 @@ public class SQLiteDatabase extends SQLiteClosable {
setLocale(Locale.getDefault());
} catch (RuntimeException e) {
Log.e(TAG, "Failed to setLocale() when constructing, closing the database", e);
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ Log.d(TAG, "captured_sql|" + mPath + "|DETACH DATABASE " +
+ getDatabaseName(mPath) + ";");
+ }
dbclose();
if (SQLiteDebug.DEBUG_SQL_CACHE) {
mTimeClosed = getTime();
@@ -1760,6 +1770,20 @@ public class SQLiteDatabase extends SQLiteClosable {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS ").format(System.currentTimeMillis());
}
+ private String getDatabaseName(String path) {
+ if (path == null || path.trim().length() == 0) {
+ return "db not specified?";
+ }
+
+ if (path.equalsIgnoreCase(":memory:")) {
+ return "memorydb";
+ }
+ String[] tokens = path.split("/");
+ String[] lastNodeTokens = tokens[tokens.length - 1].split("\\.", 2);
+ return (lastNodeTokens.length == 1) ? lastNodeTokens[0]
+ : lastNodeTokens[0] + lastNodeTokens[1];
+ }
+
/**
* return whether the DB is opened as read only.
* @return true if DB is opened as read only
diff --git a/core/java/android/database/sqlite/SQLiteDebug.java b/core/java/android/database/sqlite/SQLiteDebug.java
index d4d30592ecf4..b12034af1f60 100644
--- a/core/java/android/database/sqlite/SQLiteDebug.java
+++ b/core/java/android/database/sqlite/SQLiteDebug.java
@@ -16,12 +16,11 @@
package android.database.sqlite;
-import android.util.Config;
import android.util.Log;
/**
* Provides debugging info about all SQLite databases running in the current process.
- *
+ *
* {@hide}
*/
public final class SQLiteDebug {
@@ -38,6 +37,13 @@ public final class SQLiteDebug {
Log.isLoggable("SQLiteCompiledSql", Log.VERBOSE);
/**
+ * Controls the capturing and printing of complete sql statement including the bind args and
+ * the database name.
+ */
+ public static final boolean DEBUG_CAPTURE_SQL =
+ Log.isLoggable("SQLiteCaptureSql", Log.VERBOSE);
+
+ /**
* Controls the stack trace reporting of active cursors being
* finalized.
*/
@@ -45,20 +51,20 @@ public final class SQLiteDebug {
Log.isLoggable("SQLiteCursorClosing", Log.VERBOSE);
/**
- * Controls the tracking of time spent holding the database lock.
+ * Controls the tracking of time spent holding the database lock.
*/
public static final boolean DEBUG_LOCK_TIME_TRACKING =
Log.isLoggable("SQLiteLockTime", Log.VERBOSE);
/**
- * Controls the printing of stack traces when tracking the time spent holding the database lock.
+ * Controls the printing of stack traces when tracking the time spent holding the database lock.
*/
public static final boolean DEBUG_LOCK_TIME_TRACKING_STACK_TRACE =
Log.isLoggable("SQLiteLockStackTrace", Log.VERBOSE);
/**
* Contains statistics about the active pagers in the current process.
- *
+ *
* @see #getPagerStats(PagerStats)
*/
public static class PagerStats {
@@ -82,13 +88,13 @@ public final class SQLiteDebug {
* @return The size of the SQLite heap in bytes.
*/
public static native long getHeapSize();
-
+
/**
* Returns the amount of allocated memory in the SQLite heap.
* @return The allocated size in bytes.
*/
public static native long getHeapAllocatedSize();
-
+
/**
* Returns the amount of free memory in the SQLite heap.
* @return The freed size in bytes.
@@ -115,4 +121,62 @@ public final class SQLiteDebug {
static synchronized void notifyActiveCursorFinalized() {
sNumActiveCursorsFinalized++;
}
+
+ /**
+ * returns a message containing the given database name (path) and the string built by
+ * replacing "?" characters in the given sql string with the corresponding
+ * positional values from the given param bindArgs.
+ *
+ * @param path the database name
+ * @param sql sql string with possibly "?" for bindargs
+ * @param bindArgs args for "?"s in the above string
+ * @return the String to be logged
+ */
+ /* package */ static String captureSql(String path, String sql, Object[] bindArgs) {
+ // how many bindargs in sql
+ sql = sql.trim();
+ String args[] = sql.split("\\?");
+ // how many "?"s in the given sql string?
+ int varArgsInSql = (sql.endsWith("?")) ? args.length : args.length - 1;
+
+ // how many bind args do we have in the given input param bindArgs
+ int bindArgsLen = (bindArgs == null) ? 0 : bindArgs.length;
+ if (varArgsInSql < bindArgsLen) {
+ return "too many bindArgs provided. " +
+ "# of bindArgs = " + bindArgsLen + ", # of varargs = " + varArgsInSql +
+ "; sql = " + sql;
+ }
+
+ // if there are no bindArgs, we are done. log the sql as is.
+ if (bindArgsLen == 0 && varArgsInSql == 0) {
+ return logSql(path, sql);
+ }
+
+ StringBuilder buf = new StringBuilder();
+
+ // take the supplied bindArgs and plug them into sql
+ for (int i = 0; i < bindArgsLen; i++) {
+ buf.append(args[i]);
+ buf.append(bindArgs[i]);
+ }
+
+ // does given sql have more varArgs than the supplied bindArgs
+ // if so, assign nulls to the extra varArgs in sql
+ for (int i = bindArgsLen; i < varArgsInSql; i ++) {
+ buf.append(args[i]);
+ buf.append("null");
+ }
+
+ // if there are any characters left in the given sql string AFTER the last "?"
+ // log them also. for example, if the given sql = "select * from test where a=? and b=1
+ // then the following code appends " and b=1" string to buf.
+ if (varArgsInSql < args.length) {
+ buf.append(args[varArgsInSql]);
+ }
+ return logSql(path, buf.toString());
+ }
+
+ private static String logSql(String path, String sql) {
+ return "captured_sql|" + path + "|" + sql + ";";
+ }
}
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 00b0a8675ec0..1159c1de74c5 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -16,6 +16,12 @@
package android.database.sqlite;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
import android.util.Log;
/**
@@ -47,6 +53,11 @@ public abstract class SQLiteProgram extends SQLiteClosable {
*/
protected int nStatement = 0;
+ /**
+ * stores all bindargs for debugging purposes
+ */
+ private Map<Integer, String> mBindArgs = null;
+
/* package */ SQLiteProgram(SQLiteDatabase db, String sql) {
if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
Log.d(TAG, "processing sql: " + sql);
@@ -127,6 +138,9 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @param index The 1-based index to the parameter to bind null to
*/
public void bindNull(int index) {
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ addToBindArgs(index, "null");
+ }
acquireReference();
try {
native_bind_null(index);
@@ -143,6 +157,9 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @param value The value to bind
*/
public void bindLong(int index, long value) {
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ addToBindArgs(index, value + "");
+ }
acquireReference();
try {
native_bind_long(index, value);
@@ -159,6 +176,9 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @param value The value to bind
*/
public void bindDouble(int index, double value) {
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ addToBindArgs(index, value + "");
+ }
acquireReference();
try {
native_bind_double(index, value);
@@ -175,6 +195,9 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @param value The value to bind
*/
public void bindString(int index, String value) {
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ addToBindArgs(index, "'" + value + "'");
+ }
if (value == null) {
throw new IllegalArgumentException("the bind value at index " + index + " is null");
}
@@ -194,6 +217,9 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* @param value The value to bind
*/
public void bindBlob(int index, byte[] value) {
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ addToBindArgs(index, "blob");
+ }
if (value == null) {
throw new IllegalArgumentException("the bind value at index " + index + " is null");
}
@@ -209,6 +235,9 @@ public abstract class SQLiteProgram extends SQLiteClosable {
* Clears all existing bindings. Unset bindings are treated as NULL.
*/
public void clearBindings() {
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ mBindArgs = null;
+ }
acquireReference();
try {
native_clear_bindings();
@@ -230,6 +259,39 @@ public abstract class SQLiteProgram extends SQLiteClosable {
}
/**
+ * this method is called under the debug flag {@link SQLiteDebug.DEBUG_CAPTURE_SQL} only.
+ * it collects the bindargs as they are called by the callers the bind... methods in this
+ * class.
+ */
+ private void addToBindArgs(int index, String obj) {
+ if (mBindArgs == null) {
+ mBindArgs = new HashMap<Integer, String>();
+ }
+ mBindArgs.put(index, obj);
+ }
+
+ /**
+ * constructs all the bindargs in sequence and returns a String Array of the values.
+ * it uses the HashMap built up by the above method.
+ *
+ * @return the string array of bindArgs with the args arranged in sequence
+ */
+ /* package */ String[] getBindArgs() {
+ if (mBindArgs == null) {
+ return null;
+ }
+ Set<Integer> indexSet = mBindArgs.keySet();
+ ArrayList<Integer> indexList = new ArrayList<Integer>(indexSet);
+ Collections.sort(indexList);
+ int len = indexList.size();
+ String[] bindObjs = new String[len];
+ for (int i = 0; i < len; i++) {
+ bindObjs[i] = mBindArgs.get(indexList.get(i));
+ }
+ return bindObjs;
+ }
+
+ /**
* Compiles SQL into a SQLite program.
*
* <P>The database lock must be held when calling this method.
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index cc714ee9d8da..0cee3c526a08 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -17,7 +17,6 @@
package android.database.sqlite;
import android.os.Debug;
-import android.os.SystemClock;
import android.util.Log;
/**
@@ -56,6 +55,9 @@ public class SQLiteStatement extends SQLiteProgram
if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
Log.v(TAG, "execute() for [" + mSql + "]");
}
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ Log.v(TAG, SQLiteDebug.captureSql(mDatabase.getPath(), mSql, getBindArgs()));
+ }
native_execute();
mDatabase.logTimeStat(mSql, timeStart);
} finally {
@@ -83,6 +85,9 @@ public class SQLiteStatement extends SQLiteProgram
if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
Log.v(TAG, "executeInsert() for [" + mSql + "]");
}
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ Log.v(TAG, SQLiteDebug.captureSql(mDatabase.getPath(), mSql, getBindArgs()));
+ }
native_execute();
mDatabase.logTimeStat(mSql, timeStart);
return mDatabase.lastInsertRow();
@@ -109,6 +114,9 @@ public class SQLiteStatement extends SQLiteProgram
if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
Log.v(TAG, "simpleQueryForLong() for [" + mSql + "]");
}
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ Log.v(TAG, SQLiteDebug.captureSql(mDatabase.getPath(), mSql, getBindArgs()));
+ }
long retValue = native_1x1_long();
mDatabase.logTimeStat(mSql, timeStart);
return retValue;
@@ -135,6 +143,9 @@ public class SQLiteStatement extends SQLiteProgram
if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
Log.v(TAG, "simpleQueryForString() for [" + mSql + "]");
}
+ if (SQLiteDebug.DEBUG_CAPTURE_SQL) {
+ Log.v(TAG, SQLiteDebug.captureSql(mDatabase.getPath(), mSql, getBindArgs()));
+ }
String retValue = native_1x1_string();
mDatabase.logTimeStat(mSql, timeStart);
return retValue;
diff --git a/core/java/com/google/android/mms/util/SqliteWrapper.java b/core/java/android/database/sqlite/SqliteWrapper.java
index bcdac22ce142..b019618a0f49 100644
--- a/core/java/com/google/android/mms/util/SqliteWrapper.java
+++ b/core/java/android/database/sqlite/SqliteWrapper.java
@@ -15,9 +15,8 @@
* limitations under the License.
*/
-package com.google.android.mms.util;
+package android.database.sqlite;
-import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -27,6 +26,10 @@ import android.net.Uri;
import android.util.Log;
import android.widget.Toast;
+/**
+ * @hide
+ */
+
public final class SqliteWrapper {
private static final String TAG = "SqliteWrapper";
private static final String SQLITE_EXCEPTION_DETAIL_MESSAGE
@@ -36,21 +39,6 @@ public final class SqliteWrapper {
// Forbidden being instantiated.
}
- // FIXME: It looks like outInfo.lowMemory does not work well as we expected.
- // after run command: adb shell fillup -p 100, outInfo.lowMemory is still false.
- private static boolean isLowMemory(Context context) {
- if (null == context) {
- return false;
- }
-
- ActivityManager am = (ActivityManager)
- context.getSystemService(Context.ACTIVITY_SERVICE);
- ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();
- am.getMemoryInfo(outInfo);
-
- return outInfo.lowMemory;
- }
-
// FIXME: need to optimize this method.
private static boolean isLowMemory(SQLiteException e) {
return e.getMessage().equals(SQLITE_EXCEPTION_DETAIL_MESSAGE);
diff --git a/core/java/android/ddm/DdmHandleHeap.java b/core/java/android/ddm/DdmHandleHeap.java
index 95fa0a265d15..fa0fbbfe1658 100644
--- a/core/java/android/ddm/DdmHandleHeap.java
+++ b/core/java/android/ddm/DdmHandleHeap.java
@@ -34,6 +34,7 @@ public class DdmHandleHeap extends ChunkHandler {
public static final int CHUNK_HPIF = type("HPIF");
public static final int CHUNK_HPSG = type("HPSG");
public static final int CHUNK_HPDU = type("HPDU");
+ public static final int CHUNK_HPDS = type("HPDS");
public static final int CHUNK_NHSG = type("NHSG");
public static final int CHUNK_HPGC = type("HPGC");
public static final int CHUNK_REAE = type("REAE");
@@ -53,6 +54,7 @@ public class DdmHandleHeap extends ChunkHandler {
DdmServer.registerHandler(CHUNK_HPIF, mInstance);
DdmServer.registerHandler(CHUNK_HPSG, mInstance);
DdmServer.registerHandler(CHUNK_HPDU, mInstance);
+ DdmServer.registerHandler(CHUNK_HPDS, mInstance);
DdmServer.registerHandler(CHUNK_NHSG, mInstance);
DdmServer.registerHandler(CHUNK_HPGC, mInstance);
DdmServer.registerHandler(CHUNK_REAE, mInstance);
@@ -86,6 +88,8 @@ public class DdmHandleHeap extends ChunkHandler {
return handleHPSGNHSG(request, false);
} else if (type == CHUNK_HPDU) {
return handleHPDU(request);
+ } else if (type == CHUNK_HPDS) {
+ return handleHPDS(request);
} else if (type == CHUNK_NHSG) {
return handleHPSGNHSG(request, true);
} else if (type == CHUNK_HPGC) {
@@ -167,7 +171,7 @@ public class DdmHandleHeap extends ChunkHandler {
result = -1;
} catch (IOException ioe) {
result = -1;
- } catch (RuntimeException ioe) {
+ } catch (RuntimeException re) {
result = -1;
}
@@ -177,6 +181,38 @@ public class DdmHandleHeap extends ChunkHandler {
}
/*
+ * Handle a "HeaP Dump Streaming" request.
+ *
+ * This tells the VM to create a heap dump and send it directly to
+ * DDMS. The dumps are large enough that we don't want to copy the
+ * data into a byte[] and send it from here.
+ */
+ private Chunk handleHPDS(Chunk request) {
+ ByteBuffer in = wrapChunk(request);
+ byte result;
+
+ /* get the filename for the output file */
+ if (Config.LOGD)
+ Log.d("ddm-heap", "Heap dump: [DDMS]");
+
+ String failMsg = null;
+ try {
+ Debug.dumpHprofDataDdms();
+ } catch (UnsupportedOperationException uoe) {
+ failMsg = "hprof dumps not supported in this VM";
+ } catch (RuntimeException re) {
+ failMsg = "Exception: " + re.getMessage();
+ }
+
+ if (failMsg != null) {
+ Log.w("ddm-heap", failMsg);
+ return createFailChunk(1, failMsg);
+ } else {
+ return null;
+ }
+ }
+
+ /*
* Handle a "HeaP Garbage Collection" request.
*/
private Chunk handleHPGC(Chunk request) {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index abb74cd31392..47c2cac2952b 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -658,6 +658,25 @@ public class Camera {
width = w;
height = h;
}
+ /**
+ * Compares {@code obj} to this size.
+ *
+ * @param obj the object to compare this size with.
+ * @return {@code true} if the width and height of {@code obj} is the
+ * same as those of this size. {@code false} otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Size)) {
+ return false;
+ }
+ Size s = (Size) obj;
+ return width == s.width && height == s.height;
+ }
+ @Override
+ public int hashCode() {
+ return width * 32713 + height;
+ }
/** width of the picture */
public int width;
/** height of the picture */
@@ -685,6 +704,7 @@ public class Camera {
private static final String KEY_PREVIEW_FRAME_RATE = "preview-frame-rate";
private static final String KEY_PICTURE_SIZE = "picture-size";
private static final String KEY_PICTURE_FORMAT = "picture-format";
+ private static final String KEY_JPEG_THUMBNAIL_SIZE = "jpeg-thumbnail-size";
private static final String KEY_JPEG_THUMBNAIL_WIDTH = "jpeg-thumbnail-width";
private static final String KEY_JPEG_THUMBNAIL_HEIGHT = "jpeg-thumbnail-height";
private static final String KEY_JPEG_THUMBNAIL_QUALITY = "jpeg-thumbnail-quality";
@@ -700,6 +720,9 @@ public class Camera {
private static final String KEY_SCENE_MODE = "scene-mode";
private static final String KEY_FLASH_MODE = "flash-mode";
private static final String KEY_FOCUS_MODE = "focus-mode";
+ private static final String KEY_FOCAL_LENGTH = "focal-length";
+ private static final String KEY_HORIZONTAL_VIEW_ANGLE = "horizontal-view-angle";
+ private static final String KEY_VERTICAL_VIEW_ANGLE = "vertical-view-angle";
// Parameter key suffix for supported values.
private static final String SUPPORTED_VALUES_SUFFIX = "-values";
@@ -954,7 +977,9 @@ public class Camera {
}
/**
- * Sets the dimensions for EXIF thumbnail in Jpeg picture.
+ * Sets the dimensions for EXIF thumbnail in Jpeg picture. If
+ * applications set both width and height to 0, EXIF will not contain
+ * thumbnail.
*
* @param width the width of the thumbnail, in pixels
* @param height the height of the thumbnail, in pixels
@@ -976,6 +1001,18 @@ public class Camera {
}
/**
+ * Gets the supported jpeg thumbnail sizes.
+ *
+ * @return a List of Size object. This method will always return a list
+ * with at least two elements. Size 0,0 (no thumbnail) is always
+ * supported.
+ */
+ public List<Size> getSupportedJpegThumbnailSizes() {
+ String str = get(KEY_JPEG_THUMBNAIL_SIZE + SUPPORTED_VALUES_SUFFIX);
+ return splitSize(str);
+ }
+
+ /**
* Sets the quality of the EXIF thumbnail in Jpeg picture.
*
* @param quality the JPEG quality of the EXIF thumbnail. The range is 1
@@ -1473,6 +1510,36 @@ public class Camera {
}
/**
+ * Gets the focal length (in millimeter) of the camera.
+ *
+ * @return the focal length. This method will always return a valid
+ * value.
+ */
+ public float getFocalLength() {
+ return Float.parseFloat(get(KEY_FOCAL_LENGTH));
+ }
+
+ /**
+ * Gets the horizontal angle of view in degrees.
+ *
+ * @return horizontal angle of view. This method will always return a
+ * valid value.
+ */
+ public float getHorizontalViewAngle() {
+ return Float.parseFloat(get(KEY_HORIZONTAL_VIEW_ANGLE));
+ }
+
+ /**
+ * Gets the vertical angle of view in degrees.
+ *
+ * @return vertical angle of view. This method will always return a
+ * valid value.
+ */
+ public float getVerticalViewAngle() {
+ return Float.parseFloat(get(KEY_VERTICAL_VIEW_ANGLE));
+ }
+
+ /**
* Gets current zoom value. This also works when smooth zoom is in
* progress.
*
diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java
index da6af9dd9987..e1327ddfdcc8 100644
--- a/core/java/android/net/http/CertificateChainValidator.java
+++ b/core/java/android/net/http/CertificateChainValidator.java
@@ -29,6 +29,7 @@ import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
+import java.util.Date;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;
@@ -51,20 +52,24 @@ class CertificateChainValidator {
= new CertificateChainValidator();
/**
- * @return The singleton instance of the certificator chain validator
+ * @return The singleton instance of the certificates chain validator
*/
public static CertificateChainValidator getInstance() {
return sInstance;
}
/**
- * Creates a new certificate chain validator. This is a pivate constructor.
+ * Creates a new certificate chain validator. This is a private constructor.
* If you need a Certificate chain validator, call getInstance().
*/
private CertificateChainValidator() {}
/**
* Performs the handshake and server certificates validation
+ * Notice a new chain will be rebuilt by tracing the issuer and subject
+ * before calling checkServerTrusted().
+ * And if the last traced certificate is self issued and it is expired, it
+ * will be dropped.
* @param sslSocket The secure connection socket
* @param domain The website domain
* @return An SSL error object if there is an error and null otherwise
@@ -127,7 +132,58 @@ class CertificateChainValidator {
}
}
- // first, we validate the chain using the standard validation
+ // Clean up the certificates chain and build a new one.
+ // Theoretically, we shouldn't have to do this, but various web servers
+ // in practice are mis-configured to have out-of-order certificates or
+ // expired self-issued root certificate.
+ int chainLength = serverCertificates.length;
+ if (serverCertificates.length > 1) {
+ // 1. we clean the received certificates chain.
+ // We start from the end-entity certificate, tracing down by matching
+ // the "issuer" field and "subject" field until we can't continue.
+ // This helps when the certificates are out of order or
+ // some certificates are not related to the site.
+ int currIndex;
+ for (currIndex = 0; currIndex < serverCertificates.length; ++currIndex) {
+ boolean foundNext = false;
+ for (int nextIndex = currIndex + 1;
+ nextIndex < serverCertificates.length;
+ ++nextIndex) {
+ if (serverCertificates[currIndex].getIssuerDN().equals(
+ serverCertificates[nextIndex].getSubjectDN())) {
+ foundNext = true;
+ // Exchange certificates so that 0 through currIndex + 1 are in proper order
+ if (nextIndex != currIndex + 1) {
+ X509Certificate tempCertificate = serverCertificates[nextIndex];
+ serverCertificates[nextIndex] = serverCertificates[currIndex + 1];
+ serverCertificates[currIndex + 1] = tempCertificate;
+ }
+ break;
+ }
+ }
+ if (!foundNext) break;
+ }
+
+ // 2. we exam if the last traced certificate is self issued and it is expired.
+ // If so, we drop it and pass the rest to checkServerTrusted(), hoping we might
+ // have a similar but unexpired trusted root.
+ chainLength = currIndex + 1;
+ X509Certificate lastCertificate = serverCertificates[chainLength - 1];
+ Date now = new Date();
+ if (lastCertificate.getSubjectDN().equals(lastCertificate.getIssuerDN())
+ && now.after(lastCertificate.getNotAfter())) {
+ --chainLength;
+ }
+ }
+
+ // 3. Now we copy the newly built chain into an appropriately sized array.
+ X509Certificate[] newServerCertificates = null;
+ newServerCertificates = new X509Certificate[chainLength];
+ for (int i = 0; i < chainLength; ++i) {
+ newServerCertificates[i] = serverCertificates[i];
+ }
+
+ // first, we validate the new chain using the standard validation
// solution; if we do not find any errors, we are done; if we
// fail the standard validation, we re-validate again below,
// this time trying to retrieve any individual errors we can
@@ -135,167 +191,21 @@ class CertificateChainValidator {
//
try {
SSLParameters.getDefaultTrustManager().checkServerTrusted(
- serverCertificates, "RSA");
+ newServerCertificates, "RSA");
// no errors!!!
return null;
} catch (CertificateException e) {
+ sslSocket.getSession().invalidate();
+
if (HttpLog.LOGV) {
HttpLog.v(
"failed to pre-validate the certificate chain, error: " +
e.getMessage());
}
- }
-
- sslSocket.getSession().invalidate();
-
- SslError error = null;
-
- // we check the root certificate separately from the rest of the
- // chain; this is because we need to know what certificate in
- // the chain resulted in an error if any
- currCertificate =
- serverCertificates[serverCertificates.length - 1];
- if (currCertificate == null) {
- closeSocketThrowException(
- sslSocket, "root certificate is null");
- }
-
- // check if the last certificate in the chain (root) is trusted
- X509Certificate[] rootCertificateChain = { currCertificate };
- try {
- SSLParameters.getDefaultTrustManager().checkServerTrusted(
- rootCertificateChain, "RSA");
- } catch (CertificateExpiredException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "root certificate has expired";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- error = new SslError(
- SslError.SSL_EXPIRED, currCertificate);
- } catch (CertificateNotYetValidException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "root certificate not valid yet";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- error = new SslError(
- SslError.SSL_NOTYETVALID, currCertificate);
- } catch (CertificateException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "root certificate not trusted";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
return new SslError(
SslError.SSL_UNTRUSTED, currCertificate);
}
-
- // Then go through the certificate chain checking that each
- // certificate trusts the next and that each certificate is
- // within its valid date range. Walk the chain in the order
- // from the CA to the end-user
- X509Certificate prevCertificate =
- serverCertificates[serverCertificates.length - 1];
-
- for (int i = serverCertificates.length - 2; i >= 0; --i) {
- currCertificate = serverCertificates[i];
-
- // if a certificate is null, we cannot verify the chain
- if (currCertificate == null) {
- closeSocketThrowException(
- sslSocket, "null certificate in the chain");
- }
-
- // verify if trusted by chain
- if (!prevCertificate.getSubjectDN().equals(
- currCertificate.getIssuerDN())) {
- String errorMessage = "not trusted by chain";
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- return new SslError(
- SslError.SSL_UNTRUSTED, currCertificate);
- }
-
- try {
- currCertificate.verify(prevCertificate.getPublicKey());
- } catch (GeneralSecurityException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "not trusted by chain";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- return new SslError(
- SslError.SSL_UNTRUSTED, currCertificate);
- }
-
- // verify if the dates are valid
- try {
- currCertificate.checkValidity();
- } catch (CertificateExpiredException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "certificate expired";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- if (error == null ||
- error.getPrimaryError() < SslError.SSL_EXPIRED) {
- error = new SslError(
- SslError.SSL_EXPIRED, currCertificate);
- }
- } catch (CertificateNotYetValidException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "certificate not valid yet";
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v(errorMessage);
- }
-
- if (error == null ||
- error.getPrimaryError() < SslError.SSL_NOTYETVALID) {
- error = new SslError(
- SslError.SSL_NOTYETVALID, currCertificate);
- }
- }
-
- prevCertificate = currCertificate;
- }
-
- // if we do not have an error to report back to the user, throw
- // an exception (a generic error will be reported instead)
- if (error == null) {
- closeSocketThrowException(
- sslSocket,
- "failed to pre-validate the certificate chain due to a non-standard error");
- }
-
- return error;
}
private void closeSocketThrowException(
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index fcd8f38477dd..3e9fd420a3fe 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -53,14 +53,14 @@ public class Build {
/** The end-user-visible name for the end product. */
public static final String MODEL = getString("ro.product.model");
- /** @pending The system bootloader version number. */
+ /** The system bootloader version number. */
public static final String BOOTLOADER = getString("ro.bootloader");
- /** @pending The radio firmware version number. */
+ /** The radio firmware version number. */
public static final String RADIO = getString("gsm.version.baseband");
- /** @pending The device serial number. */
- public static final String SERIAL = getString("ro.serialno");
+ /** The name of the hardware (from the kernel command line or /proc). */
+ public static final String HARDWARE = getString("ro.hardware");
/** Various version strings. */
public static class VERSION {
@@ -178,6 +178,8 @@ public class Build {
* January 2010: Android 2.1
*/
public static final int ECLAIR_MR1 = 7;
+
+ public static final int FROYO = 8;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 8e9b11bdcd32..9ee251ebbd8d 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -726,6 +726,18 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo
}
/**
+ * Collect "hprof" and send it to DDMS. This will cause a GC.
+ *
+ * @throws UnsupportedOperationException if the VM was built without
+ * HPROF support.
+ *
+ * @hide
+ */
+ public static void dumpHprofDataDdms() {
+ VMDebug.dumpHprofDataDdms();
+ }
+
+ /**
* Returns the number of sent transactions from this process.
* @return The number of sent transactions or -1 if it could not read t.
*/
diff --git a/core/java/android/os/IMountService.aidl b/core/java/android/os/IMountService.aidl
index 2124e85b480c..a5828f65c1a4 100644
--- a/core/java/android/os/IMountService.aidl
+++ b/core/java/android/os/IMountService.aidl
@@ -17,6 +17,8 @@
package android.os;
+import android.os.IMountServiceListener;
+
/** WARNING! Update IMountService.h and IMountService.cpp if you change this file.
* In particular, the ordering of the methods below must match the
* _TRANSACTION enum in IMountService.cpp
@@ -25,44 +27,60 @@ package android.os;
interface IMountService
{
/**
- * Is mass storage support enabled?
+ * Registers an IMountServiceListener for receiving async
+ * notifications.
*/
- boolean getMassStorageEnabled();
+ void registerListener(IMountServiceListener listener);
/**
- * Enable or disable mass storage support.
+ * Unregisters an IMountServiceListener
*/
- void setMassStorageEnabled(boolean enabled);
+ void unregisterListener(IMountServiceListener listener);
/**
- * Is mass storage connected?
+ * Gets an Array of supported share methods
*/
- boolean getMassStorageConnected();
-
+ String[] getShareMethodList();
+
/**
- * Mount external storage at given mount point.
+ * Returns true if the share method is available
*/
- void mountVolume(String mountPoint);
+ boolean getShareMethodAvailable(String method);
/**
- * Safely unmount external storage at given mount point.
+ * Shares a volume via the specified method
+ * Returns an int consistent with MountServiceResultCode
*/
- void unmountVolume(String mountPoint);
+ int shareVolume(String path, String method);
/**
- * Format external storage given a mount point.
+ * Unshares a volume via the specified method
+ * Returns an int consistent with MountServiceResultCode
+ */
+ int unshareVolume(String path, String method);
+
+ /**
+ * Returns true if the volume is shared via the specified method.
*/
- void formatVolume(String mountPoint);
+ boolean getVolumeShared(String path, String method);
/**
- * Returns true if media notification sounds are enabled.
+ * Mount external storage at given mount point.
+ * Returns an int consistent with MountServiceResultCode
*/
- boolean getPlayNotificationSounds();
+ int mountVolume(String mountPoint);
/**
- * Sets whether or not media notification sounds are played.
+ * Safely unmount external storage at given mount point.
+ * Returns an int consistent with MountServiceResultCode
+ */
+ int unmountVolume(String mountPoint);
+
+ /**
+ * Format external storage given a mount point.
+ * Returns an int consistent with MountServiceResultCode
*/
- void setPlayNotificationSounds(boolean value);
+ int formatVolume(String mountPoint);
/**
* Gets the state of an volume via it's mountpoint.
@@ -71,37 +89,41 @@ interface IMountService
/*
* Creates a secure container with the specified parameters.
- * On success, the filesystem container-path is returned.
+ * Returns an int consistent with MountServiceResultCode
*/
- String createSecureContainer(String id, int sizeMb, String fstype, String key, int ownerUid);
+ int createSecureContainer(String id, int sizeMb, String fstype, String key, int ownerUid);
/*
* Finalize a container which has just been created and populated.
* After finalization, the container is immutable.
+ * Returns an int consistent with MountServiceResultCode
*/
- void finalizeSecureContainer(String id);
+ int finalizeSecureContainer(String id);
/*
* Destroy a secure container, and free up all resources associated with it.
* NOTE: Ensure all references are released prior to deleting.
+ * Returns an int consistent with MountServiceResultCode
*/
- void destroySecureContainer(String id);
+ int destroySecureContainer(String id);
/*
* Mount a secure container with the specified key and owner UID.
- * On success, the filesystem container-path is returned.
+ * Returns an int consistent with MountServiceResultCode
*/
- String mountSecureContainer(String id, String key, int ownerUid);
+ int mountSecureContainer(String id, String key, int ownerUid);
/*
* Unount a secure container.
+ * Returns an int consistent with MountServiceResultCode
*/
- void unmountSecureContainer(String id);
+ int unmountSecureContainer(String id);
/*
* Rename an unmounted secure container.
+ * Returns an int consistent with MountServiceResultCode
*/
- void renameSecureContainer(String oldId, String newId);
+ int renameSecureContainer(String oldId, String newId);
/*
* Returns the filesystem path of a mounted secure container.
diff --git a/core/java/android/os/IMountServiceListener.aidl b/core/java/android/os/IMountServiceListener.aidl
new file mode 100644
index 000000000000..3df64b213fe5
--- /dev/null
+++ b/core/java/android/os/IMountServiceListener.aidl
@@ -0,0 +1,66 @@
+/*
+ * 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.os;
+
+/**
+ * Callback class for receiving events from MountService.
+ *
+ * @hide
+ */
+interface IMountServiceListener {
+ /**
+ * A sharing method has changed availability state.
+ *
+ * @param method The share method which has changed.
+ * @param available The share availability state.
+ */
+ void onShareAvailabilityChanged(String method, boolean available);
+
+ /**
+ * Media has been inserted
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param major The backing device major number.
+ * @param minor The backing device minor number.
+ */
+ void onMediaInserted(String label, String path, int major, int minor);
+
+ /**
+ * Media has been removed
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param major The backing device major number.
+ * @param minor The backing device minor number.
+ * @param clean Indicates if the removal was clean (unmounted first).
+ */
+ void onMediaRemoved(String label, String path, int major, int minor, boolean clean);
+
+ /**
+ * Volume state has changed.
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param oldState The old state of the volume.
+ * @param newState The new state of the volume.
+ *
+ * Note: State is one of the values returned by Environment.getExternalStorageState()
+ */
+ void onVolumeStateChanged(String label, String path, String oldState, String newState);
+
+}
diff --git a/core/java/android/os/MountServiceListener.java b/core/java/android/os/MountServiceListener.java
new file mode 100644
index 000000000000..a68f464703d7
--- /dev/null
+++ b/core/java/android/os/MountServiceListener.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * Callback class for receiving progress reports during a restore operation. These
+ * methods will all be called on your application's main thread.
+ * @hide
+ */
+public abstract class MountServiceListener {
+ /**
+ * A sharing method has changed availability state.
+ *
+ * @param method The share method which has changed.
+ * @param available The share availability state.
+ */
+ void shareAvailabilityChange(String method, boolean available) {
+ }
+
+ /**
+ * Media has been inserted
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param major The backing device major number.
+ * @param minor The backing device minor number.
+ */
+ void mediaInserted(String label, String path, int major, int minor) {
+ }
+
+ /**
+ * Media has been removed
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param major The backing device major number.
+ * @param minor The backing device minor number.
+ * @param clean Indicates if the removal was clean (unmounted first).
+ */
+ void mediaRemoved(String label, String path, int major, int minor, boolean clean) {
+ }
+
+ /**
+ * Volume state has changed.
+ *
+ * @param label The volume label.
+ * @param path The volume mount path.
+ * @param oldState The old state of the volume.
+ * @param newState The new state of the volume.
+ *
+ * Note: State is one of the values returned by Environment.getExternalStorageState()
+ */
+ void volumeStateChange(String label, String path, String oldState, String newState) {
+ }
+}
diff --git a/core/java/android/os/MountServiceResultCode.java b/core/java/android/os/MountServiceResultCode.java
new file mode 100644
index 000000000000..e71dbf46f493
--- /dev/null
+++ b/core/java/android/os/MountServiceResultCode.java
@@ -0,0 +1,34 @@
+/*
+ * 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.os;
+
+import java.io.IOException;
+
+/**
+ * Class that provides access to constants returned from MountService APIs
+ *
+ * {@hide}
+ */
+public class MountServiceResultCode
+{
+ public static final int OperationSucceeded = 0;
+ public static final int OperationFailedInternalError = -1;
+ public static final int OperationFailedNoMedia = -2;
+ public static final int OperationFailedMediaBlank = -3;
+ public static final int OperationFailedMediaCorrupt = -4;
+ public static final int OperationFailedVolumeNotMounted = -5;
+}
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 0b1b16b1d5dc..36255d04ddc4 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -56,29 +56,6 @@ public class Browser {
"com.android.browser.application_id";
/**
- * The name of the extra data in the VIEW intent. The data is in boolean.
- * <p>
- * If the Browser is handling the intent and the setting for
- * USE_LOCATION_FOR_SERVICES is allow, the Browser will send the location in
- * the POST data if this extra data is presented and it is true.
- * <p>
- * pending api approval
- * @hide
- */
- public static final String EXTRA_APPEND_LOCATION = "com.android.browser.append_location";
-
- /**
- * The name of the extra data in the VIEW intent. The data is in the format of
- * a byte array.
- * <p>
- * Any value sent here will be passed in the http request to the provided url as post data.
- * <p>
- * pending api approval
- * @hide
- */
- public static final String EXTRA_POST_DATA = "com.android.browser.post_data";
-
- /**
* The name of the extra data in the VIEW intent. The data are key/value
* pairs in the format of Bundle. They will be sent in the HTTP request
* headers for the provided url. The keys can't be the standard HTTP headers
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 16746d47ee9e..544e39963da7 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -130,6 +130,57 @@ public final class ContactsContract {
public static final String REQUESTING_PACKAGE_PARAM_KEY = "requesting_package";
/**
+ * @hide
+ */
+ public static final class Preferences {
+
+ /**
+ * A key in the {@link android.provider.Settings android.provider.Settings} provider
+ * that stores the preferred sorting order for contacts (by given name vs. by family name).
+ *
+ * @hide
+ */
+ public static final String SORT_ORDER = "android.contacts.SORT_ORDER";
+
+ /**
+ * The value for the SORT_ORDER key corresponding to sorting by given name first.
+ *
+ * @hide
+ */
+ public static final int SORT_ORDER_PRIMARY = 1;
+
+ /**
+ * The value for the SORT_ORDER key corresponding to sorting by family name first.
+ *
+ * @hide
+ */
+ public static final int SORT_ORDER_ALTERNATIVE = 2;
+
+ /**
+ * A key in the {@link android.provider.Settings android.provider.Settings} provider
+ * that stores the preferred display order for contacts (given name first vs. family
+ * name first).
+ *
+ * @hide
+ */
+ public static final String DISPLAY_ORDER = "android.contacts.DISPLAY_ORDER";
+
+ /**
+ * The value for the DISPLAY_ORDER key corresponding to showing the given name first.
+ *
+ * @hide
+ */
+ public static final int DISPLAY_ORDER_PRIMARY = 1;
+
+ /**
+ * The value for the DISPLAY_ORDER key corresponding to showing the family name first.
+ *
+ * @hide
+ */
+ public static final int DISPLAY_ORDER_ALTERNATIVE = 2;
+ }
+
+ /**
* @hide should be removed when users are updated to refer to SyncState
* @deprecated use SyncState instead
*/
@@ -551,8 +602,7 @@ public final class ContactsContract {
/**
* Sort key based on the alternative representation of the full name,
* {@link #DISPLAY_NAME_ALTERNATIVE}. Thus for Western names,
- * it is the one using the "family name first" format for
- * Western names.
+ * it is the one using the "family name first" format.
*/
public static final String SORT_KEY_ALTERNATIVE = "sort_key_alt";
}
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 1b938ee64660..211bc0aca7f6 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -28,7 +28,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.MiniThumbFile;
-import android.media.ThumbnailUtil;
+import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
@@ -381,15 +381,15 @@ public final class MediaStore {
filePath = c.getString(1);
}
if (isVideo) {
- bitmap = ThumbnailUtil.createVideoThumbnail(filePath);
+ bitmap = ThumbnailUtils.createVideoThumbnail(filePath);
if (kind == MICRO_KIND && bitmap != null) {
- bitmap = ThumbnailUtil.extractMiniThumb(bitmap,
- ThumbnailUtil.MINI_THUMB_TARGET_SIZE,
- ThumbnailUtil.MINI_THUMB_TARGET_SIZE,
- ThumbnailUtil.RECYCLE_INPUT);
+ bitmap = ThumbnailUtils.extractMiniThumb(bitmap,
+ ThumbnailUtils.MINI_THUMB_TARGET_SIZE,
+ ThumbnailUtils.MINI_THUMB_TARGET_SIZE,
+ ThumbnailUtils.RECYCLE_INPUT);
}
} else {
- bitmap = ThumbnailUtil.createImageThumbnail(cr, filePath, uri, origId,
+ bitmap = ThumbnailUtils.createImageThumbnail(cr, filePath, uri, origId,
kind, false);
}
}
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 747ae30a4e05..adeef54663c4 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -16,8 +16,6 @@
package android.provider;
-import com.google.android.mms.util.SqliteWrapper;
-
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ContentResolver;
@@ -25,6 +23,7 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
+import android.database.sqlite.SqliteWrapper;
import android.net.Uri;
import android.telephony.SmsMessage;
import android.text.TextUtils;
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 9953b5609535..324fbaa86470 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -73,6 +73,11 @@ public class SearchManagerService extends ISearchManager.Stub {
packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
packageFilter.addDataScheme("package");
mContext.registerReceiver(mPackageChangedReceiver, packageFilter);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(mPackageChangedReceiver, sdFilter);
}
private synchronized Searchables getSearchables() {
@@ -90,7 +95,9 @@ public class SearchManagerService extends ISearchManager.Stub {
if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
- Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
+ Intent.ACTION_PACKAGE_CHANGED.equals(action) ||
+ Intent.ACTION_MEDIA_RESOURCES_AVAILABLE.equals(action) ||
+ Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
if (DBG) Log.d(TAG, "Got " + action);
// Update list of searchable activities
getSearchables().buildSearchableList();
diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java
index 49991bd7a689..334b04909ada 100644
--- a/core/java/android/speech/RecognizerIntent.java
+++ b/core/java/android/speech/RecognizerIntent.java
@@ -30,8 +30,14 @@ public class RecognizerIntent {
/**
* Starts an activity that will prompt the user for speech and sends it through a
- * speech recognizer. The results will be returned via activity results, or forwarded
- * via a PendingIntent if one is provided.
+ * speech recognizer. The results will be returned via activity results (in
+ * {@link Activity#onActivityResult}, if you start the intent using
+ * {@link Activity#startActivityForResult(Intent, int)}), or forwarded via a PendingIntent
+ * if one is provided.
+ *
+ * <p>Starting this intent with just {@link Activity#startActivity(Intent)} is not supported.
+ * You must either use {@link Activity#startActivityForResult(Intent, int)}, or provide a
+ * PendingIntent, to receive recognition results.
*
* <p>Required extras:
* <ul>
@@ -47,7 +53,7 @@ public class RecognizerIntent {
* <li>{@link #EXTRA_RESULTS_PENDINGINTENT_BUNDLE}
* </ul>
*
- * <p> Result extras:
+ * <p> Result extras (returned in the result, not to be specified in the request):
* <ul>
* <li>{@link #EXTRA_RESULTS}
* </ul>
@@ -73,7 +79,7 @@ public class RecognizerIntent {
* <li>{@link #EXTRA_MAX_RESULTS}
* </ul>
*
- * <p> Result extras:
+ * <p> Result extras (returned in the result, not to be specified in the request):
* <ul>
* <li>{@link #EXTRA_RESULTS}
* </ul>
@@ -167,6 +173,7 @@ public class RecognizerIntent {
*/
public static final String EXTRA_RESULTS_PENDINGINTENT =
"android.speech.extra.RESULTS_PENDINGINTENT";
+
/**
* If you use {@link #EXTRA_RESULTS_PENDINGINTENT} to supply a forwarding intent, you can
* also use this extra to supply additional extras for the final intent. The search results
@@ -187,8 +194,10 @@ public class RecognizerIntent {
public static final int RESULT_AUDIO_ERROR = Activity.RESULT_FIRST_USER + 4;
/**
- * An ArrayList<String> of the potential results when performing
- * {@link #ACTION_RECOGNIZE_SPEECH}. Only present when {@link Activity#RESULT_OK} is returned.
+ * An ArrayList&lt;String&gt; of the recognition results when performing
+ * {@link #ACTION_RECOGNIZE_SPEECH}. Returned in the results; not to be specified in the
+ * recognition request. Only present when {@link Activity#RESULT_OK} is returned in
+ * an activity result. In a PendingIntent, the lack of this extra indicates failure.
*/
public static final String EXTRA_RESULTS = "android.speech.extra.RESULTS";
diff --git a/core/java/android/speech/RecognizerResultsIntent.java b/core/java/android/speech/RecognizerResultsIntent.java
new file mode 100644
index 000000000000..228258ee1580
--- /dev/null
+++ b/core/java/android/speech/RecognizerResultsIntent.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.speech;
+
+import java.util.ArrayList;
+
+/**
+ * Constants for intents related to showing speech recognition results.
+ *
+ * These constants should not be needed for normal utilization of speech recognition. They
+ * would only be called if you wanted to trigger a view of voice search results in your
+ * application, or implemented if you wanted to offer a different view for voice search results
+ * with your application.
+ *
+ * The standard behavior here for someone receiving an {@link #ACTION_VOICE_SEARCH_RESULTS} is to
+ * first retrieve the list of {@link #EXTRA_VOICE_SEARCH_RESULT_STRINGS}, and use any provided
+ * HTML for that result in {@link #EXTRA_VOICE_SEARCH_RESULT_HTML}, if available, to display
+ * the search results. If that is not available, then the corresponding url for that result in
+ * {@link #EXTRA_VOICE_SEARCH_RESULT_URLS} should be used. And if even that is not available,
+ * then a search url should be constructed from the actual recognition result string.
+ *
+ * @hide for making public in a later release
+ */
+public class RecognizerResultsIntent {
+ private RecognizerResultsIntent() {
+ // Not for instantiating.
+ }
+
+ /**
+ * Intent that can be sent by implementations of voice search to display the results of
+ * a search in, for example, a web browser.
+ *
+ * This intent should always be accompanied by at least
+ * {@link #EXTRA_VOICE_SEARCH_RESULT_STRINGS}, and optionally but recommended,
+ * {@link #EXTRA_VOICE_SEARCH_RESULT_URLS}, and sometimes
+ * {@link #EXTRA_VOICE_SEARCH_RESULT_HTML} and
+ * {@link #EXTRA_VOICE_SEARCH_RESULT_HTML_BASE_URLS}.
+ *
+ * These are parallel arrays, where a recognition result string at index N of
+ * {@link #EXTRA_VOICE_SEARCH_RESULT_STRINGS} should be accompanied by a url to use for
+ * searching based on that string at index N of {@link #EXTRA_VOICE_SEARCH_RESULT_URLS},
+ * and, possibly, the full html to display for that result at index N of
+ * {@link #EXTRA_VOICE_SEARCH_RESULT_HTML}. If full html is provided, a base url (or
+ * list of base urls) should be provided with {@link #EXTRA_VOICE_SEARCH_RESULT_HTML_BASE_URLS}.
+ *
+ * @hide for making public in a later release
+ */
+ public static final String ACTION_VOICE_SEARCH_RESULTS =
+ "android.speech.action.VOICE_SEARCH_RESULTS";
+
+ /**
+ * The key to an extra {@link ArrayList} of {@link String}s that contains the list of
+ * recognition alternates from voice search, in order from highest to lowest confidence.
+ *
+ * @hide for making public in a later release
+ */
+ public static final String EXTRA_VOICE_SEARCH_RESULT_STRINGS =
+ "android.speech.extras.VOICE_SEARCH_RESULT_STRINGS";
+
+ /**
+ * The key to an extra {@link ArrayList} of {@link String}s that contains the search urls
+ * to use, if available, for the recognition alternates provided in
+ * {@link #EXTRA_VOICE_SEARCH_RESULT_STRINGS}. This list should always be the same size as the
+ * one provided in {@link #EXTRA_VOICE_SEARCH_RESULT_STRINGS} - if a result cannot provide a
+ * search url, that entry in this ArrayList should be <code>null</code>, and the implementor of
+ * {@link #ACTION_VOICE_SEARCH_RESULTS} should execute a search of its own choosing,
+ * based on the recognition result string.
+ *
+ * @hide for making public in a later release
+ */
+ public static final String EXTRA_VOICE_SEARCH_RESULT_URLS =
+ "android.speech.extras.VOICE_SEARCH_RESULT_URLS";
+
+ /**
+ * The key to an extra {@link ArrayList} of {@link String}s that contains the html content to
+ * use, if available, for the recognition alternates provided in
+ * {@link #EXTRA_VOICE_SEARCH_RESULT_STRINGS}. This list should always be the same size as the
+ * one provided in {@link #EXTRA_VOICE_SEARCH_RESULT_STRINGS} - if a result cannot provide
+ * html, that entry in this list should be <code>null</code>, and the implementor of
+ * {@link #ACTION_VOICE_SEARCH_RESULTS} should back off to the corresponding url provided in
+ * {@link #EXTRA_VOICE_SEARCH_RESULT_URLS}, if available, or else should execute a search of
+ * its own choosing, based on the recognition result string.
+ *
+ * Currently this html content should be expected in the form of a uri with scheme
+ * {@link #URI_SCHEME_INLINE} for the Browser. In the future this may change to a "content://"
+ * uri or some other identifier. Anyone who reads this extra should confirm that a result is
+ * in fact an "inline:" uri and back off to the urls or strings gracefully if it is not, thus
+ * maintaining future backwards compatibility if this changes.
+ *
+ * @hide not to be exposed immediately as the implementation details may change
+ */
+ public static final String EXTRA_VOICE_SEARCH_RESULT_HTML =
+ "android.speech.extras.VOICE_SEARCH_RESULT_HTML";
+
+ /**
+ * The key to an extra {@link ArrayList} of {@link String}s that contains the base url to
+ * assume when interpreting html provided in {@link #EXTRA_VOICE_SEARCH_RESULT_HTML}.
+ *
+ * A list of size 1 may be provided to apply the same base url to all html results.
+ * A list of the same size as {@link #EXTRA_VOICE_SEARCH_RESULT_STRINGS} may be provided
+ * to apply different base urls to each different html result in the
+ * {@link #EXTRA_VOICE_SEARCH_RESULT_HTML} list.
+ *
+ * @hide not to be exposed immediately as the implementation details may change
+ */
+ public static final String EXTRA_VOICE_SEARCH_RESULT_HTML_BASE_URLS =
+ "android.speech.extras.VOICE_SEARCH_RESULT_HTML_BASE_URLS";
+
+ /**
+ * The scheme used currently for html content in {@link #EXTRA_VOICE_SEARCH_RESULT_HTML}.
+ *
+ * @hide not to be exposed immediately as the implementation details may change
+ */
+ public static final String URI_SCHEME_INLINE = "inline";
+}
diff --git a/core/java/android/storage/StorageEventListener.java b/core/java/android/storage/StorageEventListener.java
new file mode 100644
index 000000000000..cd71090de382
--- /dev/null
+++ b/core/java/android/storage/StorageEventListener.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 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.
+ * 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.storage;
+
+/**
+ * Used for receiving notifications from the StorageManager
+ */
+public interface StorageEventListener {
+ /**
+ * Called when the ability to share a volume has changed.
+ * @param method the share-method which has changed.
+ * @param available true if the share is available.
+ */
+ public void onShareAvailabilityChanged(String method, boolean available);
+
+ /**
+ * Called when media has been inserted
+ * @param label the system defined label for the volume.
+ * @param path the filesystem path for the volume.
+ * @param major the major number of the device.
+ * @param minor the minor number of the device.
+ */
+ public void onMediaInserted(String label, String path, int major, int minor);
+
+ /**
+ * Called when media has been removed
+ * @param label the system defined label for the volume.
+ * @param path the filesystem path for the volume.
+ * @param major the major number of the device.
+ * @param minor the minor number of the device.
+ * @param clean the media was removed cleanly.
+ */
+ public void onMediaRemoved(String label, String path, int major, int minor, boolean clean);
+
+ /**
+ * Called when a volume has changed state
+ * @param label the system defined label for the volume.
+ * @param path the filesystem path for the volume.
+ * @param oldState the old state as returned by {@link android.os.Environment#getExternalStorageState()}.
+ * @param newState the old state as returned by {@link android.os.Environment#getExternalStorageState()}.
+ */
+ public void onVolumeStateChanged(String label, String path, String oldState, String newState);
+}
diff --git a/core/java/android/storage/StorageManager.java b/core/java/android/storage/StorageManager.java
new file mode 100644
index 000000000000..dd8bd6369982
--- /dev/null
+++ b/core/java/android/storage/StorageManager.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 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.
+ * 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.storage;
+
+import android.content.Context;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.Parcelable;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.Handler;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.os.IMountService;
+import android.os.IMountServiceListener;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Class that lets you access the device's storage management functions. Get an instance of this
+ * class by calling {@link android.content.Context#getSystemService(java.lang.String)
+ * Context.getSystemService()} with an argument of {@link android.content.Context#STORAGE_SERVICE}.
+ */
+public class StorageManager
+{
+ private static final String TAG = "StorageManager";
+
+ /*
+ * Our internal MountService binder reference
+ */
+ private IMountService mMountService;
+
+ /*
+ * The looper target for callbacks
+ */
+ Looper mTgtLooper;
+
+ /*
+ * Target listener for binder callbacks
+ */
+ private MountServiceBinderListener mBinderListener;
+
+ /*
+ * *static* list of our listeners
+ */
+ static final ArrayList<ListenerDelegate> sListeners = new ArrayList<ListenerDelegate>();
+
+ private class MountServiceBinderListener extends IMountServiceListener.Stub {
+ public void onShareAvailabilityChanged(String method, boolean available) {
+ final int size = sListeners.size();
+ for (int i = 0; i < size; i++) {
+ sListeners.get(i).sendShareAvailabilityChanged(method, available);
+ }
+ }
+
+ public void onMediaInserted(String label, String path, int major, int minor) {
+ final int size = sListeners.size();
+ for (int i = 0; i < size; i++) {
+ sListeners.get(i).sendMediaInserted(label, path, major, minor);
+ }
+ }
+
+ public void onMediaRemoved(String label, String path, int major, int minor, boolean clean) {
+ final int size = sListeners.size();
+ for (int i = 0; i < size; i++) {
+ sListeners.get(i).sendMediaRemoved(label, path, major, minor, clean);
+ }
+ }
+
+ public void onVolumeStateChanged(String label, String path, String oldState, String newState) {
+ final int size = sListeners.size();
+ for (int i = 0; i < size; i++) {
+ sListeners.get(i).sendVolumeStateChanged(label, path, oldState, newState);
+ }
+ }
+ }
+
+ /**
+ * Private base class for messages sent between the callback thread
+ * and the target looper handler
+ */
+ private class StorageEvent {
+ public static final int EVENT_SHARE_AVAILABILITY_CHANGED = 1;
+ public static final int EVENT_MEDIA_INSERTED = 2;
+ public static final int EVENT_MEDIA_REMOVED = 3;
+ public static final int EVENT_VOLUME_STATE_CHANGED = 4;
+
+ private Message mMessage;
+
+ public StorageEvent(int what) {
+ mMessage = Message.obtain();
+ mMessage.what = what;
+ mMessage.obj = this;
+ }
+
+ public Message getMessage() {
+ return mMessage;
+ }
+ }
+
+ /**
+ * Message sent on a share availability change.
+ */
+ private class ShareAvailabilityChangedStorageEvent extends StorageEvent {
+ public String method;
+ public boolean available;
+
+ public ShareAvailabilityChangedStorageEvent(String m, boolean a) {
+ super(EVENT_SHARE_AVAILABILITY_CHANGED);
+ method = m;
+ available = a;
+ }
+ }
+
+ /**
+ * Message sent on media insertion
+ */
+ private class MediaInsertedStorageEvent extends StorageEvent {
+ public String label;
+ public String path;
+ public int major;
+ public int minor;
+
+ public MediaInsertedStorageEvent(String l, String p, int maj, int min) {
+ super(EVENT_MEDIA_INSERTED);
+ label = l;
+ path = p;
+ major = maj;
+ minor = min;
+ }
+ }
+
+ /**
+ * Message sent on media removal
+ */
+ private class MediaRemovedStorageEvent extends StorageEvent {
+ public String label;
+ public String path;
+ public int major;
+ public int minor;
+ public boolean clean;
+
+ public MediaRemovedStorageEvent(String l, String p, int maj, int min, boolean c) {
+ super(EVENT_MEDIA_REMOVED);
+ label = l;
+ path = p;
+ major = maj;
+ minor = min;
+ clean = c;
+ }
+ }
+
+ /**
+ * Message sent on volume state change
+ */
+ private class VolumeStateChangedStorageEvent extends StorageEvent {
+ public String label;
+ public String path;
+ public String oldState;
+ public String newState;
+
+ public VolumeStateChangedStorageEvent(String l, String p, String oldS, String newS) {
+ super(EVENT_VOLUME_STATE_CHANGED);
+ label = l;
+ path = p;
+ oldState = oldS;
+ newState = newS;
+ }
+ }
+
+ /**
+ * Private class containing sender and receiver code for StorageEvents
+ */
+ private class ListenerDelegate {
+ final StorageEventListener mStorageEventListener;
+ private final Handler mHandler;
+
+ ListenerDelegate(StorageEventListener listener) {
+ mStorageEventListener = listener;
+ mHandler = new Handler(mTgtLooper) {
+ @Override
+ public void handleMessage(Message msg) {
+ StorageEvent e = (StorageEvent) msg.obj;
+
+ if (msg.what == StorageEvent.EVENT_SHARE_AVAILABILITY_CHANGED) {
+ ShareAvailabilityChangedStorageEvent ev = (ShareAvailabilityChangedStorageEvent) e;
+ mStorageEventListener.onShareAvailabilityChanged(ev.method, ev.available);
+ } else if (msg.what == StorageEvent.EVENT_MEDIA_INSERTED) {
+ MediaInsertedStorageEvent ev = (MediaInsertedStorageEvent) e;
+ mStorageEventListener.onMediaInserted(ev.label, ev.path, ev.major, ev.minor);
+ } else if (msg.what == StorageEvent.EVENT_MEDIA_REMOVED) {
+ MediaRemovedStorageEvent ev = (MediaRemovedStorageEvent) e;
+ mStorageEventListener.onMediaRemoved(ev.label, ev.path, ev.major, ev.minor, ev.clean);
+ } else if (msg.what == StorageEvent.EVENT_VOLUME_STATE_CHANGED) {
+ VolumeStateChangedStorageEvent ev = (VolumeStateChangedStorageEvent) e;
+ mStorageEventListener.onVolumeStateChanged(ev.label, ev.path, ev.oldState, ev.newState);
+ } else {
+ Log.e(TAG, "Unsupported event " + msg.what);
+ }
+ }
+ };
+ }
+
+ StorageEventListener getListener() {
+ return mStorageEventListener;
+ }
+
+ void sendShareAvailabilityChanged(String method, boolean available) {
+ ShareAvailabilityChangedStorageEvent e = new ShareAvailabilityChangedStorageEvent(method, available);
+ mHandler.sendMessage(e.getMessage());
+ }
+
+ void sendMediaInserted(String label, String path, int major, int minor) {
+ MediaInsertedStorageEvent e = new MediaInsertedStorageEvent(label, path, major, minor);
+ mHandler.sendMessage(e.getMessage());
+ }
+
+ void sendMediaRemoved(String label, String path, int major, int minor, boolean clean) {
+ MediaRemovedStorageEvent e = new MediaRemovedStorageEvent(label, path, major, minor, clean);
+ mHandler.sendMessage(e.getMessage());
+ }
+
+ void sendVolumeStateChanged(String label, String path, String oldState, String newState) {
+ VolumeStateChangedStorageEvent e = new VolumeStateChangedStorageEvent(label, path, oldState, newState);
+ mHandler.sendMessage(e.getMessage());
+ }
+ }
+
+ /**
+ * {@hide}
+ */
+ public StorageManager(Looper tgtLooper) throws RemoteException {
+ mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
+ mTgtLooper = tgtLooper;
+ mBinderListener = new MountServiceBinderListener();
+ mMountService.registerListener(mBinderListener);
+ }
+
+
+ /**
+ * Registers a {@link android.storage.StorageEventListener StorageEventListener}.
+ *
+ * @param listener A {@link android.storage.StorageEventListener StorageEventListener} object.
+ *
+ */
+ public void registerListener(StorageEventListener listener) {
+ if (listener == null) {
+ return;
+ }
+
+ synchronized (sListeners) {
+ sListeners.add(new ListenerDelegate(listener));
+ }
+ }
+
+ /**
+ * Unregisters a {@link android.storage.StorageEventListener StorageEventListener}.
+ *
+ * @param listener A {@link android.storage.StorageEventListener StorageEventListener} object.
+ *
+ */
+ public void unregisterListener(StorageEventListener listener) {
+ if (listener == null) {
+ return;
+ }
+ synchronized (sListeners) {
+ final int size = sListeners.size();
+ for (int i=0 ; i<size ; i++) {
+ ListenerDelegate l = sListeners.get(i);
+ if (l.getListener() == listener) {
+ sListeners.remove(i);
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index 1e558be1ccc7..3c79200410f1 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -16,9 +16,10 @@
package android.view;
+import android.content.Context;
+import android.os.Build;
import android.os.Handler;
import android.os.Message;
-import android.content.Context;
/**
* Detects various gestures and events using the supplied {@link MotionEvent}s.
@@ -231,6 +232,13 @@ public class GestureDetector {
private float mLastMotionX;
private boolean mIsLongpressEnabled;
+
+ /**
+ * True if we are at a target API level of >= Froyo or the developer can
+ * explicitly set it. If true, input events with > 1 pointer will be ignored
+ * so we can work side by side with multitouch gesture detectors.
+ */
+ private boolean mIgnoreMultitouch;
/**
* Determines speed during touch scrolling
@@ -336,6 +344,26 @@ public class GestureDetector {
* @throws NullPointerException if {@code listener} is null.
*/
public GestureDetector(Context context, OnGestureListener listener, Handler handler) {
+ this(context, listener, handler, context != null &&
+ context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.FROYO);
+ }
+
+ /**
+ * Creates a GestureDetector with the supplied listener.
+ * You may only use this constructor from a UI thread (this is the usual situation).
+ * @see android.os.Handler#Handler()
+ *
+ * @param context the application's context
+ * @param listener the listener invoked for all the callbacks, this must
+ * not be null.
+ * @param handler the handler to use
+ * @param ignoreMultitouch whether events involving more than one pointer should
+ * be ignored.
+ *
+ * @throws NullPointerException if {@code listener} is null.
+ */
+ public GestureDetector(Context context, OnGestureListener listener, Handler handler,
+ boolean ignoreMultitouch) {
if (handler != null) {
mHandler = new GestureHandler(handler);
} else {
@@ -345,14 +373,15 @@ public class GestureDetector {
if (listener instanceof OnDoubleTapListener) {
setOnDoubleTapListener((OnDoubleTapListener) listener);
}
- init(context);
+ init(context, ignoreMultitouch);
}
- private void init(Context context) {
+ private void init(Context context, boolean ignoreMultitouch) {
if (mListener == null) {
throw new NullPointerException("OnGestureListener must not be null");
}
mIsLongpressEnabled = true;
+ mIgnoreMultitouch = ignoreMultitouch;
// Fallback to support pre-donuts releases
int touchSlop, doubleTapSlop;
@@ -425,7 +454,26 @@ public class GestureDetector {
boolean handled = false;
- switch (action) {
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_POINTER_DOWN:
+ if (mIgnoreMultitouch) {
+ // Multitouch event - abort.
+ cancel();
+ }
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ // Ending a multitouch gesture and going back to 1 finger
+ if (mIgnoreMultitouch && ev.getPointerCount() == 2) {
+ int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK)
+ >> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0;
+ mLastMotionX = ev.getX(id);
+ mLastMotionY = ev.getY(id);
+ mVelocityTracker.recycle();
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ break;
+
case MotionEvent.ACTION_DOWN:
if (mDoubleTapListener != null) {
boolean hadTapMessage = mHandler.hasMessages(TAP);
@@ -462,7 +510,7 @@ public class GestureDetector {
break;
case MotionEvent.ACTION_MOVE:
- if (mInLongPress) {
+ if (mInLongPress || (mIgnoreMultitouch && ev.getPointerCount() > 1)) {
break;
}
final float scrollX = mLastMotionX - x;
@@ -525,21 +573,24 @@ public class GestureDetector {
mHandler.removeMessages(LONG_PRESS);
break;
case MotionEvent.ACTION_CANCEL:
- mHandler.removeMessages(SHOW_PRESS);
- mHandler.removeMessages(LONG_PRESS);
- mHandler.removeMessages(TAP);
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- mIsDoubleTapping = false;
- mStillDown = false;
- if (mInLongPress) {
- mInLongPress = false;
- break;
- }
+ cancel();
}
return handled;
}
+ private void cancel() {
+ mHandler.removeMessages(SHOW_PRESS);
+ mHandler.removeMessages(LONG_PRESS);
+ mHandler.removeMessages(TAP);
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ mIsDoubleTapping = false;
+ mStillDown = false;
+ if (mInLongPress) {
+ mInLongPress = false;
+ }
+ }
+
private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp,
MotionEvent secondDown) {
if (!mAlwaysInBiggerTapRegion) {
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index f991df7b637f..8140d6188a84 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -18,7 +18,6 @@ package android.view;
import android.content.Context;
import android.util.DisplayMetrics;
-import android.util.Log;
/**
* Detects transformation gestures involving more than one pointer ("multitouch")
@@ -34,7 +33,6 @@ import android.util.Log;
* {@link #onTouchEvent(MotionEvent)}. The methods defined in your
* callback will be executed when the events occur.
* </ul>
- * @hide Pending API approval
*/
public class ScaleGestureDetector {
/**
@@ -45,9 +43,9 @@ public class ScaleGestureDetector {
*
* An application will receive events in the following order:
* <ul>
- * <li>One {@link OnScaleGestureListener#onScaleBegin()}
- * <li>Zero or more {@link OnScaleGestureListener#onScale()}
- * <li>One {@link OnScaleGestureListener#onTransformEnd()}
+ * <li>One {@link OnScaleGestureListener#onScaleBegin(ScaleGestureDetector)}
+ * <li>Zero or more {@link OnScaleGestureListener#onScale(ScaleGestureDetector)}
+ * <li>One {@link OnScaleGestureListener#onScaleEnd(ScaleGestureDetector)}
* </ul>
*/
public interface OnScaleGestureListener {
@@ -82,8 +80,7 @@ public class ScaleGestureDetector {
/**
* Responds to the end of a scale gesture. Reported by existing
- * pointers going up. If the end of a gesture would result in a fling,
- * {@link onTransformFling()} is called instead.
+ * pointers going up.
*
* Once a scale has ended, {@link ScaleGestureDetector#getFocusX()}
* and {@link ScaleGestureDetector#getFocusY()} will return the location
@@ -103,7 +100,7 @@ public class ScaleGestureDetector {
* {@link OnScaleGestureListener#onScaleBegin(ScaleGestureDetector)} return
* {@code true}.
*/
- public class SimpleOnScaleGestureListener implements OnScaleGestureListener {
+ public static class SimpleOnScaleGestureListener implements OnScaleGestureListener {
public boolean onScale(ScaleGestureDetector detector) {
return true;
@@ -373,7 +370,7 @@ public class ScaleGestureDetector {
* the two pointers forming the gesture.
* If a gesture is ending, the focal point is the location of the
* remaining pointer on the screen.
- * If {@link isInProgress()} would return false, the result of this
+ * If {@link #isInProgress()} would return false, the result of this
* function is undefined.
*
* @return X coordinate of the focal point in pixels.
@@ -388,7 +385,7 @@ public class ScaleGestureDetector {
* the two pointers forming the gesture.
* If a gesture is ending, the focal point is the location of the
* remaining pointer on the screen.
- * If {@link isInProgress()} would return false, the result of this
+ * If {@link #isInProgress()} would return false, the result of this
* function is undefined.
*
* @return Y coordinate of the focal point in pixels.
@@ -430,7 +427,7 @@ public class ScaleGestureDetector {
/**
* Return the scaling factor from the previous scale event to the current
* event. This value is defined as
- * ({@link getCurrentSpan()} / {@link getPreviousSpan()}).
+ * ({@link #getCurrentSpan()} / {@link #getPreviousSpan()}).
*
* @return The current scaling factor.
*/
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 31c9b08bdfe8..f5c465e6550e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4323,6 +4323,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*/
public void cancelLongPress() {
removeLongPressCallback();
+
+ /*
+ * The prepressed state handled by the tap callback is a display
+ * construct, but the tap callback will post a long press callback
+ * less its own timeout. Remove it here.
+ */
+ removeTapCallback();
}
/**
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 8e15f89e6325..0af31f05ab34 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -369,6 +369,12 @@ public interface WindowManager extends ViewManager {
*/
public int flags;
+ /** Window flag: as long as this window is visible to the user, allow
+ * the lock screen to activate while the screen is on.
+ * This can be used independently, or in combination with
+ * {@link #FLAG_KEEP_SCREEN_ON} and/or {@link #FLAG_SHOW_WHEN_LOCKED} */
+ public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001;
+
/** Window flag: everything behind this window will be dimmed.
* Use {@link #dimAmount} to control the amount of dim. */
public static final int FLAG_DIM_BEHIND = 0x00000002;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 21577bf920ae..7bc5cced2115 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -827,6 +827,12 @@ public interface WindowManagerPolicy {
public void systemReady();
/**
+ * Called when userActivity is signalled in the power manager.
+ * This is safe to call from any thread, with any window manager locks held or not.
+ */
+ public void userActivity();
+
+ /**
* Called when we have finished booting and can now display the home
* screen to the user. This wilWl happen after systemReady(), and at
* this point the display is active.
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index 22dca3a85210..87cab3cf2727 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -30,6 +30,8 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Map;
+import com.android.common.HttpDateTime;
+
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
@@ -52,6 +54,7 @@ public final class CacheManager {
private static final String NO_STORE = "no-store";
private static final String NO_CACHE = "no-cache";
private static final String MAX_AGE = "max-age";
+ private static final String MANIFEST_MIME = "text/cache-manifest";
private static long CACHE_THRESHOLD = 6 * 1024 * 1024;
private static long CACHE_TRIM_AMOUNT = 2 * 1024 * 1024;
@@ -658,6 +661,15 @@ public final class CacheManager {
// if the contentLength is already larger than CACHE_MAX_SIZE, skip it
if (headers.getContentLength() > CACHE_MAX_SIZE) return null;
+ // The HTML 5 spec, section 6.9.4, step 7.3 of the application cache
+ // process states that HTTP caching rules are ignored for the
+ // purposes of the application cache download process.
+ // At this point we can't tell that if a file is part of this process,
+ // except for the manifest, which has its own mimeType.
+ // TODO: work out a way to distinguish all responses that are part of
+ // the application download process and skip them.
+ if (MANIFEST_MIME.equals(mimeType)) return null;
+
// TODO: if authenticated or secure, return null
CacheResult ret = new CacheResult();
ret.httpStatusCode = statusCode;
diff --git a/core/java/android/webkit/ContentLoader.java b/core/java/android/webkit/ContentLoader.java
index 19aa087c49e6..5eb54b0368a6 100644
--- a/core/java/android/webkit/ContentLoader.java
+++ b/core/java/android/webkit/ContentLoader.java
@@ -31,7 +31,6 @@ import java.io.FileInputStream;
class ContentLoader extends StreamLoader {
private String mUrl;
- private Context mContext;
private String mContentType;
/**
@@ -40,11 +39,9 @@ class ContentLoader extends StreamLoader {
* @param rawUrl "content:" url pointing to content to be loaded. This url
* is the same url passed in to the WebView.
* @param loadListener LoadListener to pass the content to
- * @param context Context to use to access the asset.
*/
- ContentLoader(String rawUrl, LoadListener loadListener, Context context) {
+ ContentLoader(String rawUrl, LoadListener loadListener) {
super(loadListener);
- mContext = context;
/* strip off mimetype */
int mimeIndex = rawUrl.lastIndexOf('?');
@@ -81,7 +78,7 @@ class ContentLoader extends StreamLoader {
try {
mDataStream = mContext.getContentResolver().openInputStream(uri);
- mHandler.status(1, 1, 0, "OK");
+ mHandler.status(1, 1, 200, "OK");
} catch (java.io.FileNotFoundException ex) {
mHandler.error(EventHandler.FILE_NOT_FOUND_ERROR, errString(ex));
return false;
@@ -112,11 +109,9 @@ class ContentLoader extends StreamLoader {
*
* @param url "content:" url pointing to content to be loaded
* @param loadListener LoadListener to pass the content to
- * @param context Context to use to access the asset.
*/
- public static void requestUrl(String url, LoadListener loadListener,
- Context context) {
- ContentLoader loader = new ContentLoader(url, loadListener, context);
+ public static void requestUrl(String url, LoadListener loadListener) {
+ ContentLoader loader = new ContentLoader(url, loadListener);
loader.load();
}
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index fca591f4fb7a..94bedde9c8c0 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -20,6 +20,8 @@ import android.net.ParseException;
import android.net.WebAddress;
import android.util.Log;
+import com.android.common.HttpDateTime;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
diff --git a/core/java/android/webkit/DataLoader.java b/core/java/android/webkit/DataLoader.java
index 6c5d10dc7049..2a68a5d85fc5 100644
--- a/core/java/android/webkit/DataLoader.java
+++ b/core/java/android/webkit/DataLoader.java
@@ -16,6 +16,10 @@
package android.webkit;
+import android.net.http.EventHandler;
+
+import com.android.internal.R;
+
import java.io.ByteArrayInputStream;
import org.apache.harmony.luni.util.Base64;
@@ -49,14 +53,22 @@ class DataLoader extends StreamLoader {
} else {
data = url.getBytes();
}
- mDataStream = new ByteArrayInputStream(data);
- mContentLength = data.length;
+ if (data != null) {
+ mDataStream = new ByteArrayInputStream(data);
+ mContentLength = data.length;
+ }
}
@Override
protected boolean setupStreamAndSendStatus() {
- mHandler.status(1, 1, 0, "OK");
- return true;
+ if (mDataStream != null) {
+ mHandler.status(1, 1, 200, "OK");
+ return true;
+ } else {
+ mHandler.error(EventHandler.ERROR,
+ mContext.getString(R.string.httpError));
+ return false;
+ }
}
@Override
diff --git a/core/java/android/webkit/FileLoader.java b/core/java/android/webkit/FileLoader.java
index 974ccbf4ac59..e856cdea372c 100644
--- a/core/java/android/webkit/FileLoader.java
+++ b/core/java/android/webkit/FileLoader.java
@@ -38,7 +38,6 @@ import java.lang.reflect.Field;
class FileLoader extends StreamLoader {
private String mPath; // Full path to the file to load
- private Context mContext; // Application context, used for asset/res loads
private int mType; // Indicates the type of the load
private boolean mAllowFileAccess; // Allow/block file system access
@@ -57,16 +56,14 @@ class FileLoader extends StreamLoader {
*
* @param url Full file url pointing to content to be loaded
* @param loadListener LoadListener to pass the content to
- * @param context Context to use to access the asset.
* @param asset true if url points to an asset.
* @param allowFileAccess true if this WebView is allowed to access files
* on the file system.
*/
- FileLoader(String url, LoadListener loadListener, Context context,
- int type, boolean allowFileAccess) {
+ FileLoader(String url, LoadListener loadListener, int type,
+ boolean allowFileAccess) {
super(loadListener);
mType = type;
- mContext = context;
mAllowFileAccess = allowFileAccess;
// clean the Url
@@ -174,7 +171,7 @@ class FileLoader extends StreamLoader {
mDataStream = new FileInputStream(mPath);
mContentLength = (new File(mPath)).length();
}
- mHandler.status(1, 1, 0, "OK");
+ mHandler.status(1, 1, 200, "OK");
} catch (java.io.FileNotFoundException ex) {
mHandler.error(EventHandler.FILE_NOT_FOUND_ERROR, errString(ex));
@@ -198,14 +195,13 @@ class FileLoader extends StreamLoader {
*
* @param url Full file url pointing to content to be loaded
* @param loadListener LoadListener to pass the content to
- * @param context Context to use to access the asset.
* @param asset true if url points to an asset.
* @param allowFileAccess true if this FileLoader can load files from the
* file system.
*/
public static void requestUrl(String url, LoadListener loadListener,
- Context context, int type, boolean allowFileAccess) {
- FileLoader loader = new FileLoader(url, loadListener, context, type,
+ int type, boolean allowFileAccess) {
+ FileLoader loader = new FileLoader(url, loadListener, type,
allowFileAccess);
loader.load();
}
diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java
index 51f60c39a9b5..58eca38edae2 100644
--- a/core/java/android/webkit/FrameLoader.java
+++ b/core/java/android/webkit/FrameLoader.java
@@ -141,22 +141,21 @@ class FrameLoader {
return true;
}
if (URLUtil.isAssetUrl(url)) {
- FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
- FileLoader.TYPE_ASSET, true);
+ FileLoader.requestUrl(url, loadListener, FileLoader.TYPE_ASSET,
+ true);
return true;
} else if (URLUtil.isResourceUrl(url)) {
- FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
- FileLoader.TYPE_RES, true);
+ FileLoader.requestUrl(url, loadListener, FileLoader.TYPE_RES,
+ true);
return true;
} else if (URLUtil.isFileUrl(url)) {
- FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
- FileLoader.TYPE_FILE, settings.getAllowFileAccess());
+ FileLoader.requestUrl(url, loadListener, FileLoader.TYPE_FILE,
+ settings.getAllowFileAccess());
return true;
} else if (URLUtil.isContentUrl(url)) {
// Send the raw url to the ContentLoader because it will do a
// permission check and the url has to match..
- ContentLoader.requestUrl(loadListener.url(), loadListener,
- loadListener.getContext());
+ ContentLoader.requestUrl(loadListener.url(), loadListener);
return true;
} else if (URLUtil.isDataUrl(url)) {
DataLoader.requestUrl(url, loadListener);
diff --git a/core/java/android/webkit/JsResult.java b/core/java/android/webkit/JsResult.java
index 0c86e0a2fc2a..e61ab216e3c4 100644
--- a/core/java/android/webkit/JsResult.java
+++ b/core/java/android/webkit/JsResult.java
@@ -26,7 +26,10 @@ public class JsResult {
private boolean mTriedToNotifyBeforeReady;
// This is a basic result of a confirm or prompt dialog.
protected boolean mResult;
- // This is the caller of the prompt and is the object that is waiting.
+ /**
+ * This is the caller of the prompt and is the object that is waiting.
+ * @hide
+ */
protected final CallbackProxy mProxy;
// This is the default value of the result.
private final boolean mDefaultValue;
diff --git a/core/java/android/webkit/StreamLoader.java b/core/java/android/webkit/StreamLoader.java
index 623ff2958714..ce26268c72a1 100644
--- a/core/java/android/webkit/StreamLoader.java
+++ b/core/java/android/webkit/StreamLoader.java
@@ -16,6 +16,7 @@
package android.webkit;
+import android.content.Context;
import android.net.http.EventHandler;
import android.net.http.Headers;
import android.os.Handler;
@@ -52,7 +53,8 @@ abstract class StreamLoader extends Handler {
private static final int MSG_DATA = 102; // Send data to loader
private static final int MSG_END = 103; // Send endData to loader
- protected LoadListener mHandler; // loader class
+ protected final Context mContext;
+ protected final LoadListener mHandler; // loader class
protected InputStream mDataStream; // stream to read data from
protected long mContentLength; // content length of data
private byte [] mData; // buffer to pass data to loader with.
@@ -66,6 +68,7 @@ abstract class StreamLoader extends Handler {
*/
StreamLoader(LoadListener loadlistener) {
mHandler = loadlistener;
+ mContext = loadlistener.getContext();
}
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index d018af05137e..6627973517e2 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -342,6 +342,7 @@ public class WebView extends AbsoluteLayout
* choice. Maybe make this in the buildspec later.
*/
private static final int TOUCH_SENT_INTERVAL = 50;
+ private int mCurrentTouchInterval = TOUCH_SENT_INTERVAL;
/**
* Helper class to get velocity for fling
@@ -464,7 +465,7 @@ public class WebView extends AbsoluteLayout
private int mHeldMotionless;
// whether support multi-touch
- private static boolean mSupportMultiTouch;
+ private boolean mSupportMultiTouch;
// use the framework's ScaleGestureDetector to handle multi-touch
private ScaleGestureDetector mScaleDetector;
// minimum scale change during multi-touch zoom
@@ -499,7 +500,7 @@ public class WebView extends AbsoluteLayout
static final int UPDATE_TEXT_ENTRY_MSG_ID = 15;
static final int WEBCORE_INITIALIZED_MSG_ID = 16;
static final int UPDATE_TEXTFIELD_TEXT_MSG_ID = 17;
- static final int FIND_AGAIN = 18;
+ static final int UPDATE_ZOOM_RANGE = 18;
static final int MOVE_OUT_OF_PLUGIN = 19;
static final int CLEAR_TEXT_ENTRY = 20;
static final int UPDATE_TEXT_SELECTION_MSG_ID = 21;
@@ -517,6 +518,7 @@ public class WebView extends AbsoluteLayout
static final int IMMEDIATE_REPAINT_MSG_ID = 32;
static final int SET_ROOT_LAYER_MSG_ID = 33;
static final int RETURN_LABEL = 34;
+ static final int FIND_AGAIN = 35;
static final String[] HandlerDebugString = {
"REMEMBER_PASSWORD", // = 1;
@@ -536,7 +538,7 @@ public class WebView extends AbsoluteLayout
"UPDATE_TEXT_ENTRY_MSG_ID", // = 15;
"WEBCORE_INITIALIZED_MSG_ID", // = 16;
"UPDATE_TEXTFIELD_TEXT_MSG_ID", // = 17;
- "FIND_AGAIN", // = 18;
+ "UPDATE_ZOOM_RANGE", // = 18;
"MOVE_OUT_OF_PLUGIN", // = 19;
"CLEAR_TEXT_ENTRY", // = 20;
"UPDATE_TEXT_SELECTION_MSG_ID", // = 21;
@@ -552,7 +554,8 @@ public class WebView extends AbsoluteLayout
"DOM_FOCUS_CHANGED", // = 31;
"IMMEDIATE_REPAINT_MSG_ID", // = 32;
"SET_ROOT_LAYER_MSG_ID", // = 33;
- "RETURN_LABEL" // = 34;
+ "RETURN_LABEL", // = 34;
+ "FIND_AGAIN" // = 35;
};
// If the site doesn't use the viewport meta tag to specify the viewport,
@@ -3107,6 +3110,7 @@ public class WebView extends AbsoluteLayout
zoomScale = mZoomScale;
// set mZoomScale to be 0 as we have done animation
mZoomScale = 0;
+ WebViewCore.resumeUpdatePicture(mWebViewCore);
// call invalidate() again to draw with the final filters
invalidate();
if (mNeedToAdjustWebTextView) {
@@ -3490,6 +3494,17 @@ public class WebView extends AbsoluteLayout
mWebViewCore.sendMessage(EventHub.DUMP_RENDERTREE, toFile ? 1 : 0, 0);
}
+ /**
+ * Dump the V8 counters to standard output.
+ * Note that you need a build with V8 and WEBCORE_INSTRUMENTATION set to
+ * true. Otherwise, this will do nothing.
+ *
+ * @hide debug only
+ */
+ public void dumpV8Counters() {
+ mWebViewCore.sendMessage(EventHub.DUMP_V8COUNTERS);
+ }
+
// This is used to determine long press with the center key. Does not
// affect long press with the trackball/touch.
private boolean mGotCenterDown = false;
@@ -3950,8 +3965,9 @@ public class WebView extends AbsoluteLayout
super.onSizeChanged(w, h, ow, oh);
// Center zooming to the center of the screen.
if (mZoomScale == 0) { // unless we're already zooming
- mZoomCenterX = getViewWidth() * .5f;
- mZoomCenterY = getViewHeight() * .5f;
+ // To anchor at top left corner.
+ mZoomCenterX = 0;
+ mZoomCenterY = getVisibleTitleHeight();
mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
}
@@ -3994,7 +4010,6 @@ public class WebView extends AbsoluteLayout
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
-
sendOurVisibleRect();
}
@@ -4329,11 +4344,12 @@ public class WebView extends AbsoluteLayout
// pass the touch events from UI thread to WebCore thread
if (mForwardTouchEvents && (action != MotionEvent.ACTION_MOVE
- || eventTime - mLastSentTouchTime > TOUCH_SENT_INTERVAL)) {
+ || eventTime - mLastSentTouchTime > mCurrentTouchInterval)) {
WebViewCore.TouchEventData ted = new WebViewCore.TouchEventData();
ted.mAction = action;
ted.mX = viewToContentX((int) x + mScrollX);
ted.mY = viewToContentY((int) y + mScrollY);
+ ted.mEventTime = eventTime;
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
mLastSentTouchTime = eventTime;
}
@@ -4456,7 +4472,7 @@ public class WebView extends AbsoluteLayout
deltaX = 0;
deltaY = 0;
- WebViewCore.reducePriority(mWebViewCore);
+ WebViewCore.reducePriority();
if (!mDragFromTextInput) {
nativeHideCursor();
}
@@ -4597,6 +4613,7 @@ public class WebView extends AbsoluteLayout
ted.mAction = WebViewCore.ACTION_DOUBLETAP;
ted.mX = viewToContentX((int) x + mScrollX);
ted.mY = viewToContentY((int) y + mScrollY);
+ ted.mEventTime = eventTime;
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
} else if (mFullScreenHolder == null) {
doDoubleTap();
@@ -4619,7 +4636,7 @@ public class WebView extends AbsoluteLayout
|| computeVerticalScrollExtent() < computeVerticalScrollRange())) {
// we will not rewrite drag code here, but we
// will try fling if it applies.
- WebViewCore.reducePriority(mWebViewCore);
+ WebViewCore.reducePriority();
// fall through to TOUCH_DRAG_MODE
} else {
break;
@@ -4656,7 +4673,7 @@ public class WebView extends AbsoluteLayout
break;
}
mLastVelocity = 0;
- WebViewCore.resumePriority(mWebViewCore);
+ WebViewCore.resumePriority();
break;
case TOUCH_DRAG_START_MODE:
case TOUCH_DONE_MODE:
@@ -4705,7 +4722,7 @@ public class WebView extends AbsoluteLayout
mVelocityTracker = null;
}
if (mTouchMode == TOUCH_DRAG_MODE) {
- WebViewCore.resumePriority(mWebViewCore);
+ WebViewCore.resumePriority();
}
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
@@ -5031,7 +5048,7 @@ public class WebView extends AbsoluteLayout
vy = vy * 3 / 4;
}
if ((maxX == 0 && vy == 0) || (maxY == 0 && vx == 0)) {
- WebViewCore.resumePriority(mWebViewCore);
+ WebViewCore.resumePriority();
return;
}
float currentVelocity = mScroller.getCurrVelocity();
@@ -5088,6 +5105,7 @@ public class WebView extends AbsoluteLayout
mInvInitialZoomScale = 1.0f / oldScale;
mInvFinalZoomScale = 1.0f / mActualScale;
mZoomScale = mActualScale;
+ WebViewCore.pauseUpdatePicture(mWebViewCore);
invalidate();
return true;
} else {
@@ -5587,7 +5605,7 @@ public class WebView extends AbsoluteLayout
// exclude INVAL_RECT_MSG_ID since it is frequently output
if (DebugFlags.WEB_VIEW && msg.what != INVAL_RECT_MSG_ID) {
Log.v(LOGTAG, msg.what < REMEMBER_PASSWORD || msg.what
- > RETURN_LABEL ? Integer.toString(msg.what)
+ > FIND_AGAIN ? Integer.toString(msg.what)
: HandlerDebugString[msg.what - REMEMBER_PASSWORD]);
}
if (mWebViewCore == null) {
@@ -5635,6 +5653,7 @@ public class WebView extends AbsoluteLayout
ted.mAction = WebViewCore.ACTION_LONGPRESS;
ted.mX = viewToContentX((int) mLastTouchX + mScrollX);
ted.mY = viewToContentY((int) mLastTouchY + mScrollY);
+ ted.mEventTime = SystemClock.uptimeMillis();
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
} else if (mPreventDrag == PREVENT_DRAG_NO) {
mTouchMode = TOUCH_DONE_MODE;
@@ -5683,6 +5702,14 @@ public class WebView extends AbsoluteLayout
case SPAWN_SCROLL_TO_MSG_ID:
spawnContentScrollTo(msg.arg1, msg.arg2);
break;
+ case UPDATE_ZOOM_RANGE: {
+ WebViewCore.RestoreState restoreState
+ = (WebViewCore.RestoreState) msg.obj;
+ // mScrollX contains the new minPrefWidth
+ updateZoomRange(restoreState, getViewWidth(),
+ restoreState.mScrollX, false);
+ break;
+ }
case NEW_PICTURE_MSG_ID: {
WebSettings settings = mWebViewCore.getSettings();
// called for new content
@@ -5695,32 +5722,8 @@ public class WebView extends AbsoluteLayout
boolean hasRestoreState = restoreState != null;
if (hasRestoreState) {
mInZoomOverview = false;
- if (restoreState.mMinScale == 0) {
- if (restoreState.mMobileSite) {
- if (draw.mMinPrefWidth >
- Math.max(0, draw.mViewPoint.x)) {
- mMinZoomScale = (float) viewWidth
- / draw.mMinPrefWidth;
- mMinZoomScaleFixed = false;
- mInZoomOverview = useWideViewport &&
- settings.getLoadWithOverviewMode();
- } else {
- mMinZoomScale = restoreState.mDefaultScale;
- mMinZoomScaleFixed = true;
- }
- } else {
- mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
- mMinZoomScaleFixed = false;
- }
- } else {
- mMinZoomScale = restoreState.mMinScale;
- mMinZoomScaleFixed = true;
- }
- if (restoreState.mMaxScale == 0) {
- mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
- } else {
- mMaxZoomScale = restoreState.mMaxScale;
- }
+ updateZoomRange(restoreState, viewSize.x,
+ draw.mMinPrefWidth, true);
if (mInitialScaleInPercent > 0) {
setNewZoomScale(mInitialScaleInPercent / 100.0f,
mInitialScaleInPercent != mTextWrapScale * 100,
@@ -5918,7 +5921,7 @@ public class WebView extends AbsoluteLayout
}
break;
case RESUME_WEBCORE_PRIORITY:
- WebViewCore.resumePriority(mWebViewCore);
+ WebViewCore.resumePriority();
break;
case LONG_PRESS_CENTER:
@@ -6082,7 +6085,7 @@ public class WebView extends AbsoluteLayout
case SHOW_RECT_MSG_ID: {
WebViewCore.ShowRectData data = (WebViewCore.ShowRectData) msg.obj;
int x = mScrollX;
- int left = contentToViewDimension(data.mLeft);
+ int left = contentToViewX(data.mLeft);
int width = contentToViewDimension(data.mWidth);
int maxWidth = contentToViewDimension(data.mContentWidth);
int viewWidth = getViewWidth();
@@ -6093,21 +6096,29 @@ public class WebView extends AbsoluteLayout
x += (int) (left + data.mXPercentInDoc * width
- mScrollX - data.mXPercentInView * viewWidth);
}
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "showRectMsg=(left=" + left + ",width=" +
+ width + ",maxWidth=" + maxWidth +
+ ",viewWidth=" + viewWidth + ",x="
+ + x + ",xPercentInDoc=" + data.mXPercentInDoc +
+ ",xPercentInView=" + data.mXPercentInView+ ")");
+ }
// use the passing content width to cap x as the current
// mContentWidth may not be updated yet
x = Math.max(0,
(Math.min(maxWidth, x + viewWidth)) - viewWidth);
- int y = mScrollY;
- int top = contentToViewDimension(data.mTop);
+ int top = contentToViewY(data.mTop);
int height = contentToViewDimension(data.mHeight);
int maxHeight = contentToViewDimension(data.mContentHeight);
int viewHeight = getViewHeight();
- if (height < viewHeight) {
- // middle align
- y += top + height / 2 - mScrollY - viewHeight / 2;
- } else {
- y += (int) (top + data.mYPercentInDoc * height
- - mScrollY - data.mYPercentInView * viewHeight);
+ int y = (int) (top + data.mYPercentInDoc * height -
+ data.mYPercentInView * viewHeight);
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "showRectMsg=(top=" + top + ",height=" +
+ height + ",maxHeight=" + maxHeight +
+ ",viewHeight=" + viewHeight + ",y="
+ + y + ",yPercentInDoc=" + data.mYPercentInDoc +
+ ",yPercentInView=" + data.mYPercentInView+ ")");
}
// use the passing content height to cap y as the current
// mContentHeight may not be updated yet
@@ -6411,6 +6422,37 @@ public class WebView extends AbsoluteLayout
new InvokeListBox(array, enabledArray, selectedArray));
}
+ private void updateZoomRange(WebViewCore.RestoreState restoreState,
+ int viewWidth, int minPrefWidth, boolean updateZoomOverview) {
+ if (restoreState.mMinScale == 0) {
+ if (restoreState.mMobileSite) {
+ if (minPrefWidth > Math.max(0, viewWidth)) {
+ mMinZoomScale = (float) viewWidth / minPrefWidth;
+ mMinZoomScaleFixed = false;
+ if (updateZoomOverview) {
+ WebSettings settings = getSettings();
+ mInZoomOverview = settings.getUseWideViewPort() &&
+ settings.getLoadWithOverviewMode();
+ }
+ } else {
+ mMinZoomScale = restoreState.mDefaultScale;
+ mMinZoomScaleFixed = true;
+ }
+ } else {
+ mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
+ mMinZoomScaleFixed = false;
+ }
+ } else {
+ mMinZoomScale = restoreState.mMinScale;
+ mMinZoomScaleFixed = true;
+ }
+ if (restoreState.mMaxScale == 0) {
+ mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
+ } else {
+ mMaxZoomScale = restoreState.mMaxScale;
+ }
+ }
+
/*
* Request a dropdown menu for a listbox with single selection or a single
* <select> element.
@@ -6596,6 +6638,16 @@ public class WebView extends AbsoluteLayout
}
/**
+ * Set the time to wait between passing touches to WebCore. See also the
+ * TOUCH_SENT_INTERVAL member for further discussion.
+ *
+ * @hide This is only used by the DRT test application.
+ */
+ public void setTouchInterval(int interval) {
+ mCurrentTouchInterval = interval;
+ }
+
+ /**
* Update our cache with updatedText.
* @param updatedText The new text to put in our cache.
*/
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 1e21cb4ccaab..6e45e39e96ff 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -512,7 +512,7 @@ final class WebViewCore {
private native void nativeTouchUp(int touchGeneration,
int framePtr, int nodePtr, int x, int y);
- private native int nativeHandleTouchEvent(int action, int x, int y);
+ private native int nativeHandleTouchEvent(int action, int x, int y, long time);
private native void nativeUpdateFrameCache();
@@ -524,6 +524,8 @@ final class WebViewCore {
private native void nativeDumpNavTree();
+ private native void nativeDumpV8Counters();
+
private native void nativeSetJsFlags(String flags);
/**
@@ -729,6 +731,7 @@ final class WebViewCore {
int mAction;
int mX;
int mY;
+ long mEventTime;
}
static class GeolocationPermissionsData {
@@ -874,8 +877,9 @@ final class WebViewCore {
static final int DUMP_DOMTREE = 170;
static final int DUMP_RENDERTREE = 171;
static final int DUMP_NAVTREE = 172;
+ static final int DUMP_V8COUNTERS = 173;
- static final int SET_JS_FLAGS = 173;
+ static final int SET_JS_FLAGS = 174;
// Geolocation
static final int GEOLOCATION_PERMISSIONS_PROVIDE = 180;
@@ -1186,7 +1190,7 @@ final class WebViewCore {
mWebView.mPrivateHandler,
WebView.PREVENT_TOUCH_ID, ted.mAction,
nativeHandleTouchEvent(ted.mAction, ted.mX,
- ted.mY)).sendToTarget();
+ ted.mY, ted.mEventTime)).sendToTarget();
break;
}
@@ -1296,6 +1300,10 @@ final class WebViewCore {
nativeDumpNavTree();
break;
+ case DUMP_V8COUNTERS:
+ nativeDumpV8Counters();
+ break;
+
case SET_JS_FLAGS:
nativeSetJsFlags((String)msg.obj);
break;
@@ -1676,6 +1684,9 @@ final class WebViewCore {
// Used to avoid posting more than one split picture message.
private boolean mSplitPictureIsScheduled;
+ // Used to suspend drawing.
+ private boolean mDrawIsPaused;
+
// mRestoreState is set in didFirstLayout(), and reset in the next
// webkitDraw after passing it to the UI thread.
private RestoreState mRestoreState = null;
@@ -1788,7 +1799,7 @@ final class WebViewCore {
return result;
}
- static void reducePriority(WebViewCore core) {
+ static void reducePriority() {
// remove the pending REDUCE_PRIORITY and RESUME_PRIORITY messages
sWebCoreHandler.removeMessages(WebCoreThread.REDUCE_PRIORITY);
sWebCoreHandler.removeMessages(WebCoreThread.RESUME_PRIORITY);
@@ -1796,7 +1807,7 @@ final class WebViewCore {
.obtainMessage(WebCoreThread.REDUCE_PRIORITY));
}
- static void resumePriority(WebViewCore core) {
+ static void resumePriority() {
// remove the pending REDUCE_PRIORITY and RESUME_PRIORITY messages
sWebCoreHandler.removeMessages(WebCoreThread.REDUCE_PRIORITY);
sWebCoreHandler.removeMessages(WebCoreThread.RESUME_PRIORITY);
@@ -1814,6 +1825,33 @@ final class WebViewCore {
.obtainMessage(WebCoreThread.BLOCK_CACHE_TICKER));
}
+ static void pauseUpdatePicture(WebViewCore core) {
+ // Note: there is one possible failure mode. If pauseUpdatePicture() is
+ // called from UI thread while WEBKIT_DRAW is just pulled out of the
+ // queue in WebCore thread to be executed. Then update won't be blocked.
+ if (core != null) {
+ synchronized (core) {
+ core.mDrawIsPaused = true;
+ if (core.mDrawIsScheduled) {
+ core.mEventHub.removeMessages(EventHub.WEBKIT_DRAW);
+ }
+ }
+ }
+
+ }
+
+ static void resumeUpdatePicture(WebViewCore core) {
+ if (core != null) {
+ synchronized (core) {
+ core.mDrawIsPaused = false;
+ if (core.mDrawIsScheduled) {
+ core.mDrawIsScheduled = false;
+ core.contentDraw();
+ }
+ }
+ }
+ }
+
//////////////////////////////////////////////////////////////////////////
private void restoreState(int index) {
@@ -1842,6 +1880,7 @@ final class WebViewCore {
synchronized (this) {
if (mDrawIsScheduled) return;
mDrawIsScheduled = true;
+ if (mDrawIsPaused) return;
mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
}
}
@@ -2053,7 +2092,19 @@ final class WebViewCore {
}
// if mViewportWidth is 0, it means device-width, always update.
- if (mViewportWidth != 0 && !updateRestoreState) return;
+ if (mViewportWidth != 0 && !updateRestoreState) {
+ RestoreState restoreState = new RestoreState();
+ restoreState.mMinScale = mViewportMinimumScale / 100.0f;
+ restoreState.mMaxScale = mViewportMaximumScale / 100.0f;
+ restoreState.mDefaultScale = adjust;
+ // as mViewportWidth is not 0, it is not mobile site.
+ restoreState.mMobileSite = false;
+ // for non-mobile site, we don't need minPrefWidth, set it as 0
+ restoreState.mScrollX = 0;
+ Message.obtain(mWebView.mPrivateHandler,
+ WebView.UPDATE_ZOOM_RANGE, restoreState).sendToTarget();
+ return;
+ }
// now notify webview
// webViewWidth refers to the width in the view system
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 3a4b92dd5028..1cc1c265b94f 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -16,6 +16,8 @@
package android.widget;
+import com.android.internal.R;
+
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
@@ -30,6 +32,7 @@ import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
@@ -41,14 +44,12 @@ import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
import android.view.inputmethod.InputMethodManager;
-import android.view.ContextMenu.ContextMenuInfo;
-
-import com.android.internal.R;
import java.util.ArrayList;
import java.util.List;
@@ -120,13 +121,24 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* Indicates the touch gesture is a scroll
*/
static final int TOUCH_MODE_SCROLL = 3;
-
+
/**
* Indicates the view is in the process of being flung
*/
static final int TOUCH_MODE_FLING = 4;
/**
+ * Indicates the touch gesture is an overscroll - a scroll beyond the beginning or end.
+ */
+ static final int TOUCH_MODE_OVERSCROLL = 5;
+
+ /**
+ * Indicates the view is being flung outside of normal content bounds
+ * and will spring back.
+ */
+ static final int TOUCH_MODE_OVERFLING = 6;
+
+ /**
* Regular layout - usually an unsolicited layout from the view system
*/
static final int LAYOUT_NORMAL = 0;
@@ -437,6 +449,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
private int mMaximumVelocity;
final boolean[] mIsScrap = new boolean[1];
+
+ // True when the popup should be hidden because of a call to
+ // dispatchDisplayHint()
+ private boolean mPopupHidden;
/**
* Interface definition for a callback to be invoked when the list or grid
@@ -1915,6 +1931,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mLayoutMode = LAYOUT_NORMAL;
layoutChildren();
}
+ } else {
+ int touchMode = mTouchMode;
+ if (touchMode == TOUCH_MODE_OVERSCROLL || touchMode == TOUCH_MODE_OVERFLING) {
+ mScrollY = 0;
+ if (mFlingRunnable != null) {
+ mFlingRunnable.endFling();
+ }
+ }
}
}
@@ -1947,43 +1971,56 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
switch (action) {
case MotionEvent.ACTION_DOWN: {
- int motionPosition = pointToPosition(x, y);
- if (!mDataChanged) {
- if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
- && (getAdapter().isEnabled(motionPosition))) {
- // User clicked on an actual view (and was not stopping a fling). It might be a
- // click or a scroll. Assume it is a click until proven otherwise
- mTouchMode = TOUCH_MODE_DOWN;
- // FIXME Debounce
- if (mPendingCheckForTap == null) {
- mPendingCheckForTap = new CheckForTap();
- }
- postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
- } else {
- if (ev.getEdgeFlags() != 0 && motionPosition < 0) {
- // If we couldn't find a view to click on, but the down event was touching
- // the edge, we will bail out and try again. This allows the edge correcting
- // code in ViewRoot to try to find a nearby view to select
- return false;
+ switch (mTouchMode) {
+ case TOUCH_MODE_OVERFLING: {
+ mFlingRunnable.endFling();
+ mTouchMode = TOUCH_MODE_OVERSCROLL;
+ mLastY = y;
+ mMotionCorrection = 0;
+ break;
+ }
+
+ default: {
+ int motionPosition = pointToPosition(x, y);
+ if (!mDataChanged) {
+ if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
+ && (getAdapter().isEnabled(motionPosition))) {
+ // User clicked on an actual view (and was not stopping a fling). It might be a
+ // click or a scroll. Assume it is a click until proven otherwise
+ mTouchMode = TOUCH_MODE_DOWN;
+ // FIXME Debounce
+ if (mPendingCheckForTap == null) {
+ mPendingCheckForTap = new CheckForTap();
+ }
+ postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
+ } else {
+ if (ev.getEdgeFlags() != 0 && motionPosition < 0) {
+ // If we couldn't find a view to click on, but the down event was touching
+ // the edge, we will bail out and try again. This allows the edge correcting
+ // code in ViewRoot to try to find a nearby view to select
+ return false;
+ }
+ // User clicked on whitespace, or stopped a fling. It is a scroll.
+ createScrollingCache();
+ mTouchMode = TOUCH_MODE_SCROLL;
+ mMotionCorrection = 0;
+ motionPosition = findMotionRow(y);
+ reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
}
- // User clicked on whitespace, or stopped a fling. It is a scroll.
- createScrollingCache();
- mTouchMode = TOUCH_MODE_SCROLL;
- mMotionCorrection = 0;
- motionPosition = findMotionRow(y);
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
}
- }
- if (motionPosition >= 0) {
- // Remember where the motion event started
- v = getChildAt(motionPosition - mFirstPosition);
- mMotionViewOriginalTop = v.getTop();
- mMotionX = x;
- mMotionY = y;
- mMotionPosition = motionPosition;
+ if (motionPosition >= 0) {
+ // Remember where the motion event started
+ v = getChildAt(motionPosition - mFirstPosition);
+ mMotionViewOriginalTop = v.getTop();
+ mMotionX = x;
+ mMotionY = y;
+ mMotionPosition = motionPosition;
+ }
+ mLastY = Integer.MIN_VALUE;
+ break;
+ }
}
- mLastY = Integer.MIN_VALUE;
break;
}
@@ -2008,17 +2045,61 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (y != mLastY) {
deltaY -= mMotionCorrection;
int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY;
+
+ int motionViewPrevTop = 0;
+ View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
+ if (motionView != null) {
+ motionViewPrevTop = motionView.getTop();
+ }
// No need to do all this work if we're not going to move anyway
if (incrementalDeltaY != 0) {
trackMotionScroll(deltaY, incrementalDeltaY);
}
// Check to see if we have bumped into the scroll limit
- View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
+ motionView = this.getChildAt(mMotionPosition - mFirstPosition);
if (motionView != null) {
// Check if the top of the motion view is where it is
// supposed to be
- if (motionView.getTop() != mMotionViewNewTop) {
+ final int motionViewRealTop = motionView.getTop();
+ final int motionViewNewTop = mMotionViewNewTop;
+ if (motionViewRealTop != motionViewNewTop) {
+ // Apply overscroll
+
+ mScrollY -= incrementalDeltaY - (motionViewRealTop - motionViewPrevTop);
+ mTouchMode = TOUCH_MODE_OVERSCROLL;
+ invalidate();
+ }
+ }
+ mLastY = y;
+ }
+ break;
+
+ case TOUCH_MODE_OVERSCROLL:
+ if (y != mLastY) {
+ deltaY -= mMotionCorrection;
+ int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY;
+
+ final int oldScroll = mScrollY;
+ final int newScroll = oldScroll - incrementalDeltaY;
+
+ if ((oldScroll >= 0 && newScroll <= 0) ||
+ (oldScroll <= 0 && newScroll >= 0)) {
+ // Coming back to 'real' list scrolling
+ incrementalDeltaY = -newScroll;
+ mScrollY = 0;
+
+ // No need to do all this work if we're not going to move anyway
+ if (incrementalDeltaY != 0) {
+ trackMotionScroll(incrementalDeltaY, incrementalDeltaY);
+ }
+
+ // Check to see if we are back in
+ View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
+ if (motionView != null) {
+ int topOffset = motionView.getTop() - mMotionViewNewTop;
+ mTouchMode = TOUCH_MODE_SCROLL;
+
// We did not scroll the full amount. Treat this essentially like the
// start of a new touch scroll
final int motionPosition = findMotionRow(y);
@@ -2029,6 +2110,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mMotionY = y;
mMotionPosition = motionPosition;
}
+ } else {
+ mScrollY -= incrementalDeltaY;
+ invalidate();
}
mLastY = y;
}
@@ -2120,6 +2204,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mFlingRunnable = new FlingRunnable();
}
reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
+
mFlingRunnable.start(-initialVelocity);
} else {
mTouchMode = TOUCH_MODE_REST;
@@ -2130,6 +2215,24 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mTouchMode = TOUCH_MODE_REST;
reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
}
+ break;
+
+ case TOUCH_MODE_OVERSCROLL:
+ if (mFlingRunnable == null) {
+ mFlingRunnable = new FlingRunnable();
+ }
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ final int initialVelocity = (int) velocityTracker.getYVelocity();
+
+ reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
+ if (Math.abs(initialVelocity) > mMinimumVelocity) {
+ mFlingRunnable.startOverfling(-initialVelocity);
+ } else {
+ mFlingRunnable.startSpringback();
+ }
+
+ break;
}
setPressed(false);
@@ -2157,25 +2260,38 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
case MotionEvent.ACTION_CANCEL: {
- mTouchMode = TOUCH_MODE_REST;
- setPressed(false);
- View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
- if (motionView != null) {
- motionView.setPressed(false);
- }
- clearScrollingCache();
+ switch (mTouchMode) {
+ case TOUCH_MODE_OVERSCROLL:
+ if (mFlingRunnable == null) {
+ mFlingRunnable = new FlingRunnable();
+ }
+ mFlingRunnable.startSpringback();
+ break;
+
+ case TOUCH_MODE_OVERFLING:
+ // Do nothing - let it play out.
+ break;
+
+ default:
+ mTouchMode = TOUCH_MODE_REST;
+ setPressed(false);
+ View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
+ if (motionView != null) {
+ motionView.setPressed(false);
+ }
+ clearScrollingCache();
- final Handler handler = getHandler();
- if (handler != null) {
- handler.removeCallbacks(mPendingCheckForLongPress);
- }
+ final Handler handler = getHandler();
+ if (handler != null) {
+ handler.removeCallbacks(mPendingCheckForLongPress);
+ }
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
}
}
-
}
return true;
@@ -2205,8 +2321,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
switch (action) {
case MotionEvent.ACTION_DOWN: {
+ int touchMode = mTouchMode;
+ if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) {
+ return true;
+ }
+
int motionPosition = findMotionRow(y);
- if (mTouchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
+ if (touchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
// User clicked on an actual view (and was not stopping a fling).
// Remember where the motion event started
v = getChildAt(motionPosition - mFirstPosition);
@@ -2218,7 +2339,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
clearScrollingCache();
}
mLastY = Integer.MIN_VALUE;
- if (mTouchMode == TOUCH_MODE_FLING) {
+ if (touchMode == TOUCH_MODE_FLING) {
return true;
}
break;
@@ -2293,18 +2414,18 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
/**
* Tracks the decay of a fling scroll
*/
- private Scroller mScroller;
+ private OverScroller mScroller;
/**
* Y value reported by mScroller on the previous fling
*/
private int mLastFlingY;
- public FlingRunnable() {
- mScroller = new Scroller(getContext());
+ FlingRunnable() {
+ mScroller = new OverScroller(getContext());
}
- public void start(int initialVelocity) {
+ void start(int initialVelocity) {
int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0;
mLastFlingY = initialY;
mScroller.fling(0, initialY, 0, initialVelocity,
@@ -2319,77 +2440,117 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
}
-
+
+ void startSpringback() {
+ if (mScroller.springback(0, mScrollY, 0, 0, 0, 0)) {
+ mTouchMode = TOUCH_MODE_OVERFLING;
+ invalidate();
+ post(this);
+ }
+ }
+
+ void startOverfling(int initialVelocity) {
+ mScroller.fling(0, mScrollY, 0, initialVelocity, 0, 0, 0, 0, 0, getHeight());
+ mTouchMode = TOUCH_MODE_OVERFLING;
+ invalidate();
+ post(this);
+ }
+
private void endFling() {
mTouchMode = TOUCH_MODE_REST;
reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
clearScrollingCache();
+ removeCallbacks(this);
}
public void run() {
- if (mTouchMode != TOUCH_MODE_FLING) {
- return;
- }
-
- if (mItemCount == 0 || getChildCount() == 0) {
- endFling();
+ switch (mTouchMode) {
+ default:
return;
- }
-
- final Scroller scroller = mScroller;
- boolean more = scroller.computeScrollOffset();
- final int y = scroller.getCurrY();
+
+ case TOUCH_MODE_FLING: {
+ if (mItemCount == 0 || getChildCount() == 0) {
+ endFling();
+ return;
+ }
- // Flip sign to convert finger direction to list items direction
- // (e.g. finger moving down means list is moving towards the top)
- int delta = mLastFlingY - y;
+ final OverScroller scroller = mScroller;
+ boolean more = scroller.computeScrollOffset();
+ final int y = scroller.getCurrY();
- // Pretend that each frame of a fling scroll is a touch scroll
- if (delta > 0) {
- // List is moving towards the top. Use first view as mMotionPosition
- mMotionPosition = mFirstPosition;
- final View firstView = getChildAt(0);
- mMotionViewOriginalTop = firstView.getTop();
+ // Flip sign to convert finger direction to list items direction
+ // (e.g. finger moving down means list is moving towards the top)
+ int delta = mLastFlingY - y;
- // Don't fling more than 1 screen
- delta = Math.min(getHeight() - mPaddingBottom - mPaddingTop - 1, delta);
- } else {
- // List is moving towards the bottom. Use last view as mMotionPosition
- int offsetToLast = getChildCount() - 1;
- mMotionPosition = mFirstPosition + offsetToLast;
+ // Pretend that each frame of a fling scroll is a touch scroll
+ if (delta > 0) {
+ // List is moving towards the top. Use first view as mMotionPosition
+ mMotionPosition = mFirstPosition;
+ final View firstView = getChildAt(0);
+ mMotionViewOriginalTop = firstView.getTop();
- final View lastView = getChildAt(offsetToLast);
- mMotionViewOriginalTop = lastView.getTop();
+ // Don't fling more than 1 screen
+ delta = Math.min(getHeight() - mPaddingBottom - mPaddingTop - 1, delta);
+ } else {
+ // List is moving towards the bottom. Use last view as mMotionPosition
+ int offsetToLast = getChildCount() - 1;
+ mMotionPosition = mFirstPosition + offsetToLast;
- // Don't fling more than 1 screen
- delta = Math.max(-(getHeight() - mPaddingBottom - mPaddingTop - 1), delta);
- }
+ final View lastView = getChildAt(offsetToLast);
+ mMotionViewOriginalTop = lastView.getTop();
- trackMotionScroll(delta, delta);
+ // Don't fling more than 1 screen
+ delta = Math.max(-(getHeight() - mPaddingBottom - mPaddingTop - 1), delta);
+ }
- // Check to see if we have bumped into the scroll limit
- View motionView = getChildAt(mMotionPosition - mFirstPosition);
- if (motionView != null) {
- // Check if the top of the motion view is where it is
- // supposed to be
- if (motionView.getTop() != mMotionViewNewTop) {
- more = false;
+ // Do something different on overscroll - offsetChildrenTopAndBottom()
+ trackMotionScroll(delta, delta);
+
+ // Check to see if we have bumped into the scroll limit
+ View motionView = getChildAt(mMotionPosition - mFirstPosition);
+ if (motionView != null) {
+ // Check if the top of the motion view is where it is
+ // supposed to be
+ if (motionView.getTop() != mMotionViewNewTop) {
+ float vel = scroller.getCurrVelocity();
+ if (delta > 0) {
+ vel = -vel;
+ }
+ startOverfling(Math.round(vel));
+ break;
+ }
}
- }
- if (more) {
- invalidate();
- mLastFlingY = y;
- post(this);
- } else {
- endFling();
- if (PROFILE_FLINGING) {
- if (mFlingProfilingStarted) {
- Debug.stopMethodTracing();
- mFlingProfilingStarted = false;
+ if (more) {
+ invalidate();
+ mLastFlingY = y;
+ post(this);
+ } else {
+ endFling();
+
+ if (PROFILE_FLINGING) {
+ if (mFlingProfilingStarted) {
+ Debug.stopMethodTracing();
+ mFlingProfilingStarted = false;
+ }
}
}
+ break;
}
+
+ case TOUCH_MODE_OVERFLING: {
+ final OverScroller scroller = mScroller;
+ if (scroller.computeScrollOffset()) {
+ mScrollY = scroller.getCurrY();
+ invalidate();
+ post(this);
+ } else {
+ endFling();
+ }
+ break;
+ }
+ }
+
}
}
@@ -2867,6 +3028,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
break;
}
+ mPopupHidden = hint == INVISIBLE;
}
/**
@@ -2876,6 +3038,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mPopup != null) {
mPopup.dismiss();
}
+ mPopupHidden = false;
}
/**
@@ -3152,7 +3315,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
public void onGlobalLayout() {
if (isShown()) {
// Show the popup if we are filtered
- if (mFiltered && mPopup != null && !mPopup.isShowing()) {
+ if (mFiltered && mPopup != null && !mPopup.isShowing() && !mPopupHidden) {
showPopup();
}
} else {
diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java
index 9067e260f31a..3dab9f2127e2 100644
--- a/core/java/android/widget/DateTimeView.java
+++ b/core/java/android/widget/DateTimeView.java
@@ -203,7 +203,7 @@ public class DateTimeView extends TextView {
private DateFormat getDateFormat() {
String format = Settings.System.getString(getContext().getContentResolver(),
Settings.System.DATE_FORMAT);
- if ("".equals(format)) {
+ if (format == null || "".equals(format)) {
return DateFormat.getDateInstance(DateFormat.SHORT);
} else {
return new SimpleDateFormat(format);
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 67c0def552e8..6b669d8ff219 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -428,12 +428,21 @@ class FastScroller {
if (mListAdapter == null && mList != null) {
getSectionsFromIndexer();
}
+ if (mList != null) {
+ mList.requestDisallowInterceptTouchEvent(true);
+ }
cancelFling();
return true;
}
- } else if (action == MotionEvent.ACTION_UP) {
+ } else if (action == MotionEvent.ACTION_UP) { // don't add ACTION_CANCEL here
if (mState == STATE_DRAGGING) {
+ if (mList != null) {
+ // ViewGroup does the right thing already, but there might
+ // be other classes that don't properly reset on touch-up,
+ // so do this explicitly just in case.
+ mList.requestDisallowInterceptTouchEvent(false);
+ }
setState(STATE_VISIBLE);
final Handler handler = mHandler;
handler.removeCallbacks(mScrollFade);
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 8c3923145e24..0078fecdaa72 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -821,10 +821,13 @@ public class HorizontalScrollView extends FrameLayout {
}
long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
if (duration > ANIMATED_SCROLL_GAP) {
- int width = getWidth() - mPaddingRight - mPaddingLeft;
- int right = getChildAt(0).getWidth();
- mScroller.startScroll(mScrollX, mScrollY, dx, dy,
- 0, Math.max(0, right - width), 0, 0);
+ final int width = getWidth() - mPaddingRight - mPaddingLeft;
+ final int right = getChildAt(0).getWidth();
+ final int maxX = Math.max(0, right - width);
+ final int scrollX = mScrollX;
+ dx = Math.max(0, Math.min(scrollX + dx, maxX)) - scrollX;
+
+ mScroller.startScroll(scrollX, mScrollY, dx, 0);
awakenScrollBars(mScroller.getDuration());
invalidate();
} else {
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index b22ae3ca8cdc..44d415e92ebb 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -383,4 +383,15 @@ public class OverScroller {
public int getFinalY() {
return mCurrScroller.getFinalY();
}
+
+ /**
+ * @hide
+ * Returns the current velocity.
+ *
+ * @return The original velocity less the deceleration. Result may be
+ * negative.
+ */
+ public float getCurrVelocity() {
+ return mCurrScroller.getCurrVelocity();
+ }
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 1a50f8589eb9..4a1d8712ca2c 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -823,10 +823,13 @@ public class ScrollView extends FrameLayout {
}
long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
if (duration > ANIMATED_SCROLL_GAP) {
- int height = getHeight() - mPaddingBottom - mPaddingTop;
- int bottom = getChildAt(0).getHeight();
- mScroller.startScroll(mScrollX, mScrollY, dx, dy,
- 0, 0, 0, Math.max(0, bottom - height));
+ final int height = getHeight() - mPaddingBottom - mPaddingTop;
+ final int bottom = getChildAt(0).getHeight();
+ final int maxY = Math.max(0, bottom - height);
+ final int scrollY = mScrollY;
+ dy = Math.max(0, Math.min(scrollY + dy, maxY)) - scrollY;
+
+ mScroller.startScroll(mScrollX, scrollY, 0, dy);
awakenScrollBars(mScroller.getDuration());
invalidate();
} else {
diff --git a/core/java/com/android/internal/app/UsbStorageActivity.java b/core/java/com/android/internal/app/UsbStorageActivity.java
index b8a2136cc9d0..34ae2b4acd10 100644
--- a/core/java/com/android/internal/app/UsbStorageActivity.java
+++ b/core/java/com/android/internal/app/UsbStorageActivity.java
@@ -16,7 +16,7 @@
package com.android.internal.app;
-import android.app.AlertDialog;
+import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -24,20 +24,29 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Environment;
import android.os.IMountService;
+import android.os.MountServiceResultCode;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.widget.ImageView;
+import android.widget.Button;
+import android.widget.TextView;
import android.widget.Toast;
+import android.view.View;
/**
* This activity is shown to the user for him/her to enable USB mass storage
* on-demand (that is, when the USB cable is connected). It uses the alert
* dialog style. It will be launched from a notification.
*/
-public class UsbStorageActivity extends AlertActivity implements DialogInterface.OnClickListener {
-
- private static final int POSITIVE_BUTTON = AlertDialog.BUTTON1;
+public class UsbStorageActivity extends Activity {
+ private Button mMountButton;
+ private Button mUnmountButton;
+ private TextView mBanner;
+ private TextView mMessage;
+ private ImageView mIcon;
/** Used to detect when the USB cable is unplugged, so we can call finish() */
private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
@@ -53,16 +62,49 @@ public class UsbStorageActivity extends AlertActivity implements DialogInterface
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // Set up the "dialog"
- final AlertController.AlertParams p = mAlertParams;
- p.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
- p.mTitle = getString(com.android.internal.R.string.usb_storage_title);
- p.mMessage = getString(com.android.internal.R.string.usb_storage_message);
- p.mPositiveButtonText = getString(com.android.internal.R.string.usb_storage_button_mount);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(com.android.internal.R.string.usb_storage_button_unmount);
- p.mNegativeButtonListener = this;
- setupAlert();
+ setTitle(getString(com.android.internal.R.string.usb_storage_activity_title));
+
+ setContentView(com.android.internal.R.layout.usb_storage_activity);
+
+ mIcon = (ImageView) findViewById(com.android.internal.R.id.icon);
+ mBanner = (TextView) findViewById(com.android.internal.R.id.banner);
+ mMessage = (TextView) findViewById(com.android.internal.R.id.message);
+
+ mMountButton = (Button) findViewById(com.android.internal.R.id.mount_button);
+ mMountButton.setOnClickListener(
+ new View.OnClickListener() {
+ public void onClick(View v) {
+ mountAsUsbStorage();
+ // TODO: replace with forthcoming MountService callbacks
+ switchDisplay(true);
+ }
+ });
+
+ mUnmountButton = (Button) findViewById(com.android.internal.R.id.unmount_button);
+ mUnmountButton.setOnClickListener(
+ new View.OnClickListener() {
+ public void onClick(View v) {
+ stopUsbStorage();
+ // TODO: replace with forthcoming MountService callbacks
+ switchDisplay(false);
+ }
+ });
+ }
+
+ private void switchDisplay(boolean usbStorageInUse) {
+ if (usbStorageInUse) {
+ mUnmountButton.setVisibility(View.VISIBLE);
+ mMountButton.setVisibility(View.GONE);
+ mIcon.setImageResource(com.android.internal.R.drawable.usb_android_connected);
+ mBanner.setText(com.android.internal.R.string.usb_storage_stop_title);
+ mMessage.setText(com.android.internal.R.string.usb_storage_stop_message);
+ } else {
+ mUnmountButton.setVisibility(View.GONE);
+ mMountButton.setVisibility(View.VISIBLE);
+ mIcon.setImageResource(com.android.internal.R.drawable.usb_android);
+ mBanner.setText(com.android.internal.R.string.usb_storage_title);
+ mMessage.setText(com.android.internal.R.string.usb_storage_message);
+ }
}
@Override
@@ -70,6 +112,19 @@ public class UsbStorageActivity extends AlertActivity implements DialogInterface
super.onResume();
registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+
+ boolean umsOn = false;
+ try {
+ IMountService mountService = IMountService.Stub.asInterface(ServiceManager
+ .getService("mount"));
+ if (mountService != null) {
+ umsOn = mountService.getVolumeShared(
+ Environment.getExternalStorageDirectory().getPath(), "ums");
+ }
+ } catch (android.os.RemoteException exc) {
+ // pass
+ }
+ switchDisplay(umsOn);
}
@Override
@@ -79,31 +134,38 @@ public class UsbStorageActivity extends AlertActivity implements DialogInterface
unregisterReceiver(mBatteryReceiver);
}
- /**
- * {@inheritDoc}
- */
- public void onClick(DialogInterface dialog, int which) {
-
- if (which == POSITIVE_BUTTON) {
- mountAsUsbStorage();
+ private void mountAsUsbStorage() {
+ IMountService mountService = IMountService.Stub.asInterface(ServiceManager
+ .getService("mount"));
+ if (mountService == null) {
+ showSharingError();
+ return;
}
- // No matter what, finish the activity
- finish();
+ try {
+ if (mountService.shareVolume(
+ Environment.getExternalStorageDirectory().getPath(), "ums") !=
+ MountServiceResultCode.OperationSucceeded) {
+ showSharingError();
+ }
+ } catch (RemoteException e) {
+ showSharingError();
+ }
}
- private void mountAsUsbStorage() {
+ private void stopUsbStorage() {
IMountService mountService = IMountService.Stub.asInterface(ServiceManager
.getService("mount"));
if (mountService == null) {
- showSharingError();
+ showStoppingError();
return;
}
try {
- mountService.setMassStorageEnabled(true);
+ mountService.unshareVolume(
+ Environment.getExternalStorageDirectory().getPath(), "ums");
} catch (RemoteException e) {
- showSharingError();
+ showStoppingError();
return;
}
}
@@ -120,5 +182,10 @@ public class UsbStorageActivity extends AlertActivity implements DialogInterface
Toast.makeText(this, com.android.internal.R.string.usb_storage_error_message,
Toast.LENGTH_LONG).show();
}
+
+ private void showStoppingError() {
+ Toast.makeText(this, com.android.internal.R.string.usb_storage_stop_error_message,
+ Toast.LENGTH_LONG).show();
+ }
}
diff --git a/core/java/com/android/internal/app/UsbStorageStopActivity.java b/core/java/com/android/internal/app/UsbStorageStopActivity.java
deleted file mode 100644
index 557a5232a624..000000000000
--- a/core/java/com/android/internal/app/UsbStorageStopActivity.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2007 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IMountService;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.widget.Toast;
-
-/**
- * This activity is shown to the user for him/her to disable USB mass storage.
- * It uses the alert dialog style. It will be launched from a notification.
- */
-public class UsbStorageStopActivity extends AlertActivity implements DialogInterface.OnClickListener {
-
- private static final int POSITIVE_BUTTON = AlertDialog.BUTTON1;
-
- /** Used to detect when the USB cable is unplugged, so we can call finish() */
- private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction() == Intent.ACTION_BATTERY_CHANGED) {
- handleBatteryChanged(intent);
- }
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Set up the "dialog"
- final AlertController.AlertParams p = mAlertParams;
- p.mIconId = com.android.internal.R.drawable.ic_dialog_alert;
- p.mTitle = getString(com.android.internal.R.string.usb_storage_stop_title);
- p.mMessage = getString(com.android.internal.R.string.usb_storage_stop_message);
- p.mPositiveButtonText = getString(com.android.internal.R.string.usb_storage_stop_button_mount);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(com.android.internal.R.string.usb_storage_stop_button_unmount);
- p.mNegativeButtonListener = this;
- setupAlert();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- unregisterReceiver(mBatteryReceiver);
- }
-
- /**
- * {@inheritDoc}
- */
- public void onClick(DialogInterface dialog, int which) {
-
- if (which == POSITIVE_BUTTON) {
- stopUsbStorage();
- }
-
- // No matter what, finish the activity
- finish();
- }
-
- private void stopUsbStorage() {
- IMountService mountService = IMountService.Stub.asInterface(ServiceManager
- .getService("mount"));
- if (mountService == null) {
- showStoppingError();
- return;
- }
-
- try {
- mountService.setMassStorageEnabled(false);
- } catch (RemoteException e) {
- showStoppingError();
- return;
- }
- }
-
- private void handleBatteryChanged(Intent intent) {
- int pluggedType = intent.getIntExtra("plugged", 0);
- if (pluggedType == 0) {
- // It was disconnected from the plug, so finish
- finish();
- }
- }
-
- private void showStoppingError() {
- Toast.makeText(this, com.android.internal.R.string.usb_storage_stop_error_message,
- Toast.LENGTH_LONG).show();
- }
-
-}
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index a830ebdbce75..9da1066d1d69 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -102,7 +102,7 @@ interface IBackupTransport {
int finishBackup();
/**
- * Get the set of backups currently available over this transport.
+ * Get the set of all backups currently available over this transport.
*
* @return Descriptions of the set of restore images available for this device,
* or null if an error occurred (the attempt should be rescheduled).
@@ -110,11 +110,22 @@ interface IBackupTransport {
RestoreSet[] getAvailableRestoreSets();
/**
+ * Get the identifying token of the backup set currently being stored from
+ * this device. This is used in the case of applications wishing to restore
+ * their last-known-good data.
+ *
+ * @return A token that can be passed to {@link #startRestore}, or 0 if there
+ * is no backup set available corresponding to the current device state.
+ */
+ long getCurrentRestoreSet();
+
+ /**
* Start restoring application data from backup. After calling this function,
* alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData}
* to walk through the actual application data.
*
- * @param token A backup token as returned by {@link #getAvailableRestoreSets}.
+ * @param token A backup token as returned by {@link #getAvailableRestoreSets}
+ * or {@link #getCurrentRestoreSet}.
* @param packages List of applications to restore (if data is available).
* Application data will be restored in the order given.
* @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far, call
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 12bc5a888fc2..23ec6470a7ab 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -33,6 +33,9 @@ public class LocalTransport extends IBackupTransport.Stub {
private static final String TRANSPORT_DIR_NAME
= "com.android.internal.backup.LocalTransport";
+ // The single hardcoded restore set always has the same (nonzero!) token
+ private static final long RESTORE_TOKEN = 1;
+
private Context mContext;
private PackageManager mPackageManager;
private File mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup");
@@ -149,11 +152,16 @@ public class LocalTransport extends IBackupTransport.Stub {
// Restore handling
public RestoreSet[] getAvailableRestoreSets() throws android.os.RemoteException {
// one hardcoded restore set
- RestoreSet set = new RestoreSet("Local disk image", "flash", 0);
+ RestoreSet set = new RestoreSet("Local disk image", "flash", RESTORE_TOKEN);
RestoreSet[] array = { set };
return array;
}
+ public long getCurrentRestoreSet() {
+ // The hardcoded restore set always has the same token
+ return RESTORE_TOKEN;
+ }
+
public int startRestore(long token, PackageInfo[] packages) {
if (DEBUG) Log.v(TAG, "start restore " + token);
mRestorePackages = packages;
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 6347146267bd..f074b80cc8a2 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -80,9 +80,10 @@ public class LockPatternUtils {
* pin = digit-only password
* password = alphanumeric password
*/
- public static final int MODE_PATTERN = DevicePolicyManager.PASSWORD_MODE_SOMETHING;
- public static final int MODE_PIN = DevicePolicyManager.PASSWORD_MODE_NUMERIC;
- public static final int MODE_PASSWORD = DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC;
+ public static final int MODE_UNSPECIFIED = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+ public static final int MODE_PATTERN = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+ public static final int MODE_PIN = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+ public static final int MODE_PASSWORD = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
/**
* The minimum number of dots the user must include in a wrong pattern
@@ -132,13 +133,13 @@ public class LockPatternUtils {
* @return
*/
public int getRequestedPasswordMode() {
- int policyMode = mDevicePolicyManager.getPasswordMode(null);
+ int policyMode = mDevicePolicyManager.getPasswordQuality(null);
switch (policyMode) {
- case DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
return MODE_PASSWORD;
- case DevicePolicyManager.PASSWORD_MODE_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
return MODE_PIN;
- case DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED:
+ case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
return MODE_PATTERN;
}
return MODE_PATTERN;
@@ -158,16 +159,16 @@ public class LockPatternUtils {
}
public void setActivePasswordState(int mode, int length) {
- int policyMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+ int policyMode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
switch (mode) {
case MODE_PATTERN:
- policyMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+ policyMode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
break;
case MODE_PIN:
- policyMode = DevicePolicyManager.PASSWORD_MODE_NUMERIC;
+ policyMode = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
break;
case MODE_PASSWORD:
- policyMode = DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC;
+ policyMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
break;
}
mDevicePolicyManager.setActivePasswordState(policyMode, length);
@@ -302,7 +303,7 @@ public class LockPatternUtils {
DevicePolicyManager dpm = (DevicePolicyManager)mContext.getSystemService(
Context.DEVICE_POLICY_SERVICE);
dpm.setActivePasswordState(
- DevicePolicyManager.PASSWORD_MODE_SOMETHING, pattern.size());
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern.size());
}
} catch (FileNotFoundException fnfe) {
// Cant do much, unless we want to fail over to using the settings provider
@@ -314,7 +315,65 @@ public class LockPatternUtils {
}
/**
- * Save a lock password.
+ * Compare the given password and mode, ensuring that the password meets
+ * the mode and returning the minimum mode needed for the given password.
+ * @param password The password to be used.
+ * @param reqMode The desired password mode.
+ * @return Returns {@link #MODE_UNSPECIFIED} if the password is not
+ * good enough for the given mode. Otherwise, returns either the original
+ * reqMode or something better if that is needed for the given password.
+ */
+ static public int adjustPasswordMode(String password, int reqMode) {
+ boolean hasDigit = false;
+ boolean hasNonDigit = false;
+ final int len = password.length();
+ for (int i = 0; i < len; i++) {
+ if (Character.isDigit(password.charAt(i))) {
+ hasDigit = true;
+ } else {
+ hasNonDigit = true;
+ }
+ }
+
+ // First check if it is sufficient.
+ switch (reqMode) {
+ case MODE_PASSWORD: {
+ if (!hasDigit || !hasNonDigit) {
+ return MODE_UNSPECIFIED;
+ }
+ } break;
+
+ case MODE_PIN:
+ case MODE_PATTERN: {
+ // Whatever we have is acceptable; we may need to promote the
+ // mode later.
+ } break;
+
+ default:
+ // If it isn't a mode we specifically know, then fail fast.
+ Log.w(TAG, "adjustPasswordMode: unknown mode " + reqMode);
+ return MODE_UNSPECIFIED;
+ }
+
+ // Do we need to promote?
+ if (hasNonDigit) {
+ if (reqMode < MODE_PASSWORD) {
+ reqMode = MODE_PASSWORD;
+ }
+ }
+ if (hasDigit) {
+ if (reqMode < MODE_PIN) {
+ reqMode = MODE_PIN;
+ }
+ }
+
+ return reqMode;
+ }
+
+ /**
+ * Save a lock password. Does not ensure that the pattern is as good
+ * as the requested mode, but will adjust the mode to be as good as the
+ * pattern.
* @param password The password to save
*/
public void saveLockPassword(String password, int mode) {
@@ -331,9 +390,9 @@ public class LockPatternUtils {
}
raf.close();
if (password != null) {
- int textMode = TextUtils.isDigitsOnly(password) ? MODE_PIN : MODE_PASSWORD;
- if (textMode > mode) {
- mode = textMode;
+ int finalMode = adjustPasswordMode(password, mode);
+ if (mode < finalMode) {
+ mode = finalMode;
}
setLong(PASSWORD_TYPE_KEY, mode);
DevicePolicyManager dpm = (DevicePolicyManager)mContext.getSystemService(
diff --git a/core/java/com/android/internal/widget/SlidingTab.java b/core/java/com/android/internal/widget/SlidingTab.java
index eb6d1a66beaa..fd3899887717 100644
--- a/core/java/com/android/internal/widget/SlidingTab.java
+++ b/core/java/com/android/internal/widget/SlidingTab.java
@@ -545,12 +545,22 @@ public class SlidingTab extends ViewGroup {
return true;
}
+ /**
+ * Reset the tabs to their original state and stop any existing animation.
+ * Animate them back into place if animate is true.
+ *
+ * @param animate
+ */
+ public void reset(boolean animate) {
+ mLeftSlider.reset(animate);
+ mRightSlider.reset(animate);
+ }
+
@Override
public void setVisibility(int visibility) {
// Clear animations so sliders don't continue to animate when we show the widget again.
if (visibility != getVisibility() && visibility == View.INVISIBLE) {
- mLeftSlider.reset(false);
- mRightSlider.reset(false);
+ reset(false);
}
super.setVisibility(visibility);
}
diff --git a/core/java/com/google/android/mms/package.html b/core/java/com/google/android/mms/package.html
deleted file mode 100755
index c9f96a66ab3b..000000000000
--- a/core/java/com/google/android/mms/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/com/google/android/mms/pdu/package.html b/core/java/com/google/android/mms/pdu/package.html
deleted file mode 100755
index c9f96a66ab3b..000000000000
--- a/core/java/com/google/android/mms/pdu/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/java/com/google/android/mms/util/package.html b/core/java/com/google/android/mms/util/package.html
deleted file mode 100755
index c9f96a66ab3b..000000000000
--- a/core/java/com/google/android/mms/util/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<body>
-
-{@hide}
-
-</body>
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index fa1ee0da75be..1d22de340376 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -656,6 +656,15 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
}
}
+ /* enable poisoning of memory of freed objects */
+ property_get("dalvik.vm.gc.overwritefree", propBuf, "false");
+ if (strcmp(propBuf, "true") == 0) {
+ opt.optionString = "-Xgc:overwritefree";
+ mOptions.add(opt);
+ } else if (strcmp(propBuf, "false") != 0) {
+ LOGW("dalvik.vm.gc.overwritefree should be 'true' or 'false'");
+ }
+
/* enable debugging; set suspend=y to pause during VM init */
#ifdef HAVE_ANDROID_OS
/* use android ADB transport */
diff --git a/core/jni/CursorWindow.cpp b/core/jni/CursorWindow.cpp
index 78641899856d..78779214b6ed 100644
--- a/core/jni/CursorWindow.cpp
+++ b/core/jni/CursorWindow.cpp
@@ -18,7 +18,8 @@
#define LOG_TAG "CursorWindow"
#include <utils/Log.h>
-#include <binder/MemoryDealer.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
#include <assert.h>
#include <string.h>
@@ -37,7 +38,7 @@ CursorWindow::CursorWindow(size_t maxSize) :
{
}
-bool CursorWindow::setMemory(sp<IMemory> memory)
+bool CursorWindow::setMemory(const sp<IMemory>& memory)
{
mMemory = memory;
mData = (uint8_t *) memory->pointer();
@@ -47,7 +48,6 @@ bool CursorWindow::setMemory(sp<IMemory> memory)
mHeader = (window_header_t *) mData;
// Make the window read-only
- mHeap = NULL;
ssize_t size = memory->size();
mSize = size;
mMaxSize = size;
@@ -60,9 +60,10 @@ bool CursorWindow::initBuffer(bool localOnly)
{
//TODO Use a non-memory dealer mmap region for localOnly
- mHeap = new MemoryDealer(new SharedHeap(mMaxSize, 0, "CursorWindow"));
- if (mHeap != NULL) {
- mMemory = mHeap->allocate(mMaxSize);
+ sp<MemoryHeapBase> heap;
+ heap = new MemoryHeapBase(mMaxSize, 0, "CursorWindow");
+ if (heap != NULL) {
+ mMemory = new MemoryBase(heap, 0, mMaxSize);
if (mMemory != NULL) {
mData = (uint8_t *) mMemory->pointer();
if (mData) {
@@ -75,10 +76,10 @@ bool CursorWindow::initBuffer(bool localOnly)
return true;
}
}
- LOGE("memory dealer allocation failed");
+ LOGE("CursorWindow heap allocation failed");
return false;
} else {
- LOGE("failed to create the memory dealer");
+ LOGE("failed to create the CursorWindow heap");
return false;
}
}
diff --git a/core/jni/CursorWindow.h b/core/jni/CursorWindow.h
index e98b00996c36..3fcb56022720 100644
--- a/core/jni/CursorWindow.h
+++ b/core/jni/CursorWindow.h
@@ -21,7 +21,7 @@
#include <stddef.h>
#include <stdint.h>
-#include <binder/MemoryDealer.h>
+#include <binder/IMemory.h>
#include <utils/RefBase.h>
#include <jni.h>
@@ -101,7 +101,7 @@ class CursorWindow
public:
CursorWindow(size_t maxSize);
CursorWindow(){}
- bool setMemory(sp<IMemory>);
+ bool setMemory(const sp<IMemory>&);
~CursorWindow();
bool initBuffer(bool localOnly);
@@ -189,7 +189,6 @@ private:
size_t mSize;
size_t mMaxSize;
window_header_t * mHeader;
- sp<MemoryDealer> mHeap;
sp<IMemory> mMemory;
/**
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 1a5987cc3c65..03107a446cb6 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -168,7 +168,7 @@ void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int
}
if(mCallbackBuffers.isEmpty()) {
- LOGW("Out of buffers, clearing callback!");
+ LOGV("Out of buffers, clearing callback!");
mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_NOOP);
mManualCameraCallbackSet = false;
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index 93e4d2b815bb..bf613e1550b6 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -24,6 +24,23 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
+// Work around differences between the generated name and the actual name.
+
+#define glBlendEquation glBlendEquationOES
+#define glBlendEquationSeparate glBlendEquationSeparateOES
+#define glBlendFuncSeparate glBlendFuncSeparateOES
+#define glGetTexGenfv glGetTexGenfvOES
+#define glGetTexGeniv glGetTexGenivOES
+#define glGetTexGenxv glGetTexGenxvOES
+#define glTexGenf glTexGenfOES
+#define glTexGenfv glTexGenfvOES
+#define glTexGeni glTexGeniOES
+#define glTexGeniv glTexGenivOES
+#define glTexGenx glTexGenxOES
+#define glTexGenxv glTexGenxvOES
+
+
+
/* special calls implemented in Android's GLES wrapper used to more
* efficiently bound-check passed arrays */
extern "C" {
@@ -59,6 +76,11 @@ static jmethodID allowIndirectBuffersID;
static jfieldID positionID;
static jfieldID limitID;
static jfieldID elementSizeShiftID;
+static jfieldID haveCheckedExtensionsID;
+static jfieldID have_OES_blend_equation_separateID;
+static jfieldID have_OES_blend_subtractID;
+static jfieldID have_OES_framebuffer_objectID;
+static jfieldID have_OES_texture_cube_mapID;
/* Cache method IDs each time the class is loaded. */
@@ -73,6 +95,11 @@ nativeClassInitBuffer(JNIEnv *_env)
jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
+ haveCheckedExtensionsID = _env->GetFieldID(G11ImplClass, "haveCheckedExtensions", "Z");
+ have_OES_blend_equation_separateID = _env->GetFieldID(G11ImplClass, "have_OES_blend_equation_separate", "Z");
+ have_OES_blend_subtractID = _env->GetFieldID(G11ImplClass, "have_OES_blend_subtract", "Z");
+ have_OES_framebuffer_objectID = _env->GetFieldID(G11ImplClass, "have_OES_framebuffer_object", "Z");
+ have_OES_texture_cube_mapID = _env->GetFieldID(G11ImplClass, "have_OES_texture_cube_map", "Z");
getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
"getBasePointer", "(Ljava/nio/Buffer;)J");
@@ -194,6 +221,64 @@ getNumCompressedTextureFormats() {
return numCompressedTextureFormats;
}
+// Check if the extension at the head of pExtensions is pExtension. Note that pExtensions is
+// terminated by either 0 or space, while pExtension is terminated by 0.
+
+static bool
+extensionEqual(const GLubyte* pExtensions, const GLubyte* pExtension) {
+ while (true) {
+ char a = *pExtensions++;
+ char b = *pExtension++;
+ bool aEnd = a == '\0' || a == ' ';
+ bool bEnd = b == '\0';
+ if ( aEnd || bEnd) {
+ return aEnd == bEnd;
+ }
+ if ( a != b ) {
+ return false;
+ }
+ }
+}
+
+static const GLubyte*
+nextExtension(const GLubyte* pExtensions) {
+ while (true) {
+ char a = *pExtensions++;
+ if ( a == '\0') {
+ return pExtensions-1;
+ } else if ( a == ' ') {
+ return pExtensions;
+ }
+ }
+}
+
+static bool
+checkForExtension(const GLubyte* pExtensions, const GLubyte* pExtension) {
+ for (;*pExtensions != '\0'; pExtensions = nextExtension(pExtensions)) {
+ if (extensionEqual(pExtensions, pExtension)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+supportsExtension(JNIEnv *_env, jobject impl, jfieldID fieldId) {
+ if (!_env->GetBooleanField(impl, haveCheckedExtensionsID)) {
+ _env->SetBooleanField(impl, haveCheckedExtensionsID, true);
+ const GLubyte* sExtensions = glGetString(GL_EXTENSIONS);
+ _env->SetBooleanField(impl, have_OES_blend_equation_separateID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_equation_separate"));
+ _env->SetBooleanField(impl, have_OES_blend_subtractID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_subtract"));
+ _env->SetBooleanField(impl, have_OES_framebuffer_objectID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_framebuffer_object"));
+ _env->SetBooleanField(impl, have_OES_texture_cube_mapID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_texture_cube_map"));
+ }
+ return _env->GetBooleanField(impl, fieldId);
+}
+
// --------------------------------------------------------------------------
/* void glActiveTexture ( GLenum texture ) */
@@ -6137,315 +6222,1084 @@ android_glWeightPointerOES__IIII
static void
android_glBindFramebufferOES__II
(JNIEnv *_env, jobject _this, jint target, jint framebuffer) {
- _env->ThrowNew(UOEClass,
- "glBindFramebufferOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glBindFramebufferOES");
+ return;
+ }
+ glBindFramebufferOES(
+ (GLint)target,
+ (GLint)framebuffer
+ );
}
/* void glBindRenderbufferOES ( GLint target, GLint renderbuffer ) */
static void
android_glBindRenderbufferOES__II
(JNIEnv *_env, jobject _this, jint target, jint renderbuffer) {
- _env->ThrowNew(UOEClass,
- "glBindRenderbufferOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glBindRenderbufferOES");
+ return;
+ }
+ glBindRenderbufferOES(
+ (GLint)target,
+ (GLint)renderbuffer
+ );
}
/* void glBlendEquation ( GLint mode ) */
static void
android_glBlendEquation__I
(JNIEnv *_env, jobject _this, jint mode) {
- _env->ThrowNew(UOEClass,
- "glBlendEquation");
+ if (! supportsExtension(_env, _this, have_OES_blend_subtractID)) {
+ _env->ThrowNew(UOEClass,
+ "glBlendEquation");
+ return;
+ }
+ glBlendEquation(
+ (GLint)mode
+ );
}
/* void glBlendEquationSeparate ( GLint modeRGB, GLint modeAlpha ) */
static void
android_glBlendEquationSeparate__II
(JNIEnv *_env, jobject _this, jint modeRGB, jint modeAlpha) {
- _env->ThrowNew(UOEClass,
- "glBlendEquationSeparate");
+ if (! supportsExtension(_env, _this, have_OES_blend_equation_separateID)) {
+ _env->ThrowNew(UOEClass,
+ "glBlendEquationSeparate");
+ return;
+ }
+ glBlendEquationSeparate(
+ (GLint)modeRGB,
+ (GLint)modeAlpha
+ );
}
/* void glBlendFuncSeparate ( GLint srcRGB, GLint dstRGB, GLint srcAlpha, GLint dstAlpha ) */
static void
android_glBlendFuncSeparate__IIII
(JNIEnv *_env, jobject _this, jint srcRGB, jint dstRGB, jint srcAlpha, jint dstAlpha) {
- _env->ThrowNew(UOEClass,
- "glBlendFuncSeparate");
+ if (! supportsExtension(_env, _this, have_OES_blend_equation_separateID)) {
+ _env->ThrowNew(UOEClass,
+ "glBlendFuncSeparate");
+ return;
+ }
+ glBlendFuncSeparate(
+ (GLint)srcRGB,
+ (GLint)dstRGB,
+ (GLint)srcAlpha,
+ (GLint)dstAlpha
+ );
}
/* GLint glCheckFramebufferStatusOES ( GLint target ) */
static jint
android_glCheckFramebufferStatusOES__I
(JNIEnv *_env, jobject _this, jint target) {
- _env->ThrowNew(UOEClass,
- "glCheckFramebufferStatusOES");
- return 0;
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glCheckFramebufferStatusOES");
+ return 0;
+ }
+ GLint _returnValue = 0;
+ _returnValue = glCheckFramebufferStatusOES(
+ (GLint)target
+ );
+ return _returnValue;
}
-/* void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers ) */
+/* void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers ) */
static void
android_glDeleteFramebuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glDeleteFramebuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glDeleteFramebuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ GLuint *framebuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ if (!framebuffers_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "framebuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ framebuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(framebuffers_ref, (jboolean *)0);
+ framebuffers = framebuffers_base + offset;
+
+ glDeleteFramebuffersOES(
+ (GLint)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (framebuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
-/* void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers ) */
+/* void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers ) */
static void
android_glDeleteFramebuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glDeleteFramebuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glDeleteFramebuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glDeleteFramebuffersOES(
+ (GLint)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
-/* void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers ) */
+/* void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
static void
android_glDeleteRenderbuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glDeleteRenderbuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glDeleteRenderbuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ GLuint *renderbuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ if (!renderbuffers_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "renderbuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ renderbuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(renderbuffers_ref, (jboolean *)0);
+ renderbuffers = renderbuffers_base + offset;
+
+ glDeleteRenderbuffersOES(
+ (GLint)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (renderbuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
-/* void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers ) */
+/* void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
static void
android_glDeleteRenderbuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glDeleteRenderbuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glDeleteRenderbuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glDeleteRenderbuffersOES(
+ (GLint)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glFramebufferRenderbufferOES ( GLint target, GLint attachment, GLint renderbuffertarget, GLint renderbuffer ) */
static void
android_glFramebufferRenderbufferOES__IIII
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint renderbuffertarget, jint renderbuffer) {
- _env->ThrowNew(UOEClass,
- "glFramebufferRenderbufferOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glFramebufferRenderbufferOES");
+ return;
+ }
+ glFramebufferRenderbufferOES(
+ (GLint)target,
+ (GLint)attachment,
+ (GLint)renderbuffertarget,
+ (GLint)renderbuffer
+ );
}
/* void glFramebufferTexture2DOES ( GLint target, GLint attachment, GLint textarget, GLint texture, GLint level ) */
static void
android_glFramebufferTexture2DOES__IIIII
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint textarget, jint texture, jint level) {
- _env->ThrowNew(UOEClass,
- "glFramebufferTexture2DOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glFramebufferTexture2DOES");
+ return;
+ }
+ glFramebufferTexture2DOES(
+ (GLint)target,
+ (GLint)attachment,
+ (GLint)textarget,
+ (GLint)texture,
+ (GLint)level
+ );
}
/* void glGenerateMipmapOES ( GLint target ) */
static void
android_glGenerateMipmapOES__I
(JNIEnv *_env, jobject _this, jint target) {
- _env->ThrowNew(UOEClass,
- "glGenerateMipmapOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGenerateMipmapOES");
+ return;
+ }
+ glGenerateMipmapOES(
+ (GLint)target
+ );
}
-/* void glGenFramebuffersOES ( GLint n, GLint *framebuffers ) */
+/* void glGenFramebuffersOES ( GLint n, GLuint *framebuffers ) */
static void
android_glGenFramebuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGenFramebuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGenFramebuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ GLuint *framebuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ if (!framebuffers_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "framebuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ framebuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(framebuffers_ref, (jboolean *)0);
+ framebuffers = framebuffers_base + offset;
+
+ glGenFramebuffersOES(
+ (GLint)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (framebuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
-/* void glGenFramebuffersOES ( GLint n, GLint *framebuffers ) */
+/* void glGenFramebuffersOES ( GLint n, GLuint *framebuffers ) */
static void
android_glGenFramebuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glGenFramebuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGenFramebuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glGenFramebuffersOES(
+ (GLint)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
-/* void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers ) */
+/* void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
static void
android_glGenRenderbuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGenRenderbuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGenRenderbuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ GLuint *renderbuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ if (!renderbuffers_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "renderbuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ renderbuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(renderbuffers_ref, (jboolean *)0);
+ renderbuffers = renderbuffers_base + offset;
+
+ glGenRenderbuffersOES(
+ (GLint)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (renderbuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
-/* void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers ) */
+/* void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
static void
android_glGenRenderbuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glGenRenderbuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGenRenderbuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glGenRenderbuffersOES(
+ (GLint)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params ) */
static void
android_glGetFramebufferAttachmentParameterivOES__III_3II
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetFramebufferAttachmentParameterivOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetFramebufferAttachmentParameterivOES");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetFramebufferAttachmentParameterivOES(
+ (GLint)target,
+ (GLint)attachment,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params ) */
static void
android_glGetFramebufferAttachmentParameterivOES__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetFramebufferAttachmentParameterivOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetFramebufferAttachmentParameterivOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glGetFramebufferAttachmentParameterivOES(
+ (GLint)target,
+ (GLint)attachment,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGetRenderbufferParameterivOES ( GLint target, GLint pname, GLint *params ) */
static void
android_glGetRenderbufferParameterivOES__II_3II
(JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetRenderbufferParameterivOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetRenderbufferParameterivOES");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetRenderbufferParameterivOES(
+ (GLint)target,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetRenderbufferParameterivOES ( GLint target, GLint pname, GLint *params ) */
static void
android_glGetRenderbufferParameterivOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetRenderbufferParameterivOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetRenderbufferParameterivOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glGetRenderbufferParameterivOES(
+ (GLint)target,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGetTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
static void
android_glGetTexGenfv__II_3FI
(JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetTexGenfv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGenfv");
+ return;
+ }
+ jint _exception = 0;
+ GLfloat *params_base = (GLfloat *) 0;
+ jint _remaining;
+ GLfloat *params = (GLfloat *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLfloat *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetTexGenfv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLfloat *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
static void
android_glGetTexGenfv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetTexGenfv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGenfv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLfloat *params = (GLfloat *) 0;
+
+ params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+ glGetTexGenfv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLfloat *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGetTexGeniv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glGetTexGeniv__II_3II
(JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetTexGeniv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGeniv");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetTexGeniv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetTexGeniv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glGetTexGeniv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetTexGeniv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGeniv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glGetTexGeniv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGetTexGenxv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glGetTexGenxv__II_3II
(JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetTexGenxv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGenxv");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetTexGenxv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetTexGenxv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glGetTexGenxv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetTexGenxv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGenxv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glGetTexGenxv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* GLboolean glIsFramebufferOES ( GLint framebuffer ) */
static jboolean
android_glIsFramebufferOES__I
(JNIEnv *_env, jobject _this, jint framebuffer) {
- _env->ThrowNew(UOEClass,
- "glIsFramebufferOES");
- return JNI_FALSE;
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glIsFramebufferOES");
+ return JNI_FALSE;
+ }
+ GLboolean _returnValue = JNI_FALSE;
+ _returnValue = glIsFramebufferOES(
+ (GLint)framebuffer
+ );
+ return _returnValue;
}
/* GLboolean glIsRenderbufferOES ( GLint renderbuffer ) */
static jboolean
android_glIsRenderbufferOES__I
(JNIEnv *_env, jobject _this, jint renderbuffer) {
- _env->ThrowNew(UOEClass,
- "glIsRenderbufferOES");
- return JNI_FALSE;
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glIsRenderbufferOES");
+ return JNI_FALSE;
+ }
+ GLboolean _returnValue = JNI_FALSE;
+ _returnValue = glIsRenderbufferOES(
+ (GLint)renderbuffer
+ );
+ return _returnValue;
}
/* void glRenderbufferStorageOES ( GLint target, GLint internalformat, GLint width, GLint height ) */
static void
android_glRenderbufferStorageOES__IIII
(JNIEnv *_env, jobject _this, jint target, jint internalformat, jint width, jint height) {
- _env->ThrowNew(UOEClass,
- "glRenderbufferStorageOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glRenderbufferStorageOES");
+ return;
+ }
+ glRenderbufferStorageOES(
+ (GLint)target,
+ (GLint)internalformat,
+ (GLint)width,
+ (GLint)height
+ );
}
/* void glTexGenf ( GLint coord, GLint pname, GLfloat param ) */
static void
android_glTexGenf__IIF
(JNIEnv *_env, jobject _this, jint coord, jint pname, jfloat param) {
- _env->ThrowNew(UOEClass,
- "glTexGenf");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenf");
+ return;
+ }
+ glTexGenf(
+ (GLint)coord,
+ (GLint)pname,
+ (GLfloat)param
+ );
}
/* void glTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
static void
android_glTexGenfv__II_3FI
(JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glTexGenfv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenfv");
+ return;
+ }
+ jint _exception = 0;
+ GLfloat *params_base = (GLfloat *) 0;
+ jint _remaining;
+ GLfloat *params = (GLfloat *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLfloat *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glTexGenfv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLfloat *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
static void
android_glTexGenfv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glTexGenfv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenfv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLfloat *params = (GLfloat *) 0;
+
+ params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+ glTexGenfv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLfloat *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glTexGeni ( GLint coord, GLint pname, GLint param ) */
static void
android_glTexGeni__III
(JNIEnv *_env, jobject _this, jint coord, jint pname, jint param) {
- _env->ThrowNew(UOEClass,
- "glTexGeni");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGeni");
+ return;
+ }
+ glTexGeni(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint)param
+ );
}
/* void glTexGeniv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glTexGeniv__II_3II
(JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glTexGeniv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGeniv");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glTexGeniv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glTexGeniv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glTexGeniv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glTexGeniv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGeniv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glTexGeniv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glTexGenx ( GLint coord, GLint pname, GLint param ) */
static void
android_glTexGenx__III
(JNIEnv *_env, jobject _this, jint coord, jint pname, jint param) {
- _env->ThrowNew(UOEClass,
- "glTexGenx");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenx");
+ return;
+ }
+ glTexGenx(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint)param
+ );
}
/* void glTexGenxv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glTexGenxv__II_3II
(JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glTexGenxv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenxv");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glTexGenxv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glTexGenxv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glTexGenxv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glTexGenxv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenxv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glTexGenxv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
static const char *classPathName = "com/google/android/gles_jni/GLImpl";
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 54e15a598d54..665088a4c5ba 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1240,7 +1240,6 @@
</intent-filter>
</activity>
<activity android:name="com.android.internal.app.UsbStorageActivity"
- android:theme="@style/Theme.Dialog.Alert"
android:excludeFromRecents="true">
</activity>
<activity android:name="com.android.internal.app.UsbStorageStopActivity"
diff --git a/core/res/res/drawable-hdpi/usb_android.png b/core/res/res/drawable-hdpi/usb_android.png
new file mode 100644
index 000000000000..8153ec4f6dce
--- /dev/null
+++ b/core/res/res/drawable-hdpi/usb_android.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/usb_android_connected.png b/core/res/res/drawable-hdpi/usb_android_connected.png
new file mode 100644
index 000000000000..6449b7cb80d1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/usb_android_connected.png
Binary files differ
diff --git a/core/res/res/layout-land/usb_storage_activity.xml b/core/res/res/layout-land/usb_storage_activity.xml
new file mode 100644
index 000000000000..d714479721cc
--- /dev/null
+++ b/core/res/res/layout-land/usb_storage_activity.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:padding="18dip"
+ android:orientation="horizontal"
+ >
+
+ <ImageView android:id="@+id/icon"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentTop="true"
+ android:layout_height="wrap_content"
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ android:src="@drawable/usb_android" />
+
+ <RelativeLayout
+ android:layout_height="wrap_content"
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ >
+
+ <TextView android:id="@+id/banner"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/icon"
+ android:layout_marginTop="10dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="24sp"
+ android:gravity="center"
+ android:text="@string/usb_storage_title" />
+
+ <TextView android:id="@+id/message"
+ android:layout_below="@id/banner"
+ android:layout_marginTop="10dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="14sp"
+ android:gravity="center"
+ android:text="@string/usb_storage_message" />
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/message"
+ android:layout_marginTop="20dip"
+ >
+
+ <Button android:id="@+id/mount_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="18dip"
+ android:paddingRight="18dip"
+ android:text="@string/usb_storage_button_mount"
+ />
+ <Button android:id="@+id/unmount_button"
+ android:visibility="gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="18dip"
+ android:paddingRight="18dip"
+ android:text="@string/usb_storage_stop_button_mount"
+ />
+
+ </RelativeLayout>
+ </RelativeLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/contact_header.xml b/core/res/res/layout/contact_header.xml
index 128adc542891..e5b6c3555eba 100644
--- a/core/res/res/layout/contact_header.xml
+++ b/core/res/res/layout/contact_header.xml
@@ -88,6 +88,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:visibility="gone"
+ android:contentDescription="@string/description_star"
style="?android:attr/starStyle" />
</LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
index 2fa7aaafd145..244afbe0ebd8 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
@@ -23,6 +23,28 @@
android:background="@android:color/background_dark"
>
+ <!-- header text ('Enter Pin Code') -->
+ <TextView android:id="@+id/headerText"
+ android:layout_above="@+id/carrier"
+ android:layout_centerHorizontal="true"
+ android:layout_marginBottom="30dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="24sp"
+ />
+
+ <!-- Carrier info -->
+ <TextView android:id="@+id/carrier"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_above="@+id/pinDisplayGroup"
+ android:layout_marginTop="9dip"
+ android:gravity="left|bottom"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+
<!-- displays dots as user enters pin -->
<LinearLayout android:id="@+id/pinDisplayGroup"
android:orientation="horizontal"
@@ -60,16 +82,6 @@
</LinearLayout>
- <!-- header text ('Enter Pin Code') -->
- <TextView android:id="@+id/headerText"
- android:layout_above="@id/pinDisplayGroup"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="30dip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="24sp"
- />
-
<LinearLayout
android:orientation="horizontal"
android:layout_alignParentBottom="true"
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index fd34f7bb216c..b40495546e31 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -39,6 +39,7 @@
android:layout_marginRight="8dip"
android:singleLine="true"
android:ellipsize="marquee"
+ android:gravity="right|bottom"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 617b73894b9a..6ee659cb1b75 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -44,6 +44,7 @@
android:layout_marginTop="20dip"
android:singleLine="true"
android:ellipsize="marquee"
+ android:gravity="right|bottom"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index efd2044f3b41..c1b406fa7bfd 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -56,6 +56,7 @@
android:layout_marginTop="32dip"
android:singleLine="true"
android:ellipsize="marquee"
+ android:gravity="right|bottom"
/>
<com.android.internal.widget.DigitalClock android:id="@+id/time"
android:layout_width="wrap_content"
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index eb150f5ddbd1..16cd48c1ee42 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -44,6 +44,7 @@
android:layout_toRightOf="@+id/time"
android:singleLine="true"
android:ellipsize="marquee"
+ android:gravity="right|bottom"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
diff --git a/core/res/res/layout/usb_storage_activity.xml b/core/res/res/layout/usb_storage_activity.xml
new file mode 100644
index 000000000000..86bfadbccc78
--- /dev/null
+++ b/core/res/res/layout/usb_storage_activity.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:padding="18dip"
+ >
+
+ <ImageView android:id="@+id/icon"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentTop="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/usb_android" />
+
+ <TextView android:id="@+id/banner"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/icon"
+ android:layout_marginTop="10dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="24sp"
+ android:gravity="center"
+ android:text="@string/usb_storage_title" />
+
+ <TextView android:id="@+id/message"
+ android:layout_below="@id/banner"
+ android:layout_marginTop="10dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="14sp"
+ android:gravity="center"
+ android:text="@string/usb_storage_message" />
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/message"
+ android:layout_marginTop="20dip"
+ >
+
+ <Button android:id="@+id/mount_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="18dip"
+ android:paddingRight="18dip"
+ android:text="@string/usb_storage_button_mount"
+ />
+ <Button android:id="@+id/unmount_button"
+ android:visibility="gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="18dip"
+ android:paddingRight="18dip"
+ android:text="@string/usb_storage_stop_button_mount"
+ />
+
+ </RelativeLayout>
+</RelativeLayout>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9a8af3f50eaa..2b8ddc4c142c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -231,4 +231,10 @@
<!-- Component name of the default wallpaper. This will be ImageWallpaper if not
specified -->
<string name="default_wallpaper_component">@null</string>
+
+ <!-- Component name of the service providing network location support. -->
+ <string name="config_networkLocationProvider">@null</string>
+
+ <!-- Component name of the service providing geocoder API support. -->
+ <string name="config_geocodeProvider">@null</string>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 42553d4b138b..30d0da74f409 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2008,21 +2008,23 @@
<string name="googlewebcontenthelper_loading">Loading\u2026</string>
<!-- USB storage dialog strings -->
- <!-- This is the label for the activity, and should never be visible to the user. -->
+ <!-- This is the title for the activity's window. -->
+ <string name="usb_storage_activity_title">USB Mass Storage</string>
+
<!-- See USB_STORAGE. USB_STORAGE_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to mount. This is the title. -->
<string name="usb_storage_title">USB connected</string>
<!-- See USB_STORAGE. This is the message. -->
- <string name="usb_storage_message">You have connected your phone to your computer via USB. Select \"Mount\" if you want to copy files between your computer and your phone\'s SD card.</string>
+ <string name="usb_storage_message">You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\u2018s SD card.</string>
<!-- See USB_STORAGE. This is the button text to mount the phone on the computer. -->
- <string name="usb_storage_button_mount">Mount</string>
- <!-- See USB_STORAGE. This is the button text to ignore the plugging in of the phone.. -->
- <string name="usb_storage_button_unmount">Don\'t mount</string>
+ <string name="usb_storage_button_mount">Turn on USB storage</string>
<!-- See USB_STORAGE_DIALOG. If there was an error mounting, this is the text. -->
<string name="usb_storage_error_message">There is a problem using your SD card for USB storage.</string>
<!-- USB_STORAGE: When the user connects the phone to a computer via USB, we show a notification asking if he wants to share files across. This is the title -->
<string name="usb_storage_notification_title">USB connected</string>
<!-- See USB_STORAGE. This is the message. -->
<string name="usb_storage_notification_message">Select to copy files to/from your computer.</string>
+
+
<!-- USB_STORAGE_STOP: While USB storage is enabled, we show a notification dialog asking if he wants to stop. This is the title -->
<string name="usb_storage_stop_notification_title">Turn off USB storage</string>
<!-- See USB_STORAGE. This is the message. -->
@@ -2031,15 +2033,13 @@
<!-- USB storage stop dialog strings -->
<!-- This is the label for the activity, and should never be visible to the user. -->
<!-- See USB_STORAGE_STOP. USB_STORAGE_STOP_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to stop usb storage. This is the title. -->
- <string name="usb_storage_stop_title">Turn off USB storage</string>
+ <string name="usb_storage_stop_title">USB storage in use</string>
<!-- See USB_STORAGE_STOP. This is the message. -->
- <string name="usb_storage_stop_message">Before turning off USB storage, make sure you have unmounted on the USB host. Select \"Turn Off\" to turn off USB storage.</string>
+ <string name="usb_storage_stop_message">Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s SD card from your computer.</string>
<!-- See USB_STORAGE_STOP. This is the button text to stop usb storage. -->
- <string name="usb_storage_stop_button_mount">Turn Off</string>
- <!-- See USB_STORAGE_STOP. This is the button text to cancel stoping usb storage. -->
- <string name="usb_storage_stop_button_unmount">Cancel</string>
+ <string name="usb_storage_stop_button_mount">Turn off USB storage</string>
<!-- See USB_STORAGE_STOP_DIALOG. If there was an error stopping, this is the text. -->
- <string name="usb_storage_stop_error_message">We\'ve encountered a problem turning off USB storage. Check to make sure you have unmounted the USB host, then try again.</string>
+ <string name="usb_storage_stop_error_message">There was a problem turning off USB storage. Check to make sure you have unmounted the USB host, then try again.</string>
<!-- External media format dialog strings -->
<!-- This is the label for the activity, and should never be visible to the user. -->
@@ -2194,4 +2194,10 @@
<string name="reset">Reset</string>
<!-- Label for <input type="submit"> button in html -->
<string name="submit">Submit</string>
+
+ <!-- String describing the Star/Favorite checkbox
+
+ Used by AccessibilityService to announce the purpose of the view.
+ -->
+ <string name="description_star">favorite</string>
</resources>
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 77c176f622cf..1fb98529b268 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -5,10 +5,14 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src) \
+ src/android/os/IAidlTest.aidl
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_PACKAGE_NAME := FrameworksCoreTests
+LOCAL_CERTIFICATE := platform
+
include $(BUILD_PACKAGE)
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 02961f4f0b3a..8d7e18728ea0 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -16,6 +16,46 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.frameworks.coretests">
+
+ <permission android:name="com.android.frameworks.coretests.permission.TEST_GRANTED"
+ android:protectionLevel="normal"
+ android:label="@string/permlab_testGranted"
+ android:description="@string/permdesc_testGranted">
+ <meta-data android:name="com.android.frameworks.coretests.string" android:value="foo" />
+ <meta-data android:name="com.android.frameworks.coretests.boolean" android:value="true" />
+ <meta-data android:name="com.android.frameworks.coretests.integer" android:value="100" />
+ <meta-data android:name="com.android.frameworks.coretests.color" android:value="#ff000000" />
+ <meta-data android:name="com.android.frameworks.coretests.float" android:value="100.1" />
+ <meta-data android:name="com.android.frameworks.coretests.reference" android:resource="@xml/metadata" />
+ </permission>
+ <permission android:name="com.android.frameworks.coretests.permission.TEST_DENIED"
+ android:protectionLevel="normal"
+ android:label="@string/permlab_testDenied"
+ android:description="@string/permdesc_testDenied" />
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+ <uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
+ <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
+ <uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
+ <uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.READ_LOGS"/>
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_SMS"/>
+ <uses-permission android:name="android.permission.USE_CREDENTIALS" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_SMS"/>
+ <uses-permission android:name="android.permission.TEST_GRANTED" />
+ <uses-permission android:name="com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD" />
+ <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
+ <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.ALL_SERVICES" />
+
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
@@ -28,12 +68,8 @@
<!-- location test permissions -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
- <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
- <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-
<uses-permission android:name="android.permission.HARDWARE_TEST" />
- <uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.ACCESSIBILITY_EVENT_VIEW_TYPES" />
<uses-permission android:name="android.permission.ACCESSIBILITY_EVENT_TRANSITION_TYPES" />
<uses-permission android:name="android.permission.ACCESSIBILITY_EVENT_NOTIFICATION_TYPES" />
@@ -975,6 +1011,187 @@
</intent-filter>
</activity>
+
+
+ <!-- Activity-level metadata -->
+ <meta-data android:name="com.android.frameworks.coretests.isApp" android:value="true" />
+ <meta-data android:name="com.android.frameworks.coretests.string" android:value="foo" />
+ <meta-data android:name="com.android.frameworks.coretests.boolean" android:value="true" />
+ <meta-data android:name="com.android.frameworks.coretests.integer" android:value="100" />
+ <meta-data android:name="com.android.frameworks.coretests.color" android:value="#ff000000" />
+ <meta-data android:name="com.android.frameworks.coretests.float" android:value="100.1" />
+ <meta-data android:name="com.android.frameworks.coretests.reference"
+ android:resource="@xml/metadata_app" />
+
+ <activity android:name="AndroidPerformanceTests" android:label="Android Performance Tests">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.UNIT_TEST" />
+ </intent-filter>
+ </activity>
+
+ <!-- Application components used for activity tests -->
+
+ <activity android:name="android.app.activity.TestedActivity"
+ android:process=":remoteActivity">
+ </activity>
+ <activity android:name="android.app.activity.LocalActivity" android:multiprocess="true">
+ <meta-data android:name="com.android.frameworks.coretests.string" android:value="foo" />
+ <meta-data android:name="com.android.frameworks.coretests.boolean" android:value="true" />
+ <meta-data android:name="com.android.frameworks.coretests.integer" android:value="100" />
+ <meta-data android:name="com.android.frameworks.coretests.color" android:value="#ff000000" />
+ <meta-data android:name="com.android.frameworks.coretests.float" android:value="100.1" />
+ <meta-data android:name="com.android.frameworks.coretests.reference" android:resource="@xml/metadata" />
+ </activity>
+ <activity android:name="android.app.activity.TestedScreen"
+ android:process=":remoteScreen">
+ </activity>
+ <activity android:name="android.app.activity.LocalScreen" android:multiprocess="true">
+ </activity>
+ <activity android:name="android.app.activity.ClearTop" android:multiprocess="true"
+ android:launchMode="singleTop">
+ </activity>
+ <activity android:name="android.app.activity.LocalDialog" android:multiprocess="true"
+ android:theme="@android:style/Theme.Dialog">
+ </activity>
+ <activity android:name="android.app.activity.SubActivityScreen">
+ </activity>
+ <activity android:name="android.app.activity.RemoteSubActivityScreen"
+ android:process=":remoteActivity">
+ </activity>
+ <activity android:name="android.app.activity.LaunchpadActivity" android:multiprocess="true">
+ </activity>
+ <activity android:name="android.app.activity.LaunchpadTabActivity" android:multiprocess="true">
+ </activity>
+
+ <receiver android:name="android.app.activity.AbortReceiver">
+ <intent-filter android:priority="1">
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_ABORT" />
+ </intent-filter>
+ </receiver>
+ <receiver android:name="android.app.activity.LocalReceiver">
+ <intent-filter android:priority="-1">
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_ABORT" />
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_ALL" />
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_REPEAT" />
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_LOCAL" />
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_FAIL_REGISTER" />
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_FAIL_BIND" />
+ </intent-filter>
+ <meta-data android:name="com.android.frameworks.coretests.string" android:value="foo" />
+ <meta-data android:name="com.android.frameworks.coretests.boolean" android:value="true" />
+ <meta-data android:name="com.android.frameworks.coretests.integer" android:value="100" />
+ <meta-data android:name="com.android.frameworks.coretests.color" android:value="#ff000000" />
+ <meta-data android:name="com.android.frameworks.coretests.float" android:value="100.1" />
+ <meta-data android:name="com.android.frameworks.coretests.reference" android:resource="@xml/metadata" />
+ </receiver>
+ <receiver android:name="android.app.activity.ResultReceiver">
+ <intent-filter>
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_RESULT" />
+ </intent-filter>
+ </receiver>
+ <receiver android:name="android.app.activity.LocalGrantedReceiver"
+ android:permission="com.android.frameworks.coretests.permission.TEST_GRANTED">
+ <intent-filter android:priority="-1">
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_LOCAL_GRANTED" />
+ </intent-filter>
+ </receiver>
+ <receiver android:name="android.app.activity.LocalDeniedReceiver"
+ android:permission="com.android.frameworks.coretests.permission.TEST_DENIED">
+ <intent-filter android:priority="-1">
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_LOCAL_DENIED" />
+ </intent-filter>
+ </receiver>
+ <receiver android:name="android.app.activity.RemoteReceiver"
+ android:process=":remoteReceiver">
+ <intent-filter android:priority="2">
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_ABORT" />
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_ALL" />
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_REPEAT" />
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_REMOTE" />
+ </intent-filter>
+ </receiver>
+ <receiver android:name="android.app.activity.RemoteGrantedReceiver"
+ android:permission="com.android.frameworks.coretests.permission.TEST_GRANTED">
+ <intent-filter android:priority="2">
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_REMOTE_GRANTED" />
+ </intent-filter>
+ </receiver>
+ <receiver android:name="android.app.activity.RemoteDeniedReceiver"
+ android:permission="com.android.frameworks.coretests.permission.TEST_DENIED">
+ <intent-filter android:priority="2">
+ <action android:name="com.android.frameworks.coretests.activity.BROADCAST_REMOTE_DENIED" />
+ </intent-filter>
+ </receiver>
+ <service android:name="android.app.activity.LocalService">
+ <intent-filter>
+ <action android:name="com.android.frameworks.coretests.activity.SERVICE_LOCAL" />
+ </intent-filter>
+ <meta-data android:name="com.android.frameworks.coretests.string" android:value="foo" />
+ <meta-data android:name="com.android.frameworks.coretests.boolean" android:value="true" />
+ <meta-data android:name="com.android.frameworks.coretests.integer" android:value="100" />
+ <meta-data android:name="com.android.frameworks.coretests.color" android:value="#ff000000" />
+ <meta-data android:name="com.android.frameworks.coretests.float" android:value="100.1" />
+ <meta-data android:name="com.android.frameworks.coretests.reference" android:resource="@xml/metadata" />
+ </service>
+ <service android:name="android.app.activity.LocalDeniedService"
+ android:permission="com.android.frameworks.coretests.permission.TEST_DENIED">
+ <intent-filter>
+ <action android:name="com.android.frameworks.coretests.activity.SERVICE_LOCAL_DENIED" />
+ </intent-filter>
+ </service>
+ <service android:name="android.app.activity.LocalGrantedService"
+ android:permission="com.android.frameworks.coretests.permission.TEST_GRANTED">
+ <intent-filter>
+ <action android:name="com.android.frameworks.coretests.activity.SERVICE_LOCAL_GRANTED" />
+ </intent-filter>
+ </service>
+
+ <provider android:name="android.app.activity.LocalProvider"
+ android:authorities="com.android.frameworks.coretests.LocalProvider">
+ <meta-data android:name="com.android.frameworks.coretests.string" android:value="foo" />
+ <meta-data android:name="com.android.frameworks.coretests.boolean" android:value="true" />
+ <meta-data android:name="com.android.frameworks.coretests.integer" android:value="100" />
+ <meta-data android:name="com.android.frameworks.coretests.color" android:value="#ff000000" />
+ <meta-data android:name="com.android.frameworks.coretests.float" android:value="100.1" />
+ <meta-data android:name="com.android.frameworks.coretests.reference" android:resource="@xml/metadata" />
+ </provider>
+
+ <!-- Application components used for content tests -->
+ <provider android:name="android.content.MemoryFileProvider"
+ android:authorities="android.content.MemoryFileProvider"
+ android:process=":MemoryFileProvider">
+ </provider>
+
+ <!-- Application components used for os tests -->
+
+ <service android:name="android.os.MessengerService"
+ android:process=":messengerService">
+ </service>
+
+ <!-- Application components used for search manager tests -->
+
+ <activity android:name="android.app.activity.SearchableActivity"
+ android:label="Searchable Activity">
+ <intent-filter>
+ <action android:name="android.intent.action.SEARCH" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data android:name="android.app.searchable"
+ android:resource="@xml/searchable" />
+ </activity>
+
+ <provider android:name="android.app.SuggestionProvider"
+ android:authorities="android.app.SuggestionProvider">
+ </provider>
+
+ <!-- Used to test IPC. -->
+ <service android:name="com.android.frameworks.coretests.binder.BinderTestService"
+ android:process="binder.BinderTestService" />
+ <service android:name="com.android.frameworks.coretests.binder.BinderPerformanceService"
+ android:process="binder.BinderPerformanceService" />
+ <service android:name="com.android.frameworks.coretests.binder.BinderVsMessagingService"
+ android:process="binder.BinderVsMessagingService" />
</application>
<instrumentation
diff --git a/tests/AndroidTests/assets/text.txt b/core/tests/coretests/assets/text.txt
index 3d8c5195bffc..3d8c5195bffc 100644
--- a/tests/AndroidTests/assets/text.txt
+++ b/core/tests/coretests/assets/text.txt
diff --git a/tests/AndroidTests/res/layout/layout_five.xml b/core/tests/coretests/res/layout/layout_five.xml
index 9923eaf0fdd2..9923eaf0fdd2 100644
--- a/tests/AndroidTests/res/layout/layout_five.xml
+++ b/core/tests/coretests/res/layout/layout_five.xml
diff --git a/tests/AndroidTests/res/layout/layout_four.xml b/core/tests/coretests/res/layout/layout_four.xml
index e5a78bcfdcf2..e5a78bcfdcf2 100644
--- a/tests/AndroidTests/res/layout/layout_four.xml
+++ b/core/tests/coretests/res/layout/layout_four.xml
diff --git a/tests/AndroidTests/res/layout/layout_one.xml b/core/tests/coretests/res/layout/layout_one.xml
index c326b2baf01f..69662466c02c 100644
--- a/tests/AndroidTests/res/layout/layout_one.xml
+++ b/core/tests/coretests/res/layout/layout_one.xml
@@ -17,4 +17,4 @@
** limitations under the License.
*/
-->
-<view xmlns:android="http://schemas.android.com/apk/res/android" class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/viewOne" android:layout_width="match_parent" android:layout_height="match_parent"/>
+<view xmlns:android="http://schemas.android.com/apk/res/android" class="android.view.InflateTest$ViewOne" android:id="@+id/viewOne" android:layout_width="match_parent" android:layout_height="match_parent"/>
diff --git a/tests/AndroidTests/res/layout/layout_six.xml b/core/tests/coretests/res/layout/layout_six.xml
index b78082d164e8..b78082d164e8 100644
--- a/tests/AndroidTests/res/layout/layout_six.xml
+++ b/core/tests/coretests/res/layout/layout_six.xml
diff --git a/tests/AndroidTests/res/layout/layout_tag.xml b/core/tests/coretests/res/layout/layout_tag.xml
index 72874a6d5b93..7fb0489478e6 100644
--- a/tests/AndroidTests/res/layout/layout_tag.xml
+++ b/core/tests/coretests/res/layout/layout_tag.xml
@@ -18,6 +18,6 @@
*/
-->
<view xmlns:android="http://schemas.android.com/apk/res/android"
- class="com.android.unit_tests.InflateTest$ViewOne"
+ class="android.view.InflateTest$ViewOne"
android:id="@+id/viewOne" android:tag="MyTag"
android:layout_width="match_parent" android:layout_height="match_parent"/>
diff --git a/core/tests/coretests/res/layout/layout_three.xml b/core/tests/coretests/res/layout/layout_three.xml
new file mode 100644
index 000000000000..7242fc88ca14
--- /dev/null
+++ b/core/tests/coretests/res/layout/layout_three.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
+ <view class="android.view.InflateTest$ViewOne" android:id="@+id/view1" android:layout_width="match_parent" android:layout_height="match_parent"/>
+ <view class="android.view.InflateTest$ViewOne" android:id="@+id/view2" android:layout_width="match_parent" android:layout_height="match_parent"/>
+ <view class="android.view.InflateTest$ViewOne" android:id="@+id/view3" android:layout_width="match_parent" android:layout_height="match_parent"/>
+ <view class="android.view.InflateTest$ViewOne" android:id="@+id/view4" android:layout_width="match_parent" android:layout_height="match_parent"/>
+ <view class="android.view.InflateTest$ViewOne" android:id="@+id/view5" android:layout_width="match_parent" android:layout_height="match_parent"/>
+ <view class="android.view.InflateTest$ViewOne" android:id="@+id/view6" android:layout_width="match_parent" android:layout_height="match_parent"/>
+</LinearLayout>
diff --git a/tests/AndroidTests/res/layout/layout_two.xml b/core/tests/coretests/res/layout/layout_two.xml
index af14228f98b5..9fb7d3bea5c3 100644
--- a/tests/AndroidTests/res/layout/layout_two.xml
+++ b/core/tests/coretests/res/layout/layout_two.xml
@@ -18,6 +18,6 @@
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
- <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/viewOne" android:layout_width="match_parent" android:layout_height="match_parent"/>
+ <view class="android.view.InflateTest$ViewOne" android:id="@+id/viewOne" android:layout_width="match_parent" android:layout_height="match_parent"/>
</LinearLayout>
diff --git a/tests/AndroidTests/res/raw/medium.xml b/core/tests/coretests/res/raw/medium.xml
index 5757a24e290f..5757a24e290f 100644
--- a/tests/AndroidTests/res/raw/medium.xml
+++ b/core/tests/coretests/res/raw/medium.xml
diff --git a/tests/AndroidTests/res/raw/small.xml b/core/tests/coretests/res/raw/small.xml
index ee859b99b217..ee859b99b217 100644
--- a/tests/AndroidTests/res/raw/small.xml
+++ b/core/tests/coretests/res/raw/small.xml
diff --git a/tests/AndroidTests/res/raw/text.txt b/core/tests/coretests/res/raw/text.txt
index 3d8c5195bffc..3d8c5195bffc 100644
--- a/tests/AndroidTests/res/raw/text.txt
+++ b/core/tests/coretests/res/raw/text.txt
diff --git a/tests/AndroidTests/res/raw/v21_backslash.vcf b/core/tests/coretests/res/raw/v21_backslash.vcf
index bd3002b32b10..bd3002b32b10 100644
--- a/tests/AndroidTests/res/raw/v21_backslash.vcf
+++ b/core/tests/coretests/res/raw/v21_backslash.vcf
diff --git a/tests/AndroidTests/res/raw/v21_complicated.vcf b/core/tests/coretests/res/raw/v21_complicated.vcf
index de34e1668f73..de34e1668f73 100644
--- a/tests/AndroidTests/res/raw/v21_complicated.vcf
+++ b/core/tests/coretests/res/raw/v21_complicated.vcf
diff --git a/tests/AndroidTests/res/raw/v21_invalid_comment_line.vcf b/core/tests/coretests/res/raw/v21_invalid_comment_line.vcf
index f910710af6d3..f910710af6d3 100644
--- a/tests/AndroidTests/res/raw/v21_invalid_comment_line.vcf
+++ b/core/tests/coretests/res/raw/v21_invalid_comment_line.vcf
diff --git a/tests/AndroidTests/res/raw/v21_japanese_1.vcf b/core/tests/coretests/res/raw/v21_japanese_1.vcf
index d05e2fffb180..d05e2fffb180 100644
--- a/tests/AndroidTests/res/raw/v21_japanese_1.vcf
+++ b/core/tests/coretests/res/raw/v21_japanese_1.vcf
diff --git a/tests/AndroidTests/res/raw/v21_japanese_2.vcf b/core/tests/coretests/res/raw/v21_japanese_2.vcf
index fa54acbc89c7..fa54acbc89c7 100644
--- a/tests/AndroidTests/res/raw/v21_japanese_2.vcf
+++ b/core/tests/coretests/res/raw/v21_japanese_2.vcf
diff --git a/tests/AndroidTests/res/raw/v21_multiple_entry.vcf b/core/tests/coretests/res/raw/v21_multiple_entry.vcf
index ebbb19a4bc3f..ebbb19a4bc3f 100644
--- a/tests/AndroidTests/res/raw/v21_multiple_entry.vcf
+++ b/core/tests/coretests/res/raw/v21_multiple_entry.vcf
diff --git a/tests/AndroidTests/res/raw/v21_org_before_title.vcf b/core/tests/coretests/res/raw/v21_org_before_title.vcf
index 8ff1190f1068..8ff1190f1068 100644
--- a/tests/AndroidTests/res/raw/v21_org_before_title.vcf
+++ b/core/tests/coretests/res/raw/v21_org_before_title.vcf
diff --git a/tests/AndroidTests/res/raw/v21_pref_handling.vcf b/core/tests/coretests/res/raw/v21_pref_handling.vcf
index 51053101a164..51053101a164 100644
--- a/tests/AndroidTests/res/raw/v21_pref_handling.vcf
+++ b/core/tests/coretests/res/raw/v21_pref_handling.vcf
diff --git a/tests/AndroidTests/res/raw/v21_simple_1.vcf b/core/tests/coretests/res/raw/v21_simple_1.vcf
index 6aabb4c023e0..6aabb4c023e0 100644
--- a/tests/AndroidTests/res/raw/v21_simple_1.vcf
+++ b/core/tests/coretests/res/raw/v21_simple_1.vcf
diff --git a/tests/AndroidTests/res/raw/v21_simple_2.vcf b/core/tests/coretests/res/raw/v21_simple_2.vcf
index f0d5ab506ae6..f0d5ab506ae6 100644
--- a/tests/AndroidTests/res/raw/v21_simple_2.vcf
+++ b/core/tests/coretests/res/raw/v21_simple_2.vcf
diff --git a/tests/AndroidTests/res/raw/v21_simple_3.vcf b/core/tests/coretests/res/raw/v21_simple_3.vcf
index beddabb96086..beddabb96086 100644
--- a/tests/AndroidTests/res/raw/v21_simple_3.vcf
+++ b/core/tests/coretests/res/raw/v21_simple_3.vcf
diff --git a/tests/AndroidTests/res/raw/v21_title_before_org.vcf b/core/tests/coretests/res/raw/v21_title_before_org.vcf
index 9fdc7389cd5f..9fdc7389cd5f 100644
--- a/tests/AndroidTests/res/raw/v21_title_before_org.vcf
+++ b/core/tests/coretests/res/raw/v21_title_before_org.vcf
diff --git a/tests/AndroidTests/res/raw/v21_winmo_65.vcf b/core/tests/coretests/res/raw/v21_winmo_65.vcf
index f380d0d5cbfb..f380d0d5cbfb 100644
--- a/tests/AndroidTests/res/raw/v21_winmo_65.vcf
+++ b/core/tests/coretests/res/raw/v21_winmo_65.vcf
diff --git a/tests/AndroidTests/res/raw/v30_comma_separated.vcf b/core/tests/coretests/res/raw/v30_comma_separated.vcf
index 98a7f20588a1..98a7f20588a1 100644
--- a/tests/AndroidTests/res/raw/v30_comma_separated.vcf
+++ b/core/tests/coretests/res/raw/v30_comma_separated.vcf
diff --git a/tests/AndroidTests/res/raw/v30_simple.vcf b/core/tests/coretests/res/raw/v30_simple.vcf
index 418661f7468a..418661f7468a 100644
--- a/tests/AndroidTests/res/raw/v30_simple.vcf
+++ b/core/tests/coretests/res/raw/v30_simple.vcf
diff --git a/core/tests/coretests/res/values/strings.xml b/core/tests/coretests/res/values/strings.xml
index 05b57e0a5942..807386a4419e 100644
--- a/core/tests/coretests/res/values/strings.xml
+++ b/core/tests/coretests/res/values/strings.xml
@@ -100,4 +100,21 @@
<string name="include_button">I was included!</string>
<string name="view">View</string>
+
+ <string name="layout_five_text_text">S</string>
+ <string name="layout_four_text_text">S</string>
+ <string name="layout_six_text_text">S</string>
+
+ <string name="menu_test">test</string>
+ <string name="metadata_text">text</string>
+
+ <string name="permlab_testGranted">Test Granted</string>
+ <string name="permdesc_testGranted">Used for running unit tests, for
+ testing operations where we have the permission.</string>
+ <string name="permlab_testDenied">Test Denied</string>
+ <string name="permdesc_testDenied">Used for running unit tests, for
+ testing operations where we do not have the permission.</string>
+
+ <string name="searchable_label">SearchManager Test</string>
+ <string name="searchable_hint">A search hint</string>
</resources>
diff --git a/tests/AndroidTests/res/xml/metadata.xml b/core/tests/coretests/res/xml/metadata.xml
index e352f27f8148..e352f27f8148 100644
--- a/tests/AndroidTests/res/xml/metadata.xml
+++ b/core/tests/coretests/res/xml/metadata.xml
diff --git a/tests/AndroidTests/res/xml/metadata_app.xml b/core/tests/coretests/res/xml/metadata_app.xml
index c37e6badcb7e..c37e6badcb7e 100644
--- a/tests/AndroidTests/res/xml/metadata_app.xml
+++ b/core/tests/coretests/res/xml/metadata_app.xml
diff --git a/tests/AndroidTests/res/xml/searchable.xml b/core/tests/coretests/res/xml/searchable.xml
index 9d293b5ac425..9d293b5ac425 100644
--- a/tests/AndroidTests/res/xml/searchable.xml
+++ b/core/tests/coretests/res/xml/searchable.xml
diff --git a/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java b/core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java
index 1e4f161d9f60..394b9f2a5041 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java
+++ b/core/tests/coretests/src/android/accounts/AccountManagerServiceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.accounts;
+package android.accounts;
import android.test.AndroidTestCase;
import android.test.RenamingDelegatingContext;
@@ -175,4 +175,4 @@ public class AccountManagerServiceTest extends AndroidTestCase {
assertNull(ams.readAuthTokenFromDatabase(a12, "att2"));
}
-} \ No newline at end of file
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java b/core/tests/coretests/src/android/app/SearchManagerTest.java
index 6f6f55dd6cd1..21ed4c5f12e0 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java
+++ b/core/tests/coretests/src/android/app/SearchManagerTest.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.app;
-import com.android.unit_tests.activity.LocalActivity;
+import android.app.activity.LocalActivity;
import android.app.Activity;
import android.app.ISearchManager;
@@ -39,8 +39,8 @@ import android.test.suitebuilder.annotation.MediumTest;
public class SearchManagerTest extends ActivityInstrumentationTestCase2<LocalActivity> {
private ComponentName SEARCHABLE_ACTIVITY =
- new ComponentName("com.android.unit_tests",
- "com.android.unit_tests.SearchableActivity");
+ new ComponentName("com.android.frameworks.coretests",
+ "android.app.activity.SearchableActivity");
/*
* Bug list of test ideas.
@@ -76,7 +76,7 @@ public class SearchManagerTest extends ActivityInstrumentationTestCase2<LocalAct
Context mContext;
public SearchManagerTest() {
- super("com.android.unit_tests", LocalActivity.class);
+ super("com.android.frameworks.coretests", LocalActivity.class);
}
/**
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java b/core/tests/coretests/src/android/app/SearchablesTest.java
index 972559df3802..9b4520e948ad 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java
+++ b/core/tests/coretests/src/android/app/SearchablesTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.app;
import android.app.SearchManager;
import android.app.SearchableInfo;
@@ -108,8 +108,8 @@ public class SearchablesTest extends AndroidTestCase {
// confirm that we return null for non-searchy activities
ComponentName nonActivity = new ComponentName(
- "com.android.unit_tests",
- "com.android.unit_tests.NO_SEARCH_ACTIVITY");
+ "com.android.frameworks.coretests",
+ "com.android.frameworks.coretests.activity.NO_SEARCH_ACTIVITY");
SearchableInfo si = searchables.getSearchableInfo(nonActivity);
assertNull(si);
}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SuggestionProvider.java b/core/tests/coretests/src/android/app/SuggestionProvider.java
index bc61e27b10df..9fb7dcf82506 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SuggestionProvider.java
+++ b/core/tests/coretests/src/android/app/SuggestionProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.app;
import android.app.SearchManager;
import android.content.ContentProvider;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/AbortReceiver.java b/core/tests/coretests/src/android/app/activity/AbortReceiver.java
index d9d6101e93ae..fef177539ec4 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/AbortReceiver.java
+++ b/core/tests/coretests/src/android/app/activity/AbortReceiver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.Context;
import android.content.Intent;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityManagerTest.java b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
index ab9176140312..61d73bc918d5 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityManagerTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.ActivityManager;
import android.content.Context;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTests.java b/core/tests/coretests/src/android/app/activity/ActivityTests.java
index cffc60a69505..c57fe980962e 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTests.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import junit.framework.TestSuite;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTestsBase.java b/core/tests/coretests/src/android/app/activity/ActivityTestsBase.java
index f9609698c7ed..232abe281e0f 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/ActivityTestsBase.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityTestsBase.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.Activity;
import android.content.Context;
@@ -25,9 +25,9 @@ import android.test.PerformanceTestCase;
public class ActivityTestsBase extends AndroidTestCase
implements PerformanceTestCase, LaunchpadActivity.CallingTest {
public static final String PERMISSION_GRANTED =
- "com.android.unit_tests.permission.TEST_GRANTED";
+ "com.android.frameworks.coretests.permission.TEST_GRANTED";
public static final String PERMISSION_DENIED =
- "com.android.unit_tests.permission.TEST_DENIED";
+ "com.android.frameworks.coretests.permission.TEST_DENIED";
protected Intent mIntent;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/BroadcastTest.java b/core/tests/coretests/src/android/app/activity/BroadcastTest.java
index 7f6db3c42498..4b1f9fddc6e4 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/BroadcastTest.java
+++ b/core/tests/coretests/src/android/app/activity/BroadcastTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.Activity;
import android.app.ActivityManagerNative;
@@ -36,35 +36,35 @@ public class BroadcastTest extends ActivityTestsBase {
public static final int BROADCAST_TIMEOUT = 5 * 1000;
public static final String BROADCAST_REGISTERED =
- "com.android.unit_tests.activity.BROADCAST_REGISTERED";
+ "com.android.frameworks.coretests.activity.BROADCAST_REGISTERED";
public static final String BROADCAST_LOCAL =
- "com.android.unit_tests.activity.BROADCAST_LOCAL";
+ "com.android.frameworks.coretests.activity.BROADCAST_LOCAL";
public static final String BROADCAST_LOCAL_GRANTED =
- "com.android.unit_tests.activity.BROADCAST_LOCAL_GRANTED";
+ "com.android.frameworks.coretests.activity.BROADCAST_LOCAL_GRANTED";
public static final String BROADCAST_LOCAL_DENIED =
- "com.android.unit_tests.activity.BROADCAST_LOCAL_DENIED";
+ "com.android.frameworks.coretests.activity.BROADCAST_LOCAL_DENIED";
public static final String BROADCAST_REMOTE =
- "com.android.unit_tests.activity.BROADCAST_REMOTE";
+ "com.android.frameworks.coretests.activity.BROADCAST_REMOTE";
public static final String BROADCAST_REMOTE_GRANTED =
- "com.android.unit_tests.activity.BROADCAST_REMOTE_GRANTED";
+ "com.android.frameworks.coretests.activity.BROADCAST_REMOTE_GRANTED";
public static final String BROADCAST_REMOTE_DENIED =
- "com.android.unit_tests.activity.BROADCAST_REMOTE_DENIED";
+ "com.android.frameworks.coretests.activity.BROADCAST_REMOTE_DENIED";
public static final String BROADCAST_ALL =
- "com.android.unit_tests.activity.BROADCAST_ALL";
+ "com.android.frameworks.coretests.activity.BROADCAST_ALL";
public static final String BROADCAST_MULTI =
- "com.android.unit_tests.activity.BROADCAST_MULTI";
+ "com.android.frameworks.coretests.activity.BROADCAST_MULTI";
public static final String BROADCAST_ABORT =
- "com.android.unit_tests.activity.BROADCAST_ABORT";
+ "com.android.frameworks.coretests.activity.BROADCAST_ABORT";
public static final String BROADCAST_STICKY1 =
- "com.android.unit_tests.activity.BROADCAST_STICKY1";
+ "com.android.frameworks.coretests.activity.BROADCAST_STICKY1";
public static final String BROADCAST_STICKY2 =
- "com.android.unit_tests.activity.BROADCAST_STICKY2";
+ "com.android.frameworks.coretests.activity.BROADCAST_STICKY2";
public static final String BROADCAST_FAIL_REGISTER =
- "com.android.unit_tests.activity.BROADCAST_FAIL_REGISTER";
+ "com.android.frameworks.coretests.activity.BROADCAST_FAIL_REGISTER";
public static final String BROADCAST_FAIL_BIND =
- "com.android.unit_tests.activity.BROADCAST_FAIL_BIND";
+ "com.android.frameworks.coretests.activity.BROADCAST_FAIL_BIND";
public static final String RECEIVER_REG = "receiver-reg";
public static final String RECEIVER_LOCAL = "receiver-local";
@@ -276,7 +276,7 @@ public class BroadcastTest extends ActivityTestsBase {
map.putString("foo", "you");
map.putString("remove", "me");
getContext().sendOrderedBroadcast(
- new Intent("com.android.unit_tests.activity.BROADCAST_RESULT"),
+ new Intent("com.android.frameworks.coretests.activity.BROADCAST_RESULT"),
null, broadcastReceiver, null, 1, "foo", map);
while (!broadcastReceiver.mHaveResult) {
try {
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ClearTop.java b/core/tests/coretests/src/android/app/activity/ClearTop.java
index dd5274a32002..a5ee2ce64786 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/ClearTop.java
+++ b/core/tests/coretests/src/android/app/activity/ClearTop.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.Activity;
import android.content.Intent;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/IntentSenderTest.java b/core/tests/coretests/src/android/app/activity/IntentSenderTest.java
index a30c1cbf7742..3c309154eedc 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/IntentSenderTest.java
+++ b/core/tests/coretests/src/android/app/activity/IntentSenderTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.Activity;
import android.app.PendingIntent;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchTest.java b/core/tests/coretests/src/android/app/activity/LaunchTest.java
index 12b1b5d7d780..5893fd092211 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchTest.java
+++ b/core/tests/coretests/src/android/app/activity/LaunchTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.ComponentName;
import android.test.suitebuilder.annotation.LargeTest;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadActivity.java b/core/tests/coretests/src/android/app/activity/LaunchpadActivity.java
index 06e7a84758aa..766245600d13 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadActivity.java
+++ b/core/tests/coretests/src/android/app/activity/LaunchpadActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.Activity;
import android.content.BroadcastReceiver;
@@ -71,49 +71,49 @@ public class LaunchpadActivity extends Activity {
}
// Also used as the Binder interface descriptor string in these tests
- public static final String LAUNCH = "com.android.unit_tests.activity.LAUNCH";
+ public static final String LAUNCH = "com.android.frameworks.coretests.activity.LAUNCH";
public static final String FORWARD_RESULT =
- "com.android.unit_tests.activity.FORWARD_RESULT";
+ "com.android.frameworks.coretests.activity.FORWARD_RESULT";
public static final String RETURNED_RESULT =
- "com.android.unit_tests.activity.RETURNED_RESULT";
+ "com.android.frameworks.coretests.activity.RETURNED_RESULT";
public static final String BAD_PARCELABLE =
- "com.android.unit_tests.activity.BAD_PARCELABLE";
+ "comcom.android.frameworks.coretests.activity.BAD_PARCELABLE";
public static final int LAUNCHED_RESULT = 1;
public static final int FORWARDED_RESULT = 2;
public static final String LIFECYCLE_BASIC =
- "com.android.unit_tests.activity.LIFECYCLE_BASIC";
+ "com.android.frameworks.coretests.activity.LIFECYCLE_BASIC";
public static final String LIFECYCLE_SCREEN =
- "com.android.unit_tests.activity.LIFECYCLE_SCREEN";
+ "com.android.frameworks.coretests.activity.LIFECYCLE_SCREEN";
public static final String LIFECYCLE_DIALOG =
- "com.android.unit_tests.activity.LIFECYCLE_DIALOG";
+ "com.android.frameworks.coretests.activity.LIFECYCLE_DIALOG";
public static final String LIFECYCLE_FINISH_CREATE =
- "com.android.unit_tests.activity.LIFECYCLE_FINISH_CREATE";
+ "com.android.frameworks.coretests.activity.LIFECYCLE_FINISH_CREATE";
public static final String LIFECYCLE_FINISH_START =
- "com.android.unit_tests.activity.LIFECYCLE_FINISH_START";
+ "com.android.frameworks.coretests.activity.LIFECYCLE_FINISH_START";
public static final String BROADCAST_REGISTERED =
- "com.android.unit_tests.activity.BROADCAST_REGISTERED";
+ "com.android.frameworks.coretests.activity.BROADCAST_REGISTERED";
public static final String BROADCAST_LOCAL =
- "com.android.unit_tests.activity.BROADCAST_LOCAL";
+ "com.android.frameworks.coretests.activity.BROADCAST_LOCAL";
public static final String BROADCAST_REMOTE =
- "com.android.unit_tests.activity.BROADCAST_REMOTE";
+ "com.android.frameworks.coretests.activity.BROADCAST_REMOTE";
public static final String BROADCAST_ALL =
- "com.android.unit_tests.activity.BROADCAST_ALL";
+ "com.android.frameworks.coretests.activity.BROADCAST_ALL";
public static final String BROADCAST_REPEAT =
- "com.android.unit_tests.activity.BROADCAST_REPEAT";
+ "com.android.frameworks.coretests.activity.BROADCAST_REPEAT";
public static final String BROADCAST_MULTI =
- "com.android.unit_tests.activity.BROADCAST_MULTI";
+ "com.android.frameworks.coretests.activity.BROADCAST_MULTI";
public static final String BROADCAST_ABORT =
- "com.android.unit_tests.activity.BROADCAST_ABORT";
+ "com.android.frameworks.coretests.activity.BROADCAST_ABORT";
public static final String BROADCAST_STICKY1 =
- "com.android.unit_tests.activity.BROADCAST_STICKY1";
+ "com.android.frameworks.coretests.activity.BROADCAST_STICKY1";
public static final String BROADCAST_STICKY2 =
- "com.android.unit_tests.activity.BROADCAST_STICKY2";
+ "com.android.frameworks.coretests.activity.BROADCAST_STICKY2";
public static final String RECEIVER_REG = "receiver-reg";
public static final String RECEIVER_LOCAL = "receiver-local";
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadTabActivity.java b/core/tests/coretests/src/android/app/activity/LaunchpadTabActivity.java
index 1e0e4a62cc97..79b860f6f671 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LaunchpadTabActivity.java
+++ b/core/tests/coretests/src/android/app/activity/LaunchpadTabActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.TabActivity;
import android.content.ComponentName;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LifecycleTest.java b/core/tests/coretests/src/android/app/activity/LifecycleTest.java
index 069b697d373f..768a9a446e08 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LifecycleTest.java
+++ b/core/tests/coretests/src/android/app/activity/LifecycleTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.ComponentName;
import android.content.Intent;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalActivity.java b/core/tests/coretests/src/android/app/activity/LocalActivity.java
index 3c107be8a9ae..01f1fb69a16f 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalActivity.java
+++ b/core/tests/coretests/src/android/app/activity/LocalActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import java.util.Map;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedReceiver.java b/core/tests/coretests/src/android/app/activity/LocalDeniedReceiver.java
index ac235c0200d6..2120a1db463c 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedReceiver.java
+++ b/core/tests/coretests/src/android/app/activity/LocalDeniedReceiver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedService.java b/core/tests/coretests/src/android/app/activity/LocalDeniedService.java
index 0473ea9e906d..3bdac22d9f1f 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDeniedService.java
+++ b/core/tests/coretests/src/android/app/activity/LocalDeniedService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
public class LocalDeniedService extends LocalService
{
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDialog.java b/core/tests/coretests/src/android/app/activity/LocalDialog.java
index 36943752949d..c92fa43c59fb 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalDialog.java
+++ b/core/tests/coretests/src/android/app/activity/LocalDialog.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import java.util.Map;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedReceiver.java b/core/tests/coretests/src/android/app/activity/LocalGrantedReceiver.java
index 48f5658b1812..c9e6ab4a57d6 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedReceiver.java
+++ b/core/tests/coretests/src/android/app/activity/LocalGrantedReceiver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedService.java b/core/tests/coretests/src/android/app/activity/LocalGrantedService.java
index 0dbcd002f196..7ab0fb4d372c 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalGrantedService.java
+++ b/core/tests/coretests/src/android/app/activity/LocalGrantedService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
public class LocalGrantedService extends LocalService
{
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalProvider.java b/core/tests/coretests/src/android/app/activity/LocalProvider.java
index a3375bdedf3f..085e62280d1e 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalProvider.java
+++ b/core/tests/coretests/src/android/app/activity/LocalProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.UriMatcher;
import android.content.*;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalReceiver.java b/core/tests/coretests/src/android/app/activity/LocalReceiver.java
index 019c5c09e906..bfd543fdbe12 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalReceiver.java
+++ b/core/tests/coretests/src/android/app/activity/LocalReceiver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalScreen.java b/core/tests/coretests/src/android/app/activity/LocalScreen.java
index ad65fcc5d9d5..f7c8c33fcaeb 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalScreen.java
+++ b/core/tests/coretests/src/android/app/activity/LocalScreen.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import java.util.Map;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalService.java b/core/tests/coretests/src/android/app/activity/LocalService.java
index d79205d33fb2..c31ca4b30a76 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/LocalService.java
+++ b/core/tests/coretests/src/android/app/activity/LocalService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.Service;
import android.content.Intent;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/MetaDataTest.java b/core/tests/coretests/src/android/app/activity/MetaDataTest.java
index 4660e29607da..214bc9106cdc 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/MetaDataTest.java
+++ b/core/tests/coretests/src/android/app/activity/MetaDataTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
@@ -29,7 +29,7 @@ import android.os.Bundle;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.unit_tests.R;
+import com.android.frameworks.coretests.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -47,18 +47,18 @@ public class MetaDataTest extends AndroidTestCase {
Bundle md = ci.metaData;
assertNotNull("No meta data found", md);
- assertEquals("foo", md.getString("com.android.unit_tests.string"));
- assertTrue(md.getBoolean("com.android.unit_tests.boolean"));
- assertEquals(100, md.getInt("com.android.unit_tests.integer"));
- assertEquals(0xff000000, md.getInt("com.android.unit_tests.color"));
+ assertEquals("foo", md.getString("com.android.frameworks.coretests.string"));
+ assertTrue(md.getBoolean("com.android.frameworks.coretests.boolean"));
+ assertEquals(100, md.getInt("com.android.frameworks.coretests.integer"));
+ assertEquals(0xff000000, md.getInt("com.android.frameworks.coretests.color"));
assertEquals((double) 1001,
- Math.floor(md.getFloat("com.android.unit_tests.float") * 10 + .5));
+ Math.floor(md.getFloat("com.android.frameworks.coretests.float") * 10 + .5));
- assertEquals(R.xml.metadata, md.getInt("com.android.unit_tests.reference"));
+ assertEquals(R.xml.metadata, md.getInt("com.android.frameworks.coretests.reference"));
XmlResourceParser xml = ci.loadXmlMetaData(mContext.getPackageManager(),
- "com.android.unit_tests.reference");
+ "com.android.frameworks.coretests.reference");
assertNotNull(xml);
int type;
@@ -138,12 +138,12 @@ public class MetaDataTest extends AndroidTestCase {
public void testProviderWithData() throws Exception {
ComponentName cn = new ComponentName(mContext, LocalProvider.class);
ProviderInfo pi = mContext.getPackageManager().resolveContentProvider(
- "com.android.unit_tests.LocalProvider",
+ "com.android.frameworks.coretests.LocalProvider",
PackageManager.GET_META_DATA);
checkMetaData(cn, pi);
pi = mContext.getPackageManager().resolveContentProvider(
- "com.android.unit_tests.LocalProvider", 0);
+ "com.android.frameworks.coretests.LocalProvider", 0);
assertNull("Meta data returned when not requested", pi.metaData);
}
@@ -151,7 +151,7 @@ public class MetaDataTest extends AndroidTestCase {
@SmallTest
public void testPermissionWithData() throws Exception {
ComponentName cn = new ComponentName("foo",
- "com.android.unit_tests.permission.TEST_GRANTED");
+ "com.android.frameworks.coretests.permission.TEST_GRANTED");
PermissionInfo pi = mContext.getPackageManager().getPermissionInfo(
cn.getClassName(), PackageManager.GET_META_DATA);
checkMetaData(cn, pi);
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteDeniedReceiver.java b/core/tests/coretests/src/android/app/activity/RemoteDeniedReceiver.java
index 76565801317b..7c89346e820d 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteDeniedReceiver.java
+++ b/core/tests/coretests/src/android/app/activity/RemoteDeniedReceiver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteGrantedReceiver.java b/core/tests/coretests/src/android/app/activity/RemoteGrantedReceiver.java
index 034aa1df38aa..0eca8f7f04a7 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteGrantedReceiver.java
+++ b/core/tests/coretests/src/android/app/activity/RemoteGrantedReceiver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteReceiver.java b/core/tests/coretests/src/android/app/activity/RemoteReceiver.java
index 818bffe62507..9608fc4b4dff 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteReceiver.java
+++ b/core/tests/coretests/src/android/app/activity/RemoteReceiver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.Context;
import android.content.Intent;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteSubActivityScreen.java b/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java
index e750ed6e753e..e969d10403cf 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/RemoteSubActivityScreen.java
+++ b/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java
@@ -15,7 +15,7 @@
** limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.Intent;
import android.os.Bundle;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ResultReceiver.java b/core/tests/coretests/src/android/app/activity/ResultReceiver.java
index 4b5d46808825..f7daf2ca64e7 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/ResultReceiver.java
+++ b/core/tests/coretests/src/android/app/activity/ResultReceiver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.Context;
import android.content.Intent;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchableActivity.java b/core/tests/coretests/src/android/app/activity/SearchableActivity.java
index 53f40e992847..e2385729f688 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SearchableActivity.java
+++ b/core/tests/coretests/src/android/app/activity/SearchableActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.app.activity;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/ServiceTest.java b/core/tests/coretests/src/android/app/activity/ServiceTest.java
index 95f6e362f065..d3ae415223e0 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/ServiceTest.java
+++ b/core/tests/coretests/src/android/app/activity/ServiceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.content.ComponentName;
import android.content.Context;
@@ -38,11 +38,11 @@ import android.util.Log;
public class ServiceTest extends ActivityTestsBase {
public static final String SERVICE_LOCAL =
- "com.android.unit_tests.activity.SERVICE_LOCAL";
+ "com.android.frameworks.coretests.activity.SERVICE_LOCAL";
public static final String SERVICE_LOCAL_GRANTED =
- "com.android.unit_tests.activity.SERVICE_LOCAL_GRANTED";
+ "com.android.frameworks.coretests.activity.SERVICE_LOCAL_GRANTED";
public static final String SERVICE_LOCAL_DENIED =
- "com.android.unit_tests.activity.SERVICE_LOCAL_DENIED";
+ "com.android.frameworks.coretests.activity.SERVICE_LOCAL_DENIED";
public static final String REPORT_OBJ_NAME = "report";
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/SetTimeZonePermissionsTest.java b/core/tests/coretests/src/android/app/activity/SetTimeZonePermissionsTest.java
index 1fa7579fc614..41b95476baf3 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/SetTimeZonePermissionsTest.java
+++ b/core/tests/coretests/src/android/app/activity/SetTimeZonePermissionsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.AlarmManager;
import android.content.Context;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityScreen.java b/core/tests/coretests/src/android/app/activity/SubActivityScreen.java
index 914b909fd3cb..919c59150bb4 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityScreen.java
+++ b/core/tests/coretests/src/android/app/activity/SubActivityScreen.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.Activity;
import android.app.PendingIntent;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityTest.java b/core/tests/coretests/src/android/app/activity/SubActivityTest.java
index ee02c98b4de2..35dde8a51567 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/SubActivityTest.java
+++ b/core/tests/coretests/src/android/app/activity/SubActivityTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.test.suitebuilder.annotation.Suppress;
import android.content.ComponentName;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/TestedActivity.java b/core/tests/coretests/src/android/app/activity/TestedActivity.java
index ec407a9b9655..3a1c15f24903 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/TestedActivity.java
+++ b/core/tests/coretests/src/android/app/activity/TestedActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.Activity;
import android.os.Handler;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/activity/TestedScreen.java b/core/tests/coretests/src/android/app/activity/TestedScreen.java
index 4085aa95c2b5..1682d1a99350 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/activity/TestedScreen.java
+++ b/core/tests/coretests/src/android/app/activity/TestedScreen.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.activity;
+package android.app.activity;
import android.app.Activity;
import android.content.Intent;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/AssetTest.java b/core/tests/coretests/src/android/content/AssetTest.java
index f38d062283e3..b66574cee231 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/content/AssetTest.java
+++ b/core/tests/coretests/src/android/content/AssetTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.content;
+package android.content;
import android.content.res.AssetManager;
import android.test.AndroidTestCase;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/ContentQueryMapTest.java b/core/tests/coretests/src/android/content/ContentQueryMapTest.java
index 241a1bf8f3d4..d1b8c24b3fe8 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/ContentQueryMapTest.java
+++ b/core/tests/coretests/src/android/content/ContentQueryMapTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.content;
import android.content.ContentQueryMap;
import android.content.ContentResolver;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ContentTests.java b/core/tests/coretests/src/android/content/ContentTests.java
index 636660f8d48e..a1299e3a0e8d 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/content/ContentTests.java
+++ b/core/tests/coretests/src/android/content/ContentTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.content;
+package android.content;
import junit.framework.TestSuite;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/MemoryFileProvider.java b/core/tests/coretests/src/android/content/MemoryFileProvider.java
index b31ce18da429..c4bc7678820f 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/content/MemoryFileProvider.java
+++ b/core/tests/coretests/src/android/content/MemoryFileProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.content;
+package android.content;
import android.content.ContentProvider;
import android.content.ContentValues;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/MemoryFileProviderTest.java b/core/tests/coretests/src/android/content/MemoryFileProviderTest.java
index f88a9dac3962..6708af6e83d8 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/content/MemoryFileProviderTest.java
+++ b/core/tests/coretests/src/android/content/MemoryFileProviderTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.content;
+package android.content;
import android.content.ContentResolver;
import android.net.Uri;
@@ -34,7 +34,7 @@ public class MemoryFileProviderTest extends AndroidTestCase {
@MediumTest
public void testRead() throws Exception {
ContentResolver resolver = getContext().getContentResolver();
- Uri uri = Uri.parse("content://com.android.unit_tests.content.MemoryFileProvider/data/1/blob");
+ Uri uri = Uri.parse("content://android.content.MemoryFileProvider/data/1/blob");
byte[] buf = new byte[MemoryFileProvider.TEST_BLOB.length];
InputStream in = resolver.openInputStream(uri);
assertNotNull(in);
@@ -52,7 +52,7 @@ public class MemoryFileProviderTest extends AndroidTestCase {
// open enough file descriptors that we will crash something if we leak FDs
// or address space
for (int i = 0; i < 1025; i++) {
- Uri uri = Uri.parse("content://com.android.unit_tests.content.MemoryFileProvider/huge");
+ Uri uri = Uri.parse("content://android.content.MemoryFileProvider/huge");
InputStream in = resolver.openInputStream(uri);
assertNotNull("Failed to open stream number " + i, in);
assertEquals(1000000, in.skip(1000000));
@@ -68,7 +68,7 @@ public class MemoryFileProviderTest extends AndroidTestCase {
@MediumTest
public void testFile() throws Exception {
ContentResolver resolver = getContext().getContentResolver();
- Uri uri = Uri.parse("content://com.android.unit_tests.content.MemoryFileProvider/file");
+ Uri uri = Uri.parse("content://android.content.MemoryFileProvider/file");
byte[] buf = new byte[MemoryFileProvider.TEST_BLOB.length];
InputStream in = resolver.openInputStream(uri);
assertNotNull(in);
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CursorWindowTest.java b/core/tests/coretests/src/android/database/CursorWindowTest.java
index 0247355901e7..07e75cb5b318 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/CursorWindowTest.java
+++ b/core/tests/coretests/src/android/database/CursorWindowTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.database;
import android.database.AbstractCursor;
import android.test.suitebuilder.annotation.SmallTest;
diff --git a/core/tests/coretests/src/android/database/DatabaseCursorTest.java b/core/tests/coretests/src/android/database/DatabaseCursorTest.java
new file mode 100644
index 000000000000..fad43498ee89
--- /dev/null
+++ b/core/tests/coretests/src/android/database/DatabaseCursorTest.java
@@ -0,0 +1,630 @@
+/*
+ * 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.database;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.CursorIndexOutOfBoundsException;
+import android.database.DataSetObserver;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteCursor;
+import android.database.sqlite.SQLiteCursorDriver;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQuery;
+import android.database.sqlite.SQLiteStatement;
+import android.os.Looper;
+import android.test.AndroidTestCase;
+import android.test.PerformanceTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.util.Log;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+public class DatabaseCursorTest extends AndroidTestCase implements PerformanceTestCase {
+
+ private static final String sString1 = "this is a test";
+ private static final String sString2 = "and yet another test";
+ private static final String sString3 = "this string is a little longer, but still a test";
+
+ private static final int CURRENT_DATABASE_VERSION = 42;
+ private SQLiteDatabase mDatabase;
+ private File mDatabaseFile;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ File dbDir = getContext().getDir("tests", Context.MODE_PRIVATE);
+ mDatabaseFile = new File(dbDir, "database_test.db");
+
+ if (mDatabaseFile.exists()) {
+ mDatabaseFile.delete();
+ }
+ mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
+ assertNotNull(mDatabase);
+ mDatabase.setVersion(CURRENT_DATABASE_VERSION);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mDatabase.close();
+ mDatabaseFile.delete();
+ super.tearDown();
+ }
+
+ public boolean isPerformanceOnly() {
+ return false;
+ }
+
+ // These test can only be run once.
+ public int startPerformance(Intermediates intermediates) {
+ return 1;
+ }
+
+ private void populateDefaultTable() {
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);");
+
+ mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString1 + "');");
+ mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString2 + "');");
+ mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString3 + "');");
+ }
+
+ @MediumTest
+ public void testCursorUpdate() {
+ mDatabase.execSQL(
+ "CREATE TABLE test (_id INTEGER PRIMARY KEY, d INTEGER, s INTEGER);");
+ for(int i = 0; i < 20; i++) {
+ mDatabase.execSQL("INSERT INTO test (d, s) VALUES (" + i +
+ "," + i%2 + ");");
+ }
+
+ Cursor c = mDatabase.query("test", null, "s = 0", null, null, null, null);
+ int dCol = c.getColumnIndexOrThrow("d");
+ int sCol = c.getColumnIndexOrThrow("s");
+
+ int count = 0;
+ while (c.moveToNext()) {
+ assertTrue(c.updateInt(dCol, 3));
+ count++;
+ }
+ assertEquals(10, count);
+
+ assertTrue(c.commitUpdates());
+
+ assertTrue(c.requery());
+
+ count = 0;
+ while (c.moveToNext()) {
+ assertEquals(3, c.getInt(dCol));
+ count++;
+ }
+
+ assertEquals(10, count);
+ assertTrue(c.moveToFirst());
+ assertTrue(c.deleteRow());
+ assertEquals(9, c.getCount());
+ c.close();
+ }
+
+ @MediumTest
+ public void testBlob() throws Exception {
+ // create table
+ mDatabase.execSQL(
+ "CREATE TABLE test (_id INTEGER PRIMARY KEY, s TEXT, d REAL, l INTEGER, b BLOB);");
+ // insert blob
+ Object[] args = new Object[4];
+
+ byte[] blob = new byte[1000];
+ byte value = 99;
+ Arrays.fill(blob, value);
+ args[3] = blob;
+
+ String s = new String("text");
+ args[0] = s;
+ Double d = 99.9;
+ args[1] = d;
+ Long l = (long)1000;
+ args[2] = l;
+
+ String sql = "INSERT INTO test (s, d, l, b) VALUES (?,?,?,?)";
+ mDatabase.execSQL(sql, args);
+ // use cursor to access blob
+ Cursor c = mDatabase.query("test", null, null, null, null, null, null);
+ c.moveToNext();
+ ContentValues cv = new ContentValues();
+ DatabaseUtils.cursorRowToContentValues(c, cv);
+
+ int bCol = c.getColumnIndexOrThrow("b");
+ int sCol = c.getColumnIndexOrThrow("s");
+ int dCol = c.getColumnIndexOrThrow("d");
+ int lCol = c.getColumnIndexOrThrow("l");
+ byte[] cBlob = c.getBlob(bCol);
+ assertTrue(Arrays.equals(blob, cBlob));
+ assertEquals(s, c.getString(sCol));
+ assertEquals((double)d, c.getDouble(dCol));
+ assertEquals((long)l, c.getLong(lCol));
+
+ // new byte[]
+ byte[] newblob = new byte[1000];
+ value = 98;
+ Arrays.fill(blob, value);
+
+ c.updateBlob(bCol, newblob);
+ cBlob = c.getBlob(bCol);
+ assertTrue(Arrays.equals(newblob, cBlob));
+
+ // commit
+ assertTrue(c.commitUpdates());
+ assertTrue(c.requery());
+ c.moveToNext();
+ cBlob = c.getBlob(bCol);
+ assertTrue(Arrays.equals(newblob, cBlob));
+ c.close();
+ }
+
+ @MediumTest
+ public void testRealColumns() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data REAL);");
+ ContentValues values = new ContentValues();
+ values.put("data", 42.11);
+ long id = mDatabase.insert("test", "data", values);
+ assertTrue(id > 0);
+ Cursor c = mDatabase.rawQuery("SELECT data FROM test", null);
+ assertNotNull(c);
+ assertTrue(c.moveToFirst());
+ assertEquals(42.11, c.getDouble(0));
+ c.close();
+ }
+
+ @MediumTest
+ public void testCursor1() throws Exception {
+ populateDefaultTable();
+
+ Cursor c = mDatabase.query("test", null, null, null, null, null, null);
+
+ int dataColumn = c.getColumnIndexOrThrow("data");
+
+ // The cursor should ignore text before the last period when looking for a column. (This
+ // is a temporary hack in all implementations of getColumnIndex.)
+ int dataColumn2 = c.getColumnIndexOrThrow("junk.data");
+ assertEquals(dataColumn, dataColumn2);
+
+ assertSame(3, c.getCount());
+
+ assertTrue(c.isBeforeFirst());
+
+ try {
+ c.getInt(0);
+ fail("CursorIndexOutOfBoundsException expected");
+ } catch (CursorIndexOutOfBoundsException ex) {
+ // expected
+ }
+
+ c.moveToNext();
+ assertEquals(1, c.getInt(0));
+
+ String s = c.getString(dataColumn);
+ assertEquals(sString1, s);
+
+ c.moveToNext();
+ s = c.getString(dataColumn);
+ assertEquals(sString2, s);
+
+ c.moveToNext();
+ s = c.getString(dataColumn);
+ assertEquals(sString3, s);
+
+ c.moveToPosition(-1);
+ c.moveToNext();
+ s = c.getString(dataColumn);
+ assertEquals(sString1, s);
+
+ c.moveToPosition(2);
+ s = c.getString(dataColumn);
+ assertEquals(sString3, s);
+
+ int i;
+
+ for (c.moveToFirst(), i = 0; !c.isAfterLast(); c.moveToNext(), i++) {
+ c.getInt(0);
+ }
+
+ assertEquals(3, i);
+
+ try {
+ c.getInt(0);
+ fail("CursorIndexOutOfBoundsException expected");
+ } catch (CursorIndexOutOfBoundsException ex) {
+ // expected
+ }
+ c.close();
+ }
+
+ @MediumTest
+ public void testCursor2() throws Exception {
+ populateDefaultTable();
+
+ Cursor c = mDatabase.query("test", null, "_id > 1000", null, null, null, null);
+ assertEquals(0, c.getCount());
+ assertTrue(c.isBeforeFirst());
+
+ try {
+ c.getInt(0);
+ fail("CursorIndexOutOfBoundsException expected");
+ } catch (CursorIndexOutOfBoundsException ex) {
+ // expected
+ }
+
+ int i;
+ for (c.moveToFirst(), i = 0; !c.isAfterLast(); c.moveToNext(), i++) {
+ c.getInt(0);
+ }
+ assertEquals(0, i);
+ try {
+ c.getInt(0);
+ fail("CursorIndexOutOfBoundsException expected");
+ } catch (CursorIndexOutOfBoundsException ex) {
+ // expected
+ }
+ c.close();
+ }
+
+ @MediumTest
+ public void testLargeField() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);");
+
+ StringBuilder sql = new StringBuilder(2100);
+ sql.append("INSERT INTO test (data) VALUES ('");
+ Random random = new Random(System.currentTimeMillis());
+ StringBuilder randomString = new StringBuilder(1979);
+ for (int i = 0; i < 1979; i++) {
+ randomString.append((random.nextInt() & 0xf) % 10);
+ }
+ sql.append(randomString);
+ sql.append("');");
+ mDatabase.execSQL(sql.toString());
+
+ Cursor c = mDatabase.query("test", null, null, null, null, null, null);
+ assertNotNull(c);
+ assertEquals(1, c.getCount());
+
+ assertTrue(c.moveToFirst());
+ assertEquals(0, c.getPosition());
+ String largeString = c.getString(c.getColumnIndexOrThrow("data"));
+ assertNotNull(largeString);
+ assertEquals(randomString.toString(), largeString);
+ c.close();
+ }
+
+ class TestObserver extends DataSetObserver {
+ int total;
+ SQLiteCursor c;
+ boolean quit = false;
+ public TestObserver(int total_, SQLiteCursor cursor) {
+ c = cursor;
+ total = total_;
+ }
+
+ @Override
+ public void onChanged() {
+ int count = c.getCount();
+ if (total == count) {
+ int i = 0;
+ while (c.moveToNext()) {
+ assertEquals(i, c.getInt(1));
+ i++;
+ }
+ assertEquals(count, i);
+ quit = true;
+ Looper.myLooper().quit();
+ }
+ }
+
+ @Override
+ public void onInvalidated() {
+ }
+ }
+
+ //@Large
+ @Suppress
+ public void testLoadingThreadDelayRegisterData() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data INT);");
+
+ final int count = 505;
+ String sql = "INSERT INTO test (data) VALUES (?);";
+ SQLiteStatement s = mDatabase.compileStatement(sql);
+ for (int i = 0; i < count; i++) {
+ s.bindLong(1, i);
+ s.execute();
+ }
+
+ int maxRead = 500;
+ int initialRead = 5;
+ SQLiteCursor c = (SQLiteCursor)mDatabase.rawQuery("select * from test;",
+ null, initialRead, maxRead);
+
+ TestObserver observer = new TestObserver(count, c);
+ c.getCount();
+ c.registerDataSetObserver(observer);
+ if (!observer.quit) {
+ Looper.loop();
+ }
+ c.close();
+ }
+
+ @LargeTest
+ public void testLoadingThread() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data INT);");
+
+ final int count = 50000;
+ String sql = "INSERT INTO test (data) VALUES (?);";
+ SQLiteStatement s = mDatabase.compileStatement(sql);
+ for (int i = 0; i < count; i++) {
+ s.bindLong(1, i);
+ s.execute();
+ }
+
+ int maxRead = 1000;
+ int initialRead = 5;
+ SQLiteCursor c = (SQLiteCursor)mDatabase.rawQuery("select * from test;",
+ null, initialRead, maxRead);
+
+ TestObserver observer = new TestObserver(count, c);
+ c.registerDataSetObserver(observer);
+ c.getCount();
+
+ Looper.loop();
+ c.close();
+ }
+
+ @LargeTest
+ public void testLoadingThreadClose() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data INT);");
+
+ final int count = 1000;
+ String sql = "INSERT INTO test (data) VALUES (?);";
+ SQLiteStatement s = mDatabase.compileStatement(sql);
+ for (int i = 0; i < count; i++) {
+ s.bindLong(1, i);
+ s.execute();
+ }
+
+ int maxRead = 11;
+ int initialRead = 5;
+ SQLiteCursor c = (SQLiteCursor)mDatabase.rawQuery("select * from test;",
+ null, initialRead, maxRead);
+
+ TestObserver observer = new TestObserver(count, c);
+ c.registerDataSetObserver(observer);
+ c.getCount();
+ c.close();
+ }
+
+ @LargeTest
+ public void testLoadingThreadDeactivate() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data INT);");
+
+ final int count = 1000;
+ String sql = "INSERT INTO test (data) VALUES (?);";
+ SQLiteStatement s = mDatabase.compileStatement(sql);
+ for (int i = 0; i < count; i++) {
+ s.bindLong(1, i);
+ s.execute();
+ }
+
+ int maxRead = 11;
+ int initialRead = 5;
+ SQLiteCursor c = (SQLiteCursor)mDatabase.rawQuery("select * from test;",
+ null, initialRead, maxRead);
+
+ TestObserver observer = new TestObserver(count, c);
+ c.registerDataSetObserver(observer);
+ c.getCount();
+ c.deactivate();
+ c.close();
+ }
+
+ @LargeTest
+ public void testManyRowsLong() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data INT);");
+
+ final int count = 36799;
+ for (int i = 0; i < count; i++) {
+ mDatabase.execSQL("INSERT INTO test (data) VALUES (" + i + ");");
+ }
+
+ Cursor c = mDatabase.query("test", new String[]{"data"}, null, null, null, null, null);
+ assertNotNull(c);
+
+ int i = 0;
+ while (c.moveToNext()) {
+ assertEquals(i, c.getInt(0));
+ i++;
+ }
+ assertEquals(count, i);
+ assertEquals(count, c.getCount());
+
+ Log.d("testManyRows", "count " + Integer.toString(i));
+ c.close();
+ }
+
+ @LargeTest
+ public void testManyRowsTxt() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);");
+ StringBuilder sql = new StringBuilder(2100);
+ sql.append("INSERT INTO test (data) VALUES ('");
+ Random random = new Random(System.currentTimeMillis());
+ StringBuilder randomString = new StringBuilder(1979);
+ for (int i = 0; i < 1979; i++) {
+ randomString.append((random.nextInt() & 0xf) % 10);
+ }
+ sql.append(randomString);
+ sql.append("');");
+
+ // if cursor window size changed, adjust this value too
+ final int count = 600; // more than two fillWindow needed
+ for (int i = 0; i < count; i++) {
+ mDatabase.execSQL(sql.toString());
+ }
+
+ Cursor c = mDatabase.query("test", new String[]{"data"}, null, null, null, null, null);
+ assertNotNull(c);
+
+ int i = 0;
+ while (c.moveToNext()) {
+ assertEquals(randomString.toString(), c.getString(0));
+ i++;
+ }
+ assertEquals(count, i);
+ assertEquals(count, c.getCount());
+ c.close();
+ }
+
+ @LargeTest
+ public void testManyRowsTxtLong() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, txt TEXT, data INT);");
+
+ Random random = new Random(System.currentTimeMillis());
+ StringBuilder randomString = new StringBuilder(1979);
+ for (int i = 0; i < 1979; i++) {
+ randomString.append((random.nextInt() & 0xf) % 10);
+ }
+
+ // if cursor window size changed, adjust this value too
+ final int count = 600;
+ for (int i = 0; i < count; i++) {
+ StringBuilder sql = new StringBuilder(2100);
+ sql.append("INSERT INTO test (txt, data) VALUES ('");
+ sql.append(randomString);
+ sql.append("','");
+ sql.append(i);
+ sql.append("');");
+ mDatabase.execSQL(sql.toString());
+ }
+
+ Cursor c = mDatabase.query("test", new String[]{"txt", "data"}, null, null, null, null, null);
+ assertNotNull(c);
+
+ int i = 0;
+ while (c.moveToNext()) {
+ assertEquals(randomString.toString(), c.getString(0));
+ assertEquals(i, c.getInt(1));
+ i++;
+ }
+ assertEquals(count, i);
+ assertEquals(count, c.getCount());
+ c.close();
+ }
+
+ @MediumTest
+ public void testRequery() throws Exception {
+ populateDefaultTable();
+
+ Cursor c = mDatabase.rawQuery("SELECT * FROM test", null);
+ assertNotNull(c);
+ assertEquals(3, c.getCount());
+ c.deactivate();
+ c.requery();
+ assertEquals(3, c.getCount());
+ c.close();
+ }
+
+ @MediumTest
+ public void testRequeryWithSelection() throws Exception {
+ populateDefaultTable();
+
+ Cursor c = mDatabase.rawQuery("SELECT data FROM test WHERE data = '" + sString1 + "'",
+ null);
+ assertNotNull(c);
+ assertEquals(1, c.getCount());
+ assertTrue(c.moveToFirst());
+ assertEquals(sString1, c.getString(0));
+ c.deactivate();
+ c.requery();
+ assertEquals(1, c.getCount());
+ assertTrue(c.moveToFirst());
+ assertEquals(sString1, c.getString(0));
+ c.close();
+ }
+
+ @MediumTest
+ public void testRequeryWithSelectionArgs() throws Exception {
+ populateDefaultTable();
+
+ Cursor c = mDatabase.rawQuery("SELECT data FROM test WHERE data = ?",
+ new String[]{sString1});
+ assertNotNull(c);
+ assertEquals(1, c.getCount());
+ assertTrue(c.moveToFirst());
+ assertEquals(sString1, c.getString(0));
+ c.deactivate();
+ c.requery();
+ assertEquals(1, c.getCount());
+ assertTrue(c.moveToFirst());
+ assertEquals(sString1, c.getString(0));
+ c.close();
+ }
+
+ @MediumTest
+ public void testRequeryWithAlteredSelectionArgs() throws Exception {
+ /**
+ * Test the ability of a subclass of SQLiteCursor to change its query arguments.
+ */
+ populateDefaultTable();
+
+ SQLiteDatabase.CursorFactory factory = new SQLiteDatabase.CursorFactory() {
+ public Cursor newCursor(
+ SQLiteDatabase db, SQLiteCursorDriver masterQuery, String editTable,
+ SQLiteQuery query) {
+ return new SQLiteCursor(db, masterQuery, editTable, query) {
+ @Override
+ public boolean requery() {
+ setSelectionArguments(new String[]{"2"});
+ return super.requery();
+ }
+ };
+ }
+ };
+ Cursor c = mDatabase.rawQueryWithFactory(
+ factory, "SELECT data FROM test WHERE _id <= ?", new String[]{"1"},
+ null);
+ assertNotNull(c);
+ assertEquals(1, c.getCount());
+ assertTrue(c.moveToFirst());
+ assertEquals(sString1, c.getString(0));
+
+ // Our hacked requery() changes the query arguments in the cursor.
+ c.requery();
+
+ assertEquals(2, c.getCount());
+ assertTrue(c.moveToFirst());
+ assertEquals(sString1, c.getString(0));
+ assertTrue(c.moveToNext());
+ assertEquals(sString2, c.getString(0));
+
+ // Test that setting query args on a deactivated cursor also works.
+ c.deactivate();
+ c.requery();
+ }
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
index d7dd601adc86..ca650e0b2b7c 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.database;
import android.content.ContentValues;
import android.content.Context;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseLocaleTest.java b/core/tests/coretests/src/android/database/DatabaseLocaleTest.java
index f07ca7c74ef6..b32829412cb5 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/DatabaseLocaleTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseLocaleTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.database;
import android.database.sqlite.SQLiteDatabase;
import android.database.Cursor;
@@ -126,4 +126,4 @@ public class DatabaseLocaleTest extends TestCase {
if (cursor != null) cursor.close();
}
}
-} \ No newline at end of file
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseLockTest.java b/core/tests/coretests/src/android/database/DatabaseLockTest.java
index 326f873630f8..f7a9f8af3801 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/DatabaseLockTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseLockTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.database;
import android.app.Activity;
import android.content.Context;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabasePerformanceTests.java b/core/tests/coretests/src/android/database/DatabasePerformanceTests.java
index 68ce5e1585e7..b8ebcc4a025e 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/DatabasePerformanceTests.java
+++ b/core/tests/coretests/src/android/database/DatabasePerformanceTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.database;
import junit.framework.Assert;
diff --git a/core/tests/coretests/src/android/database/DatabaseStatementTest.java b/core/tests/coretests/src/android/database/DatabaseStatementTest.java
new file mode 100644
index 000000000000..71dc3ae08439
--- /dev/null
+++ b/core/tests/coretests/src/android/database/DatabaseStatementTest.java
@@ -0,0 +1,324 @@
+/*
+ * 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.database;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteConstraintException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDoneException;
+import android.database.sqlite.SQLiteStatement;
+import android.test.AndroidTestCase;
+import android.test.PerformanceTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+
+import java.io.File;
+
+public class DatabaseStatementTest extends AndroidTestCase implements PerformanceTestCase {
+
+ private static final String sString1 = "this is a test";
+ private static final String sString2 = "and yet another test";
+ private static final String sString3 = "this string is a little longer, but still a test";
+
+ private static final int CURRENT_DATABASE_VERSION = 42;
+ private SQLiteDatabase mDatabase;
+ private File mDatabaseFile;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ File dbDir = getContext().getDir("tests", Context.MODE_PRIVATE);
+ mDatabaseFile = new File(dbDir, "database_test.db");
+
+ if (mDatabaseFile.exists()) {
+ mDatabaseFile.delete();
+ }
+ mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
+ assertNotNull(mDatabase);
+ mDatabase.setVersion(CURRENT_DATABASE_VERSION);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mDatabase.close();
+ mDatabaseFile.delete();
+ super.tearDown();
+ }
+
+ public boolean isPerformanceOnly() {
+ return false;
+ }
+
+ // These test can only be run once.
+ public int startPerformance(Intermediates intermediates) {
+ return 1;
+ }
+
+ private void populateDefaultTable() {
+ mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);");
+
+ mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString1 + "');");
+ mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString2 + "');");
+ mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString3 + "');");
+ }
+
+ @MediumTest
+ public void testExecuteStatement() throws Exception {
+ populateDefaultTable();
+ SQLiteStatement statement = mDatabase.compileStatement("DELETE FROM test");
+ statement.execute();
+
+ Cursor c = mDatabase.query("test", null, null, null, null, null, null);
+ assertEquals(0, c.getCount());
+ c.deactivate();
+ statement.close();
+ }
+
+ @MediumTest
+ public void testSimpleQuery() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (num INTEGER NOT NULL, str TEXT NOT NULL);");
+ mDatabase.execSQL("INSERT INTO test VALUES (1234, 'hello');");
+ SQLiteStatement statement1 =
+ mDatabase.compileStatement("SELECT num FROM test WHERE str = ?");
+ SQLiteStatement statement2 =
+ mDatabase.compileStatement("SELECT str FROM test WHERE num = ?");
+
+ try {
+ statement1.bindString(1, "hello");
+ long value = statement1.simpleQueryForLong();
+ assertEquals(1234, value);
+
+ statement1.bindString(1, "world");
+ statement1.simpleQueryForLong();
+ fail("shouldn't get here");
+ } catch (SQLiteDoneException e) {
+ // expected
+ }
+
+ try {
+ statement2.bindLong(1, 1234);
+ String value = statement1.simpleQueryForString();
+ assertEquals("hello", value);
+
+ statement2.bindLong(1, 5678);
+ statement1.simpleQueryForString();
+ fail("shouldn't get here");
+ } catch (SQLiteDoneException e) {
+ // expected
+ }
+
+ statement1.close();
+ statement2.close();
+ }
+
+ @MediumTest
+ public void testStatementLongBinding() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (num INTEGER);");
+ SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)");
+
+ for (int i = 0; i < 10; i++) {
+ statement.bindLong(1, i);
+ statement.execute();
+ }
+ statement.close();
+
+ Cursor c = mDatabase.query("test", null, null, null, null, null, null);
+ int numCol = c.getColumnIndexOrThrow("num");
+ c.moveToFirst();
+ for (long i = 0; i < 10; i++) {
+ long num = c.getLong(numCol);
+ assertEquals(i, num);
+ c.moveToNext();
+ }
+ c.close();
+ }
+
+ @MediumTest
+ public void testStatementStringBinding() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (num TEXT);");
+ SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)");
+
+ for (long i = 0; i < 10; i++) {
+ statement.bindString(1, Long.toHexString(i));
+ statement.execute();
+ }
+ statement.close();
+
+ Cursor c = mDatabase.query("test", null, null, null, null, null, null);
+ int numCol = c.getColumnIndexOrThrow("num");
+ c.moveToFirst();
+ for (long i = 0; i < 10; i++) {
+ String num = c.getString(numCol);
+ assertEquals(Long.toHexString(i), num);
+ c.moveToNext();
+ }
+ c.close();
+ }
+
+ @MediumTest
+ public void testStatementClearBindings() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (num INTEGER);");
+ SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)");
+
+ for (long i = 0; i < 10; i++) {
+ statement.bindLong(1, i);
+ statement.clearBindings();
+ statement.execute();
+ }
+ statement.close();
+
+ Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID");
+ int numCol = c.getColumnIndexOrThrow("num");
+ assertTrue(c.moveToFirst());
+ for (long i = 0; i < 10; i++) {
+ assertTrue(c.isNull(numCol));
+ c.moveToNext();
+ }
+ c.close();
+ }
+
+ @MediumTest
+ public void testSimpleStringBinding() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (num TEXT, value TEXT);");
+ String statement = "INSERT INTO test (num, value) VALUES (?,?)";
+
+ String[] args = new String[2];
+ for (int i = 0; i < 2; i++) {
+ args[i] = Integer.toHexString(i);
+ }
+
+ mDatabase.execSQL(statement, args);
+
+ Cursor c = mDatabase.query("test", null, null, null, null, null, null);
+ int numCol = c.getColumnIndexOrThrow("num");
+ int valCol = c.getColumnIndexOrThrow("value");
+ c.moveToFirst();
+ String num = c.getString(numCol);
+ assertEquals(Integer.toHexString(0), num);
+
+ String val = c.getString(valCol);
+ assertEquals(Integer.toHexString(1), val);
+ c.close();
+ }
+
+ @MediumTest
+ public void testStatementMultipleBindings() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (num INTEGER, str TEXT);");
+ SQLiteStatement statement =
+ mDatabase.compileStatement("INSERT INTO test (num, str) VALUES (?, ?)");
+
+ for (long i = 0; i < 10; i++) {
+ statement.bindLong(1, i);
+ statement.bindString(2, Long.toHexString(i));
+ statement.execute();
+ }
+ statement.close();
+
+ Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID");
+ int numCol = c.getColumnIndexOrThrow("num");
+ int strCol = c.getColumnIndexOrThrow("str");
+ assertTrue(c.moveToFirst());
+ for (long i = 0; i < 10; i++) {
+ long num = c.getLong(numCol);
+ String str = c.getString(strCol);
+ assertEquals(i, num);
+ assertEquals(Long.toHexString(i), str);
+ c.moveToNext();
+ }
+ c.close();
+ }
+
+ private static class StatementTestThread extends Thread {
+ private SQLiteDatabase mDatabase;
+ private SQLiteStatement mStatement;
+
+ public StatementTestThread(SQLiteDatabase db, SQLiteStatement statement) {
+ super();
+ mDatabase = db;
+ mStatement = statement;
+ }
+
+ @Override
+ public void run() {
+ mDatabase.beginTransaction();
+ for (long i = 0; i < 10; i++) {
+ mStatement.bindLong(1, i);
+ mStatement.bindString(2, Long.toHexString(i));
+ mStatement.execute();
+ }
+ mDatabase.setTransactionSuccessful();
+ mDatabase.endTransaction();
+
+ Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID");
+ int numCol = c.getColumnIndexOrThrow("num");
+ int strCol = c.getColumnIndexOrThrow("str");
+ assertTrue(c.moveToFirst());
+ for (long i = 0; i < 10; i++) {
+ long num = c.getLong(numCol);
+ String str = c.getString(strCol);
+ assertEquals(i, num);
+ assertEquals(Long.toHexString(i), str);
+ c.moveToNext();
+ }
+ c.close();
+ }
+ }
+
+ @MediumTest
+ public void testStatementMultiThreaded() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (num INTEGER, str TEXT);");
+ SQLiteStatement statement =
+ mDatabase.compileStatement("INSERT INTO test (num, str) VALUES (?, ?)");
+
+ StatementTestThread thread = new StatementTestThread(mDatabase, statement);
+ thread.start();
+ try {
+ thread.join();
+ } finally {
+ statement.close();
+ }
+ }
+
+ @MediumTest
+ public void testStatementConstraint() throws Exception {
+ mDatabase.execSQL("CREATE TABLE test (num INTEGER NOT NULL);");
+ SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)");
+
+ // Try to insert NULL, which violates the constraint
+ try {
+ statement.clearBindings();
+ statement.execute();
+ fail("expected exception not thrown");
+ } catch (SQLiteConstraintException e) {
+ // expected
+ }
+
+ // Make sure the statement can still be used
+ statement.bindLong(1, 1);
+ statement.execute();
+ statement.close();
+
+ Cursor c = mDatabase.query("test", null, null, null, null, null, null);
+ int numCol = c.getColumnIndexOrThrow("num");
+ c.moveToFirst();
+ long num = c.getLong(numCol);
+ assertEquals(1, num);
+ c.close();
+ }
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseStressTest.java b/core/tests/coretests/src/android/database/DatabaseStressTest.java
index b1101254556b..30e46e7dfb90 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/DatabaseStressTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseStressTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.database;
import android.content.Context;
import android.database.sqlite.*;
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteDebugTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteDebugTest.java
new file mode 100644
index 000000000000..ea807bd64cb5
--- /dev/null
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteDebugTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 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.
+ * 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.database.sqlite;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for the SQLiteDebug
+ */
+public class SQLiteDebugTest extends TestCase {
+ private static final String TEST_DB = "test.db";
+
+ public void testCaptureSql() {
+ String rslt = SQLiteDebug.captureSql(TEST_DB, "select * from t1 where a=? and b=1",
+ new Object[] {"blah"});
+ String expectedVal = "select * from t1 where a='blah' and b=1";
+ assertTrue(rslt.equals("captured_sql|" + TEST_DB + "|" + expectedVal));
+
+ rslt = SQLiteDebug.captureSql(TEST_DB, "select * from t1 where a=?",
+ new Object[] {"blah"});
+ expectedVal = "select * from t1 where a='blah'";
+ assertTrue(rslt.equals("captured_sql|" + TEST_DB + "|" + expectedVal));
+
+ rslt = SQLiteDebug.captureSql(TEST_DB, "select * from t1 where a=1",
+ new Object[] {"blah"});
+ assertTrue(rslt.startsWith("too many bindArgs provided."));
+
+ rslt = SQLiteDebug.captureSql(TEST_DB, "update t1 set a=? where b=?",
+ new Object[] {"blah", "foo"});
+ expectedVal = "update t1 set a='blah' where b='foo'";
+ assertTrue(rslt.equals("captured_sql|" + TEST_DB + "|" + expectedVal));
+ }
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/LocalSocketTest.java b/core/tests/coretests/src/android/net/LocalSocketTest.java
index 0b8ec7408b6e..1349844c80cf 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/LocalSocketTest.java
+++ b/core/tests/coretests/src/android/net/LocalSocketTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.net;
import android.net.Credentials;
import android.net.LocalServerSocket;
@@ -35,11 +35,11 @@ public class LocalSocketTest extends TestCase {
LocalSocket ls;
LocalSocket ls1;
- ss = new LocalServerSocket("com.android.unit_tests.LocalSocketTest");
+ ss = new LocalServerSocket("android.net.LocalSocketTest");
ls = new LocalSocket();
- ls.connect(new LocalSocketAddress("com.android.unit_tests.LocalSocketTest"));
+ ls.connect(new LocalSocketAddress("android.net.LocalSocketTest"));
ls1 = ss.accept();
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SSLTest.java b/core/tests/coretests/src/android/net/SSLTest.java
index 94811801b55e..810ed0d5882d 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SSLTest.java
+++ b/core/tests/coretests/src/android/net/SSLTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.net;
import android.net.SSLCertificateSocketFactory;
import android.test.suitebuilder.annotation.Suppress;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/UriMatcherTest.java b/core/tests/coretests/src/android/net/UriMatcherTest.java
index ce3ea75675ae..287214460b6a 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/UriMatcherTest.java
+++ b/core/tests/coretests/src/android/net/UriMatcherTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.net;
import android.content.UriMatcher;
import android.net.Uri;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index 42066d9536ec..ad71fcbad6cf 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.net;
import android.net.Uri;
import android.content.ContentUris;
@@ -52,15 +52,20 @@ public class UriTest extends TestCase {
private void parcelAndUnparcel(Uri u) {
Parcel p = Parcel.obtain();
- Uri.writeToParcel(p, u);
- p.setDataPosition(0);
- assertEquals(u, Uri.CREATOR.createFromParcel(p));
-
- p.setDataPosition(0);
- u = u.buildUpon().build();
- Uri.writeToParcel(p, u);
- p.setDataPosition(0);
- assertEquals(u, Uri.CREATOR.createFromParcel(p));
+ try {
+ Uri.writeToParcel(p, u);
+ p.setDataPosition(0);
+ assertEquals(u, Uri.CREATOR.createFromParcel(p));
+
+ p.setDataPosition(0);
+ u = u.buildUpon().build();
+ Uri.writeToParcel(p, u);
+ p.setDataPosition(0);
+ assertEquals(u, Uri.CREATOR.createFromParcel(p));
+ }
+ finally {
+ p.recycle();
+ }
}
@SmallTest
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.aidl b/core/tests/coretests/src/android/os/AidlTest.aidl
index 62c75a514a86..6004f4b870a2 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.aidl
+++ b/core/tests/coretests/src/android/os/AidlTest.aidl
@@ -15,6 +15,6 @@
** limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
parcelable AidlTest.TestParcelable;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.java b/core/tests/coretests/src/android/os/AidlTest.java
index 52e666d84e25..bf11d56de045 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/AidlTest.java
+++ b/core/tests/coretests/src/android/os/AidlTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.os.IInterface;
import android.os.Parcel;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/BroadcasterTest.java b/core/tests/coretests/src/android/os/BroadcasterTest.java
index 0df1653a46f1..551ea8d7d5d4 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/BroadcasterTest.java
+++ b/core/tests/coretests/src/android/os/BroadcasterTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.os.Broadcaster;
import android.os.Handler;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/BuildTest.java b/core/tests/coretests/src/android/os/BuildTest.java
index 88fa3ccbd829..37586279d980 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/BuildTest.java
+++ b/core/tests/coretests/src/android/os/BuildTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.os;
import android.os.Build;
import android.test.suitebuilder.annotation.SmallTest;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java b/core/tests/coretests/src/android/os/FileObserverTest.java
index a9be5bdad15b..ca4e0d657c46 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java
+++ b/core/tests/coretests/src/android/os/FileObserverTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index f2c92932f8a1..f12cbe1e7983 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.content.Context;
import android.os.FileUtils;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerTester.java b/core/tests/coretests/src/android/os/HandlerTester.java
index 303245f59ff8..a216a0bf7169 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerTester.java
+++ b/core/tests/coretests/src/android/os/HandlerTester.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.os.Handler;
import android.os.Looper;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java b/core/tests/coretests/src/android/os/HandlerThreadTest.java
index f2025c6b91db..9772aa427999 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java
+++ b/core/tests/coretests/src/android/os/HandlerThreadTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import junit.framework.TestCase;
import android.os.Handler;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/HierarchicalStateMachineTest.java b/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java
index c5ca5a721118..6e50c7e56117 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/HierarchicalStateMachineTest.java
+++ b/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import junit.framework.TestCase;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/IAidlTest.aidl b/core/tests/coretests/src/android/os/IAidlTest.aidl
index 94c39ff74e10..a09022e0a135 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/IAidlTest.aidl
+++ b/core/tests/coretests/src/android/os/IAidlTest.aidl
@@ -15,9 +15,9 @@
** limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
-import com.android.unit_tests.os.AidlTest;
+import android.os.AidlTest;
interface IAidlTest {
int intMethod(int a);
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/IdleHandlerTest.java b/core/tests/coretests/src/android/os/IdleHandlerTest.java
index fc3b00745d4f..6c0a862aa2ea 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/IdleHandlerTest.java
+++ b/core/tests/coretests/src/android/os/IdleHandlerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.os.Handler;
import android.os.Looper;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java b/core/tests/coretests/src/android/os/MemoryFileTest.java
index 18b3d6321e83..411bdaa309f8 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java
+++ b/core/tests/coretests/src/android/os/MemoryFileTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.os.MemoryFile;
import android.test.AndroidTestCase;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/MessageQueueTest.java b/core/tests/coretests/src/android/os/MessageQueueTest.java
index 155a2471b22e..b7c2d1f1c149 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/MessageQueueTest.java
+++ b/core/tests/coretests/src/android/os/MessageQueueTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.os.Handler;
import android.os.Message;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/MessengerService.java b/core/tests/coretests/src/android/os/MessengerService.java
index 9228a43fb7b7..f15e13408084 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/MessengerService.java
+++ b/core/tests/coretests/src/android/os/MessengerService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.app.Service;
import android.content.Intent;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/MessengerTest.java b/core/tests/coretests/src/android/os/MessengerTest.java
index 2a3e204df41b..473ffe2298b3 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/MessengerTest.java
+++ b/core/tests/coretests/src/android/os/MessengerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.content.ComponentName;
import android.content.Context;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/OsTests.java b/core/tests/coretests/src/android/os/OsTests.java
index bf02509ed35f..582bf1ae204a 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/OsTests.java
+++ b/core/tests/coretests/src/android/os/OsTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import com.google.android.collect.Lists;
import junit.framework.TestSuite;
@@ -30,10 +30,8 @@ public class OsTests {
suite.addTestSuite(BroadcasterTest.class);
suite.addTestSuite(FileObserverTest.class);
suite.addTestSuite(IdleHandlerTest.class);
- suite.addTestSuite(MemoryFileTest.class);
suite.addTestSuite(MessageQueueTest.class);
suite.addTestSuite(MessengerTest.class);
- suite.addTestSuite(PowerManagerTest.class);
suite.addTestSuite(SystemPropertiesTest.class);
return suite;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/PerformanceCollectorTest.java b/core/tests/coretests/src/android/os/PerformanceCollectorTest.java
index 25b6e0ef05dc..a382239e7869 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/PerformanceCollectorTest.java
+++ b/core/tests/coretests/src/android/os/PerformanceCollectorTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.os.Bundle;
import android.os.Parcelable;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java b/core/tests/coretests/src/android/os/PowerManagerTest.java
index 2f1a7389e8fc..e089b3e0768e 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java
+++ b/core/tests/coretests/src/android/os/PowerManagerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.content.Context;
import android.os.PowerManager;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/SystemPropertiesTest.java b/core/tests/coretests/src/android/os/SystemPropertiesTest.java
index df08bb9293ae..25868ce0b702 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/SystemPropertiesTest.java
+++ b/core/tests/coretests/src/android/os/SystemPropertiesTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import static junit.framework.Assert.assertEquals;
import junit.framework.TestCase;
@@ -23,7 +23,7 @@ import android.os.SystemProperties;
import android.test.suitebuilder.annotation.SmallTest;
public class SystemPropertiesTest extends TestCase {
- private static final String KEY = "com.android.unit_tests";
+ private static final String KEY = "com.android.frameworks.coretests";
@SmallTest
public void testProperties() throws Exception {
if (false) {
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/TestHandlerThread.java b/core/tests/coretests/src/android/os/TestHandlerThread.java
index dba8dde9ed17..7e84af363a86 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/TestHandlerThread.java
+++ b/core/tests/coretests/src/android/os/TestHandlerThread.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.os;
+package android.os;
import android.os.Handler;
import android.os.Looper;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/TraceTest.java b/core/tests/coretests/src/android/os/TraceTest.java
index 670508053717..7a788ee6c25d 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/TraceTest.java
+++ b/core/tests/coretests/src/android/os/TraceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.os;
import android.os.Debug;
import android.test.AndroidTestCase;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesBuilder.java b/core/tests/coretests/src/android/pim/vcard/ContentValuesBuilder.java
index e99e4cb6b0f3..b3c0773903fa 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesBuilder.java
+++ b/core/tests/coretests/src/android/pim/vcard/ContentValuesBuilder.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentValues;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesVerifier.java b/core/tests/coretests/src/android/pim/vcard/ContentValuesVerifier.java
index 3fa6ae6b0edf..b9e9875cd9a7 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesVerifier.java
+++ b/core/tests/coretests/src/android/pim/vcard/ContentValuesVerifier.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.pim.vcard.VCardConfig;
import android.pim.vcard.VCardEntry;
@@ -98,4 +98,4 @@ import java.util.List;
elem.verifyResolver();
}
}
-} \ No newline at end of file
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesVerifierElem.java b/core/tests/coretests/src/android/pim/vcard/ContentValuesVerifierElem.java
index f5112171c70e..2edbb36d4220 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/ContentValuesVerifierElem.java
+++ b/core/tests/coretests/src/android/pim/vcard/ContentValuesVerifierElem.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentValues;
import android.pim.vcard.VCardConfig;
@@ -92,4 +92,4 @@ import java.io.InputStream;
public void onParsingEnd() {
mHandler.onEnd();
}
-} \ No newline at end of file
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/ExportTestResolver.java b/core/tests/coretests/src/android/pim/vcard/ExportTestResolver.java
index a76dfd8b6911..1b3cdcc55545 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/ExportTestResolver.java
+++ b/core/tests/coretests/src/android/pim/vcard/ExportTestResolver.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -210,4 +210,4 @@ import java.util.List;
}
};
}
-} \ No newline at end of file
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/ImportTestResolver.java b/core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java
index a1e9d75f64ad..019b9e39f824 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/ImportTestResolver.java
+++ b/core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/LineVerifier.java b/core/tests/coretests/src/android/pim/vcard/LineVerifier.java
index 27b95a603fa4..cef15fd762c0 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/LineVerifier.java
+++ b/core/tests/coretests/src/android/pim/vcard/LineVerifier.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.Context;
import android.pim.vcard.VCardComposer;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/LineVerifierElem.java b/core/tests/coretests/src/android/pim/vcard/LineVerifierElem.java
index fc478afcf11b..b23b29be8a6a 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/LineVerifierElem.java
+++ b/core/tests/coretests/src/android/pim/vcard/LineVerifierElem.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.pim.vcard.VCardConfig;
import android.text.TextUtils;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNode.java b/core/tests/coretests/src/android/pim/vcard/PropertyNode.java
index 14a789abd861..2c1f6d28de98 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNode.java
+++ b/core/tests/coretests/src/android/pim/vcard/PropertyNode.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentValues;
import android.pim.vcard.VCardEntry;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java b/core/tests/coretests/src/android/pim/vcard/PropertyNodesVerifier.java
index 0afad490b383..cfdd0743fa5c 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/PropertyNodesVerifier.java
+++ b/core/tests/coretests/src/android/pim/vcard/PropertyNodesVerifier.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentValues;
import android.pim.vcard.VCardConfig;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java b/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java
index e744a9226fdf..004a197352d9 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java
+++ b/core/tests/coretests/src/android/pim/vcard/VCardExporterTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentValues;
import android.pim.vcard.VCardConfig;
@@ -31,7 +31,7 @@ import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
-import com.android.unit_tests.vcard.PropertyNodesVerifierElem.TypeSet;
+import android.pim.vcard.PropertyNodesVerifierElem.TypeSet;
import java.util.Arrays;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java b/core/tests/coretests/src/android/pim/vcard/VCardImporterTests.java
index 45d3e3c7faee..21f22540c697 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardImporterTests.java
+++ b/core/tests/coretests/src/android/pim/vcard/VCardImporterTests.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentValues;
import android.pim.vcard.VCardConfig;
@@ -28,8 +28,8 @@ import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
-import com.android.unit_tests.R;
-import com.android.unit_tests.vcard.PropertyNodesVerifierElem.TypeSet;
+import com.android.frameworks.coretests.R;
+import android.pim.vcard.PropertyNodesVerifierElem.TypeSet;
import java.util.Arrays;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardJapanizationTests.java b/core/tests/coretests/src/android/pim/vcard/VCardJapanizationTests.java
index eea98c601ee6..5b60342c872b 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardJapanizationTests.java
+++ b/core/tests/coretests/src/android/pim/vcard/VCardJapanizationTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentValues;
import android.pim.vcard.VCardConfig;
@@ -24,7 +24,7 @@ import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import com.android.unit_tests.vcard.PropertyNodesVerifierElem.TypeSet;
+import android.pim.vcard.PropertyNodesVerifierElem.TypeSet;
import java.util.Arrays;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java b/core/tests/coretests/src/android/pim/vcard/VCardTestsBase.java
index 2382b42df709..0857e0c6e3ad 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardTestsBase.java
+++ b/core/tests/coretests/src/android/pim/vcard/VCardTestsBase.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardUtilsTests.java b/core/tests/coretests/src/android/pim/vcard/VCardUtilsTests.java
index 9f173af716e3..59299f9dff35 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardUtilsTests.java
+++ b/core/tests/coretests/src/android/pim/vcard/VCardUtilsTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.pim.vcard.VCardUtils;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardVerifier.java b/core/tests/coretests/src/android/pim/vcard/VCardVerifier.java
index 4b97750aa74d..bfc315829c2d 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardVerifier.java
+++ b/core/tests/coretests/src/android/pim/vcard/VCardVerifier.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentProvider;
import android.content.ContentResolver;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VNode.java b/core/tests/coretests/src/android/pim/vcard/VNode.java
index 75873203b005..79f10dc92e19 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VNode.java
+++ b/core/tests/coretests/src/android/pim/vcard/VNode.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import java.util.ArrayList;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VNodeBuilder.java b/core/tests/coretests/src/android/pim/vcard/VNodeBuilder.java
index 971fe0dc494a..0e6c3259b5fa 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VNodeBuilder.java
+++ b/core/tests/coretests/src/android/pim/vcard/VNodeBuilder.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.unit_tests.vcard;
+package android.pim.vcard;
import android.content.ContentValues;
import android.pim.vcard.VCardInterpreter;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SettingsProviderTest.java b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
index 7d828ec32032..f82d79ad728b 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SettingsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.provider;
import android.content.ContentResolver;
import android.content.ContentUris;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SmsProviderTest.java b/core/tests/coretests/src/android/provider/SmsProviderTest.java
index 0e2f0c54619a..c8ed728715cb 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SmsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SmsProviderTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.provider;
import android.content.ContentResolver;
import android.content.ContentValues;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SpannedTest.java b/core/tests/coretests/src/android/text/SpannedTest.java
index 9e3f483fe179..1c22cf9fe84b 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SpannedTest.java
+++ b/core/tests/coretests/src/android/text/SpannedTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.text;
import android.graphics.Typeface;
import android.os.Parcel;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/TextLayoutTest.java b/core/tests/coretests/src/android/text/TextLayoutTest.java
index 8cfcd5e698ec..6cf30005ee76 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/TextLayoutTest.java
+++ b/core/tests/coretests/src/android/text/TextLayoutTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.text;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.DynamicLayout;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index b1948962e63b..5b427be23dc7 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.text;
import android.graphics.Paint;
import android.test.suitebuilder.annotation.LargeTest;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/TimeTest.java b/core/tests/coretests/src/android/text/format/TimeTest.java
index 724ef6a56137..489f58b03cdb 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/TimeTest.java
+++ b/core/tests/coretests/src/android/text/format/TimeTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.text.format;
import android.test.suitebuilder.annotation.SmallTest;
import android.test.suitebuilder.annotation.Suppress;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/LogTest.java b/core/tests/coretests/src/android/util/LogTest.java
index 786c4b97c7bb..41947d7214da 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/LogTest.java
+++ b/core/tests/coretests/src/android/util/LogTest.java
@@ -1,4 +1,4 @@
-package com.android.unit_tests;
+package android.util;
import junit.framework.Assert;
import junit.framework.TestCase;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/TimeUtilsTest.java b/core/tests/coretests/src/android/util/TimeUtilsTest.java
index 6ba64fdeb173..65a6078f692c 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/TimeUtilsTest.java
+++ b/core/tests/coretests/src/android/util/TimeUtilsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.util;
import junit.framework.TestCase;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CreateViewTest.java b/core/tests/coretests/src/android/view/CreateViewTest.java
index 0c57ac4fa77e..16656f688640 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/CreateViewTest.java
+++ b/core/tests/coretests/src/android/view/CreateViewTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.view;
import android.content.Context;
import android.test.AndroidTestCase;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/InflateTest.java b/core/tests/coretests/src/android/view/InflateTest.java
index d7c9d60d0935..cb4f8e2399b1 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/InflateTest.java
+++ b/core/tests/coretests/src/android/view/InflateTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.view;
import android.content.Context;
import android.content.res.Resources;
@@ -24,6 +24,7 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
+import com.android.frameworks.coretests.R;
import java.util.Map;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/MenuTest.java b/core/tests/coretests/src/android/view/MenuTest.java
index c436726a0fc8..e8a8438607f8 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/MenuTest.java
+++ b/core/tests/coretests/src/android/view/MenuTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.view;
import com.android.internal.view.menu.MenuBuilder;
@@ -29,6 +29,8 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
+import com.android.frameworks.coretests.R;
+
public class MenuTest extends AndroidTestCase {
private MenuBuilder mMenu;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/WebkitTest.java b/core/tests/coretests/src/android/webkit/WebkitTest.java
index 4a0519e271e3..17b4088f0996 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/WebkitTest.java
+++ b/core/tests/coretests/src/android/webkit/WebkitTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.webkit;
import android.test.AndroidTestCase;
import android.text.format.DateFormat;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/LabelView.java b/core/tests/coretests/src/android/widget/LabelView.java
index ac297766faf9..4661c0115db4 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/LabelView.java
+++ b/core/tests/coretests/src/android/widget/LabelView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.widget;
import android.content.Context;
import android.graphics.Canvas;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/TextViewPerformanceTest.java b/core/tests/coretests/src/android/widget/TextViewPerformanceTest.java
index 6fa8f4fffbe8..c25df7c1b44e 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/TextViewPerformanceTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewPerformanceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.widget;
import android.content.Context;
import android.graphics.Bitmap;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 8e491181de99..d8d145c98b2e 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.widget;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/BitwiseStreamsTest.java b/core/tests/coretests/src/com/android/internal/util/BitwiseStreamsTest.java
index c5562b36b7e3..a304b68145df 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/BitwiseStreamsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/BitwiseStreamsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package com.android.internal.util;
import com.android.internal.util.BitwiseInputStream;
import com.android.internal.util.BitwiseOutputStream;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CharSequencesTest.java b/core/tests/coretests/src/com/android/internal/util/CharSequencesTest.java
index 092f309189ad..55d186c292f6 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/CharSequencesTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/CharSequencesTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package com.android.internal.util;
import com.android.internal.util.CharSequences;
import static com.android.internal.util.CharSequences.forAsciiBytes;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/ParentalControlTest.java b/core/tests/coretests/src/com/google/android/net/ParentalControlTest.java
index d4d2a8257186..d8ffeab2892e 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/ParentalControlTest.java
+++ b/core/tests/coretests/src/com/google/android/net/ParentalControlTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package com.google.android.net;
import com.google.android.net.ParentalControl;
import com.google.android.net.ParentalControlState;
diff --git a/docs/html/guide/developing/debug-tasks.jd b/docs/html/guide/developing/debug-tasks.jd
index a980efc2fe0b..500ef588dc4c 100644
--- a/docs/html/guide/developing/debug-tasks.jd
+++ b/docs/html/guide/developing/debug-tasks.jd
@@ -58,8 +58,8 @@ Log.i("MyActivity", "MyClass.getView() &mdash; get item number " + position);
<pre class="no-pretty-print">
I/MyActivity( 1557): MyClass.getView() &mdash; get item number 1
</pre>
- <p>Logcat is also the place to look when debugging a web page in the Android browser. All
-browser bugs will be output to logcat with the {@code WebCore} tag.
+ <p>Logcat is also the place to look when debugging a web page in the Android Browser app. See
+<a href="#DebuggingWebPages">Debugging Web Pages</a> below.</p>
</dl>
<p>For more information about all the development tools provided with the Android SDK, see the <a
@@ -148,10 +148,10 @@ following options (among others):</p>
<h2 id="DebuggingWebPages">Debugging Web Pages</h2>
-<p>If you're developing a web application for Android devices, you can debug your JavaScript on
-Android using the Console APIs, which will output messages to logcat. If you're familiar
+<p>If you're developing a web application for Android devices, you can debug your JavaScript in the
+Android Browser using the Console APIs, which will output messages to logcat. If you're familiar
debugging web pages with Firefox's FireBug or WebKit's Web Inspector, then you're probably familiar
-with the Console APIs. The Android Browser (and {@link android.webkit.WebChromeClient}) supports
+with the Console APIs. The Android Browser (and the {@link android.webkit.WebChromeClient}) supports
most of the same APIs.</p>
<p>When you call a function from the Console APIs (in the DOM's {@code window.console} object),
@@ -162,19 +162,28 @@ console.log("Hello World");
</pre>
<p>Then the logcat output from the Android Browser will look like this:</p>
<pre class="no-pretty-print">
-W/browser ( 202): Console: Hello World :0
+W/browser ( 202): Console: Hello World http://www.example.com/hello.html :82
</pre>
-<p class="note"><strong>Note:</strong> All Console messages from the Android
-Browser are tagged with the name "browser" on Android platforms running API Level 7 or higher and
-tagged with the name "WebCore" for platforms running API Level 6 or lower.</p>
-
-<p>Not all of the Console APIs available in Firefox or other WebKit browsers are implemented
-on Android. Mostly, you need to depend on basic text logging provided by
-functions like {@code console.log(String)}, {@code console.info(String)}, {@code
-console.warn(String)}, and {@code console.error(String)}. Although other Console functions may not
-be implemented, they will not raise run-time errors, but will simply not behave as you might
-expect.</p>
+<p>All Console messages from the Android Browser are tagged with the name "browser" on Android
+platforms running API Level 7 or higher. On platforms running API Level 6 or lower, Browser
+messages are tagged with the name "WebCore". The Android Browser also formats console messages
+with the log message
+preceded by "Console:" and then followed by the address and line number where the
+message occurred. (The format for the address and line number will appear different from the example
+above on platforms running API Level 6 or lower.)</p>
+
+<p>The Android Browser (and {@link android.webkit.WebChromeClient}) does not implement all of the
+Console APIs provided by Firefox or other WebKit-based browsers. Primarily, you need to depend
+on the basic text logging functions:</p>
+<ul>
+ <li>{@code console.log(String)}</li>
+ <li>{@code console.info(String)}</li>
+ <li>{@code console.warn(String)}</li>
+ <li>{@code console.error(String)}</li>
+</ul>
+<p>Although the Android Browser may not fully implement other Console functions, they will not raise
+run-time errors, but may not behave the same as they do on other desktop browsers.</p>
<p>If you've implemented a custom {@link android.webkit.WebView} in your application, then in order
to receive messages that are sent through the Console APIs, you must provide a {@link
@@ -185,7 +194,7 @@ android.webkit.WebView} in your application, you can log debug messages like thi
<pre>
myWebView.setWebChromeClient(new WebChromeClient() {
public void onConsoleMessage(String message, int lineNumber, String sourceID) {
- Log.d("MyApplication", message);
+ Log.d("MyApplication", message + " -- From line " + lineNumber + " of " + sourceID);
}
});
</pre>
@@ -195,13 +204,14 @@ within your {@link android.webkit.WebView}.</p>
<p>When the "Hello World" log is executed through your {@link android.webkit.WebView}, it will
now look like this:</p>
<pre class="no-pretty-print">
-D/MyApplication ( 430): Hello World
+D/MyApplication ( 430): Hello World -- From line 82 of http://www.example.com/hello.html
</pre>
<p class="note"><strong>Note:</strong> The {@link
android.webkit.WebChromeClient#onConsoleMessage(String,int,String) onConsoleMessage()} callback
-method was added with API Level 7. If you are targetting platforms running API Level 6 or lower,
-then your Console messages will automatically be sent to logcat with the "WebCore" logging tag.</p>
+method was added with API Level 7. If you are using a custom {@link
+android.webkit.WebView} on a platform running API Level 6 or lower, then your Console messages will
+automatically be sent to logcat with the "WebCore" logging tag.</p>
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index 643d30720b77..0fad4c6788e6 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -260,7 +260,7 @@ UI dimensions are declared in dip, the result is that they are displayed at the
same physical size on all screens in a given configuration. </p> -->
<p>Although the platform currently supports the nine possible size-density
-configurations listed in the table, you do not necessarily need to custom
+configurations listed in the table, you do not necessarily need to create custom
resources for each one of them. The platform provides robust compatibility
features, described in the sections below, that can handle most of the work of
rendering your application on the current device screen, provided that the UI is
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index d7fc563ec28b..8594452932dc 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -14,23 +14,44 @@ page.title=&lt;uses-feature&gt;
<dd><code><a
href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
+ <div class="sidebox-wrapper">
+ <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
+ <div id="qv-sub-rule">
+ <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;">
+ <p style="color:#669999;">Android Market and &lt;uses-feature&gt; elements</p>
+ <p>Android Market filters the applications that are visible to users, so
+that users can see and download only those applications that are compatible with their
+devices. One of the ways Market filters applications is by feature compatibility.</p>
+
+<p style="margin-top:1em;">To do this, Market checks the
+<code>&lt;uses-feature&gt;</code> elements in each application's manifest, to
+establish the app's feature needs. Market then shows or hides the application to
+each user, based on a comparison with the features available on the user's
+device. </p>
+
+<p style="margin-top:1em;">By specifying the features your application requires,
+you enable Android Market to present your application only to users whose
+devices meet the application's feature requirements, rather than presenting it
+to all users. </p>
+</div>
+</div>
+
<dt>description:</dt>
-<dd>This element declares a specific feature used by the application.
-Android provides some features that may not be equally supported by all
-Android devices. In a manner similar to the <code><a
-href="uses-sdk-element.html">&lt;uses-sdk></a></code>
-element, this element allows an application to specify which device-variable
-features it uses. In this way, the application
-will not be installed on devices that do not offer the feature.</p>
-
-<p>For example, an application might specify that it requires a camera with auto-focus capabilities.
-If a device does not provide a camera with auto-focus, then it will not allow
-installation of the application.</p>
-
-<p>In order to maintain strict device compatibility, it's very important that you use
-this element to declare all applicable features (listed below) that your application uses. Failure
-to declare a feature may result in your application being installed on a device
-that does not support the feature and your application failing.</p>
+<dd>This element declares a specific feature used by the application. Android
+provides some features that may not be equally supported by all Android devices.
+In a manner similar to the <a
+href="uses-sdk-element.html">{@code &lt;uses-sdk>}</a> element, this element
+allows an application to specify which device-variable features it uses. For
+example, an application might specify that it requires a camera with auto-focus
+capabilities.</p>
+
+<p>Declaring a {@code &lt;uses-feature>} element is informational only, meaning
+that the Android system itself does not check for matching feature support on
+the device before installing an application. However, note that other services
+(such as Android Market) or applications may check your application's
+{@code &lt;uses-feature>} declarations as part of handling or interacting
+with your application. For this reason, it's very important that you declare all of
+the features (from the list below) that your application uses. </p>
<p>For some features, there may exist a specfic attribute that allows you to define
a version of the feature, such as the version of Open GL used (declared with
@@ -38,11 +59,12 @@ a version of the feature, such as the version of Open GL used (declared with
exist for a device, such as a camera, are declared using the
<a href="#name">{@code name}</a> attribute.</p>
-<p>Any software or hardware features that may vary among Android-powered
-devices will be listed on this page among the attributes below. If you see any features
-here that you use in your application, you should include a {@code
-&lt;uses-feature>} element for each one. For example, if your application uses the device
-camera, then you should include the following in your {@code AndroidManifest.xml}:</p>
+<p>Any software or hardware features that may vary among Android-powered devices
+will be listed on this page among the attributes below. If you see any features
+here that you use in your application, you should include a
+{@code &lt;uses-feature>} element for each one. For example, if your
+application uses the device camera, then you should include the following in
+your {@code AndroidManifest.xml}:</p>
<pre>
&lt;uses-feature android:name="android.hardware.camera" />
@@ -77,10 +99,29 @@ instance of this element.</p>
<dd>
<dl class="attr">
<dt><a name="glEsVersion"></a>{@code android:glEsVersion}</dt>
- <dd>The GLES version needed by the application.
- The higher 16 bits represent the major number and the lower 16 bits
- represent the minor number. For example, for GL 1.2,
- the value should be set as {@code 0x00010002}.
+ <dd>The OpenGL ES version required by the application. The higher 16 bits
+represent the major number and the lower 16 bits represent the minor number. For
+example, to specify OpenGL ES version 2.0, you would set the value as
+"0x00020000". To specify OpenGL ES 2.1, if/when such a version were made
+available, you would set the value as "0x00020001".
+
+ <p>An application should specify at most one <code>android:glEsVersion</code>
+attribute in its manifest. If it specifies more than one, the
+<code>android:glEsVersion</code> with the numerically highest value is used and
+any other values are ignored.</p>
+
+ <p>If an application does not specify an <code>android:glEsVersion</code>
+attribute, then it is assumed that the application requires only OpenGL ES 1.0,
+which is supported by all Android-powered devices.</p>
+
+ <p>An application can assume that if a platform supports a given OpenGL ES
+version, it also supports all numerically lower OpenGL ES versions. Therefore,
+an application that requires both OpenGL ES 1.0 and OpenGL ES 2.0 must specify
+that it requires OpenGL ES 2.0.</p>
+
+ <p>An application that can work with any of several OpenGL ES versions should
+only specify the numerically lowest version of OpenGL ES that it requires. (It
+can check at run-time whether a higher level of OpenGL ES is available.)</p>
</dd>
<dt><a name="name"></a>{@code android:name}</dt>
@@ -90,7 +131,7 @@ instance of this element.</p>
<table>
<tr>
<th>Feature</th>
- <th>Value</th>
+ <th>Attribute Value</th>
<th>Description</th>
</tr><tr>
<td rowspan="2">Camera</td>
@@ -130,6 +171,11 @@ instance of this element.</p>
<td>The application requires a device with a light sensor.
</td>
</tr><tr>
+ <td>Live Wallpaper</td>
+ <td>{@code android.software.live_wallpaper}</td>
+ <td>The application uses or provides Live Wallpapers and should be installed only on devices that support Live Wallpapers.
+ </td>
+ </tr><tr>
<td>Proximity sensor</td>
<td>{@code android.hardware.sensor.proximity}</td>
<td>The application requires a device with a proximity sensor.
diff --git a/docs/html/index.jd b/docs/html/index.jd
index e12a00a5d60d..e3bf685df530 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -13,7 +13,7 @@ home=true
<!-- total max width is 520px -->
<img src="/assets/images/home/Android_Dev_Lab_l.png" alt="Android developer labs" width="100px" style="padding-left:78px;padding-right:46px;padding-bottom: 8px;"/>
<div id="announcement" style="width:275px">
-<p>We're hosting the next Android Developer Lab in Barcelona at <a href="http://www.mobileworldcongress.com/index.htm">Mobile World Congress&nbsp;&raquo;</a> on Wednesday February 17th at <a href="http://www.mobileworldcongress.com/exhibition/app_planet.htm">App Planet&nbsp;&raquo;</a>, located in Hall 7. Come visit us to attend a technical presentation, talk to our Android developer relations team, and meet other members of the developer community.</p><p>Check the Android Developers blog for more information soon!</p>
+<p>We're hosting the next Android Developer Lab in Barcelona at <a href="http://www.mobileworldcongress.com/index.htm">Mobile World Congress&nbsp;&raquo;</a> on Wednesday February 17th at <a href="http://www.mobileworldcongress.com/exhibition/app_planet.htm">App Planet&nbsp;&raquo;</a>, located in Hall 7. Come visit us to attend a technical presentation, talk to our Android developer relations team, and meet other members of the developer community.</p><p><a href="http://sites.google.com/site/androidmwc/home">Learn more &raquo;</a></p>
<!--<p><a href="http://android-developers.blogspot.com/2009/11/bring-your-lab-coats.html">Learn more &raquo;</a></p>-->
</div> <!-- end annoucement -->
</div> <!-- end annoucement-block -->
diff --git a/docs/html/mwc2010/index.html b/docs/html/mwc2010/index.html
index 22319a27bcb6..c91386f91070 100644
--- a/docs/html/mwc2010/index.html
+++ b/docs/html/mwc2010/index.html
@@ -1,7 +1,7 @@
<html>
<head>
<title>Redirecting...</title>
-<meta http-equiv="refresh" content="0;url=/index.html">
+<meta http-equiv="refresh" content="0;url=http://sites.google.com/site/androidmwc/home">
</head>
<body>
</body>
diff --git a/docs/html/sdk/android-2.1.jd b/docs/html/sdk/android-2.1.jd
index ecdc36672ff8..b546f0f44f9c 100644
--- a/docs/html/sdk/android-2.1.jd
+++ b/docs/html/sdk/android-2.1.jd
@@ -218,6 +218,21 @@ href="{@docRoot}guide/appendix/api-levels.html">API Levels</a> document. </p>
<li>Updated {@link android.app.WallpaperManager}.</li>
</ul>
+<p>Additionally, if your application uses or provides Live Wallpapers, you must
+remember to add a <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature></code></a>
+ element to the application's manifest, declaring the attribute
+<code>android:name="android.software.live_wallpaper"</code>. For example:</p>
+
+<pre class="no-pretty-print">
+&lt;uses-feature android:name="android.software.live_wallpaper" />
+</pre>
+
+<p>When you've published your application, Android Market checks for the
+presence of this element and uses it as a filter, ensuring that your application
+is not made available to users whose devices do not support Live Wallpapers.
+</p>
+
<h4>Telephony</h4>
<ul>
diff --git a/graphics/java/android/renderscript/FieldPacker.java b/graphics/java/android/renderscript/FieldPacker.java
new file mode 100644
index 000000000000..b26e47d068fb
--- /dev/null
+++ b/graphics/java/android/renderscript/FieldPacker.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 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.
+ * 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.renderscript;
+
+
+/**
+ * @hide
+ *
+ **/
+public class FieldPacker {
+ public FieldPacker(int len) {
+ mPos = 0;
+ mData = new byte[len];
+ }
+
+ public void align(int v) {
+ while ((mPos & (v - 1)) != 0) {
+ mData[mPos++] = 0;
+ }
+ }
+
+ void reset() {
+ mPos = 0;
+ }
+
+ void addI8(byte v) {
+ mData[mPos++] = v;
+ }
+
+ void addI16(short v) {
+ align(2);
+ mData[mPos++] = (byte)(v & 0xff);
+ mData[mPos++] = (byte)(v >> 8);
+ }
+
+ void addI32(int v) {
+ align(4);
+ mData[mPos++] = (byte)(v & 0xff);
+ mData[mPos++] = (byte)((v >> 8) & 0xff);
+ mData[mPos++] = (byte)((v >> 16) & 0xff);
+ mData[mPos++] = (byte)((v >> 24) & 0xff);
+ }
+
+ void addI64(long v) {
+ align(8);
+ mData[mPos++] = (byte)(v & 0xff);
+ mData[mPos++] = (byte)((v >> 8) & 0xff);
+ mData[mPos++] = (byte)((v >> 16) & 0xff);
+ mData[mPos++] = (byte)((v >> 24) & 0xff);
+ mData[mPos++] = (byte)((v >> 32) & 0xff);
+ mData[mPos++] = (byte)((v >> 40) & 0xff);
+ mData[mPos++] = (byte)((v >> 48) & 0xff);
+ mData[mPos++] = (byte)((v >> 56) & 0xff);
+ }
+
+ void addU8(short v) {
+ if ((v < 0) || (v > 0xff)) {
+ throw new IllegalArgumentException("Saving value out of range for type");
+ }
+ mData[mPos++] = (byte)v;
+ }
+
+ void addU16(int v) {
+ if ((v < 0) || (v > 0xffff)) {
+ throw new IllegalArgumentException("Saving value out of range for type");
+ }
+ align(2);
+ mData[mPos++] = (byte)(v & 0xff);
+ mData[mPos++] = (byte)(v >> 8);
+ }
+
+ void addU32(long v) {
+ if ((v < 0) || (v > 0xffffffff)) {
+ throw new IllegalArgumentException("Saving value out of range for type");
+ }
+ align(4);
+ mData[mPos++] = (byte)(v & 0xff);
+ mData[mPos++] = (byte)((v >> 8) & 0xff);
+ mData[mPos++] = (byte)((v >> 16) & 0xff);
+ mData[mPos++] = (byte)((v >> 24) & 0xff);
+ }
+
+ void addU64(long v) {
+ if (v < 0) {
+ throw new IllegalArgumentException("Saving value out of range for type");
+ }
+ align(8);
+ mData[mPos++] = (byte)(v & 0xff);
+ mData[mPos++] = (byte)((v >> 8) & 0xff);
+ mData[mPos++] = (byte)((v >> 16) & 0xff);
+ mData[mPos++] = (byte)((v >> 24) & 0xff);
+ mData[mPos++] = (byte)((v >> 32) & 0xff);
+ mData[mPos++] = (byte)((v >> 40) & 0xff);
+ mData[mPos++] = (byte)((v >> 48) & 0xff);
+ mData[mPos++] = (byte)((v >> 56) & 0xff);
+ }
+
+ void addF32(float v) {
+ addI32(Float.floatToRawIntBits(v));
+ }
+
+ void addF64(float v) {
+ addI64(Double.doubleToRawLongBits(v));
+ }
+
+ final byte[] getData() {
+ return mData;
+ }
+
+ private final byte mData[];
+ private int mPos;
+
+}
+
+
diff --git a/graphics/java/android/renderscript/Matrix2f.java b/graphics/java/android/renderscript/Matrix2f.java
new file mode 100644
index 000000000000..4b5e61ba1eaf
--- /dev/null
+++ b/graphics/java/android/renderscript/Matrix2f.java
@@ -0,0 +1,58 @@
+/*
+ * 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.renderscript;
+
+import java.lang.Math;
+import android.util.Log;
+
+
+/**
+ * @hide
+ *
+ **/
+public class Matrix2f {
+
+ public Matrix2f() {
+ mMat = new float[4];
+ loadIdentity();
+ }
+
+ public float get(int i, int j) {
+ return mMat[i*2 + j];
+ }
+
+ public void set(int i, int j, float v) {
+ mMat[i*2 + j] = v;
+ }
+
+ public void loadIdentity() {
+ mMat[0] = 1;
+ mMat[1] = 0;
+
+ mMat[2] = 0;
+ mMat[3] = 1;
+ }
+
+ public void load(Matrix2f src) {
+ System.arraycopy(mMat, 0, src, 0, 4);
+ }
+
+ final float[] mMat;
+}
+
+
+
diff --git a/graphics/java/android/renderscript/Matrix3f.java b/graphics/java/android/renderscript/Matrix3f.java
new file mode 100644
index 000000000000..19d7b4353e0d
--- /dev/null
+++ b/graphics/java/android/renderscript/Matrix3f.java
@@ -0,0 +1,63 @@
+/*
+ * 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.renderscript;
+
+import java.lang.Math;
+import android.util.Log;
+
+
+/**
+ * @hide
+ *
+ **/
+public class Matrix3f {
+
+ public Matrix3f() {
+ mMat = new float[9];
+ loadIdentity();
+ }
+
+ public float get(int i, int j) {
+ return mMat[i*3 + j];
+ }
+
+ public void set(int i, int j, float v) {
+ mMat[i*3 + j] = v;
+ }
+
+ public void loadIdentity() {
+ mMat[0] = 1;
+ mMat[1] = 0;
+ mMat[2] = 0;
+
+ mMat[3] = 0;
+ mMat[4] = 1;
+ mMat[5] = 0;
+
+ mMat[6] = 0;
+ mMat[7] = 0;
+ mMat[8] = 1;
+ }
+
+ public void load(Matrix3f src) {
+ System.arraycopy(mMat, 0, src, 0, 9);
+ }
+
+ final float[] mMat;
+}
+
+
diff --git a/graphics/java/android/renderscript/Matrix.java b/graphics/java/android/renderscript/Matrix4f.java
index a266d6baba10..ebd5bdedfe68 100644
--- a/graphics/java/android/renderscript/Matrix.java
+++ b/graphics/java/android/renderscript/Matrix4f.java
@@ -24,9 +24,9 @@ import android.util.Log;
* @hide
*
**/
-public class Matrix {
+public class Matrix4f {
- public Matrix() {
+ public Matrix4f() {
mMat = new float[16];
loadIdentity();
}
@@ -49,7 +49,7 @@ public class Matrix {
mMat[5] = 1;
mMat[6] = 0;
mMat[7] = 0;
-
+
mMat[8] = 0;
mMat[9] = 0;
mMat[10] = 1;
@@ -61,8 +61,8 @@ public class Matrix {
mMat[15] = 1;
}
- public void load(Matrix src) {
- mMat = src.mMat;
+ public void load(Matrix4f src) {
+ System.arraycopy(mMat, 0, src, 0, 16);
}
public void loadRotate(float rot, float x, float y, float z) {
@@ -77,7 +77,7 @@ public class Matrix {
rot *= (float)(java.lang.Math.PI / 180.0f);
c = (float)java.lang.Math.cos(rot);
s = (float)java.lang.Math.sin(rot);
-
+
float len = (float)java.lang.Math.sqrt(x*x + y*y + z*z);
if (!(len != 1)) {
float recipLen = 1.f / len;
@@ -91,7 +91,7 @@ public class Matrix {
float zx = z * x;
float xs = x * s;
float ys = y * s;
- float zs = z * s;
+ float zs = z * s;
mMat[ 0] = x*x*nc + c;
mMat[ 4] = xy*nc - zs;
mMat[ 8] = zx*nc + ys;
@@ -109,7 +109,7 @@ public class Matrix {
mMat[5] = y;
mMat[10] = z;
}
-
+
public void loadTranslate(float x, float y, float z) {
loadIdentity();
mMat[12] = x;
@@ -117,7 +117,7 @@ public class Matrix {
mMat[14] = z;
}
- public void loadMultiply(Matrix lhs, Matrix rhs) {
+ public void loadMultiply(Matrix4f lhs, Matrix4f rhs) {
for (int i=0 ; i<4 ; i++) {
float ri0 = 0;
float ri1 = 0;
@@ -159,31 +159,28 @@ public class Matrix {
mMat[15]= 0;
}
- public void multiply(Matrix rhs) {
- Matrix tmp = new Matrix();
+ public void multiply(Matrix4f rhs) {
+ Matrix4f tmp = new Matrix4f();
tmp.loadMultiply(this, rhs);
load(tmp);
}
public void rotate(float rot, float x, float y, float z) {
- Matrix tmp = new Matrix();
+ Matrix4f tmp = new Matrix4f();
tmp.loadRotate(rot, x, y, z);
multiply(tmp);
}
public void scale(float x, float y, float z) {
- Matrix tmp = new Matrix();
+ Matrix4f tmp = new Matrix4f();
tmp.loadScale(x, y, z);
multiply(tmp);
}
public void translate(float x, float y, float z) {
- Matrix tmp = new Matrix();
+ Matrix4f tmp = new Matrix4f();
tmp.loadTranslate(x, y, z);
multiply(tmp);
}
-
-
- float[] mMat;
-
+ final float[] mMat;
}
diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java
index 84f6f2d03e17..1b155d7c4bf8 100644
--- a/graphics/java/android/renderscript/ProgramVertex.java
+++ b/graphics/java/android/renderscript/ProgramVertex.java
@@ -96,16 +96,16 @@ public class ProgramVertex extends Program {
static final int PROJECTION_OFFSET = 16;
static final int TEXTURE_OFFSET = 32;
- Matrix mModel;
- Matrix mProjection;
- Matrix mTexture;
+ Matrix4f mModel;
+ Matrix4f mProjection;
+ Matrix4f mTexture;
public Allocation mAlloc;
public MatrixAllocation(RenderScript rs) {
- mModel = new Matrix();
- mProjection = new Matrix();
- mTexture = new Matrix();
+ mModel = new Matrix4f();
+ mProjection = new Matrix4f();
+ mTexture = new Matrix4f();
mAlloc = Allocation.createSized(rs, Element.createUser(rs, Element.DataType.FLOAT_32), 48);
mAlloc.subData1D(MODELVIEW_OFFSET, 16, mModel.mMat);
@@ -118,17 +118,17 @@ public class ProgramVertex extends Program {
mAlloc = null;
}
- public void loadModelview(Matrix m) {
+ public void loadModelview(Matrix4f m) {
mModel = m;
mAlloc.subData1D(MODELVIEW_OFFSET, 16, m.mMat);
}
- public void loadProjection(Matrix m) {
+ public void loadProjection(Matrix4f m) {
mProjection = m;
mAlloc.subData1D(PROJECTION_OFFSET, 16, m.mMat);
}
- public void loadTexture(Matrix m) {
+ public void loadTexture(Matrix4f m) {
mTexture = m;
mAlloc.subData1D(TEXTURE_OFFSET, 16, m.mMat);
}
@@ -152,8 +152,8 @@ public class ProgramVertex extends Program {
public void setupProjectionNormalized(int w, int h) {
// range -1,1 in the narrow axis at z = 0.
- Matrix m1 = new Matrix();
- Matrix m2 = new Matrix();
+ Matrix4f m1 = new Matrix4f();
+ Matrix4f m2 = new Matrix4f();
if(w > h) {
float aspect = ((float)w) / h;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseTests.java b/graphics/java/android/renderscript/Vector2f.java
index a288c73facdd..567d57fad2c4 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/DatabaseTests.java
+++ b/graphics/java/android/renderscript/Vector2f.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * 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.
@@ -14,19 +14,24 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.renderscript;
-import junit.framework.TestSuite;
+import java.lang.Math;
+import android.util.Log;
-public class DatabaseTests {
- public static TestSuite suite() {
- TestSuite suite = new TestSuite(DatabaseTests.class.getName());
- suite.addTestSuite(DatabaseGeneralTest.class);
- suite.addTestSuite(DatabaseLocaleTest.class);
- suite.addTestSuite(CursorWindowTest.class);
- suite.addTestSuite(DatabaseLockTest.class);
-
- return suite;
+/**
+ * @hide
+ *
+ **/
+public class Vector2f {
+ public Vector2f() {
}
+
+ public float x;
+ public float y;
}
+
+
+
+
diff --git a/graphics/java/android/renderscript/Vector3f.java b/graphics/java/android/renderscript/Vector3f.java
new file mode 100644
index 000000000000..f2842f3b4909
--- /dev/null
+++ b/graphics/java/android/renderscript/Vector3f.java
@@ -0,0 +1,38 @@
+/*
+ * 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.renderscript;
+
+import java.lang.Math;
+import android.util.Log;
+
+
+/**
+ * @hide
+ *
+ **/
+public class Vector3f {
+ public Vector3f() {
+ }
+
+ public float x;
+ public float y;
+ public float z;
+}
+
+
+
+
diff --git a/graphics/java/android/renderscript/Vector4f.java b/graphics/java/android/renderscript/Vector4f.java
new file mode 100644
index 000000000000..fabd9593db6b
--- /dev/null
+++ b/graphics/java/android/renderscript/Vector4f.java
@@ -0,0 +1,38 @@
+/*
+ * 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.renderscript;
+
+import java.lang.Math;
+import android.util.Log;
+
+
+/**
+ * @hide
+ *
+ **/
+public class Vector4f {
+ public Vector4f() {
+ }
+
+ public float x;
+ public float y;
+ public float z;
+ public float w;
+}
+
+
+
diff --git a/graphics/tests/graphicstests/Android.mk b/graphics/tests/graphicstests/Android.mk
new file mode 100644
index 000000000000..1845395a7790
--- /dev/null
+++ b/graphics/tests/graphicstests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PACKAGE_NAME := FrameworksGraphicsTests
+
+include $(BUILD_PACKAGE)
+
diff --git a/graphics/tests/graphicstests/AndroidManifest.xml b/graphics/tests/graphicstests/AndroidManifest.xml
new file mode 100644
index 000000000000..5fb5959bc068
--- /dev/null
+++ b/graphics/tests/graphicstests/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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.
+ 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.graphicstests">
+ <uses-permission android:name="android.permission.RECEIVE_SMS"/>
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
+ <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
+ <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.frameworks.graphicstests"
+ android:label="Frameworks Graphics Tests" />
+</manifest>
diff --git a/tests/AndroidTests/res/drawable/test128x96.png b/graphics/tests/graphicstests/res/drawable/test128x96.png
index 28dc925d266e..28dc925d266e 100644
--- a/tests/AndroidTests/res/drawable/test128x96.png
+++ b/graphics/tests/graphicstests/res/drawable/test128x96.png
Binary files differ
diff --git a/tests/AndroidTests/res/drawable/test16x12.png b/graphics/tests/graphicstests/res/drawable/test16x12.png
index 1a3c7e5f9e97..1a3c7e5f9e97 100644
--- a/tests/AndroidTests/res/drawable/test16x12.png
+++ b/graphics/tests/graphicstests/res/drawable/test16x12.png
Binary files differ
diff --git a/tests/AndroidTests/res/drawable/test256x192.png b/graphics/tests/graphicstests/res/drawable/test256x192.png
index ce8ee04b68be..ce8ee04b68be 100644
--- a/tests/AndroidTests/res/drawable/test256x192.png
+++ b/graphics/tests/graphicstests/res/drawable/test256x192.png
Binary files differ
diff --git a/tests/AndroidTests/res/drawable/test320x240.png b/graphics/tests/graphicstests/res/drawable/test320x240.png
index 9b5800da243d..9b5800da243d 100644
--- a/tests/AndroidTests/res/drawable/test320x240.png
+++ b/graphics/tests/graphicstests/res/drawable/test320x240.png
Binary files differ
diff --git a/tests/AndroidTests/res/drawable/test32x24.png b/graphics/tests/graphicstests/res/drawable/test32x24.png
index 76bab755c943..76bab755c943 100644
--- a/tests/AndroidTests/res/drawable/test32x24.png
+++ b/graphics/tests/graphicstests/res/drawable/test32x24.png
Binary files differ
diff --git a/tests/AndroidTests/res/drawable/test64x48.png b/graphics/tests/graphicstests/res/drawable/test64x48.png
index 91196130154c..91196130154c 100644
--- a/tests/AndroidTests/res/drawable/test64x48.png
+++ b/graphics/tests/graphicstests/res/drawable/test64x48.png
Binary files differ
diff --git a/tests/AndroidTests/src/com/android/unit_tests/graphics/BitmapTest.java b/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java
index e8001e34c086..6734bb798c6f 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/graphics/BitmapTest.java
+++ b/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.graphics;
+package android.graphics;
import android.graphics.Bitmap;
import android.graphics.Color;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/GraphicsPerformanceTests.java b/graphics/tests/graphicstests/src/android/graphics/GraphicsPerformanceTests.java
index a6c58699b2dc..f60ac7bdb5e5 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/GraphicsPerformanceTests.java
+++ b/graphics/tests/graphicstests/src/android/graphics/GraphicsPerformanceTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.graphics;
import junit.framework.Assert;
import android.content.Context;
@@ -28,6 +28,8 @@ import android.test.PerformanceTestCase;
import android.test.suitebuilder.annotation.Suppress;
import android.util.Log;
+import com.android.frameworks.graphicstests.R;
+
/**
* Graphics Performance Tests
*
diff --git a/tests/AndroidTests/src/com/android/unit_tests/graphics/GraphicsTests.java b/graphics/tests/graphicstests/src/android/graphics/GraphicsTests.java
index a8b6b9ab2cbd..8d01ea7ffd41 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/graphics/GraphicsTests.java
+++ b/graphics/tests/graphicstests/src/android/graphics/GraphicsTests.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.graphics;
+package android.graphics;
import junit.framework.TestSuite;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/ThreadBitmapTest.java b/graphics/tests/graphicstests/src/android/graphics/ThreadBitmapTest.java
index 220bc99ebfda..84bdc5683ac6 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/ThreadBitmapTest.java
+++ b/graphics/tests/graphicstests/src/android/graphics/ThreadBitmapTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.graphics;
import junit.framework.TestCase;
import android.graphics.Bitmap;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/graphics/TypefaceTest.java b/graphics/tests/graphicstests/src/android/graphics/TypefaceTest.java
index 5c40e6f91c94..334fddf78fbf 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/graphics/TypefaceTest.java
+++ b/graphics/tests/graphicstests/src/android/graphics/TypefaceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests.graphics;
+package android.graphics;
import android.graphics.Paint;
import android.graphics.Typeface;
diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h
index 03ac70a6b325..170f20d67a02 100644
--- a/include/binder/MemoryDealer.h
+++ b/include/binder/MemoryDealer.h
@@ -22,232 +22,35 @@
#include <sys/types.h>
#include <binder/IMemory.h>
-#include <utils/threads.h>
#include <binder/MemoryHeapBase.h>
namespace android {
// ----------------------------------------------------------------------------
-class String8;
-/*
- * interface for implementing a "heap". A heap basically provides
- * the IMemoryHeap interface for cross-process sharing and the
- * ability to map/unmap pages within the heap.
- */
-class HeapInterface : public virtual BnMemoryHeap
-{
-public:
- // all values must be page-aligned
- virtual sp<IMemory> mapMemory(size_t offset, size_t size) = 0;
-
- HeapInterface();
-protected:
- virtual ~HeapInterface();
-};
-
-// ----------------------------------------------------------------------------
-
-/*
- * interface for implementing an allocator. An allocator provides
- * methods for allocating and freeing memory blocks and dumping
- * its state.
- */
-class AllocatorInterface : public RefBase
-{
-public:
- enum {
- PAGE_ALIGNED = 0x00000001
- };
-
- virtual size_t allocate(size_t size, uint32_t flags = 0) = 0;
- virtual status_t deallocate(size_t offset) = 0;
- virtual size_t size() const = 0;
- virtual void dump(const char* what, uint32_t flags = 0) const = 0;
- virtual void dump(String8& res,
- const char* what, uint32_t flags = 0) const = 0;
-
- AllocatorInterface();
-protected:
- virtual ~AllocatorInterface();
-};
-
-// ----------------------------------------------------------------------------
-
-/*
- * concrete implementation of HeapInterface on top of mmap()
- */
-class SharedHeap : public HeapInterface, public MemoryHeapBase
-{
-public:
- SharedHeap();
- SharedHeap(size_t size, uint32_t flags = 0, char const * name = NULL);
- virtual ~SharedHeap();
- virtual sp<IMemory> mapMemory(size_t offset, size_t size);
-};
-
-// ----------------------------------------------------------------------------
-
-/*
- * A simple templatized doubly linked-list implementation
- */
-
-template <typename NODE>
-class LinkedList
-{
- NODE* mFirst;
- NODE* mLast;
-
-public:
- LinkedList() : mFirst(0), mLast(0) { }
- bool isEmpty() const { return mFirst == 0; }
- NODE const* head() const { return mFirst; }
- NODE* head() { return mFirst; }
- NODE const* tail() const { return mLast; }
- NODE* tail() { return mLast; }
-
- void insertAfter(NODE* node, NODE* newNode) {
- newNode->prev = node;
- newNode->next = node->next;
- if (node->next == 0) mLast = newNode;
- else node->next->prev = newNode;
- node->next = newNode;
- }
-
- void insertBefore(NODE* node, NODE* newNode) {
- newNode->prev = node->prev;
- newNode->next = node;
- if (node->prev == 0) mFirst = newNode;
- else node->prev->next = newNode;
- node->prev = newNode;
- }
-
- void insertHead(NODE* newNode) {
- if (mFirst == 0) {
- mFirst = mLast = newNode;
- newNode->prev = newNode->next = 0;
- } else {
- newNode->prev = 0;
- newNode->next = mFirst;
- mFirst->prev = newNode;
- mFirst = newNode;
- }
- }
-
- void insertTail(NODE* newNode) {
- if (mLast == 0) {
- insertHead(newNode);
- } else {
- newNode->prev = mLast;
- newNode->next = 0;
- mLast->next = newNode;
- mLast = newNode;
- }
- }
-
- NODE* remove(NODE* node) {
- if (node->prev == 0) mFirst = node->next;
- else node->prev->next = node->next;
- if (node->next == 0) mLast = node->prev;
- else node->next->prev = node->prev;
- return node;
- }
-};
-
-
-/*
- * concrete implementation of AllocatorInterface using a simple
- * best-fit allocation scheme
- */
-class SimpleBestFitAllocator : public AllocatorInterface
-{
-public:
-
- SimpleBestFitAllocator(size_t size);
- virtual ~SimpleBestFitAllocator();
-
- virtual size_t allocate(size_t size, uint32_t flags = 0);
- virtual status_t deallocate(size_t offset);
- virtual size_t size() const;
- virtual void dump(const char* what, uint32_t flags = 0) const;
- virtual void dump(String8& res,
- const char* what, uint32_t flags = 0) const;
-
-private:
-
- struct chunk_t {
- chunk_t(size_t start, size_t size)
- : start(start), size(size), free(1), prev(0), next(0) {
- }
- size_t start;
- size_t size : 28;
- int free : 4;
- mutable chunk_t* prev;
- mutable chunk_t* next;
- };
-
- ssize_t alloc(size_t size, uint32_t flags);
- chunk_t* dealloc(size_t start);
- void dump_l(const char* what, uint32_t flags = 0) const;
- void dump_l(String8& res, const char* what, uint32_t flags = 0) const;
-
- static const int kMemoryAlign;
- mutable Mutex mLock;
- LinkedList<chunk_t> mList;
- size_t mHeapSize;
-};
+class SimpleBestFitAllocator;
// ----------------------------------------------------------------------------
class MemoryDealer : public RefBase
{
public:
+ MemoryDealer(size_t size, const char* name = 0);
- enum {
- READ_ONLY = MemoryHeapBase::READ_ONLY,
- PAGE_ALIGNED = AllocatorInterface::PAGE_ALIGNED
- };
-
- // creates a memory dealer with the SharedHeap and SimpleBestFitAllocator
- MemoryDealer(size_t size, uint32_t flags = 0, const char* name = 0);
-
- // provide a custom heap but use the SimpleBestFitAllocator
- MemoryDealer(const sp<HeapInterface>& heap);
-
- // provide both custom heap and allocotar
- MemoryDealer(
- const sp<HeapInterface>& heap,
- const sp<AllocatorInterface>& allocator);
-
- virtual sp<IMemory> allocate(size_t size, uint32_t flags = 0);
+ virtual sp<IMemory> allocate(size_t size);
virtual void deallocate(size_t offset);
- virtual void dump(const char* what, uint32_t flags = 0) const;
-
+ virtual void dump(const char* what) const;
sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
- sp<AllocatorInterface> getAllocator() const { return allocator(); }
protected:
virtual ~MemoryDealer();
-private:
- const sp<HeapInterface>& heap() const;
- const sp<AllocatorInterface>& allocator() const;
-
- class Allocation : public BnMemory {
- public:
- Allocation(const sp<MemoryDealer>& dealer,
- ssize_t offset, size_t size, const sp<IMemory>& memory);
- virtual ~Allocation();
- virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const;
- private:
- sp<MemoryDealer> mDealer;
- ssize_t mOffset;
- size_t mSize;
- sp<IMemory> mMemory;
- };
+private:
+ const sp<IMemoryHeap>& heap() const;
+ SimpleBestFitAllocator* allocator() const;
- sp<HeapInterface> mHeap;
- sp<AllocatorInterface> mAllocator;
+ sp<IMemoryHeap> mHeap;
+ SimpleBestFitAllocator* mAllocator;
};
diff --git a/include/binder/MemoryHeapPmem.h b/include/binder/MemoryHeapPmem.h
index dbf26ff1ffc6..aac164f72b1d 100644
--- a/include/binder/MemoryHeapPmem.h
+++ b/include/binder/MemoryHeapPmem.h
@@ -20,10 +20,10 @@
#include <stdlib.h>
#include <stdint.h>
-#include <binder/MemoryDealer.h>
#include <binder/MemoryHeapBase.h>
#include <binder/IMemory.h>
#include <utils/SortedVector.h>
+#include <utils/threads.h>
namespace android {
@@ -31,7 +31,7 @@ class MemoryHeapBase;
// ---------------------------------------------------------------------------
-class MemoryHeapPmem : public HeapInterface, public MemoryHeapBase
+class MemoryHeapPmem : public MemoryHeapBase
{
public:
class MemoryPmem : public BnMemory {
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
new file mode 100644
index 000000000000..be928ec58381
--- /dev/null
+++ b/include/media/MediaProfiles.h
@@ -0,0 +1,303 @@
+/*
+ **
+ ** Copyright 2010, The Android Open Source Project.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIAPROFILES_H
+#define ANDROID_MEDIAPROFILES_H
+
+#include <utils/threads.h>
+#include <media/mediarecorder.h>
+
+namespace android {
+
+enum camcorder_quality {
+ CAMCORDER_QUALITY_HIGH = 0,
+ CAMCORDER_QUALITY_LOW = 1
+};
+
+enum video_decoder {
+ VIDEO_DECODER_WMV,
+};
+
+enum audio_decoder {
+ AUDIO_DECODER_WMA,
+};
+
+
+class MediaProfiles
+{
+public:
+
+ /**
+ * Returns the singleton instance for subsequence queries.
+ * or NULL if error.
+ */
+ static MediaProfiles* getInstance();
+
+ /**
+ * Returns the value for the given param name at the given quality level,
+ * or -1 if error.
+ *
+ * Supported param name are:
+ * file.format - output file format. see mediarecorder.h for details
+ * codec.vid - video encoder. see mediarecorder.h for details.
+ * codec.aud - audio encoder. see mediarecorder.h for details.
+ * vid.width - video frame width
+ * vid.height - video frame height
+ * vid.fps - video frame rate
+ * vid.bps - video bit rate
+ * aud.bps - audio bit rate
+ * aud.hz - audio sample rate
+ * aud.ch - number of audio channels
+ */
+ int getCamcorderProfileParamByName(const char *name, camcorder_quality quality) const;
+
+ /**
+ * Returns the output file formats supported.
+ */
+ Vector<output_format> getOutputFileFormats() const;
+
+ /**
+ * Returns the video encoders supported.
+ */
+ Vector<video_encoder> getVideoEncoders() const;
+
+ /**
+ * Returns the value for the given param name for the given video encoder
+ * returned from getVideoEncoderByIndex or -1 if error.
+ *
+ * Supported param name are:
+ * enc.vid.width.min - min video frame width
+ * enc.vid.width.max - max video frame width
+ * enc.vid.height.min - min video frame height
+ * enc.vid.height.max - max video frame height
+ * enc.vid.bps.min - min bit rate in bits per second
+ * enc.vid.bps.max - max bit rate in bits per second
+ * enc.vid.fps.min - min frame rate in frames per second
+ * enc.vid.fps.max - max frame rate in frames per second
+ */
+ int getVideoEncoderParamByName(const char *name, video_encoder codec) const;
+
+ /**
+ * Returns the audio encoders supported.
+ */
+ Vector<audio_encoder> getAudioEncoders() const;
+
+ /**
+ * Returns the value for the given param name for the given audio encoder
+ * returned from getAudioEncoderByIndex or -1 if error.
+ *
+ * Supported param name are:
+ * enc.aud.ch.min - min number of channels
+ * enc.aud.ch.max - max number of channels
+ * enc.aud.bps.min - min bit rate in bits per second
+ * enc.aud.bps.max - max bit rate in bits per second
+ * enc.aud.hz.min - min sample rate in samples per second
+ * enc.aud.hz.max - max sample rate in samples per second
+ */
+ int getAudioEncoderParamByName(const char *name, audio_encoder codec) const;
+
+ /**
+ * Returns the video decoders supported.
+ */
+ Vector<video_decoder> getVideoDecoders() const;
+
+ /**
+ * Returns the audio decoders supported.
+ */
+ Vector<audio_decoder> getAudioDecoders() const;
+
+private:
+ MediaProfiles& operator=(const MediaProfiles&); // Don't call me
+ MediaProfiles(const MediaProfiles&); // Don't call me
+ MediaProfiles() {} // Dummy default constructor
+ ~MediaProfiles(); // Don't delete me
+
+ struct VideoCodec {
+ VideoCodec(video_encoder codec, int bitRate, int frameWidth, int frameHeight, int frameRate)
+ : mCodec(codec),
+ mBitRate(bitRate),
+ mFrameWidth(frameWidth),
+ mFrameHeight(frameHeight),
+ mFrameRate(frameRate) {}
+
+ ~VideoCodec() {}
+
+ video_encoder mCodec;
+ int mBitRate;
+ int mFrameWidth;
+ int mFrameHeight;
+ int mFrameRate;
+ };
+
+ struct AudioCodec {
+ AudioCodec(audio_encoder codec, int bitRate, int sampleRate, int channels)
+ : mCodec(codec),
+ mBitRate(bitRate),
+ mSampleRate(sampleRate),
+ mChannels(channels) {}
+
+ ~AudioCodec() {}
+
+ audio_encoder mCodec;
+ int mBitRate;
+ int mSampleRate;
+ int mChannels;
+ };
+
+ struct CamcorderProfile {
+ CamcorderProfile()
+ : mFileFormat(OUTPUT_FORMAT_THREE_GPP),
+ mQuality(CAMCORDER_QUALITY_HIGH),
+ mDuration(0),
+ mVideoCodec(0),
+ mAudioCodec(0) {}
+
+ ~CamcorderProfile() {
+ delete mVideoCodec;
+ delete mAudioCodec;
+ }
+
+ output_format mFileFormat;
+ camcorder_quality mQuality;
+ int mDuration;
+ VideoCodec *mVideoCodec;
+ AudioCodec *mAudioCodec;
+ };
+
+ struct VideoEncoderCap {
+ // Ugly constructor
+ VideoEncoderCap(video_encoder codec,
+ int minBitRate, int maxBitRate,
+ int minFrameWidth, int maxFrameWidth,
+ int minFrameHeight, int maxFrameHeight,
+ int minFrameRate, int maxFrameRate)
+ : mCodec(codec),
+ mMinBitRate(minBitRate), mMaxBitRate(maxBitRate),
+ mMinFrameWidth(minFrameWidth), mMaxFrameWidth(maxFrameWidth),
+ mMinFrameHeight(minFrameHeight), mMaxFrameHeight(maxFrameHeight),
+ mMinFrameRate(minFrameRate), mMaxFrameRate(maxFrameRate) {}
+
+ ~VideoEncoderCap() {}
+
+ video_encoder mCodec;
+ int mMinBitRate, mMaxBitRate;
+ int mMinFrameWidth, mMaxFrameWidth;
+ int mMinFrameHeight, mMaxFrameHeight;
+ int mMinFrameRate, mMaxFrameRate;
+ };
+
+ struct AudioEncoderCap {
+ // Ugly constructor
+ AudioEncoderCap(audio_encoder codec,
+ int minBitRate, int maxBitRate,
+ int minSampleRate, int maxSampleRate,
+ int minChannels, int maxChannels)
+ : mCodec(codec),
+ mMinBitRate(minBitRate), mMaxBitRate(maxBitRate),
+ mMinSampleRate(minSampleRate), mMaxSampleRate(maxSampleRate),
+ mMinChannels(minChannels), mMaxChannels(maxChannels) {}
+
+ ~AudioEncoderCap() {}
+
+ audio_encoder mCodec;
+ int mMinBitRate, mMaxBitRate;
+ int mMinSampleRate, mMaxSampleRate;
+ int mMinChannels, mMaxChannels;
+ };
+
+ struct VideoDecoderCap {
+ VideoDecoderCap(video_decoder codec): mCodec(codec) {}
+ ~VideoDecoderCap() {}
+
+ video_decoder mCodec;
+ };
+
+ struct AudioDecoderCap {
+ AudioDecoderCap(audio_decoder codec): mCodec(codec) {}
+ ~AudioDecoderCap() {}
+
+ audio_decoder mCodec;
+ };
+
+ struct NameToTagMap {
+ const char* name;
+ int tag;
+ };
+
+ // Debug
+ static void logVideoCodec(const VideoCodec& codec);
+ static void logAudioCodec(const AudioCodec& codec);
+ static void logVideoEncoderCap(const VideoEncoderCap& cap);
+ static void logAudioEncoderCap(const AudioEncoderCap& cap);
+ static void logVideoDecoderCap(const VideoDecoderCap& cap);
+ static void logAudioDecoderCap(const AudioDecoderCap& cap);
+
+ // If the xml configuration file does exist, use the settings
+ // from the xml
+ static MediaProfiles* createInstanceFromXmlFile(const char *xml);
+ static output_format createEncoderOutputFileFormat(const char **atts);
+ static VideoCodec* createVideoCodec(const char **atts, MediaProfiles *profiles);
+ static AudioCodec* createAudioCodec(const char **atts, MediaProfiles *profiles);
+ static AudioDecoderCap* createAudioDecoderCap(const char **atts);
+ static VideoDecoderCap* createVideoDecoderCap(const char **atts);
+ static VideoEncoderCap* createVideoEncoderCap(const char **atts);
+ static AudioEncoderCap* createAudioEncoderCap(const char **atts);
+ static CamcorderProfile* createCamcorderProfile(const char **atts);
+
+ // Customized element tag handler for parsing the xml configuration file.
+ static void startElementHandler(void *userData, const char *name, const char **atts);
+
+ // If the xml configuration file does not exist, use hard-coded values
+ static MediaProfiles* createDefaultInstance();
+ static CamcorderProfile *createDefaultCamcorderLowProfile();
+ static CamcorderProfile *createDefaultCamcorderHighProfile();
+ static void createDefaultCamcorderProfiles(MediaProfiles *profiles);
+ static void createDefaultVideoEncoders(MediaProfiles *profiles);
+ static void createDefaultAudioEncoders(MediaProfiles *profiles);
+ static void createDefaultVideoDecoders(MediaProfiles *profiles);
+ static void createDefaultAudioDecoders(MediaProfiles *profiles);
+ static void createDefaultEncoderOutputFileFormats(MediaProfiles *profiles);
+ static VideoEncoderCap* createDefaultH263VideoEncoderCap();
+ static VideoEncoderCap* createDefaultM4vVideoEncoderCap();
+ static AudioEncoderCap* createDefaultAmrNBEncoderCap();
+
+ static int findTagForName(const NameToTagMap *map, size_t nMappings, const char *name);
+
+ // Mappings from name (for instance, codec name) to enum value
+ static const NameToTagMap sVideoEncoderNameMap[];
+ static const NameToTagMap sAudioEncoderNameMap[];
+ static const NameToTagMap sFileFormatMap[];
+ static const NameToTagMap sVideoDecoderNameMap[];
+ static const NameToTagMap sAudioDecoderNameMap[];
+ static const NameToTagMap sCamcorderQualityNameMap[];
+
+ static bool sIsInitialized;
+ static MediaProfiles *sInstance;
+ static Mutex sLock;
+
+ Vector<CamcorderProfile*> mCamcorderProfiles;
+ Vector<AudioEncoderCap*> mAudioEncoders;
+ Vector<VideoEncoderCap*> mVideoEncoders;
+ Vector<AudioDecoderCap*> mAudioDecoders;
+ Vector<VideoDecoderCap*> mVideoDecoders;
+ Vector<output_format> mEncoderOutputFileFormats;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAPROFILES_H
+
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 71344e6f89d7..26fcc9586877 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -47,7 +47,7 @@ public:
// Return time in us.
virtual int64_t getRealTimeUs();
- void start();
+ status_t start();
void pause();
void resume();
diff --git a/include/media/stagefright/CachingDataSource.h b/include/media/stagefright/CachingDataSource.h
index 30b7ad92ac80..42d50e5381aa 100644
--- a/include/media/stagefright/CachingDataSource.h
+++ b/include/media/stagefright/CachingDataSource.h
@@ -33,6 +33,8 @@ public:
virtual ssize_t readAt(off_t offset, void *data, size_t size);
+ virtual status_t getSize(off_t *size);
+
virtual uint32_t flags();
protected:
diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h
index 895cda3aa846..98ebc48ba6fa 100644
--- a/include/media/stagefright/HTTPDataSource.h
+++ b/include/media/stagefright/HTTPDataSource.h
@@ -39,6 +39,8 @@ public:
virtual ssize_t readAt(off_t offset, void *data, size_t size);
+ virtual status_t getSize(off_t *size);
+
virtual uint32_t flags() {
return kWantsPrefetching;
}
@@ -61,10 +63,16 @@ private:
void *mBuffer;
size_t mBufferLength;
off_t mBufferOffset;
- bool mFirstRequest;
+
+ bool mContentLengthValid;
+ unsigned long long mContentLength;
status_t mInitCheck;
+ void init(
+ const char *_host, int port, const char *_path,
+ const KeyedVector<String8, String8> *headers);
+
ssize_t sendRangeRequest(size_t offset);
void initHeaders(const KeyedVector<String8, String8> *overrides);
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 82dd2b52f0f3..f8bc7ab0bfbb 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -95,6 +95,7 @@ private:
kRequiresAllocateBufferOnOutputPorts = 32,
kRequiresFlushBeforeShutdown = 64,
kDefersOutputBufferAllocation = 128,
+ kDecoderLiesAboutNumberOfChannels = 256,
};
struct BufferInfo {
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index 26cde38693b9..e0deba9574a6 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -36,7 +36,12 @@ struct android_native_buffer_t;
namespace android {
-const unsigned int OGLES_NUM_COMPRESSED_TEXTURE_FORMATS = 10;
+
+const unsigned int OGLES_NUM_COMPRESSED_TEXTURE_FORMATS = 10
+#ifdef GL_OES_compressed_ETC1_RGB8_texture
+ + 1
+#endif
+ ;
class EGLTextureObject;
class EGLSurfaceManager;
diff --git a/include/ui/CameraParameters.h b/include/ui/CameraParameters.h
index cae06761abe5..2c29bfb0ef9b 100644
--- a/include/ui/CameraParameters.h
+++ b/include/ui/CameraParameters.h
@@ -34,8 +34,10 @@ public:
void set(const char *key, const char *value);
void set(const char *key, int value);
+ void setFloat(const char *key, float value);
const char *get(const char *key) const;
int getInt(const char *key) const;
+ float getFloat(const char *key) const;
/* preview-size=176x144 */
void setPreviewSize(int width, int height);
@@ -176,6 +178,16 @@ public:
// Supported focus modes.
// Example value: "auto,macro,fixed". Read only.
static const char KEY_SUPPORTED_FOCUS_MODES[];
+ // Focal length in millimeter.
+ // Example value: "4.31". Read only.
+ static const char KEY_FOCAL_LENGTH[];
+ // Horizontal angle of view in degrees.
+ // Example value: "54.8". Read only.
+ static const char KEY_HORIZONTAL_VIEW_ANGLE[];
+ // Vertical angle of view in degrees.
+ // Example value: "42.5". Read only.
+ static const char KEY_VERTICAL_VIEW_ANGLE[];
+
// Values for white balance settings.
static const char WHITE_BALANCE_AUTO[];
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index cad420a9b153..9d52882da786 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -2929,7 +2929,7 @@ void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
: RefBase(),
mAudioFlinger(audioFlinger),
- mMemoryDealer(new MemoryDealer(1024*1024)),
+ mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
mPid(pid)
{
// 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp
index 055dbcaa39ad..096aa7384a40 100644
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ b/libs/audioflinger/AudioPolicyManagerBase.cpp
@@ -15,8 +15,7 @@
*/
#define LOG_TAG "AudioPolicyManagerBase"
-//
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <hardware_legacy/AudioPolicyManagerBase.h>
#include <media/mediarecorder.h>
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index d5ffe7f6d388..18669f76dde0 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -17,12 +17,13 @@
#define LOG_TAG "MemoryDealer"
#include <binder/MemoryDealer.h>
+#include <binder/IPCThreadState.h>
+#include <binder/MemoryBase.h>
#include <utils/Log.h>
-#include <binder/IPCThreadState.h>
#include <utils/SortedVector.h>
#include <utils/String8.h>
-#include <binder/MemoryBase.h>
+#include <utils/threads.h>
#include <stdint.h>
#include <stdio.h>
@@ -40,90 +41,203 @@
namespace android {
// ----------------------------------------------------------------------------
-HeapInterface::HeapInterface() { }
-HeapInterface::~HeapInterface() { }
+/*
+ * A simple templatized doubly linked-list implementation
+ */
+
+template <typename NODE>
+class LinkedList
+{
+ NODE* mFirst;
+ NODE* mLast;
-// ----------------------------------------------------------------------------
+public:
+ LinkedList() : mFirst(0), mLast(0) { }
+ bool isEmpty() const { return mFirst == 0; }
+ NODE const* head() const { return mFirst; }
+ NODE* head() { return mFirst; }
+ NODE const* tail() const { return mLast; }
+ NODE* tail() { return mLast; }
+
+ void insertAfter(NODE* node, NODE* newNode) {
+ newNode->prev = node;
+ newNode->next = node->next;
+ if (node->next == 0) mLast = newNode;
+ else node->next->prev = newNode;
+ node->next = newNode;
+ }
-AllocatorInterface::AllocatorInterface() { }
-AllocatorInterface::~AllocatorInterface() { }
+ void insertBefore(NODE* node, NODE* newNode) {
+ newNode->prev = node->prev;
+ newNode->next = node;
+ if (node->prev == 0) mFirst = newNode;
+ else node->prev->next = newNode;
+ node->prev = newNode;
+ }
+
+ void insertHead(NODE* newNode) {
+ if (mFirst == 0) {
+ mFirst = mLast = newNode;
+ newNode->prev = newNode->next = 0;
+ } else {
+ newNode->prev = 0;
+ newNode->next = mFirst;
+ mFirst->prev = newNode;
+ mFirst = newNode;
+ }
+ }
+
+ void insertTail(NODE* newNode) {
+ if (mLast == 0) {
+ insertHead(newNode);
+ } else {
+ newNode->prev = mLast;
+ newNode->next = 0;
+ mLast->next = newNode;
+ mLast = newNode;
+ }
+ }
+
+ NODE* remove(NODE* node) {
+ if (node->prev == 0) mFirst = node->next;
+ else node->prev->next = node->next;
+ if (node->next == 0) mLast = node->prev;
+ else node->next->prev = node->prev;
+ return node;
+ }
+};
// ----------------------------------------------------------------------------
-class SimpleMemory : public MemoryBase {
+class Allocation : public MemoryBase {
public:
- SimpleMemory(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
- virtual ~SimpleMemory();
+ Allocation(const sp<MemoryDealer>& dealer,
+ const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
+ virtual ~Allocation();
+private:
+ sp<MemoryDealer> mDealer;
};
+// ----------------------------------------------------------------------------
+
+class SimpleBestFitAllocator
+{
+ enum {
+ PAGE_ALIGNED = 0x00000001
+ };
+public:
+ SimpleBestFitAllocator(size_t size);
+ ~SimpleBestFitAllocator();
+
+ size_t allocate(size_t size, uint32_t flags = 0);
+ status_t deallocate(size_t offset);
+ size_t size() const;
+ void dump(const char* what) const;
+ void dump(String8& res, const char* what) const;
+
+private:
+
+ struct chunk_t {
+ chunk_t(size_t start, size_t size)
+ : start(start), size(size), free(1), prev(0), next(0) {
+ }
+ size_t start;
+ size_t size : 28;
+ int free : 4;
+ mutable chunk_t* prev;
+ mutable chunk_t* next;
+ };
+
+ ssize_t alloc(size_t size, uint32_t flags);
+ chunk_t* dealloc(size_t start);
+ void dump_l(const char* what) const;
+ void dump_l(String8& res, const char* what) const;
+
+ static const int kMemoryAlign;
+ mutable Mutex mLock;
+ LinkedList<chunk_t> mList;
+ size_t mHeapSize;
+};
// ----------------------------------------------------------------------------
-MemoryDealer::Allocation::Allocation(
- const sp<MemoryDealer>& dealer, ssize_t offset, size_t size,
- const sp<IMemory>& memory)
- : mDealer(dealer), mOffset(offset), mSize(size), mMemory(memory)
+Allocation::Allocation(
+ const sp<MemoryDealer>& dealer,
+ const sp<IMemoryHeap>& heap, ssize_t offset, size_t size)
+ : MemoryBase(heap, offset, size), mDealer(dealer)
{
+#ifndef NDEBUG
+ void* const start_ptr = (void*)(intptr_t(heap->base()) + offset);
+ memset(start_ptr, 0xda, size);
+#endif
}
-MemoryDealer::Allocation::~Allocation()
+Allocation::~Allocation()
{
- if (mSize) {
+ size_t freedOffset = getOffset();
+ size_t freedSize = getSize();
+ if (freedSize) {
/* NOTE: it's VERY important to not free allocations of size 0 because
* they're special as they don't have any record in the allocator
* and could alias some real allocation (their offset is zero). */
- mDealer->deallocate(mOffset);
- }
-}
+ mDealer->deallocate(freedOffset);
+
+ // keep the size to unmap in excess
+ size_t pagesize = getpagesize();
+ size_t start = freedOffset;
+ size_t end = start + freedSize;
+ start &= ~(pagesize-1);
+ end = (end + pagesize-1) & ~(pagesize-1);
+
+ // give back to the kernel the pages we don't need
+ size_t free_start = freedOffset;
+ size_t free_end = free_start + freedSize;
+ if (start < free_start)
+ start = free_start;
+ if (end > free_end)
+ end = free_end;
+ start = (start + pagesize-1) & ~(pagesize-1);
+ end &= ~(pagesize-1);
+
+ if (start < end) {
+ void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start);
+ size_t size = end-start;
-sp<IMemoryHeap> MemoryDealer::Allocation::getMemory(
- ssize_t* offset, size_t* size) const
-{
- return mMemory->getMemory(offset, size);
+#ifndef NDEBUG
+ memset(start_ptr, 0xdf, size);
+#endif
+
+ // MADV_REMOVE is not defined on Dapper based Goobuntu
+#ifdef MADV_REMOVE
+ if (size) {
+ int err = madvise(start_ptr, size, MADV_REMOVE);
+ LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s",
+ start_ptr, size, err<0 ? strerror(errno) : "Ok");
+ }
+#endif
+ }
+ }
}
// ----------------------------------------------------------------------------
-MemoryDealer::MemoryDealer(size_t size, uint32_t flags, const char* name)
- : mHeap(new SharedHeap(size, flags, name)),
+MemoryDealer::MemoryDealer(size_t size, const char* name)
+ : mHeap(new MemoryHeapBase(size, 0, name)),
mAllocator(new SimpleBestFitAllocator(size))
{
}
-MemoryDealer::MemoryDealer(const sp<HeapInterface>& heap)
- : mHeap(heap),
- mAllocator(new SimpleBestFitAllocator(heap->virtualSize()))
-{
-}
-
-MemoryDealer::MemoryDealer( const sp<HeapInterface>& heap,
- const sp<AllocatorInterface>& allocator)
- : mHeap(heap), mAllocator(allocator)
-{
-}
-
MemoryDealer::~MemoryDealer()
{
+ delete mAllocator;
}
-sp<IMemory> MemoryDealer::allocate(size_t size, uint32_t flags)
+sp<IMemory> MemoryDealer::allocate(size_t size)
{
sp<IMemory> memory;
- const ssize_t offset = allocator()->allocate(size, flags);
+ const ssize_t offset = allocator()->allocate(size);
if (offset >= 0) {
- sp<IMemory> new_memory = heap()->mapMemory(offset, size);
- if (new_memory != 0) {
- memory = new Allocation(this, offset, size, new_memory);
- } else {
- LOGE("couldn't map [%8lx, %u]", offset, size);
- if (size) {
- /* NOTE: it's VERY important to not free allocations of size 0
- * because they're special as they don't have any record in the
- * allocator and could alias some real allocation
- * (their offset is zero). */
- allocator()->deallocate(offset);
- }
- }
+ memory = new Allocation(this, heap(), offset, size);
}
return memory;
}
@@ -133,16 +247,16 @@ void MemoryDealer::deallocate(size_t offset)
allocator()->deallocate(offset);
}
-void MemoryDealer::dump(const char* what, uint32_t flags) const
+void MemoryDealer::dump(const char* what) const
{
- allocator()->dump(what, flags);
+ allocator()->dump(what);
}
-const sp<HeapInterface>& MemoryDealer::heap() const {
+const sp<IMemoryHeap>& MemoryDealer::heap() const {
return mHeap;
}
-const sp<AllocatorInterface>& MemoryDealer::allocator() const {
+SimpleBestFitAllocator* MemoryDealer::allocator() const {
return mAllocator;
}
@@ -287,28 +401,28 @@ SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start)
return 0;
}
-void SimpleBestFitAllocator::dump(const char* what, uint32_t flags) const
+void SimpleBestFitAllocator::dump(const char* what) const
{
Mutex::Autolock _l(mLock);
- dump_l(what, flags);
+ dump_l(what);
}
-void SimpleBestFitAllocator::dump_l(const char* what, uint32_t flags) const
+void SimpleBestFitAllocator::dump_l(const char* what) const
{
String8 result;
- dump_l(result, what, flags);
+ dump_l(result, what);
LOGD("%s", result.string());
}
void SimpleBestFitAllocator::dump(String8& result,
- const char* what, uint32_t flags) const
+ const char* what) const
{
Mutex::Autolock _l(mLock);
- dump_l(result, what, flags);
+ dump_l(result, what);
}
void SimpleBestFitAllocator::dump_l(String8& result,
- const char* what, uint32_t flags) const
+ const char* what) const
{
size_t size = 0;
int32_t i = 0;
@@ -341,81 +455,10 @@ void SimpleBestFitAllocator::dump_l(String8& result,
i++;
cur = cur->next;
}
- snprintf(buffer, SIZE, " size allocated: %u (%u KB)\n", int(size), int(size/1024));
+ snprintf(buffer, SIZE,
+ " size allocated: %u (%u KB)\n", int(size), int(size/1024));
result.append(buffer);
}
-
-// ----------------------------------------------------------------------------
-
-SharedHeap::SharedHeap()
- : HeapInterface(), MemoryHeapBase()
-{
-}
-SharedHeap::SharedHeap(size_t size, uint32_t flags, char const * name)
- : MemoryHeapBase(size, flags, name)
-{
-}
-
-SharedHeap::~SharedHeap()
-{
-}
-
-sp<IMemory> SharedHeap::mapMemory(size_t offset, size_t size)
-{
- return new SimpleMemory(this, offset, size);
-}
-
-
-SimpleMemory::SimpleMemory(const sp<IMemoryHeap>& heap,
- ssize_t offset, size_t size)
- : MemoryBase(heap, offset, size)
-{
-#ifndef NDEBUG
- void* const start_ptr = (void*)(intptr_t(heap->base()) + offset);
- memset(start_ptr, 0xda, size);
-#endif
-}
-
-SimpleMemory::~SimpleMemory()
-{
- size_t freedOffset = getOffset();
- size_t freedSize = getSize();
-
- // keep the size to unmap in excess
- size_t pagesize = getpagesize();
- size_t start = freedOffset;
- size_t end = start + freedSize;
- start &= ~(pagesize-1);
- end = (end + pagesize-1) & ~(pagesize-1);
-
- // give back to the kernel the pages we don't need
- size_t free_start = freedOffset;
- size_t free_end = free_start + freedSize;
- if (start < free_start)
- start = free_start;
- if (end > free_end)
- end = free_end;
- start = (start + pagesize-1) & ~(pagesize-1);
- end &= ~(pagesize-1);
-
- if (start < end) {
- void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start);
- size_t size = end-start;
-
-#ifndef NDEBUG
- memset(start_ptr, 0xdf, size);
-#endif
-
- // MADV_REMOVE is not defined on Dapper based Goobuntu
-#ifdef MADV_REMOVE
- if (size) {
- int err = madvise(start_ptr, size, MADV_REMOVE);
- LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s",
- start_ptr, size, err<0 ? strerror(errno) : "Ok");
- }
-#endif
- }
-}
}; // namespace android
diff --git a/libs/binder/MemoryHeapPmem.cpp b/libs/binder/MemoryHeapPmem.cpp
index c66094761df5..16e92f939ee3 100644
--- a/libs/binder/MemoryHeapPmem.cpp
+++ b/libs/binder/MemoryHeapPmem.cpp
@@ -127,7 +127,7 @@ void SubRegionMemory::revoke()
MemoryHeapPmem::MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap,
uint32_t flags)
- : HeapInterface(), MemoryHeapBase()
+ : MemoryHeapBase()
{
char const * const device = pmemHeap->getDevice();
#if HAVE_ANDROID_OS
diff --git a/libs/ui/CameraParameters.cpp b/libs/ui/CameraParameters.cpp
index a94f6b9e435c..c4958a085896 100644
--- a/libs/ui/CameraParameters.cpp
+++ b/libs/ui/CameraParameters.cpp
@@ -56,6 +56,9 @@ const char CameraParameters::KEY_FLASH_MODE[] = "flash-mode";
const char CameraParameters::KEY_SUPPORTED_FLASH_MODES[] = "flash-mode-values";
const char CameraParameters::KEY_FOCUS_MODE[] = "focus-mode";
const char CameraParameters::KEY_SUPPORTED_FOCUS_MODES[] = "focus-mode-values";
+const char CameraParameters::KEY_FOCAL_LENGTH[] = "focal-length";
+const char CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE[] = "horizontal-view-angle";
+const char CameraParameters::KEY_VERTICAL_VIEW_ANGLE[] = "vertical-view-angle";
// Values for white balance settings.
const char CameraParameters::WHITE_BALANCE_AUTO[] = "auto";
@@ -206,6 +209,13 @@ void CameraParameters::set(const char *key, int value)
set(key, str);
}
+void CameraParameters::setFloat(const char *key, float value)
+{
+ char str[16]; // 14 should be enough. We overestimate to be safe.
+ snprintf(str, sizeof(str), "%g", value);
+ set(key, str);
+}
+
const char *CameraParameters::get(const char *key) const
{
String8 v = mMap.valueFor(String8(key));
@@ -222,6 +232,13 @@ int CameraParameters::getInt(const char *key) const
return strtol(v, 0, 0);
}
+float CameraParameters::getFloat(const char *key) const
+{
+ const char *v = get(key);
+ if (v == 0) return -1;
+ return strtof(v, 0);
+}
+
static int parse_size(const char *str, int &width, int &height)
{
// Find the width.
diff --git a/location/java/android/location/ILocationProvider.aidl b/location/java/android/location/ILocationProvider.aidl
index 7da16e455fd1..9fe6ab41fc4a 100644
--- a/location/java/android/location/ILocationProvider.aidl
+++ b/location/java/android/location/ILocationProvider.aidl
@@ -37,7 +37,6 @@ interface ILocationProvider {
int getAccuracy();
void enable();
void disable();
- boolean isEnabled();
int getStatus(out Bundle extras);
long getStatusUpdateTime();
void enableLocationTracking(boolean enable);
diff --git a/location/java/android/location/LocationProviderImpl.java b/location/java/android/location/LocationProviderImpl.java
index 9a3624eadc1a..7148a02f96ba 100644
--- a/location/java/android/location/LocationProviderImpl.java
+++ b/location/java/android/location/LocationProviderImpl.java
@@ -75,10 +75,6 @@ public abstract class LocationProviderImpl extends LocationProvider {
LocationProviderImpl.this.disable();
}
- public boolean isEnabled() {
- return LocationProviderImpl.this.isEnabled();
- }
-
public int getStatus(Bundle extras) {
return LocationProviderImpl.this.getStatus(extras);
}
@@ -138,11 +134,6 @@ public abstract class LocationProviderImpl extends LocationProvider {
public abstract void disable();
/**
- * Returns true if the provider is currently enabled
- */
- public abstract boolean isEnabled();
-
- /**
* Returns a information on the status of this provider.
* {@link #OUT_OF_SERVICE} is returned if the provider is
* out of service, and this is not expected to change in the near
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 9d678825978f..8b5f7020a9e6 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -56,6 +56,7 @@ import java.io.StringBufferInputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.Date;
import java.util.Properties;
import java.util.Map.Entry;
@@ -239,10 +240,14 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
// how often to request NTP time, in milliseconds
// current setting 4 hours
- private static final long NTP_INTERVAL = 4*60*60*1000;
+ private static final long NTP_INTERVAL = 4*60*60*1000;
// how long to wait if we have a network error in NTP or XTRA downloading
// current setting - 5 minutes
- private static final long RETRY_INTERVAL = 5*60*1000;
+ 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 {
@@ -571,10 +576,6 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
}
}
- public boolean isEnabled() {
- return mEnabled;
- }
-
public int getStatus(Bundle extras) {
if (extras != null) {
extras.putInt("satellites", mSvCount);
@@ -884,6 +885,7 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
switch (status) {
case GPS_STATUS_SESSION_BEGIN:
mNavigating = true;
+ mEngineOn = true;
break;
case GPS_STATUS_SESSION_END:
mNavigating = false;
@@ -893,6 +895,7 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
break;
case GPS_STATUS_ENGINE_OFF:
mEngineOn = false;
+ mNavigating = false;
break;
}
@@ -1250,13 +1253,26 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
long time = client.getNtpTime();
long timeReference = client.getNtpTimeReference();
int certainty = (int)(client.getRoundTripTime()/2);
+ long now = System.currentTimeMillis();
+ long systemTimeOffset = time - now;
- if (DEBUG) Log.d(TAG, "calling native_inject_time: " +
- time + " reference: " + timeReference
- + " certainty: " + certainty);
-
- native_inject_time(time, timeReference, certainty);
- mNextNtpTime = System.currentTimeMillis() + NTP_INTERVAL;
+ Log.d(TAG, "NTP server returned: "
+ + time + " (" + new Date(time)
+ + ") reference: " + timeReference
+ + " certainty: " + certainty
+ + " system time offset: " + systemTimeOffset);
+
+ // sanity check NTP time and do not use if it is too far from system time
+ if (systemTimeOffset < 0) {
+ systemTimeOffset = -systemTimeOffset;
+ }
+ if (systemTimeOffset < MAX_NTP_SYSTEM_TIME_OFFSET) {
+ native_inject_time(time, timeReference, certainty);
+ } else {
+ Log.e(TAG, "NTP time differs from system time by " + systemTimeOffset
+ + "ms. Ignoring.");
+ }
+ mNextNtpTime = now + NTP_INTERVAL;
} else {
if (DEBUG) Log.d(TAG, "requestTime failed");
mNextNtpTime = System.currentTimeMillis() + RETRY_INTERVAL;
diff --git a/location/java/com/android/internal/location/LocationProviderProxy.java b/location/java/com/android/internal/location/LocationProviderProxy.java
index 89337b369d6f..2e0be8914cff 100644
--- a/location/java/com/android/internal/location/LocationProviderProxy.java
+++ b/location/java/com/android/internal/location/LocationProviderProxy.java
@@ -40,6 +40,7 @@ public class LocationProviderProxy implements IBinder.DeathRecipient {
private final String mName;
private final ILocationProvider mProvider;
private boolean mLocationTracking = false;
+ private boolean mEnabled = false;
private long mMinTime = 0;
private boolean mDead;
@@ -152,6 +153,7 @@ public class LocationProviderProxy implements IBinder.DeathRecipient {
public void enable() {
try {
mProvider.enable();
+ mEnabled = true;
} catch (RemoteException e) {
Log.e(TAG, "enable failed", e);
}
@@ -160,18 +162,14 @@ public class LocationProviderProxy implements IBinder.DeathRecipient {
public void disable() {
try {
mProvider.disable();
+ mEnabled = false;
} catch (RemoteException e) {
Log.e(TAG, "disable failed", e);
}
}
public boolean isEnabled() {
- try {
- return mProvider.isEnabled();
- } catch (RemoteException e) {
- Log.e(TAG, "isEnabled failed", e);
- return false;
- }
+ return mEnabled;
}
public int getStatus(Bundle extras) {
diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java
index 2614f827a15d..7d9e86cab359 100644
--- a/location/java/com/android/internal/location/MockProvider.java
+++ b/location/java/com/android/internal/location/MockProvider.java
@@ -95,10 +95,6 @@ public class MockProvider extends ILocationProvider.Stub {
return mStatusUpdateTime;
}
- public boolean isEnabled() {
- return mEnabled;
- }
-
public int getAccuracy() {
return mAccuracy;
}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/GeocoderTest.java b/location/tests/locationtests/src/android/location/GeocoderTest.java
index e28a7dc489f5..8a13a24cf5e6 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/GeocoderTest.java
+++ b/location/tests/locationtests/src/android/location/GeocoderTest.java
@@ -1,4 +1,4 @@
-package com.android.unit_tests;
+package android.location;
/*
* Copyright (C) 2007 The Android Open Source Project
diff --git a/tests/AndroidTests/src/com/android/unit_tests/LocationManagerTest.java b/location/tests/locationtests/src/android/location/LocationManagerTest.java
index 47c7522a7960..0b8e61d2539c 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/LocationManagerTest.java
+++ b/location/tests/locationtests/src/android/location/LocationManagerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.location;
import android.content.Context;
import android.location.Criteria;
diff --git a/media/java/android/media/EncoderCapabilities.java b/media/java/android/media/EncoderCapabilities.java
new file mode 100644
index 000000000000..71cb1b345be0
--- /dev/null
+++ b/media/java/android/media/EncoderCapabilities.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import java.util.List;
+import java.util.ArrayList;
+import android.util.Log;
+
+/**
+ * The EncoderCapabilities class is used to retrieve the
+ * capabilities for different video and audio
+ * encoders supported on a specific Android platform.
+ * {@hide}
+ */
+public class EncoderCapabilities
+{
+ private static final String TAG = "EncoderCapabilities";
+
+ /**
+ * The VideoEncoderCap class represents a video encoder's
+ * supported parameter range in:
+ *
+ * <ul>
+ * <li>Resolution: the frame size (width/height) in pixels;
+ * <li>Bit rate: the compressed output bit rate in bits per second;
+ * <li>Frame rate: the output number of frames per second.
+ * </ul>
+ *
+ */
+ static public class VideoEncoderCap {
+ // These are not modifiable externally, thus are public accessible
+ public final int mCodec; // @see android.media.MediaRecorder.VideoEncoder
+ public final int mMinBitRate, mMaxBitRate; // min and max bit rate (bps)
+ public final int mMinFrameRate, mMaxFrameRate; // min and max frame rate (fps)
+ public final int mMinFrameWidth, mMaxFrameWidth; // min and max frame width (pixel)
+ public final int mMinFrameHeight, mMaxFrameHeight; // minn and max frame height (pixel)
+
+ // Private constructor called by JNI
+ private VideoEncoderCap(int codec,
+ int minBitRate, int maxBitRate,
+ int minFrameRate, int maxFrameRate,
+ int minFrameWidth, int maxFrameWidth,
+ int minFrameHeight, int maxFrameHeight) {
+ mCodec = codec;
+ mMinBitRate = minBitRate;
+ mMaxBitRate = maxBitRate;
+ mMinFrameRate = minFrameRate;
+ mMaxFrameRate = maxFrameRate;
+ mMinFrameWidth = minFrameWidth;
+ mMaxFrameWidth = maxFrameWidth;
+ mMinFrameHeight = minFrameHeight;
+ mMaxFrameHeight = maxFrameHeight;
+ }
+ };
+
+ /**
+ * The AudioEncoderCap class represents an audio encoder's
+ * parameter range in:
+ *
+ * <ul>
+ * <li>Bit rate: the compressed output bit rate in bits per second;
+ * <li>Sample rate: the sampling rate used for recording the audio in samples per second;
+ * <li>Number of channels: the number of channels the audio is recorded.
+ * </ul>
+ *
+ */
+ static public class AudioEncoderCap {
+ // These are not modifiable externally, thus are public accessible
+ public final int mCodec; // @see android.media.MediaRecorder.AudioEncoder
+ public final int mMinChannels, mMaxChannels; // min and max number of channels
+ public final int mMinSampleRate, mMaxSampleRate; // min and max sample rate (hz)
+ public final int mMinBitRate, mMaxBitRate; // min and max bit rate (bps)
+
+ // Private constructor called by JNI
+ private AudioEncoderCap(int codec,
+ int minBitRate, int maxBitRate,
+ int minSampleRate, int maxSampleRate,
+ int minChannels, int maxChannels) {
+ mCodec = codec;
+ mMinBitRate = minBitRate;
+ mMaxBitRate = maxBitRate;
+ mMinSampleRate = minSampleRate;
+ mMaxSampleRate = maxSampleRate;
+ mMinChannels = minChannels;
+ mMaxChannels = maxChannels;
+ }
+ };
+
+ static {
+ System.loadLibrary("media_jni");
+ native_init();
+ }
+
+ /**
+ * Returns the array of supported output file formats.
+ * @see android.media.MediaRecorder.OutputFormat
+ */
+ public static int[] getOutputFileFormats() {
+ int nFormats = native_get_num_file_formats();
+ if (nFormats == 0) return null;
+
+ int[] formats = new int[nFormats];
+ for (int i = 0; i < nFormats; ++i) {
+ formats[i] = native_get_file_format(i);
+ }
+ return formats;
+ }
+
+ /**
+ * Returns the capabilities of the supported video encoders.
+ * @see android.media.EncoderCapabilities.VideoEncoderCap
+ */
+ public static List<VideoEncoderCap> getVideoEncoders() {
+ int nEncoders = native_get_num_video_encoders();
+ if (nEncoders == 0) return null;
+
+ List<VideoEncoderCap> encoderList = new ArrayList<VideoEncoderCap>();
+ for (int i = 0; i < nEncoders; ++i) {
+ encoderList.add(native_get_video_encoder_cap(i));
+ }
+ return encoderList;
+ }
+
+ /**
+ * Returns the capabilities of the supported audio encoders.
+ * @see android.media.EncoderCapabilities.AudioEncoderCap
+ */
+ public static List<AudioEncoderCap> getAudioEncoders() {
+ int nEncoders = native_get_num_audio_encoders();
+ if (nEncoders == 0) return null;
+
+ List<AudioEncoderCap> encoderList = new ArrayList<AudioEncoderCap>();
+ for (int i = 0; i < nEncoders; ++i) {
+ encoderList.add(native_get_audio_encoder_cap(i));
+ }
+ return encoderList;
+ }
+
+
+ private EncoderCapabilities() {} // Don't call me
+
+ // Implemented by JNI
+ private static native final void native_init();
+ private static native final int native_get_num_file_formats();
+ private static native final int native_get_file_format(int index);
+ private static native final int native_get_num_video_encoders();
+ private static native final VideoEncoderCap native_get_video_encoder_cap(int index);
+ private static native final int native_get_num_audio_encoders();
+ private static native final AudioEncoderCap native_get_audio_encoder_cap(int index);
+}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index ba7e9bb8accc..e9d33722d205 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -41,6 +41,8 @@ public class ExifInterface {
public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+ public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+ public static final String TAG_GPS_DATESTAMP = "GPSDateStamp";
public static final String TAG_WHITE_BALANCE = "WhiteBalance";
// Constants used for the Orientation Exif tag.
@@ -62,8 +64,7 @@ public class ExifInterface {
static {
System.loadLibrary("exif");
sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
- //TODO: uncomment this when our EXIF datetime is encoded as UTC
- //sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+ sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
}
private String mFilename;
@@ -248,7 +249,7 @@ public class ExifInterface {
}
/**
- * Returns number of milliseconds since Jan. 1, 1970, midnight GMT.
+ * Returns number of milliseconds since Jan. 1, 1970, midnight.
* Returns -1 if the date time information if not available.
* @hide
*/
@@ -258,9 +259,32 @@ public class ExifInterface {
ParsePosition pos = new ParsePosition(0);
try {
- Date date = sFormatter.parse(dateTimeString, pos);
- if (date == null) return -1;
- return date.getTime();
+ Date datetime = sFormatter.parse(dateTimeString, pos);
+ if (datetime == null) return -1;
+ return datetime.getTime();
+ } catch (IllegalArgumentException ex) {
+ return -1;
+ }
+ }
+
+ /**
+ * Returns number of milliseconds since Jan. 1, 1970, midnight UTC.
+ * Returns -1 if the date time information if not available.
+ * @hide
+ */
+ public long getGpsDateTime() {
+ String date = mAttributes.get(TAG_GPS_DATESTAMP);
+ String time = mAttributes.get(TAG_GPS_TIMESTAMP);
+ if (date == null || time == null) return -1;
+
+ String dateTimeString = date + ' ' + time;
+ if (dateTimeString == null) return -1;
+
+ ParsePosition pos = new ParsePosition(0);
+ try {
+ Date datetime = sFormatter.parse(dateTimeString, pos);
+ if (datetime == null) return -1;
+ return datetime.getTime();
} catch (IllegalArgumentException ex) {
return -1;
}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index fcb02f43140e..8c1b0ea51efb 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -744,7 +744,7 @@ public class MediaScanner
values.put(Images.Media.LONGITUDE, latlng[1]);
}
- long time = exif.getDateTime();
+ long time = exif.getGpsDateTime();
if (time != -1) {
values.put(Images.Media.DATE_TAKEN, time);
}
diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java
index f6e63173b67b..df141c1919a2 100644
--- a/media/java/android/media/MiniThumbFile.java
+++ b/media/java/android/media/MiniThumbFile.java
@@ -17,7 +17,6 @@
package android.media;
import android.graphics.Bitmap;
-import android.media.ThumbnailUtil;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
diff --git a/media/java/android/media/ThumbnailUtil.java b/media/java/android/media/ThumbnailUtils.java
index 0cf4e76d508c..225d4b6dea8f 100644
--- a/media/java/android/media/ThumbnailUtil.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -16,13 +16,6 @@
package android.media;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
-import android.provider.BaseColumns;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Images.Thumbnails;
-import android.util.Log;
-
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -34,47 +27,171 @@ import android.graphics.Matrix;
import android.graphics.Rect;
import android.media.MediaMetadataRetriever;
import android.media.MediaFile.MediaFileType;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.provider.BaseColumns;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.Images.Thumbnails;
+import android.util.Log;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.OutputStream;
/**
- * Thumbnail generation routines for media provider. This class should only be used internaly.
- * {@hide} THIS IS NOT FOR PUBLIC API.
+ * Thumbnail generation routines for media provider.
*/
-public class ThumbnailUtil {
- private static final String TAG = "ThumbnailUtil";
- //Whether we should recycle the input (unless the output is the input).
+public class ThumbnailUtils {
+ private static final String TAG = "ThumbnailUtils";
+
+ /* Maximum pixels size for created bitmap. */
+ private static final int THUMBNAIL_MAX_NUM_PIXELS = 512 * 384;
+ private static final int MINI_THUMB_MAX_NUM_PIXELS = 128 * 128;
+ private static final int UNCONSTRAINED = -1;
+
+ /* Whether we should rotate the resulting bitmap. */
+ private static final boolean ROTATE_AS_NEEDED = true;
+ private static final boolean NO_ROTATE = false;
+
+ /* Whether we should create bitmap in native memory. */
+ private static final boolean USE_NATIVE = true;
+ private static final boolean NO_NATIVE = false;
+
+ /**
+ * Constant used to indicate we should recycle the input in
+ * {@link #extractMiniThumb(Bitmap, int, int, boolean)} unless the output is the input.
+ */
public static final boolean RECYCLE_INPUT = true;
+
+ /**
+ * Constant used to indicate we should not recycle the input in
+ * {@link #extractMiniThumb(Bitmap, int, int, boolean)}.
+ */
public static final boolean NO_RECYCLE_INPUT = false;
- public static final boolean ROTATE_AS_NEEDED = true;
- public static final boolean NO_ROTATE = false;
- public static final boolean USE_NATIVE = true;
- public static final boolean NO_NATIVE = false;
+ /**
+ * Constant used to indicate the dimension of normal thumbnail in
+ * {@link #extractMiniThumb(Bitmap, int, int, boolean)}.
+ */
public static final int THUMBNAIL_TARGET_SIZE = 320;
+
+ /**
+ * Constant used to indicate the dimension of mini thumbnail in
+ * {@link #extractMiniThumb(Bitmap, int, int, boolean)}.
+ */
public static final int MINI_THUMB_TARGET_SIZE = 96;
- public static final int THUMBNAIL_MAX_NUM_PIXELS = 512 * 384;
- public static final int MINI_THUMB_MAX_NUM_PIXELS = 128 * 128;
- public static final int UNCONSTRAINED = -1;
- // Returns Options that set the native alloc flag for Bitmap decode.
- public static BitmapFactory.Options createNativeAllocOptions() {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inNativeAlloc = true;
- return options;
+ /**
+ * This method first examines if the thumbnail embedded in EXIF is bigger than our target
+ * size. If not, then it'll create a thumbnail from original image. Due to efficiency
+ * consideration, we want to let MediaThumbRequest avoid calling this method twice for
+ * both kinds, so it only requests for MICRO_KIND and set saveImage to true.
+ *
+ * This method always returns a "square thumbnail" for MICRO_KIND thumbnail.
+ *
+ * @param cr ContentResolver
+ * @param filePath file path needed by EXIF interface
+ * @param uri URI of original image
+ * @param origId image id
+ * @param kind either MINI_KIND or MICRO_KIND
+ * @param saveMini Whether to save MINI_KIND thumbnail obtained in this method.
+ * @return Bitmap
+ */
+ public static Bitmap createImageThumbnail(ContentResolver cr, String filePath, Uri uri,
+ long origId, int kind, boolean saveMini) {
+ boolean wantMini = (kind == Images.Thumbnails.MINI_KIND || saveMini);
+ int targetSize = wantMini ?
+ THUMBNAIL_TARGET_SIZE : MINI_THUMB_TARGET_SIZE;
+ int maxPixels = wantMini ?
+ THUMBNAIL_MAX_NUM_PIXELS : MINI_THUMB_MAX_NUM_PIXELS;
+ SizedThumbnailBitmap sizedThumbnailBitmap = new SizedThumbnailBitmap();
+ Bitmap bitmap = null;
+ MediaFileType fileType = MediaFile.getFileType(filePath);
+ if (fileType != null && fileType.fileType == MediaFile.FILE_TYPE_JPEG) {
+ createThumbnailFromEXIF(filePath, targetSize, maxPixels, sizedThumbnailBitmap);
+ bitmap = sizedThumbnailBitmap.mBitmap;
+ }
+
+ if (bitmap == null) {
+ bitmap = makeBitmap(targetSize, maxPixels, uri, cr);
+ }
+
+ if (bitmap == null) {
+ return null;
+ }
+
+ if (saveMini) {
+ if (sizedThumbnailBitmap.mThumbnailData != null) {
+ storeThumbnail(cr, origId,
+ sizedThumbnailBitmap.mThumbnailData,
+ sizedThumbnailBitmap.mThumbnailWidth,
+ sizedThumbnailBitmap.mThumbnailHeight);
+ } else {
+ storeThumbnail(cr, origId, bitmap);
+ }
+ }
+
+ if (kind == Images.Thumbnails.MICRO_KIND) {
+ // now we make it a "square thumbnail" for MICRO_KIND thumbnail
+ bitmap = extractMiniThumb(bitmap,
+ MINI_THUMB_TARGET_SIZE,
+ MINI_THUMB_TARGET_SIZE, RECYCLE_INPUT);
+ }
+ return bitmap;
}
+
/**
- * Make a bitmap from a given Uri.
+ * Create a video thumbnail for a video. May return null if the video is
+ * corrupt.
*
- * @param uri
+ * @param filePath
*/
- public static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
- Uri uri, ContentResolver cr) {
- return makeBitmap(minSideLength, maxNumOfPixels, uri, cr,
- NO_NATIVE);
+ public static Bitmap createVideoThumbnail(String filePath) {
+ Bitmap bitmap = null;
+ MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+ try {
+ retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
+ retriever.setDataSource(filePath);
+ bitmap = retriever.captureFrame();
+ } catch (IllegalArgumentException ex) {
+ // Assume this is a corrupt video file
+ } catch (RuntimeException ex) {
+ // Assume this is a corrupt video file.
+ } finally {
+ try {
+ retriever.release();
+ } catch (RuntimeException ex) {
+ // Ignore failures while cleaning up.
+ }
+ }
+ return bitmap;
+ }
+
+ /**
+ * Creates a centered bitmap of the desired size.
+ *
+ * @param source original bitmap source
+ * @param width targeted width
+ * @param height targeted height
+ * @param recycle whether we want to recycle the input
+ */
+ public static Bitmap extractMiniThumb(
+ Bitmap source, int width, int height, boolean recycle) {
+ if (source == null) {
+ return null;
+ }
+
+ float scale;
+ if (source.getWidth() < source.getHeight()) {
+ scale = width / (float) source.getWidth();
+ } else {
+ scale = height / (float) source.getHeight();
+ }
+ Matrix matrix = new Matrix();
+ matrix.setScale(scale, scale);
+ Bitmap miniThumbnail = transform(matrix, source, width, height, true, recycle);
+ return miniThumbnail;
}
/*
@@ -96,7 +213,7 @@ public class ThumbnailUtil {
* For example, BitmapFactory downsamples an image by 2 even though the
* request is 3. So we round up the sample size to avoid OOM.
*/
- public static int computeSampleSize(BitmapFactory.Options options,
+ private static int computeSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength,
maxNumOfPixels);
@@ -140,7 +257,30 @@ public class ThumbnailUtil {
}
}
- public static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
+ /**
+ * Returns Options that set the native alloc flag for Bitmap decode.
+ */
+ private static BitmapFactory.Options createNativeAllocOptions() {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inNativeAlloc = true;
+ return options;
+ }
+
+ /**
+ * Make a bitmap from a given Uri, minimal side length, and maximum number of pixels.
+ */
+ private static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
+ Uri uri, ContentResolver cr) {
+ return makeBitmap(minSideLength, maxNumOfPixels, uri, cr,
+ NO_NATIVE);
+ }
+
+ /**
+ * Make a bitmap from a given Uri, minimal side length, and maximum number of pixels.
+ * The image data will be read from specified ContentResolver and clients are allowed to specify
+ * whether they want the Bitmap be created in native memory.
+ */
+ private static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
Uri uri, ContentResolver cr, boolean useNative) {
ParcelFileDescriptor input = null;
try {
@@ -159,49 +299,18 @@ public class ThumbnailUtil {
}
}
- // Rotates the bitmap by the specified degree.
- // If a new bitmap is created, the original bitmap is recycled.
- public static Bitmap rotate(Bitmap b, int degrees) {
- if (degrees != 0 && b != null) {
- Matrix m = new Matrix();
- m.setRotate(degrees,
- (float) b.getWidth() / 2, (float) b.getHeight() / 2);
- try {
- Bitmap b2 = Bitmap.createBitmap(
- b, 0, 0, b.getWidth(), b.getHeight(), m, true);
- if (b != b2) {
- b.recycle();
- b = b2;
- }
- } catch (OutOfMemoryError ex) {
- // We have no memory to rotate. Return the original bitmap.
- }
- }
- return b;
- }
-
- private static void closeSilently(ParcelFileDescriptor c) {
- if (c == null) return;
- try {
- c.close();
- } catch (Throwable t) {
- // do nothing
- }
- }
-
- private static ParcelFileDescriptor makeInputStream(
- Uri uri, ContentResolver cr) {
- try {
- return cr.openFileDescriptor(uri, "r");
- } catch (IOException ex) {
- return null;
- }
- }
-
- public static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
- Uri uri, ContentResolver cr, ParcelFileDescriptor pfd,
- BitmapFactory.Options options) {
- Bitmap b = null;
+ /**
+ * Make a bitmap from a given Uri, minimal side length, and maximum number of pixels.
+ * The image data will be read from specified pfd if it's not null, otherwise
+ * a new input stream will be created using specified ContentResolver.
+ *
+ * Clients are allowed to pass their own BitmapFactory.Options used for bitmap decoding. A
+ * new BitmapFactory.Options will be created if options is null.
+ */
+ private static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
+ Uri uri, ContentResolver cr, ParcelFileDescriptor pfd,
+ BitmapFactory.Options options) {
+ Bitmap b = null;
try {
if (pfd == null) pfd = makeInputStream(uri, cr);
if (pfd == null) return null;
@@ -232,115 +341,50 @@ public class ThumbnailUtil {
}
/**
- * Creates a centered bitmap of the desired size.
- * @param source
- * @param recycle whether we want to recycle the input
- */
- public static Bitmap extractMiniThumb(
- Bitmap source, int width, int height, boolean recycle) {
- if (source == null) {
- return null;
- }
-
- float scale;
- if (source.getWidth() < source.getHeight()) {
- scale = width / (float) source.getWidth();
- } else {
- scale = height / (float) source.getHeight();
- }
- Matrix matrix = new Matrix();
- matrix.setScale(scale, scale);
- Bitmap miniThumbnail = transform(matrix, source, width, height, true, recycle);
- return miniThumbnail;
- }
-
- /**
- * Create a video thumbnail for a video. May return null if the video is
- * corrupt.
- *
- * @param filePath
+ * Rotates the bitmap by the specified degree.
+ * If a new bitmap is created, the original bitmap is recycled.
*/
- public static Bitmap createVideoThumbnail(String filePath) {
- Bitmap bitmap = null;
- MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- try {
- retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
- retriever.setDataSource(filePath);
- bitmap = retriever.captureFrame();
- } catch (IllegalArgumentException ex) {
- // Assume this is a corrupt video file
- } catch (RuntimeException ex) {
- // Assume this is a corrupt video file.
- } finally {
+ private static Bitmap rotate(Bitmap b, int degrees) {
+ if (degrees != 0 && b != null) {
+ Matrix m = new Matrix();
+ m.setRotate(degrees,
+ (float) b.getWidth() / 2, (float) b.getHeight() / 2);
try {
- retriever.release();
- } catch (RuntimeException ex) {
- // Ignore failures while cleaning up.
+ Bitmap b2 = Bitmap.createBitmap(
+ b, 0, 0, b.getWidth(), b.getHeight(), m, true);
+ if (b != b2) {
+ b.recycle();
+ b = b2;
+ }
+ } catch (OutOfMemoryError ex) {
+ // We have no memory to rotate. Return the original bitmap.
}
}
- return bitmap;
+ return b;
}
- /**
- * This method first examines if the thumbnail embedded in EXIF is bigger than our target
- * size. If not, then it'll create a thumbnail from original image. Due to efficiency
- * consideration, we want to let MediaThumbRequest avoid calling this method twice for
- * both kinds, so it only requests for MICRO_KIND and set saveImage to true.
- *
- * This method always returns a "square thumbnail" for MICRO_KIND thumbnail.
- *
- * @param cr ContentResolver
- * @param filePath file path needed by EXIF interface
- * @param uri URI of original image
- * @param origId image id
- * @param kind either MINI_KIND or MICRO_KIND
- * @param saveMini Whether to save MINI_KIND thumbnail obtained in this method.
- * @return Bitmap
- */
- public static Bitmap createImageThumbnail(ContentResolver cr, String filePath, Uri uri,
- long origId, int kind, boolean saveMini) {
- boolean wantMini = (kind == Images.Thumbnails.MINI_KIND || saveMini);
- int targetSize = wantMini ?
- ThumbnailUtil.THUMBNAIL_TARGET_SIZE : ThumbnailUtil.MINI_THUMB_TARGET_SIZE;
- int maxPixels = wantMini ?
- ThumbnailUtil.THUMBNAIL_MAX_NUM_PIXELS : ThumbnailUtil.MINI_THUMB_MAX_NUM_PIXELS;
- SizedThumbnailBitmap sizedThumbnailBitmap = new SizedThumbnailBitmap();
- Bitmap bitmap = null;
- MediaFileType fileType = MediaFile.getFileType(filePath);
- if (fileType != null && fileType.fileType == MediaFile.FILE_TYPE_JPEG) {
- createThumbnailFromEXIF(filePath, targetSize, maxPixels, sizedThumbnailBitmap);
- bitmap = sizedThumbnailBitmap.mBitmap;
- }
-
- if (bitmap == null) {
- bitmap = ThumbnailUtil.makeBitmap(targetSize, maxPixels, uri, cr);
- }
+ private static void closeSilently(ParcelFileDescriptor c) {
+ if (c == null) return;
+ try {
+ c.close();
+ } catch (Throwable t) {
+ // do nothing
+ }
+ }
- if (bitmap == null) {
+ private static ParcelFileDescriptor makeInputStream(
+ Uri uri, ContentResolver cr) {
+ try {
+ return cr.openFileDescriptor(uri, "r");
+ } catch (IOException ex) {
return null;
}
-
- if (saveMini) {
- if (sizedThumbnailBitmap.mThumbnailData != null) {
- ThumbnailUtil.storeThumbnail(cr, origId,
- sizedThumbnailBitmap.mThumbnailData,
- sizedThumbnailBitmap.mThumbnailWidth,
- sizedThumbnailBitmap.mThumbnailHeight);
- } else {
- ThumbnailUtil.storeThumbnail(cr, origId, bitmap);
- }
- }
-
- if (kind == Images.Thumbnails.MICRO_KIND) {
- // now we make it a "square thumbnail" for MICRO_KIND thumbnail
- bitmap = ThumbnailUtil.extractMiniThumb(bitmap,
- ThumbnailUtil.MINI_THUMB_TARGET_SIZE,
- ThumbnailUtil.MINI_THUMB_TARGET_SIZE, ThumbnailUtil.RECYCLE_INPUT);
- }
- return bitmap;
}
- public static Bitmap transform(Matrix scaler,
+ /**
+ * Transform source Bitmap to targeted width and height.
+ */
+ private static Bitmap transform(Matrix scaler,
Bitmap source,
int targetWidth,
int targetHeight,
@@ -441,10 +485,6 @@ public class ThumbnailUtil {
/**
* Look up thumbnail uri by given imageId, it will be automatically created if it's not created
* yet. Most of the time imageId is identical to thumbId, but it's not always true.
- * @param req
- * @param width
- * @param height
- * @return Uri Thumbnail uri
*/
private static Uri getImageThumbnailUri(ContentResolver cr, long origId, int width, int height) {
Uri thumbUri = Images.Thumbnails.EXTERNAL_CONTENT_URI;
@@ -513,10 +553,14 @@ public class ThumbnailUtil {
}
}
- // SizedThumbnailBitmap contains the bitmap, which is downsampled either from
- // the thumbnail in exif or the full image.
- // mThumbnailData, mThumbnailWidth and mThumbnailHeight are set together only if mThumbnail is not null.
- // The width/height of the sized bitmap may be different from mThumbnailWidth/mThumbnailHeight.
+ /**
+ * SizedThumbnailBitmap contains the bitmap, which is downsampled either from
+ * the thumbnail in exif or the full image.
+ * mThumbnailData, mThumbnailWidth and mThumbnailHeight are set together only if mThumbnail
+ * is not null.
+ *
+ * The width/height of the sized bitmap may be different from mThumbnailWidth/mThumbnailHeight.
+ */
private static class SizedThumbnailBitmap {
public byte[] mThumbnailData;
public Bitmap mBitmap;
@@ -524,9 +568,11 @@ public class ThumbnailUtil {
public int mThumbnailHeight;
}
- // Creates a bitmap by either downsampling from the thumbnail in EXIF or the full image.
- // The functions returns a SizedThumbnailBitmap,
- // which contains a downsampled bitmap and the thumbnail data in EXIF if exists.
+ /**
+ * Creates a bitmap by either downsampling from the thumbnail in EXIF or the full image.
+ * The functions returns a SizedThumbnailBitmap,
+ * which contains a downsampled bitmap and the thumbnail data in EXIF if exists.
+ */
private static void createThumbnailFromEXIF(String filePath, int targetSize,
int maxPixels, SizedThumbnailBitmap sizedThumbBitmap) {
if (filePath == null) return;
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 1d82e321afc6..d83f49329a48 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -10,7 +10,8 @@ LOCAL_SRC_FILES:= \
android_media_MediaRecorder.cpp \
android_media_MediaScanner.cpp \
android_media_MediaMetadataRetriever.cpp \
- android_media_ResampleInputStream.cpp
+ android_media_ResampleInputStream.cpp \
+ android_media_MediaProfiles.cpp
LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 27f5668a48db..76d167458804 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -739,6 +739,7 @@ extern int register_android_media_MediaMetadataRetriever(JNIEnv *env);
extern int register_android_media_MediaRecorder(JNIEnv *env);
extern int register_android_media_MediaScanner(JNIEnv *env);
extern int register_android_media_ResampleInputStream(JNIEnv *env);
+extern int register_android_media_MediaProfiles(JNIEnv *env);
#ifndef NO_OPENCORE
extern int register_android_media_AmrInputStream(JNIEnv *env);
@@ -787,6 +788,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
goto bail;
}
+ if (register_android_media_MediaProfiles(env) < 0) {
+ LOGE("ERROR: MediaProfiles native registration failed");
+ goto bail;
+ }
+
/* success -- return valid version number */
result = JNI_VERSION_1_4;
diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp
new file mode 100644
index 000000000000..cd3ad8817e06
--- /dev/null
+++ b/media/jni/android_media_MediaProfiles.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaProfilesJNI"
+#include <utils/Log.h>
+
+#include <stdio.h>
+#include <utils/threads.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+#include <media/MediaProfiles.h>
+
+using namespace android;
+
+static Mutex sLock;
+MediaProfiles *sProfiles = NULL;
+
+// This function is called from a static block in MediaProfiles.java class,
+// which won't run until the first time an instance of this class is used.
+static void
+android_media_MediaProfiles_native_init(JNIEnv *env)
+{
+ LOGV("native_init");
+ Mutex::Autolock lock(sLock);
+
+ if (sProfiles == NULL) {
+ sProfiles = MediaProfiles::getInstance();
+ }
+}
+
+static int
+android_media_MediaProfiles_native_get_num_file_formats(JNIEnv *env, jobject thiz)
+{
+ LOGV("native_get_num_file_formats");
+ return sProfiles->getOutputFileFormats().size();
+}
+
+static int
+android_media_MediaProfiles_native_get_file_format(JNIEnv *env, jobject thiz, jint index)
+{
+ LOGV("native_get_file_format: %d", index);
+ Vector<output_format> formats = sProfiles->getOutputFileFormats();
+ int nSize = formats.size();
+ if (index < 0 || index >= nSize) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "out of array boundary");
+ return -1;
+ }
+ int format = static_cast<int>(formats[index]);
+ return format;
+}
+
+static int
+android_media_MediaProfiles_native_get_num_video_encoders(JNIEnv *env, jobject thiz)
+{
+ LOGV("native_get_num_video_encoders");
+ return sProfiles->getVideoEncoders().size();
+}
+
+static jobject
+android_media_MediaProfiles_native_get_video_encoder_cap(JNIEnv *env, jobject thiz, jint index)
+{
+ LOGV("native_get_video_encoder_cap: %d", index);
+ Vector<video_encoder> encoders = sProfiles->getVideoEncoders();
+ int nSize = encoders.size();
+ if (index < 0 || index >= nSize) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "out of array boundary");
+ return NULL;
+ }
+
+ video_encoder encoder = encoders[index];
+ int minBitRate = sProfiles->getVideoEncoderParamByName("enc.vid.bps.min", encoder);
+ int maxBitRate = sProfiles->getVideoEncoderParamByName("enc.vid.bps.max", encoder);
+ int minFrameRate = sProfiles->getVideoEncoderParamByName("enc.vid.fps.min", encoder);
+ int maxFrameRate = sProfiles->getVideoEncoderParamByName("enc.vid.fps.max", encoder);
+ int minFrameWidth = sProfiles->getVideoEncoderParamByName("enc.vid.width.min", encoder);
+ int maxFrameWidth = sProfiles->getVideoEncoderParamByName("enc.vid.width.max", encoder);
+ int minFrameHeight = sProfiles->getVideoEncoderParamByName("enc.vid.height.min", encoder);
+ int maxFrameHeight = sProfiles->getVideoEncoderParamByName("enc.vid.height.max", encoder);
+
+ // Check on the values retrieved
+ if ((minBitRate == -1 || maxBitRate == -1) ||
+ (minFrameRate == -1 || maxFrameRate == -1) ||
+ (minFrameWidth == -1 || maxFrameWidth == -1) ||
+ (minFrameHeight == -1 || maxFrameHeight == -1)) {
+
+ jniThrowException(env, "java/lang/RuntimeException", "Error retrieving video encoder capability params");
+ return NULL;
+ }
+
+ // Construct an instance of the VideoEncoderCap and set its member variables
+ jclass videoEncoderCapClazz = env->FindClass("android/media/EncoderCapabilities$VideoEncoderCap");
+ jmethodID videoEncoderCapConstructorMethodID = env->GetMethodID(videoEncoderCapClazz, "<init>", "(IIIIIIIII)V");
+ jobject cap = env->NewObject(videoEncoderCapClazz,
+ videoEncoderCapConstructorMethodID,
+ static_cast<int>(encoder),
+ minBitRate, maxBitRate,
+ minFrameRate, maxFrameRate,
+ minFrameWidth, maxFrameWidth,
+ minFrameHeight, maxFrameHeight);
+ return cap;
+}
+
+static int
+android_media_MediaProfiles_native_get_num_audio_encoders(JNIEnv *env, jobject thiz)
+{
+ LOGV("native_get_num_audio_encoders");
+ return sProfiles->getAudioEncoders().size();
+}
+
+static jobject
+android_media_MediaProfiles_native_get_audio_encoder_cap(JNIEnv *env, jobject thiz, jint index)
+{
+ LOGV("native_get_audio_encoder_cap: %d", index);
+ Vector<audio_encoder> encoders = sProfiles->getAudioEncoders();
+ int nSize = encoders.size();
+ if (index < 0 || index >= nSize) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "out of array boundary");
+ return NULL;
+ }
+
+ audio_encoder encoder = encoders[index];
+ int minBitRate = sProfiles->getAudioEncoderParamByName("enc.aud.bps.min", encoder);
+ int maxBitRate = sProfiles->getAudioEncoderParamByName("enc.aud.bps.max", encoder);
+ int minSampleRate = sProfiles->getAudioEncoderParamByName("enc.aud.hz.min", encoder);
+ int maxSampleRate = sProfiles->getAudioEncoderParamByName("enc.aud.hz.max", encoder);
+ int minChannels = sProfiles->getAudioEncoderParamByName("enc.aud.ch.min", encoder);
+ int maxChannels = sProfiles->getAudioEncoderParamByName("enc.aud.ch.max", encoder);
+
+ // Check on the values retrieved
+ if ((minBitRate == -1 || maxBitRate == -1) ||
+ (minSampleRate == -1 || maxSampleRate == -1) ||
+ (minChannels == -1 || maxChannels == -1)) {
+
+ jniThrowException(env, "java/lang/RuntimeException", "Error retrieving video encoder capability params");
+ return NULL;
+ }
+
+ jclass audioEncoderCapClazz = env->FindClass("android/media/EncoderCapabilities$AudioEncoderCap");
+ jmethodID audioEncoderCapConstructorMethodID = env->GetMethodID(audioEncoderCapClazz, "<init>", "(IIIIIII)V");
+ jobject cap = env->NewObject(audioEncoderCapClazz,
+ audioEncoderCapConstructorMethodID,
+ static_cast<int>(encoder),
+ minBitRate, maxBitRate,
+ minSampleRate, maxSampleRate,
+ minChannels, maxChannels);
+ return cap;
+}
+
+static JNINativeMethod gMethods[] = {
+ {"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
+ {"native_get_num_file_formats", "()I", (void *)android_media_MediaProfiles_native_get_num_file_formats},
+ {"native_get_file_format", "(I)I", (void *)android_media_MediaProfiles_native_get_file_format},
+ {"native_get_num_video_encoders", "()I", (void *)android_media_MediaProfiles_native_get_num_video_encoders},
+ {"native_get_num_audio_encoders", "()I", (void *)android_media_MediaProfiles_native_get_num_audio_encoders},
+
+ {"native_get_video_encoder_cap", "(I)Landroid/media/EncoderCapabilities$VideoEncoderCap;",
+ (void *)android_media_MediaProfiles_native_get_video_encoder_cap},
+
+ {"native_get_audio_encoder_cap", "(I)Landroid/media/EncoderCapabilities$AudioEncoderCap;",
+ (void *)android_media_MediaProfiles_native_get_audio_encoder_cap},
+};
+
+static const char* const kClassPathName = "android/media/MediaProfiles";
+
+// This function only registers the native methods, and is called from
+// JNI_OnLoad in android_media_MediaPlayer.cpp
+int register_android_media_MediaProfiles(JNIEnv *env)
+{
+ return AndroidRuntime::registerNativeMethods(env,
+ "android/media/EncoderCapabilities", gMethods, NELEM(gMethods));
+}
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 4ae4ec9b493f..c59d3230420f 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -25,10 +25,11 @@ LOCAL_SRC_FILES:= \
MediaScanner.cpp \
MediaScannerClient.cpp \
autodetect.cpp \
- IMediaDeathNotifier.cpp
+ IMediaDeathNotifier.cpp \
+ MediaProfiles.cpp
LOCAL_SHARED_LIBRARIES := \
- libui libcutils libutils libbinder libsonivox libicuuc
+ libui libcutils libutils libbinder libsonivox libicuuc libexpat
LOCAL_MODULE:= libmedia
@@ -43,10 +44,11 @@ endif
LOCAL_C_INCLUDES := \
$(JNI_H_INCLUDE) \
$(call include-path-for, graphics corecg) \
- $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
- external/speex/include \
- external/speex/libspeex \
- external/icu4c/common
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+ external/speex/include \
+ external/speex/libspeex \
+ external/icu4c/common \
+ external/expat/lib
LOCAL_STATIC_LIBRARIES := libspeex
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index f4165ffede88..7bbd0b2e8e91 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -32,7 +32,6 @@
#include <binder/IServiceManager.h>
#include <utils/Log.h>
-#include <binder/MemoryDealer.h>
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/Timers.h>
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index ad0f42e95acc..74852dcd7a79 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -32,7 +32,6 @@
#include <media/AudioTrack.h>
#include <utils/Log.h>
-#include <binder/MemoryDealer.h>
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/Timers.h>
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
new file mode 100644
index 000000000000..0efade1289c8
--- /dev/null
+++ b/media/libmedia/MediaProfiles.cpp
@@ -0,0 +1,675 @@
+/*
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaProfiles"
+
+#include <stdlib.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+#include <cutils/properties.h>
+#include <expat.h>
+#include <media/MediaProfiles.h>
+#include <media/stagefright/MediaDebug.h>
+
+namespace android {
+
+Mutex MediaProfiles::sLock;
+bool MediaProfiles::sIsInitialized = false;
+MediaProfiles *MediaProfiles::sInstance = NULL;
+
+const MediaProfiles::NameToTagMap MediaProfiles::sVideoEncoderNameMap[] = {
+ {"h263", VIDEO_ENCODER_H263},
+ {"h264", VIDEO_ENCODER_H264},
+ {"m4v", VIDEO_ENCODER_MPEG_4_SP}
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = {
+ {"amrnb", AUDIO_ENCODER_AMR_NB},
+ {"amrwb", AUDIO_ENCODER_AMR_WB},
+ {"aac", AUDIO_ENCODER_AAC},
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sFileFormatMap[] = {
+ {"3gp", OUTPUT_FORMAT_THREE_GPP},
+ {"mp4", OUTPUT_FORMAT_MPEG_4}
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sVideoDecoderNameMap[] = {
+ {"wmv", VIDEO_DECODER_WMV}
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sAudioDecoderNameMap[] = {
+ {"wma", AUDIO_DECODER_WMA}
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = {
+ {"high", CAMCORDER_QUALITY_HIGH},
+ {"low", CAMCORDER_QUALITY_LOW}
+};
+
+/*static*/ void
+MediaProfiles::logVideoCodec(const MediaProfiles::VideoCodec& codec)
+{
+ LOGV("video codec:");
+ LOGV("codec = %d", codec.mCodec);
+ LOGV("bit rate: %d", codec.mBitRate);
+ LOGV("frame width: %d", codec.mFrameWidth);
+ LOGV("frame height: %d", codec.mFrameHeight);
+ LOGV("frame rate: %d", codec.mFrameRate);
+}
+
+/*static*/ void
+MediaProfiles::logAudioCodec(const MediaProfiles::AudioCodec& codec)
+{
+ LOGV("audio codec:");
+ LOGV("codec = %d", codec.mCodec);
+ LOGV("bit rate: %d", codec.mBitRate);
+ LOGV("sample rate: %d", codec.mSampleRate);
+ LOGV("number of channels: %d", codec.mChannels);
+}
+
+/*static*/ void
+MediaProfiles::logVideoEncoderCap(const MediaProfiles::VideoEncoderCap& cap)
+{
+ LOGV("video encoder cap:");
+ LOGV("codec = %d", cap.mCodec);
+ LOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate);
+ LOGV("frame width: min = %d and max = %d", cap.mMinFrameWidth, cap.mMaxFrameWidth);
+ LOGV("frame height: min = %d and max = %d", cap.mMinFrameHeight, cap.mMaxFrameHeight);
+ LOGV("frame rate: min = %d and max = %d", cap.mMinFrameRate, cap.mMaxFrameRate);
+}
+
+/*static*/ void
+MediaProfiles::logAudioEncoderCap(const MediaProfiles::AudioEncoderCap& cap)
+{
+ LOGV("audio encoder cap:");
+ LOGV("codec = %d", cap.mCodec);
+ LOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate);
+ LOGV("sample rate: min = %d and max = %d", cap.mMinSampleRate, cap.mMaxSampleRate);
+ LOGV("number of channels: min = %d and max = %d", cap.mMinChannels, cap.mMaxChannels);
+}
+
+/*static*/ void
+MediaProfiles::logVideoDecoderCap(const MediaProfiles::VideoDecoderCap& cap)
+{
+ LOGV("video decoder cap:");
+ LOGV("codec = %d", cap.mCodec);
+}
+
+/*static*/ void
+MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap)
+{
+ LOGV("audio codec cap:");
+ LOGV("codec = %d", cap.mCodec);
+}
+
+/*static*/ int
+MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings, const char *name)
+{
+ int tag = -1;
+ for (size_t i = 0; i < nMappings; ++i) {
+ if (!strcmp(map[i].name, name)) {
+ tag = map[i].tag;
+ break;
+ }
+ }
+ return tag;
+}
+
+/*static*/ MediaProfiles::VideoCodec*
+MediaProfiles::createVideoCodec(const char **atts, MediaProfiles *profiles)
+{
+ CHECK(!strcmp("codec", atts[0]) &&
+ !strcmp("bitRate", atts[2]) &&
+ !strcmp("width", atts[4]) &&
+ !strcmp("height", atts[6]) &&
+ !strcmp("frameRate", atts[8]));
+
+ const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
+ const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::VideoCodec *videoCodec =
+ new MediaProfiles::VideoCodec(static_cast<video_encoder>(codec),
+ atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), atoi(atts[9]));
+ logVideoCodec(*videoCodec);
+
+ size_t nCamcorderProfiles;
+ CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1);
+ profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mVideoCodec = videoCodec;
+ return videoCodec;
+}
+
+/*static*/ MediaProfiles::AudioCodec*
+MediaProfiles::createAudioCodec(const char **atts, MediaProfiles *profiles)
+{
+ CHECK(!strcmp("codec", atts[0]) &&
+ !strcmp("bitRate", atts[2]) &&
+ !strcmp("sampleRate", atts[4]) &&
+ !strcmp("channels", atts[6]));
+ const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]);
+ const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::AudioCodec *audioCodec =
+ new MediaProfiles::AudioCodec(static_cast<audio_encoder>(codec),
+ atoi(atts[3]), atoi(atts[5]), atoi(atts[7]));
+ logAudioCodec(*audioCodec);
+
+ size_t nCamcorderProfiles;
+ CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1);
+ profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mAudioCodec = audioCodec;
+ return audioCodec;
+}
+/*static*/ MediaProfiles::AudioDecoderCap*
+MediaProfiles::createAudioDecoderCap(const char **atts)
+{
+ CHECK(!strcmp("name", atts[0]) &&
+ !strcmp("enabled", atts[2]));
+
+ const size_t nMappings = sizeof(sAudioDecoderNameMap)/sizeof(sAudioDecoderNameMap[0]);
+ const int codec = findTagForName(sAudioDecoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::AudioDecoderCap *cap =
+ new MediaProfiles::AudioDecoderCap(static_cast<audio_decoder>(codec));
+ logAudioDecoderCap(*cap);
+ return cap;
+}
+
+/*static*/ MediaProfiles::VideoDecoderCap*
+MediaProfiles::createVideoDecoderCap(const char **atts)
+{
+ CHECK(!strcmp("name", atts[0]) &&
+ !strcmp("enabled", atts[2]));
+
+ const size_t nMappings = sizeof(sVideoDecoderNameMap)/sizeof(sVideoDecoderNameMap[0]);
+ const int codec = findTagForName(sVideoDecoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::VideoDecoderCap *cap =
+ new MediaProfiles::VideoDecoderCap(static_cast<video_decoder>(codec));
+ logVideoDecoderCap(*cap);
+ return cap;
+}
+
+/*static*/ MediaProfiles::VideoEncoderCap*
+MediaProfiles::createVideoEncoderCap(const char **atts)
+{
+ CHECK(!strcmp("name", atts[0]) &&
+ !strcmp("enabled", atts[2]) &&
+ !strcmp("minBitRate", atts[4]) &&
+ !strcmp("maxBitRate", atts[6]) &&
+ !strcmp("minFrameWidth", atts[8]) &&
+ !strcmp("maxFrameWidth", atts[10]) &&
+ !strcmp("minFrameHeight", atts[12]) &&
+ !strcmp("maxFrameHeight", atts[14]) &&
+ !strcmp("minFrameRate", atts[16]) &&
+ !strcmp("maxFrameRate", atts[18]));
+
+ const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
+ const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::VideoEncoderCap *cap =
+ new MediaProfiles::VideoEncoderCap(static_cast<video_encoder>(codec),
+ atoi(atts[5]), atoi(atts[7]), atoi(atts[9]), atoi(atts[11]), atoi(atts[13]),
+ atoi(atts[15]), atoi(atts[17]), atoi(atts[19]));
+ logVideoEncoderCap(*cap);
+ return cap;
+}
+
+/*static*/ MediaProfiles::AudioEncoderCap*
+MediaProfiles::createAudioEncoderCap(const char **atts)
+{
+ CHECK(!strcmp("name", atts[0]) &&
+ !strcmp("enabled", atts[2]) &&
+ !strcmp("minBitRate", atts[4]) &&
+ !strcmp("maxBitRate", atts[6]) &&
+ !strcmp("minSampleRate", atts[8]) &&
+ !strcmp("maxSampleRate", atts[10]) &&
+ !strcmp("minChannels", atts[12]) &&
+ !strcmp("maxChannels", atts[14]));
+
+ const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]);
+ const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::AudioEncoderCap *cap =
+ new MediaProfiles::AudioEncoderCap(static_cast<audio_encoder>(codec), atoi(atts[5]), atoi(atts[7]),
+ atoi(atts[9]), atoi(atts[11]), atoi(atts[13]),
+ atoi(atts[15]));
+ logAudioEncoderCap(*cap);
+ return cap;
+}
+
+/*static*/ output_format
+MediaProfiles::createEncoderOutputFileFormat(const char **atts)
+{
+ CHECK(!strcmp("name", atts[0]));
+
+ const size_t nMappings =sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]);
+ const int format = findTagForName(sFileFormatMap, nMappings, atts[1]);
+ CHECK(format != -1);
+
+ return static_cast<output_format>(format);
+}
+
+/*static*/ MediaProfiles::CamcorderProfile*
+MediaProfiles::createCamcorderProfile(const char **atts)
+{
+ CHECK(!strcmp("quality", atts[0]) &&
+ !strcmp("fileFormat", atts[2]) &&
+ !strcmp("duration", atts[4]));
+
+ const size_t nProfileMappings = sizeof(sCamcorderQualityNameMap)/sizeof(sCamcorderQualityNameMap[0]);
+ const int quality = findTagForName(sCamcorderQualityNameMap, nProfileMappings, atts[1]);
+ CHECK(quality != -1);
+
+ const size_t nFormatMappings = sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]);
+ const int fileFormat = findTagForName(sFileFormatMap, nFormatMappings, atts[3]);
+ CHECK(fileFormat != -1);
+
+ MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+ profile->mFileFormat = static_cast<output_format>(fileFormat);
+ profile->mQuality = static_cast<camcorder_quality>(quality);
+ profile->mDuration = atoi(atts[5]);
+ return profile;
+}
+
+/*static*/ void
+MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts)
+{
+ MediaProfiles *profiles = (MediaProfiles *) userData;
+ if (strcmp("Video", name) == 0) {
+ createVideoCodec(atts, profiles);
+ } else if (strcmp("Audio", name) == 0) {
+ createAudioCodec(atts, profiles);
+ } else if (strcmp("VideoEncoderCap", name) == 0 &&
+ strcmp("true", atts[3]) == 0) {
+ profiles->mVideoEncoders.add(createVideoEncoderCap(atts));
+ } else if (strcmp("AudioEncoderCap", name) == 0 &&
+ strcmp("true", atts[3]) == 0) {
+ profiles->mAudioEncoders.add(createAudioEncoderCap(atts));
+ } else if (strcmp("VideoDecoderCap", name) == 0 &&
+ strcmp("true", atts[3]) == 0) {
+ profiles->mVideoDecoders.add(createVideoDecoderCap(atts));
+ } else if (strcmp("AudioDecoderCap", name) == 0 &&
+ strcmp("true", atts[3]) == 0) {
+ profiles->mAudioDecoders.add(createAudioDecoderCap(atts));
+ } else if (strcmp("EncoderOutputFileFormat", name) == 0) {
+ profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts));
+ } else if (strcmp("EncoderProfile", name) == 0) {
+ profiles->mCamcorderProfiles.add(createCamcorderProfile(atts));
+ }
+}
+
+/*static*/ MediaProfiles*
+MediaProfiles::getInstance()
+{
+ LOGV("getInstance");
+ Mutex::Autolock lock(sLock);
+ if (!sIsInitialized) {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.settings.xml", value, NULL) <= 0) {
+ const char *defaultXmlFile = "/etc/media_profiles.xml";
+ FILE *fp = fopen(defaultXmlFile, "r");
+ if (fp == NULL) {
+ LOGW("could not find media config xml file");
+ sInstance = createDefaultInstance();
+ } else {
+ fclose(fp); // close the file first.
+ sInstance = createInstanceFromXmlFile(defaultXmlFile);
+ }
+ } else {
+ sInstance = createInstanceFromXmlFile(value);
+ }
+ }
+
+ return sInstance;
+}
+
+/*static*/ MediaProfiles::VideoEncoderCap*
+MediaProfiles::createDefaultH263VideoEncoderCap()
+{
+ return new MediaProfiles::VideoEncoderCap(
+ VIDEO_ENCODER_H263, 192000, 420000, 176, 352, 144, 288, 1, 20);
+}
+
+/*static*/ MediaProfiles::VideoEncoderCap*
+MediaProfiles::createDefaultM4vVideoEncoderCap()
+{
+ return new MediaProfiles::VideoEncoderCap(
+ VIDEO_ENCODER_MPEG_4_SP, 192000, 420000, 176, 352, 144, 288, 1, 20);
+}
+
+
+/*static*/ void
+MediaProfiles::createDefaultVideoEncoders(MediaProfiles *profiles)
+{
+ profiles->mVideoEncoders.add(createDefaultH263VideoEncoderCap());
+ profiles->mVideoEncoders.add(createDefaultM4vVideoEncoderCap());
+}
+
+/*static*/ MediaProfiles::CamcorderProfile*
+MediaProfiles::createDefaultCamcorderHighProfile()
+{
+ MediaProfiles::VideoCodec *videoCodec =
+ new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20);
+
+ AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
+ CamcorderProfile *profile = new CamcorderProfile;
+ profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
+ profile->mQuality = CAMCORDER_QUALITY_HIGH;
+ profile->mDuration = 60;
+ profile->mVideoCodec = videoCodec;
+ profile->mAudioCodec = audioCodec;
+ return profile;
+}
+
+/*static*/ MediaProfiles::CamcorderProfile*
+MediaProfiles::createDefaultCamcorderLowProfile()
+{
+ MediaProfiles::VideoCodec *videoCodec =
+ new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 192000, 176, 144, 20);
+
+ MediaProfiles::AudioCodec *audioCodec =
+ new MediaProfiles::AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
+
+ MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+ profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
+ profile->mQuality = CAMCORDER_QUALITY_LOW;
+ profile->mDuration = 30;
+ profile->mVideoCodec = videoCodec;
+ profile->mAudioCodec = audioCodec;
+ return profile;
+}
+
+/*static*/ void
+MediaProfiles::createDefaultCamcorderProfiles(MediaProfiles *profiles)
+{
+ profiles->mCamcorderProfiles.add(createDefaultCamcorderHighProfile());
+ profiles->mCamcorderProfiles.add(createDefaultCamcorderLowProfile());
+}
+
+/*static*/ void
+MediaProfiles::createDefaultAudioEncoders(MediaProfiles *profiles)
+{
+ profiles->mAudioEncoders.add(createDefaultAmrNBEncoderCap());
+}
+
+/*static*/ void
+MediaProfiles::createDefaultVideoDecoders(MediaProfiles *profiles)
+{
+ MediaProfiles::VideoDecoderCap *cap =
+ new MediaProfiles::VideoDecoderCap(VIDEO_DECODER_WMV);
+
+ profiles->mVideoDecoders.add(cap);
+}
+
+/*static*/ void
+MediaProfiles::createDefaultAudioDecoders(MediaProfiles *profiles)
+{
+ MediaProfiles::AudioDecoderCap *cap =
+ new MediaProfiles::AudioDecoderCap(AUDIO_DECODER_WMA);
+
+ profiles->mAudioDecoders.add(cap);
+}
+
+/*static*/ void
+MediaProfiles::createDefaultEncoderOutputFileFormats(MediaProfiles *profiles)
+{
+ profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_THREE_GPP);
+ profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_MPEG_4);
+}
+
+/*static*/ MediaProfiles::AudioEncoderCap*
+MediaProfiles::createDefaultAmrNBEncoderCap()
+{
+ return new MediaProfiles::AudioEncoderCap(
+ AUDIO_ENCODER_AMR_NB, 5525, 12200, 8000, 8000, 1, 1);
+}
+
+/*static*/ MediaProfiles*
+MediaProfiles::createDefaultInstance()
+{
+ MediaProfiles *profiles = new MediaProfiles;
+ createDefaultCamcorderProfiles(profiles);
+ createDefaultVideoEncoders(profiles);
+ createDefaultAudioEncoders(profiles);
+ createDefaultVideoDecoders(profiles);
+ createDefaultAudioDecoders(profiles);
+ createDefaultEncoderOutputFileFormats(profiles);
+ sIsInitialized = true;
+ return profiles;
+}
+
+/*static*/ MediaProfiles*
+MediaProfiles::createInstanceFromXmlFile(const char *xml)
+{
+ FILE *fp = NULL;
+ CHECK((fp = fopen(xml, "r")));
+
+ XML_Parser parser = ::XML_ParserCreate(NULL);
+ CHECK(parser != NULL);
+
+ MediaProfiles *profiles = new MediaProfiles();
+ ::XML_SetUserData(parser, profiles);
+ ::XML_SetElementHandler(parser, startElementHandler, NULL);
+
+ /*
+ FIXME:
+ expat is not compiled with -DXML_DTD. We don't have DTD parsing support.
+
+ if (!::XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS)) {
+ LOGE("failed to enable DTD support in the xml file");
+ return UNKNOWN_ERROR;
+ }
+
+ */
+
+ const int BUFF_SIZE = 512;
+ for (;;) {
+ void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
+ if (buff == NULL) {
+ LOGE("failed to in call to XML_GetBuffer()");
+ delete profiles;
+ profiles = NULL;
+ goto exit;
+ }
+
+ int bytes_read = ::fread(buff, 1, BUFF_SIZE, fp);
+ if (bytes_read < 0) {
+ LOGE("failed in call to read");
+ delete profiles;
+ profiles = NULL;
+ goto exit;
+ }
+
+ CHECK(::XML_ParseBuffer(parser, bytes_read, bytes_read == 0));
+
+ if (bytes_read == 0) break; // done parsing the xml file
+ }
+
+exit:
+ ::XML_ParserFree(parser);
+ ::fclose(fp);
+ if (profiles) {
+ sIsInitialized = true;
+ }
+ return profiles;
+}
+
+Vector<output_format> MediaProfiles::getOutputFileFormats() const
+{
+ return mEncoderOutputFileFormats; // copy out
+}
+
+Vector<video_encoder> MediaProfiles::getVideoEncoders() const
+{
+ Vector<video_encoder> encoders;
+ for (size_t i = 0; i < mVideoEncoders.size(); ++i) {
+ encoders.add(mVideoEncoders[i]->mCodec);
+ }
+ return encoders; // copy out
+}
+
+int MediaProfiles::getVideoEncoderParamByName(const char *name, video_encoder codec) const
+{
+ LOGV("getVideoEncoderParamByName: %s for codec %d", name, codec);
+ int index = -1;
+ for (size_t i = 0, n = mVideoEncoders.size(); i < n; ++i) {
+ if (mVideoEncoders[i]->mCodec == codec) {
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) {
+ LOGE("The given video encoder %d is not found", codec);
+ return -1;
+ }
+
+ if (!strcmp("enc.vid.width.min", name)) return mVideoEncoders[index]->mMinFrameWidth;
+ if (!strcmp("enc.vid.width.max", name)) return mVideoEncoders[index]->mMaxFrameWidth;
+ if (!strcmp("enc.vid.height.min", name)) return mVideoEncoders[index]->mMinFrameHeight;
+ if (!strcmp("enc.vid.height.max", name)) return mVideoEncoders[index]->mMaxFrameHeight;
+ if (!strcmp("enc.vid.bps.min", name)) return mVideoEncoders[index]->mMinBitRate;
+ if (!strcmp("enc.vid.bps.max", name)) return mVideoEncoders[index]->mMaxBitRate;
+ if (!strcmp("enc.vid.fps.min", name)) return mVideoEncoders[index]->mMinFrameRate;
+ if (!strcmp("enc.vid.fps.max", name)) return mVideoEncoders[index]->mMaxFrameRate;
+
+ LOGE("The given video encoder param name %s is not found", name);
+ return -1;
+}
+
+Vector<audio_encoder> MediaProfiles::getAudioEncoders() const
+{
+ Vector<audio_encoder> encoders;
+ for (size_t i = 0; i < mAudioEncoders.size(); ++i) {
+ encoders.add(mAudioEncoders[i]->mCodec);
+ }
+ return encoders; // copy out
+}
+
+int MediaProfiles::getAudioEncoderParamByName(const char *name, audio_encoder codec) const
+{
+ LOGV("getAudioEncoderParamByName: %s for codec %d", name, codec);
+ int index = -1;
+ for (size_t i = 0, n = mAudioEncoders.size(); i < n; ++i) {
+ if (mAudioEncoders[i]->mCodec == codec) {
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) {
+ LOGE("The given audio encoder %d is not found", codec);
+ return -1;
+ }
+
+ if (!strcmp("enc.aud.ch.min", name)) return mAudioEncoders[index]->mMinChannels;
+ if (!strcmp("enc.aud.ch.max", name)) return mAudioEncoders[index]->mMaxChannels;
+ if (!strcmp("enc.aud.bps.min", name)) return mAudioEncoders[index]->mMinBitRate;
+ if (!strcmp("enc.aud.bps.max", name)) return mAudioEncoders[index]->mMaxBitRate;
+ if (!strcmp("enc.aud.hz.min", name)) return mAudioEncoders[index]->mMinSampleRate;
+ if (!strcmp("enc.aud.hz.max", name)) return mAudioEncoders[index]->mMaxSampleRate;
+
+ LOGE("The given audio encoder param name %s is not found", name);
+ return -1;
+}
+
+Vector<video_decoder> MediaProfiles::getVideoDecoders() const
+{
+ Vector<video_decoder> decoders;
+ for (size_t i = 0; i < mVideoDecoders.size(); ++i) {
+ decoders.add(mVideoDecoders[i]->mCodec);
+ }
+ return decoders; // copy out
+}
+
+Vector<audio_decoder> MediaProfiles::getAudioDecoders() const
+{
+ Vector<audio_decoder> decoders;
+ for (size_t i = 0; i < mAudioDecoders.size(); ++i) {
+ decoders.add(mAudioDecoders[i]->mCodec);
+ }
+ return decoders; // copy out
+}
+
+int MediaProfiles::getCamcorderProfileParamByName(const char *name, camcorder_quality quality) const
+{
+ LOGV("getCamcorderProfileParamByName: %s for quality %d", name, quality);
+
+ int index = -1;
+ for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
+ if (mCamcorderProfiles[i]->mQuality == quality) {
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) {
+ LOGE("The given camcorder profile quality %d is not found", quality);
+ return -1;
+ }
+
+ if (!strcmp("file.format", name)) return mCamcorderProfiles[index]->mFileFormat;
+ if (!strcmp("vid.codec", name)) return mCamcorderProfiles[index]->mVideoCodec->mCodec;
+ if (!strcmp("vid.width", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameWidth;
+ if (!strcmp("vid.height", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameHeight;
+ if (!strcmp("vid.bps", name)) return mCamcorderProfiles[index]->mVideoCodec->mBitRate;
+ if (!strcmp("vid.fps", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameRate;
+ if (!strcmp("aud.codec", name)) return mCamcorderProfiles[index]->mAudioCodec->mCodec;
+ if (!strcmp("aud.bps", name)) return mCamcorderProfiles[index]->mAudioCodec->mBitRate;
+ if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodec->mChannels;
+ if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodec->mSampleRate;
+
+ LOGE("The given camcorder profile param name %s is not found", name);
+ return -1;
+}
+
+MediaProfiles::~MediaProfiles()
+{
+ CHECK("destructor should never be called" == 0);
+#if 0
+ for (size_t i = 0; i < mAudioEncoders.size(); ++i) {
+ delete mAudioEncoders[i];
+ }
+ mAudioEncoders.clear();
+
+ for (size_t i = 0; i < mVideoEncoders.size(); ++i) {
+ delete mVideoEncoders[i];
+ }
+ mVideoEncoders.clear();
+
+ for (size_t i = 0; i < mVideoDecoders.size(); ++i) {
+ delete mVideoDecoders[i];
+ }
+ mVideoDecoders.clear();
+
+ for (size_t i = 0; i < mAudioDecoders.size(); ++i) {
+ delete mAudioDecoders[i];
+ }
+ mAudioDecoders.clear();
+
+ for (size_t i = 0; i < mCamcorderProfiles.size(); ++i) {
+ delete mCamcorderProfiles[i];
+ }
+ mCamcorderProfiles.clear();
+#endif
+}
+} // namespace android
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 66de2eee69a4..550b84dfb347 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -28,7 +28,8 @@
#include <string.h>
#include <cutils/atomic.h>
#include <cutils/properties.h>
-#include <binder/MemoryDealer.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
#include <android_runtime/ActivityManager.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -62,8 +63,6 @@ MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid)
{
LOGV("MetadataRetrieverClient constructor pid(%d)", pid);
mPid = pid;
- mThumbnailDealer = NULL;
- mAlbumArtDealer = NULL;
mThumbnail = NULL;
mAlbumArt = NULL;
mRetriever = NULL;
@@ -94,8 +93,6 @@ void MetadataRetrieverClient::disconnect()
LOGV("disconnect from pid %d", mPid);
Mutex::Autolock lock(mLock);
mRetriever.clear();
- mThumbnailDealer.clear();
- mAlbumArtDealer.clear();
mThumbnail.clear();
mAlbumArt.clear();
mMode = METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL;
@@ -242,7 +239,6 @@ sp<IMemory> MetadataRetrieverClient::captureFrame()
LOGV("captureFrame");
Mutex::Autolock lock(mLock);
mThumbnail.clear();
- mThumbnailDealer.clear();
if (mRetriever == NULL) {
LOGE("retriever is not initialized");
return NULL;
@@ -253,16 +249,15 @@ sp<IMemory> MetadataRetrieverClient::captureFrame()
return NULL;
}
size_t size = sizeof(VideoFrame) + frame->mSize;
- mThumbnailDealer = new MemoryDealer(size);
- if (mThumbnailDealer == NULL) {
+ sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
+ if (heap == NULL) {
LOGE("failed to create MemoryDealer");
delete frame;
return NULL;
}
- mThumbnail = mThumbnailDealer->allocate(size);
+ mThumbnail = new MemoryBase(heap, 0, size);
if (mThumbnail == NULL) {
LOGE("not enough memory for VideoFrame size=%u", size);
- mThumbnailDealer.clear();
delete frame;
return NULL;
}
@@ -283,7 +278,6 @@ sp<IMemory> MetadataRetrieverClient::extractAlbumArt()
LOGV("extractAlbumArt");
Mutex::Autolock lock(mLock);
mAlbumArt.clear();
- mAlbumArtDealer.clear();
if (mRetriever == NULL) {
LOGE("retriever is not initialized");
return NULL;
@@ -294,16 +288,15 @@ sp<IMemory> MetadataRetrieverClient::extractAlbumArt()
return NULL;
}
size_t size = sizeof(MediaAlbumArt) + albumArt->mSize;
- mAlbumArtDealer = new MemoryDealer(size);
- if (mAlbumArtDealer == NULL) {
+ sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
+ if (heap == NULL) {
LOGE("failed to create MemoryDealer object");
delete albumArt;
return NULL;
}
- mAlbumArt = mAlbumArtDealer->allocate(size);
+ mAlbumArt = new MemoryBase(heap, 0, size);
if (mAlbumArt == NULL) {
LOGE("not enough memory for MediaAlbumArt size=%u", size);
- mAlbumArtDealer.clear();
delete albumArt;
return NULL;
}
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
index 8cb8ad13f1b0..4aab94fa7573 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.h
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -63,8 +63,6 @@ private:
int mMode;
// Keep the shared memory copy of album art and capture frame (for thumbnail)
- sp<MemoryDealer> mAlbumArtDealer;
- sp<MemoryDealer> mThumbnailDealer;
sp<IMemory> mAlbumArt;
sp<IMemory> mThumbnail;
};
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 14842c099be4..01578c1a6009 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -58,12 +58,15 @@ void AudioPlayer::setSource(const sp<MediaSource> &source) {
mSource = source;
}
-void AudioPlayer::start() {
+status_t AudioPlayer::start() {
CHECK(!mStarted);
CHECK(mSource != NULL);
status_t err = mSource->start();
- CHECK_EQ(err, OK);
+
+ if (err != OK) {
+ return err;
+ }
sp<MetaData> format = mSource->getFormat();
const char *mime;
@@ -83,7 +86,11 @@ void AudioPlayer::start() {
mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
DEFAULT_AUDIOSINK_BUFFERCOUNT,
&AudioPlayer::AudioSinkCallback, this);
- CHECK_EQ(err, OK);
+ if (err != OK) {
+ mSource->stop();
+
+ return err;
+ }
mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
mFrameSize = mAudioSink->frameSize();
@@ -97,7 +104,14 @@ void AudioPlayer::start() {
: AudioSystem::CHANNEL_OUT_MONO,
8192, 0, &AudioCallback, this, 0);
- CHECK_EQ(mAudioTrack->initCheck(), OK);
+ if (mAudioTrack->initCheck() != OK) {
+ delete mAudioTrack;
+ mAudioTrack = NULL;
+
+ mSource->stop();
+
+ return mAudioTrack->initCheck();
+ }
mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
mFrameSize = mAudioTrack->frameSize();
@@ -106,6 +120,8 @@ void AudioPlayer::start() {
}
mStarted = true;
+
+ return OK;
}
void AudioPlayer::pause() {
@@ -233,7 +249,8 @@ void AudioPlayer::fillBuffer(void *data, size_t size) {
kKeyTime, &mPositionTimeMediaUs));
mPositionTimeRealUs =
- ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
+ -mLatencyUs
+ + ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
/ mSampleRate;
LOGV("buffer->size() = %d, "
@@ -281,6 +298,10 @@ int64_t AudioPlayer::getRealTimeUsLocked() const {
int64_t AudioPlayer::getMediaTimeUs() {
Mutex::Autolock autoLock(mLock);
+ if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
+ return 0;
+ }
+
return mPositionTimeMediaUs + (getRealTimeUsLocked() - mPositionTimeRealUs);
}
@@ -291,7 +312,7 @@ bool AudioPlayer::getMediaTimeMapping(
*realtime_us = mPositionTimeRealUs;
*mediatime_us = mPositionTimeMediaUs;
- return mPositionTimeRealUs != -1 || mPositionTimeMediaUs != -1;
+ return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
}
status_t AudioPlayer::seekTo(int64_t time_us) {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index d6db59fc6181..4e7738e637c3 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -249,7 +249,16 @@ void AwesomePlayer::reset_l() {
if (mVideoSource != NULL) {
mVideoSource->stop();
+
+ // The following hack is necessary to ensure that the OMX
+ // component is completely released by the time we may try
+ // to instantiate it again.
+ wp<MediaSource> tmp = mVideoSource;
mVideoSource.clear();
+ while (tmp.promote() != NULL) {
+ usleep(1000);
+ }
+ IPCThreadState::self()->flushCommands();
}
mAudioSource.clear();
@@ -369,7 +378,16 @@ status_t AwesomePlayer::play() {
&AwesomePlayer::AudioNotify, this);
mAudioPlayer->setSource(mAudioSource);
- mAudioPlayer->start();
+ status_t err = mAudioPlayer->start();
+
+ if (err != OK) {
+ delete mAudioPlayer;
+ mAudioPlayer = NULL;
+
+ mFlags &= ~(PLAYING | FIRST_FRAME);
+
+ return err;
+ }
delete mTimeSource;
mTimeSource = mAudioPlayer;
diff --git a/media/libstagefright/CachingDataSource.cpp b/media/libstagefright/CachingDataSource.cpp
index 8d04ead950d6..1ca463e78269 100644
--- a/media/libstagefright/CachingDataSource.cpp
+++ b/media/libstagefright/CachingDataSource.cpp
@@ -65,6 +65,10 @@ status_t CachingDataSource::initCheck() const {
return mSource->initCheck();
}
+status_t CachingDataSource::getSize(off_t *size) {
+ return mSource->getSize(size);
+}
+
uint32_t CachingDataSource::flags() {
return mSource->flags();
}
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index 5564886fd664..4b630b999c6b 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -34,7 +34,7 @@ static bool PerformRedirectIfNecessary(
HTTPStream *http, const String8 &headers,
string *host, string *path, int *port) {
String8 request;
- request.append("HEAD ");
+ request.append("GET ");
request.append(path->c_str());
request.append(" HTTP/1.1\r\n");
request.append(headers);
@@ -94,19 +94,9 @@ static bool PerformRedirectIfNecessary(
}
HTTPDataSource::HTTPDataSource(
- const char *uri, const KeyedVector<String8, String8> *headers)
- : mHttp(new HTTPStream),
- mHost(NULL),
- mPort(0),
- mPath(NULL),
- mBuffer(malloc(kBufferSize)),
- mBufferLength(0),
- mBufferOffset(0),
- mFirstRequest(true) {
+ const char *uri, const KeyedVector<String8, String8> *headers) {
CHECK(!strncasecmp("http://", uri, 7));
- initHeaders(headers);
-
string host;
string path;
int port;
@@ -133,33 +123,27 @@ HTTPDataSource::HTTPDataSource(
host = string(host, 0, colon - host.c_str());
}
- do {
- LOGI("Connecting to host '%s', port %d, path '%s'",
- host.c_str(), port, path.c_str());
-
- mInitCheck = mHttp->connect(host.c_str(), port);
-
- if (mInitCheck != OK) {
- return;
- }
- } while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port));
-
- mHost = strdup(host.c_str());
- mPort = port;
- mPath = strdup(path.c_str());
+ init(host.c_str(), port, path.c_str(), headers);
}
HTTPDataSource::HTTPDataSource(
const char *_host, int port, const char *_path,
- const KeyedVector<String8, String8> *headers)
- : mHttp(new HTTPStream),
- mHost(NULL),
- mPort(0),
- mPath(NULL),
- mBuffer(malloc(kBufferSize)),
- mBufferLength(0),
- mBufferOffset(0),
- mFirstRequest(true) {
+ const KeyedVector<String8, String8> *headers) {
+ init(_host, port, _path, headers);
+}
+
+void HTTPDataSource::init(
+ const char *_host, int port, const char *_path,
+ const KeyedVector<String8, String8> *headers) {
+ mHttp = new HTTPStream;
+ mHost = NULL;
+ mPort = 0;
+ mPath = NULL,
+ mBuffer = malloc(kBufferSize);
+ mBufferLength = 0;
+ mBufferOffset = 0;
+ mContentLengthValid = false;
+
initHeaders(headers);
string host = _host;
@@ -168,13 +152,22 @@ HTTPDataSource::HTTPDataSource(
LOGI("Connecting to host '%s', port %d, path '%s'",
host.c_str(), port, path.c_str());
+ int numRedirectsRemaining = 5;
do {
mInitCheck = mHttp->connect(host.c_str(), port);
if (mInitCheck != OK) {
return;
}
- } while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port));
+ } while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port)
+ && numRedirectsRemaining-- > 0);
+
+ string value;
+ if (mHttp->find_header_value("Content-Length", &value)) {
+ char *end;
+ mContentLength = strtoull(value.c_str(), &end, 10);
+ mContentLengthValid = true;
+ }
mHost = strdup(host.c_str());
mPort = port;
@@ -185,6 +178,22 @@ status_t HTTPDataSource::initCheck() const {
return mInitCheck;
}
+status_t HTTPDataSource::getSize(off_t *size) {
+ *size = 0;
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (!mContentLengthValid) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ *size = mContentLength;
+
+ return OK;
+}
+
HTTPDataSource::~HTTPDataSource() {
mHttp->disconnect();
@@ -272,11 +281,11 @@ ssize_t HTTPDataSource::readAt(off_t offset, void *data, size_t size) {
}
ssize_t contentLength = 0;
- if (mFirstRequest || offset != mBufferOffset + mBufferLength) {
- if (!mFirstRequest) {
- mHttp->disconnect();
- }
- mFirstRequest = false;
+ if (offset != (off_t)(mBufferOffset + mBufferLength)) {
+ LOGV("new range offset=%ld (old=%ld)",
+ offset, mBufferOffset + mBufferLength);
+
+ mHttp->disconnect();
contentLength = sendRangeRequest(offset);
@@ -295,6 +304,12 @@ ssize_t HTTPDataSource::readAt(off_t offset, void *data, size_t size) {
ssize_t num_bytes_received = mHttp->receive(mBuffer, contentLength);
+ if (num_bytes_received < 0) {
+ mBufferLength = 0;
+
+ return num_bytes_received;
+ }
+
mBufferLength = (size_t)num_bytes_received;
size_t copy = mBufferLength;
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp
index 02f9439b84fa..3711acacdde6 100644
--- a/media/libstagefright/HTTPStream.cpp
+++ b/media/libstagefright/HTTPStream.cpp
@@ -52,7 +52,7 @@ status_t HTTPStream::connect(const char *server, int port) {
CHECK_EQ(mSocket, -1);
mSocket = socket(AF_INET, SOCK_STREAM, 0);
-
+
if (mSocket < 0) {
return UNKNOWN_ERROR;
}
@@ -132,6 +132,14 @@ status_t HTTPStream::send(const char *data) {
return send(data, strlen(data));
}
+// A certain application spawns a local webserver that sends invalid responses,
+// specifically it terminates header line with only a newline instead of the
+// CRLF (carriage-return followed by newline) required by the HTTP specs.
+// The workaround accepts both behaviours but could potentially break
+// legitimate responses that use a single newline to "fold" headers, which is
+// why it's not yet on by default.
+#define WORKAROUND_FOR_MISSING_CR 0
+
status_t HTTPStream::receive_line(char *line, size_t size) {
if (mState != CONNECTED) {
return ERROR_NOT_CONNECTED;
@@ -157,16 +165,27 @@ status_t HTTPStream::receive_line(char *line, size_t size) {
return ERROR_CONNECTION_LOST;
}
- if (saw_CR && c == '\n') {
+#if WORKAROUND_FOR_MISSING_CR
+ if (c == '\n') {
+ // We have a complete line.
+
+ line[saw_CR ? length - 1 : length] = '\0';
+ return OK;
+ }
+#else
+ if (saw_CR && c == '\n') {
// We have a complete line.
line[length - 1] = '\0';
return OK;
}
+#endif
saw_CR = (c == '\r');
- CHECK(length + 1 < size);
+ if (length + 1 >= size) {
+ return ERROR_MALFORMED;
+ }
line[length++] = c;
}
}
@@ -175,7 +194,7 @@ status_t HTTPStream::receive_header(int *http_status) {
*http_status = -1;
mHeaders.clear();
- char line[1024];
+ char line[2048];
status_t err = receive_line(line, sizeof(line));
if (err != OK) {
return err;
@@ -257,11 +276,11 @@ ssize_t HTTPStream::receive(void *data, size_t size) {
}
disconnect();
- return ERROR_IO;
+ return total == 0 ? ERROR_IO : total;
} else if (n == 0) {
disconnect();
- return ERROR_CONNECTION_LOST;
+ return total == 0 ? ERROR_CONNECTION_LOST : total;
}
total += (size_t)n;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index ed12b6d6748c..6274a6c6a648 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -28,6 +28,7 @@
#include <string.h>
#include <media/stagefright/DataSource.h>
+#include "include/ESDS.h"
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDebug.h>
@@ -84,6 +85,112 @@ private:
MPEG4Source &operator=(const MPEG4Source &);
};
+// This custom data source wraps an existing one and satisfies requests
+// falling entirely within a cached range from the cache while forwarding
+// all remaining requests to the wrapped datasource.
+// This is used to cache the full sampletable metadata for a single track,
+// possibly wrapping multiple times to cover all tracks, i.e.
+// Each MPEG4DataSource caches the sampletable metadata for a single track.
+
+struct MPEG4DataSource : public DataSource {
+ MPEG4DataSource(const sp<DataSource> &source);
+
+ virtual status_t initCheck() const;
+ virtual ssize_t readAt(off_t offset, void *data, size_t size);
+ virtual status_t getSize(off_t *size);
+ virtual uint32_t flags();
+
+ status_t setCachedRange(off_t offset, size_t size);
+
+protected:
+ virtual ~MPEG4DataSource();
+
+private:
+ Mutex mLock;
+
+ sp<DataSource> mSource;
+ off_t mCachedOffset;
+ size_t mCachedSize;
+ uint8_t *mCache;
+
+ void clearCache();
+
+ MPEG4DataSource(const MPEG4DataSource &);
+ MPEG4DataSource &operator=(const MPEG4DataSource &);
+};
+
+MPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
+ : mSource(source),
+ mCachedOffset(0),
+ mCachedSize(0),
+ mCache(NULL) {
+}
+
+MPEG4DataSource::~MPEG4DataSource() {
+ clearCache();
+}
+
+void MPEG4DataSource::clearCache() {
+ if (mCache) {
+ free(mCache);
+ mCache = NULL;
+ }
+
+ mCachedOffset = 0;
+ mCachedSize = 0;
+}
+
+status_t MPEG4DataSource::initCheck() const {
+ return mSource->initCheck();
+}
+
+ssize_t MPEG4DataSource::readAt(off_t offset, void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (offset >= mCachedOffset
+ && offset + size <= mCachedOffset + mCachedSize) {
+ memcpy(data, &mCache[offset - mCachedOffset], size);
+ return size;
+ }
+
+ return mSource->readAt(offset, data, size);
+}
+
+status_t MPEG4DataSource::getSize(off_t *size) {
+ return mSource->getSize(size);
+}
+
+uint32_t MPEG4DataSource::flags() {
+ return mSource->flags();
+}
+
+status_t MPEG4DataSource::setCachedRange(off_t offset, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ clearCache();
+
+ mCache = (uint8_t *)malloc(size);
+
+ if (mCache == NULL) {
+ return -ENOMEM;
+ }
+
+ mCachedOffset = offset;
+ mCachedSize = size;
+
+ ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
+
+ if (err < (ssize_t)size) {
+ clearCache();
+
+ return ERROR_IO;
+ }
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
static void hexdump(const void *_data, size_t size) {
const uint8_t *data = (const uint8_t *)_data;
size_t offset = 0;
@@ -374,6 +481,19 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
case FOURCC('u', 'd', 't', 'a'):
case FOURCC('i', 'l', 's', 't'):
{
+ if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
+ LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
+
+ if (mDataSource->flags() & DataSource::kWantsPrefetching) {
+ sp<MPEG4DataSource> cachedSource =
+ new MPEG4DataSource(mDataSource);
+
+ if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
+ mDataSource = cachedSource;
+ }
+ }
+ }
+
off_t stop_offset = *offset + chunk_size;
*offset = data_offset;
while (*offset < stop_offset) {
@@ -779,6 +899,21 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
mLastTrack->meta->setData(
kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
+ if (mPath.size() >= 2
+ && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
+ // Information from the ESDS must be relied on for proper
+ // setup of sample rate and channel count for MPEG4 Audio.
+ // The generic header appears to only contain generic
+ // information...
+
+ status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
+ &buffer[4], chunk_data_size - 4);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
*offset += chunk_size;
break;
}
@@ -1002,6 +1137,86 @@ sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
track->meta, mDataSource, track->timescale, track->sampleTable);
}
+status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
+ const void *esds_data, size_t esds_size) {
+ ESDS esds(esds_data, esds_size);
+ const uint8_t *csd;
+ size_t csd_size;
+ if (esds.getCodecSpecificInfo(
+ (const void **)&csd, &csd_size) != OK) {
+ return ERROR_MALFORMED;
+ }
+
+#if 0
+ printf("ESD of size %d\n", csd_size);
+ hexdump(csd, csd_size);
+#endif
+
+ if (csd_size < 2) {
+ return ERROR_MALFORMED;
+ }
+
+ uint32_t objectType = csd[0] >> 3;
+
+ if (objectType == 31) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
+ int32_t sampleRate = 0;
+ int32_t numChannels = 0;
+ if (freqIndex == 15) {
+ if (csd_size < 5) {
+ return ERROR_MALFORMED;
+ }
+
+ sampleRate = (csd[1] & 0x7f) << 17
+ | csd[2] << 9
+ | csd[3] << 1
+ | (csd[4] >> 7);
+
+ numChannels = (csd[4] >> 3) & 15;
+ } else {
+ static uint32_t kSamplingRate[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+ 16000, 12000, 11025, 8000, 7350
+ };
+
+ if (freqIndex == 13 || freqIndex == 14) {
+ return ERROR_MALFORMED;
+ }
+
+ sampleRate = kSamplingRate[freqIndex];
+ numChannels = (csd[1] >> 3) & 15;
+ }
+
+ if (numChannels == 0) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ int32_t prevSampleRate;
+ CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
+
+ if (prevSampleRate != sampleRate) {
+ LOGW("mpeg4 audio sample rate different from previous setting. "
+ "was: %d, now: %d", prevSampleRate, sampleRate);
+ }
+
+ mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
+
+ int32_t prevChannelCount;
+ CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
+
+ if (prevChannelCount != numChannels) {
+ LOGW("mpeg4 audio channel count different from previous setting. "
+ "was: %d, now: %d", prevChannelCount, numChannels);
+ }
+
+ mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
+
+ return OK;
+}
+
////////////////////////////////////////////////////////////////////////////////
MPEG4Source::MPEG4Source(
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index aee4d153999e..2cf0ddf7b69f 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -38,7 +38,7 @@ public:
void stop();
bool reachedEOS();
- int64_t getDuration() const;
+ int64_t getDurationUs() const;
void writeTrackHeader(int32_t trackID);
private:
@@ -46,6 +46,7 @@ private:
sp<MetaData> mMeta;
sp<MediaSource> mSource;
volatile bool mDone;
+ int64_t mMaxTimeStampUs;
pthread_t mThread;
@@ -140,7 +141,7 @@ void MPEG4Writer::stop() {
it != mTracks.end(); ++it) {
(*it)->stop();
- int64_t duration = (*it)->getDuration();
+ int64_t duration = (*it)->getDurationUs();
if (duration > max_duration) {
max_duration = duration;
}
@@ -162,7 +163,7 @@ void MPEG4Writer::stop() {
writeInt32(now); // creation time
writeInt32(now); // modification time
writeInt32(1000); // timescale
- writeInt32(max_duration);
+ writeInt32(max_duration / 1000);
writeInt32(0x10000); // rate
writeInt16(0x100); // volume
writeInt16(0); // reserved
@@ -316,6 +317,7 @@ MPEG4Writer::Track::Track(
mMeta(source->getFormat()),
mSource(source),
mDone(false),
+ mMaxTimeStampUs(0),
mCodecSpecificData(NULL),
mCodecSpecificDataSize(0),
mReachedEOS(false) {
@@ -343,6 +345,7 @@ status_t MPEG4Writer::Track::start() {
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
mDone = false;
+ mMaxTimeStampUs = 0;
mReachedEOS = false;
pthread_create(&mThread, &attr, ThreadWrapper, this);
@@ -483,6 +486,10 @@ void MPEG4Writer::Track::threadEntry() {
int64_t timestampUs;
CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+ if (timestampUs > mMaxTimeStampUs) {
+ mMaxTimeStampUs = timestampUs;
+ }
+
// Our timestamp is in ms.
info.timestamp = (timestampUs + 500) / 1000;
@@ -495,8 +502,8 @@ void MPEG4Writer::Track::threadEntry() {
mReachedEOS = true;
}
-int64_t MPEG4Writer::Track::getDuration() const {
- return 10000; // XXX
+int64_t MPEG4Writer::Track::getDurationUs() const {
+ return mMaxTimeStampUs;
}
void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
@@ -516,7 +523,7 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
mOwner->writeInt32(now); // modification time
mOwner->writeInt32(trackID);
mOwner->writeInt32(0); // reserved
- mOwner->writeInt32(getDuration());
+ mOwner->writeInt32(getDurationUs() / 1000);
mOwner->writeInt32(0); // reserved
mOwner->writeInt32(0); // reserved
mOwner->writeInt16(0); // layer
@@ -555,7 +562,7 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
mOwner->writeInt32(now); // creation time
mOwner->writeInt32(now); // modification time
mOwner->writeInt32(1000); // timescale
- mOwner->writeInt32(getDuration());
+ mOwner->writeInt32(getDurationUs() / 1000);
mOwner->writeInt16(0); // language code XXX
mOwner->writeInt16(0); // predefined
mOwner->endBox();
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 986dcb2f998d..90bbdfe5b083 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -290,6 +290,7 @@ uint32_t OMXCodec::getComponentQuirks(const char *componentName) {
}
if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
quirks |= kNeedsFlushBeforeDisable;
+ quirks |= kDecoderLiesAboutNumberOfChannels;
}
if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
quirks |= kNeedsFlushBeforeDisable;
@@ -1183,7 +1184,7 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
}
size_t totalSize = def.nBufferCountActual * def.nBufferSize;
- mDealer[portIndex] = new MemoryDealer(totalSize);
+ mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
@@ -2817,7 +2818,9 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
if ((OMX_U32)numChannels != params.nChannels) {
LOGW("Codec outputs a different number of channels than "
- "the input stream contains.");
+ "the input stream contains (contains %d channels, "
+ "codec outputs %ld channels).",
+ numChannels, params.nChannels);
}
mOutputFormat->setCString(
@@ -2825,8 +2828,12 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
// Use the codec-advertised number of channels, as some
// codecs appear to output stereo even if the input data is
- // mono.
- mOutputFormat->setInt32(kKeyChannelCount, params.nChannels);
+ // mono. If we know the codec lies about this information,
+ // use the actual number of channels instead.
+ mOutputFormat->setInt32(
+ kKeyChannelCount,
+ (mQuirks & kDecoderLiesAboutNumberOfChannels)
+ ? numChannels : params.nChannels);
// The codec-reported sampleRate is not reliable...
mOutputFormat->setInt32(kKeySampleRate, sampleRate);
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index da8fe795da95..7365dfafcb52 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -178,7 +178,8 @@ status_t WAVExtractor::init() {
mBitsPerSample = U16_LE_AT(&formatSpec[14]);
- if (mBitsPerSample != 8 && mBitsPerSample != 16) {
+ if (mBitsPerSample != 8 && mBitsPerSample != 16
+ && mBitsPerSample != 24) {
return ERROR_UNSUPPORTED;
}
@@ -329,6 +330,24 @@ status_t WAVSource::read(
buffer->release();
buffer = tmp;
+ } else if (mBitsPerSample == 24) {
+ // Convert 24-bit signed samples to 16-bit signed.
+
+ const uint8_t *src =
+ (const uint8_t *)buffer->data() + buffer->range_offset();
+ int16_t *dst = (int16_t *)src;
+
+ size_t numSamples = buffer->range_length() / 3;
+ for (size_t i = 0; i < numSamples; ++i) {
+ int32_t x = (int32_t)(src[0] | src[1] << 8 | src[2] << 16);
+ x = (x << 8) >> 8; // sign extension
+
+ x = x >> 8;
+ *dst++ = (int16_t)x;
+ src += 3;
+ }
+
+ buffer->set_range(buffer->range_offset(), 2 * numSamples);
}
size_t bytesPerSample = mBitsPerSample >> 3;
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index d87422492f2d..aa2a3d146f27 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -80,6 +80,8 @@ AVCDecoder::~AVCDecoder() {
stop();
}
+ PVAVCCleanUpDecoder(mHandle);
+
delete mHandle;
mHandle = NULL;
}
@@ -320,8 +322,10 @@ status_t AVCDecoder::read(
crop_top = crop_left = 0;
}
- mFormat->setInt32(kKeyWidth, crop_right - crop_left + 1);
- mFormat->setInt32(kKeyHeight, crop_bottom - crop_top + 1);
+ int32_t aligned_width = (crop_right - crop_left + 1 + 15) & ~15;
+ int32_t aligned_height = (crop_bottom - crop_top + 1 + 15) & ~15;
+ mFormat->setInt32(kKeyWidth, aligned_width);
+ mFormat->setInt32(kKeyHeight, aligned_height);
mInputBuffer->release();
mInputBuffer = NULL;
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index ef6ede02b029..ed91eea954fc 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -20,6 +20,7 @@
#include "../include/SoftwareRenderer.h"
#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryHeapPmem.h>
#include <media/stagefright/MediaDebug.h>
#include <ui/ISurface.h>
@@ -38,8 +39,16 @@ SoftwareRenderer::SoftwareRenderer(
mDecodedWidth(decodedWidth),
mDecodedHeight(decodedHeight),
mFrameSize(mDecodedWidth * mDecodedHeight * 2), // RGB565
- mMemoryHeap(new MemoryHeapBase(2 * mFrameSize)),
mIndex(0) {
+ // TODO: How do I allocate physical memory on Droid?
+ mMemoryHeap = new MemoryHeapBase("/dev/pmem_adsp", 2 * mFrameSize);
+ if (mMemoryHeap->heapID() < 0) {
+ LOGI("Creating physical memory heap failed, reverting to regular heap.");
+ mMemoryHeap = new MemoryHeapBase(2 * mFrameSize);
+ } else {
+ mMemoryHeap = new MemoryHeapPmem(mMemoryHeap);
+ }
+
CHECK(mISurface.get() != NULL);
CHECK(mDecodedWidth > 0);
CHECK(mDecodedHeight > 0);
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 1a1344654aea..3a63e8872b4e 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -65,6 +65,9 @@ private:
status_t parseChunk(off_t *offset, int depth);
status_t parseMetaData(off_t offset, size_t size);
+ status_t updateAudioTrackInfoFromESDS_MPEG4Audio(
+ const void *esds_data, size_t esds_size);
+
MPEG4Extractor(const MPEG4Extractor &);
MPEG4Extractor &operator=(const MPEG4Extractor &);
};
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 6c36163fb23b..51fcaf5f4438 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -286,7 +286,7 @@ status_t Harness::testStateTransitions(
return OK;
}
- sp<MemoryDealer> dealer = new MemoryDealer(8 * 1024 * 1024);
+ sp<MemoryDealer> dealer = new MemoryDealer(8 * 1024 * 1024, "OMXHarness");
IOMX::node_id node;
status_t err =
diff --git a/media/sdutils/sdutil.cpp b/media/sdutils/sdutil.cpp
index a61cccb122ab..6d3e87c0dd9d 100644
--- a/media/sdutils/sdutil.cpp
+++ b/media/sdutils/sdutil.cpp
@@ -38,65 +38,27 @@ static void init() {
}
}
-static bool isMounted(const char* mountPoint) {
- char s[2000];
- FILE *f = fopen("/proc/mounts", "r");
- bool mounted = false;
-
- while (fgets(s, sizeof(s), f))
- {
- char *c, *path = NULL;
-
- for (c = s; *c; c++)
- {
- if (*c == ' ')
- {
- *c = 0;
- path = c + 1;
- break;
- }
- }
-
- for (c = path; *c; c++)
- {
- if (*c == ' ')
- {
- *c = '\0';
- break;
- }
- }
-
- if (strcmp(mountPoint, path) == 0) {
- mounted = true;
- break;
- }
- }
-
- fclose(f);
- return mounted;
+static int mount(const char* path) {
+ String16 string(path);
+ return gMountService->mountVolume(string);
}
-static void millisecondSleep(int milliseconds) {
- struct timespec reqt, remt;
- reqt.tv_sec = milliseconds / 1000;
- reqt.tv_nsec = 1000000 * (milliseconds % 1000);
- nanosleep(&reqt, &remt) ;
+static int share(const char *path, const char *method) {
+ String16 sPath(path);
+ String16 sMethod(method);
+ return gMountService->shareVolume(sPath, sMethod);
+}
+static int unshare(const char *path, const char *method) {
+ String16 sPath(path);
+ String16 sMethod(method);
+ return gMountService->unshareVolume(sPath, sMethod);
}
-static int mount(const char* path) {
- String16 string(path);
- gMountService->mountVolume(string);
-
- for (int i = 0; i < 60; i++) {
- if (isMounted(path)) {
- return 0;
- }
- millisecondSleep(500);
- }
-
- fprintf(stderr, "failed to mount %s\n", path);
- return -1;
+static bool shared(const char *path, const char *method) {
+ String16 sPath(path);
+ String16 sMethod(method);
+ return gMountService->getVolumeShared(sPath, sMethod);
}
static int asec_create(const char *id, int sizeMb, const char *fstype,
@@ -105,39 +67,35 @@ static int asec_create(const char *id, int sizeMb, const char *fstype,
String16 sFstype(fstype);
String16 sKey(key);
- String16 r = gMountService->createSecureContainer(sId, sizeMb, sFstype,
- sKey, ownerUid);
- return 0;
+ return gMountService->createSecureContainer(
+ sId, sizeMb, sFstype, sKey, ownerUid);
}
static int asec_finalize(const char *id) {
String16 sId(id);
- gMountService->finalizeSecureContainer(sId);
- return 0;
+ return gMountService->finalizeSecureContainer(sId);
}
static int asec_destroy(const char *id) {
String16 sId(id);
- gMountService->destroySecureContainer(sId);
- return 0;
+ return gMountService->destroySecureContainer(sId);
}
static int asec_mount(const char *id, const char *key, int ownerUid) {
String16 sId(id);
String16 sKey(key);
- gMountService->mountSecureContainer(sId, sKey, ownerUid);
- return 0;
+ return gMountService->mountSecureContainer(sId, sKey, ownerUid);
}
-static void asec_unmount(const char *id) {
+static int asec_unmount(const char *id) {
String16 sId(id);
- gMountService->unmountSecureContainer(sId);
+ return gMountService->unmountSecureContainer(sId);
}
-static void asec_rename(const char *oldId, const char *newId) {
+static int asec_rename(const char *oldId, const char *newId) {
String16 sOldId(oldId);
String16 sNewId(newId);
- gMountService->renameSecureContainer(sOldId, sNewId);
+ return gMountService->renameSecureContainer(sOldId, sNewId);
}
static int asec_path(const char *id) {
@@ -148,98 +106,85 @@ static int asec_path(const char *id) {
static int unmount(const char* path) {
String16 string(path);
- gMountService->unmountVolume(string);
-
- for (int i = 0; i < 20; i++) {
- if (!isMounted(path)) {
- return 0;
- }
- millisecondSleep(500);
- }
-
- fprintf(stderr, "failed to unmount %s\n", path);
- return -1;
+ return gMountService->unmountVolume(string);
}
static int format(const char* path) {
String16 string(path);
-
- if (isMounted(path))
- return -EBUSY;
- gMountService->formatVolume(string);
-
- return 0;
-}
-
-static int umsEnable(bool enable) {
- gMountService->setMassStorageEnabled(enable);
- return 0;
+ return gMountService->formatVolume(string);
}
};
+static void usage(void);
+
int main(int argc, char **argv)
{
- const char* command = (argc > 1 ? argv[1] : "");
- const char* argument = (argc > 2 ? argv[2] : "");
-
- if (strcmp(command, "mount") == 0) {
- android::init();
- return android::mount(argument);
- } else if (strcmp(command, "format") == 0) {
- android::init();
- return android::format(argument);
- } else if (strcmp(command, "unmount") == 0) {
- android::init();
- return android::unmount(argument);
- } else if (strcmp(command, "ums") == 0) {
- if (strcmp(argument, "enable") == 0) {
- android::init();
- return android::umsEnable(true);
- } else if (strcmp(argument, "disable") == 0) {
- android::init();
- return android::umsEnable(false);
- }
- } else if (!strcmp(command, "asec")) {
- const char* id = (argc > 3 ? argv[3] : NULL);
-
- if (!id)
- goto usage;
+ if (argc < 2)
+ usage();
- android::init();
- if (!strcmp(argument, "create")) {
+ android::init();
+ int rc = 0;
+
+ if (strcmp(argv[1], "mount") == 0) {
+ rc = android::mount(argv[2]);
+ } else if (strcmp(argv[1], "format") == 0) {
+ rc = android::format(argv[2]);
+ } else if (strcmp(argv[1], "unmount") == 0) {
+ rc = android::unmount(argv[2]);
+ } else if (strcmp(argv[1], "share") == 0) {
+ if (argc != 3)
+ usage();
+ rc = android::share(argv[2], argv[3]);
+ } else if (strcmp(argv[1], "unshare") == 0) {
+ if (argc != 3)
+ usage();
+ rc = android::unshare(argv[2], argv[3]);
+ } else if (strcmp(argv[1], "shared") == 0) {
+ if (argc != 3)
+ usage();
+ fprintf(stdout, "%s\n", (android::shared(argv[2], argv[3]) ? "true" : "false"));
+ } else if (!strcmp(argv[1], "asec")) {
+ if (argc < 3)
+ usage();
+
+ if (!strcmp(argv[2], "create")) {
if (argc != 8)
- goto usage;
- return android::asec_create(id, atoi(argv[4]), argv[5], argv[6],
- atoi(argv[7]));
- } else if (!strcmp(argument, "finalize")) {
- return android::asec_finalize(id);
- } else if (!strcmp(argument, "destroy")) {
- return android::asec_destroy(id);
- } else if (!strcmp(argument, "mount")) {
- if (argc == 6)
- return android::asec_mount(id, argv[4], atoi(argv[5]));
- } else if (!strcmp(argument, "rename")) {
- if (argc == 5) {
- android::asec_rename(id, argv[4]);
- return 0;
- }
- } else if (!strcmp(argument, "unmount")) {
- android::asec_unmount(id);
- return 0;
- } else if (!strcmp(argument, "path")) {
- return android::asec_path(id);
+ usage();
+ rc = android::asec_create(argv[3], atoi(argv[4]), argv[5], argv[6], atoi(argv[7]));
+ } else if (!strcmp(argv[3], "finalize")) {
+ rc = android::asec_finalize(argv[3]);
+ } else if (!strcmp(argv[3], "destroy")) {
+ return android::asec_destroy(argv[3]);
+ } else if (!strcmp(argv[3], "mount")) {
+ if (argc != 6)
+ usage();
+ rc = android::asec_mount(argv[3], argv[4], atoi(argv[5]));
+ } else if (!strcmp(argv[3], "rename")) {
+ if (argc != 5)
+ usage();
+ rc = android::asec_rename(argv[3], argv[4]);
+ } else if (!strcmp(argv[3], "unmount")) {
+ rc = android::asec_unmount(argv[3]);
+ } else if (!strcmp(argv[3], "path")) {
+ rc = android::asec_path(argv[3]);
}
}
-
-usage:
+
+ fprintf(stdout, "Operation completed with code %d\n", rc);
+ return rc;
+}
+
+static void usage()
+{
fprintf(stderr, "usage:\n"
" sdutil mount <mount path> - mounts the SD card at the given mount point\n"
" sdutil unmount <mount path> - unmounts the SD card at the given mount point\n"
" sdutil format <mount path> - formats the SD card at the given mount point\n"
- " sdutil ums enable - enables USB mass storage\n"
- " sdutil ums disable - disables USB mass storage\n"
+ " sdutil share <path> <method> - shares a volume\n"
+ " sdutil unshare <path> <method> - unshares a volume\n"
+ " sdutil shared <path> <method> - Queries volume share state\n"
" sdutil asec create <id> <sizeMb> <fstype> <key> <ownerUid>\n"
" sdutil asec finalize <id>\n"
" sdutil asec destroy <id>\n"
@@ -248,5 +193,5 @@ usage:
" sdutil asec rename <oldId, newId>\n"
" sdutil asec path <id>\n"
);
- return -1;
+ exit(1);
}
diff --git a/mms-common/Android.mk b/mms-common/Android.mk
new file mode 100644
index 000000000000..de994c0cd229
--- /dev/null
+++ b/mms-common/Android.mk
@@ -0,0 +1,29 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# Note: the source code is in java/, not src/, because this code is also part of
+# the framework library, and build/core/pathmap.mk expects a java/ subdirectory.
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := mms-common
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Include this library in the build server's output directory
+$(call dist-for-goals, droid, $(LOCAL_BUILT_MODULE):mms-common.jar)
+
+# Build the test package
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/java/com/google/android/mms/pdu/CharacterSets.java b/mms-common/java/com/android/mmscommon/CharacterSets.java
index 4e22ca5e2cf8..f19b07835485 100644
--- a/core/java/com/google/android/mms/pdu/CharacterSets.java
+++ b/mms-common/java/com/android/mmscommon/CharacterSets.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
diff --git a/core/java/com/google/android/mms/ContentType.java b/mms-common/java/com/android/mmscommon/ContentType.java
index 94bc9fdcd4bf..ca449fe2e365 100644
--- a/core/java/com/google/android/mms/ContentType.java
+++ b/mms-common/java/com/android/mmscommon/ContentType.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms;
+package com.android.mmscommon;
import java.util.ArrayList;
@@ -26,6 +26,7 @@ public class ContentType {
public static final String MMS_GENERIC = "application/vnd.wap.mms-generic";
public static final String MULTIPART_MIXED = "application/vnd.wap.multipart.mixed";
public static final String MULTIPART_RELATED = "application/vnd.wap.multipart.related";
+ public static final String MULTIPART_ALTERNATIVE = "application/vnd.wap.multipart.alternative";
public static final String TEXT_PLAIN = "text/plain";
public static final String TEXT_HTML = "text/html";
diff --git a/core/java/com/google/android/mms/pdu/EncodedStringValue.java b/mms-common/java/com/android/mmscommon/EncodedStringValue.java
index a27962d41e4d..0a4424e2880a 100644
--- a/core/java/com/google/android/mms/pdu/EncodedStringValue.java
+++ b/mms-common/java/com/android/mmscommon/EncodedStringValue.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon;
import android.util.Config;
import android.util.Log;
@@ -269,7 +269,7 @@ public class EncodedStringValue implements Cloneable {
return new EncodedStringValue(value.mCharacterSet, value.mData);
}
-
+
public static EncodedStringValue[] encodeStrings(String[] array) {
int count = array.length;
if (count > 0) {
diff --git a/core/java/com/google/android/mms/InvalidHeaderValueException.java b/mms-common/java/com/android/mmscommon/InvalidHeaderValueException.java
index 73d78328e257..34d5871ec87a 100644
--- a/core/java/com/google/android/mms/InvalidHeaderValueException.java
+++ b/mms-common/java/com/android/mmscommon/InvalidHeaderValueException.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms;
+package com.android.mmscommon;
/**
* Thrown when an invalid header value was set.
diff --git a/core/java/com/google/android/mms/MmsException.java b/mms-common/java/com/android/mmscommon/MmsException.java
index 6ca0c7eab9ac..296a2c3460fb 100644
--- a/core/java/com/google/android/mms/MmsException.java
+++ b/mms-common/java/com/android/mmscommon/MmsException.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms;
+package com.android.mmscommon;
/**
* A generic exception that is thrown by the Mms client.
diff --git a/core/java/com/google/android/mms/pdu/PduHeaders.java b/mms-common/java/com/android/mmscommon/PduHeaders.java
index 43138150f804..d8f12111bf54 100644
--- a/core/java/com/google/android/mms/pdu/PduHeaders.java
+++ b/mms-common/java/com/android/mmscommon/PduHeaders.java
@@ -15,9 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
-
-import com.google.android.mms.InvalidHeaderValueException;
+package com.android.mmscommon;
import java.util.ArrayList;
import java.util.HashMap;
@@ -339,7 +337,7 @@ public class PduHeaders {
* with specified header field. Return 0 if
* the value is not set.
*/
- protected int getOctet(int field) {
+ public int getOctet(int field) {
Integer octet = (Integer) mHeaderMap.get(field);
if (null == octet) {
return 0;
@@ -355,7 +353,7 @@ public class PduHeaders {
* @param field the field
* @throws InvalidHeaderValueException if the value is invalid.
*/
- protected void setOctet(int value, int field)
+ public void setOctet(int value, int field)
throws InvalidHeaderValueException{
/**
* Check whether this field can be set for specific
@@ -499,7 +497,7 @@ public class PduHeaders {
* @return the TextString value of the pdu header
* with specified header field
*/
- protected byte[] getTextString(int field) {
+ public byte[] getTextString(int field) {
return (byte[]) mHeaderMap.get(field);
}
@@ -512,7 +510,7 @@ public class PduHeaders {
* with specified header field
* @throws NullPointerException if the value is null.
*/
- protected void setTextString(byte[] value, int field) {
+ public void setTextString(byte[] value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
@@ -548,7 +546,7 @@ public class PduHeaders {
* @return the EncodedStringValue value of the pdu header
* with specified header field
*/
- protected EncodedStringValue getEncodedStringValue(int field) {
+ public EncodedStringValue getEncodedStringValue(int field) {
return (EncodedStringValue) mHeaderMap.get(field);
}
@@ -559,7 +557,7 @@ public class PduHeaders {
* @return the EncodeStringValue array of the pdu header
* with specified header field
*/
- protected EncodedStringValue[] getEncodedStringValues(int field) {
+ public EncodedStringValue[] getEncodedStringValues(int field) {
ArrayList<EncodedStringValue> list =
(ArrayList<EncodedStringValue>) mHeaderMap.get(field);
if (null == list) {
@@ -578,7 +576,7 @@ public class PduHeaders {
* with specified header field
* @throws NullPointerException if the value is null.
*/
- protected void setEncodedStringValue(EncodedStringValue value, int field) {
+ public void setEncodedStringValue(EncodedStringValue value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
@@ -615,7 +613,7 @@ public class PduHeaders {
* with specified header field
* @throws NullPointerException if the value is null.
*/
- protected void setEncodedStringValues(EncodedStringValue[] value, int field) {
+ public void setEncodedStringValues(EncodedStringValue[] value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
@@ -648,7 +646,7 @@ public class PduHeaders {
* @param field the field
* @throws NullPointerException if the value is null.
*/
- protected void appendEncodedStringValue(EncodedStringValue value,
+ public void appendEncodedStringValue(EncodedStringValue value,
int field) {
if (null == value) {
throw new NullPointerException();
@@ -680,7 +678,7 @@ public class PduHeaders {
* with specified header field. if return -1, the
* field is not existed in pdu header.
*/
- protected long getLongInteger(int field) {
+ public long getLongInteger(int field) {
Long longInteger = (Long) mHeaderMap.get(field);
if (null == longInteger) {
return -1;
@@ -695,7 +693,7 @@ public class PduHeaders {
* @param value the value
* @param field the field
*/
- protected void setLongInteger(long value, int field) {
+ public void setLongInteger(long value, int field) {
/**
* Check whether this field can be set for specific
* header and check validity of the field.
diff --git a/mms-common/java/com/android/mmscommon/mms/ContentType.java b/mms-common/java/com/android/mmscommon/mms/ContentType.java
new file mode 100644
index 000000000000..f21eba8b857a
--- /dev/null
+++ b/mms-common/java/com/android/mmscommon/mms/ContentType.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2007-2008 Esmertec AG.
+ * Copyright (C) 2007-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.
+ * 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.mmscommon.mms;
+
+import java.util.ArrayList;
+
+public class ContentType {
+ public static final String MMS_MESSAGE = "application/vnd.wap.mms-message";
+ // The phony content type for generic PDUs (e.g. ReadOrig.ind,
+ // Notification.ind, Delivery.ind).
+ public static final String MMS_GENERIC = "application/vnd.wap.mms-generic";
+ public static final String MULTIPART_MIXED = "application/vnd.wap.multipart.mixed";
+ public static final String MULTIPART_RELATED = "application/vnd.wap.multipart.related";
+ public static final String MULTIPART_ALTERNATIVE = "application/vnd.wap.multipart.alternative";
+
+ public static final String TEXT_PLAIN = "text/plain";
+ public static final String TEXT_HTML = "text/html";
+ public static final String TEXT_VCALENDAR = "text/x-vCalendar";
+ public static final String TEXT_VCARD = "text/x-vCard";
+
+ public static final String IMAGE_UNSPECIFIED = "image/*";
+ public static final String IMAGE_JPEG = "image/jpeg";
+ public static final String IMAGE_JPG = "image/jpg";
+ public static final String IMAGE_GIF = "image/gif";
+ public static final String IMAGE_WBMP = "image/vnd.wap.wbmp";
+ public static final String IMAGE_PNG = "image/png";
+
+ public static final String AUDIO_UNSPECIFIED = "audio/*";
+ public static final String AUDIO_AAC = "audio/aac";
+ public static final String AUDIO_AMR = "audio/amr";
+ public static final String AUDIO_IMELODY = "audio/imelody";
+ public static final String AUDIO_MID = "audio/mid";
+ public static final String AUDIO_MIDI = "audio/midi";
+ public static final String AUDIO_MP3 = "audio/mp3";
+ public static final String AUDIO_MPEG3 = "audio/mpeg3";
+ public static final String AUDIO_MPEG = "audio/mpeg";
+ public static final String AUDIO_MPG = "audio/mpg";
+ public static final String AUDIO_MP4 = "audio/mp4";
+ public static final String AUDIO_X_MID = "audio/x-mid";
+ public static final String AUDIO_X_MIDI = "audio/x-midi";
+ public static final String AUDIO_X_MP3 = "audio/x-mp3";
+ public static final String AUDIO_X_MPEG3 = "audio/x-mpeg3";
+ public static final String AUDIO_X_MPEG = "audio/x-mpeg";
+ public static final String AUDIO_X_MPG = "audio/x-mpg";
+ public static final String AUDIO_3GPP = "audio/3gpp";
+ public static final String AUDIO_OGG = "application/ogg";
+
+ public static final String VIDEO_UNSPECIFIED = "video/*";
+ public static final String VIDEO_3GPP = "video/3gpp";
+ public static final String VIDEO_3G2 = "video/3gpp2";
+ public static final String VIDEO_H263 = "video/h263";
+ public static final String VIDEO_MP4 = "video/mp4";
+
+ public static final String APP_SMIL = "application/smil";
+ public static final String APP_WAP_XHTML = "application/vnd.wap.xhtml+xml";
+ public static final String APP_XHTML = "application/xhtml+xml";
+
+ public static final String APP_DRM_CONTENT = "application/vnd.oma.drm.content";
+ public static final String APP_DRM_MESSAGE = "application/vnd.oma.drm.message";
+
+ private static final ArrayList<String> sSupportedContentTypes = new ArrayList<String>();
+ private static final ArrayList<String> sSupportedImageTypes = new ArrayList<String>();
+ private static final ArrayList<String> sSupportedAudioTypes = new ArrayList<String>();
+ private static final ArrayList<String> sSupportedVideoTypes = new ArrayList<String>();
+
+ static {
+ sSupportedContentTypes.add(TEXT_PLAIN);
+ sSupportedContentTypes.add(TEXT_HTML);
+ sSupportedContentTypes.add(TEXT_VCALENDAR);
+ sSupportedContentTypes.add(TEXT_VCARD);
+
+ sSupportedContentTypes.add(IMAGE_JPEG);
+ sSupportedContentTypes.add(IMAGE_GIF);
+ sSupportedContentTypes.add(IMAGE_WBMP);
+ sSupportedContentTypes.add(IMAGE_PNG);
+ sSupportedContentTypes.add(IMAGE_JPG);
+ //supportedContentTypes.add(IMAGE_SVG); not yet supported.
+
+ sSupportedContentTypes.add(AUDIO_AAC);
+ sSupportedContentTypes.add(AUDIO_AMR);
+ sSupportedContentTypes.add(AUDIO_IMELODY);
+ sSupportedContentTypes.add(AUDIO_MID);
+ sSupportedContentTypes.add(AUDIO_MIDI);
+ sSupportedContentTypes.add(AUDIO_MP3);
+ sSupportedContentTypes.add(AUDIO_MPEG3);
+ sSupportedContentTypes.add(AUDIO_MPEG);
+ sSupportedContentTypes.add(AUDIO_MPG);
+ sSupportedContentTypes.add(AUDIO_X_MID);
+ sSupportedContentTypes.add(AUDIO_X_MIDI);
+ sSupportedContentTypes.add(AUDIO_X_MP3);
+ sSupportedContentTypes.add(AUDIO_X_MPEG3);
+ sSupportedContentTypes.add(AUDIO_X_MPEG);
+ sSupportedContentTypes.add(AUDIO_X_MPG);
+ sSupportedContentTypes.add(AUDIO_3GPP);
+ sSupportedContentTypes.add(AUDIO_OGG);
+
+ sSupportedContentTypes.add(VIDEO_3GPP);
+ sSupportedContentTypes.add(VIDEO_3G2);
+ sSupportedContentTypes.add(VIDEO_H263);
+ sSupportedContentTypes.add(VIDEO_MP4);
+
+ sSupportedContentTypes.add(APP_SMIL);
+ sSupportedContentTypes.add(APP_WAP_XHTML);
+ sSupportedContentTypes.add(APP_XHTML);
+
+ sSupportedContentTypes.add(APP_DRM_CONTENT);
+ sSupportedContentTypes.add(APP_DRM_MESSAGE);
+
+ // add supported image types
+ sSupportedImageTypes.add(IMAGE_JPEG);
+ sSupportedImageTypes.add(IMAGE_GIF);
+ sSupportedImageTypes.add(IMAGE_WBMP);
+ sSupportedImageTypes.add(IMAGE_PNG);
+ sSupportedImageTypes.add(IMAGE_JPG);
+
+ // add supported audio types
+ sSupportedAudioTypes.add(AUDIO_AAC);
+ sSupportedAudioTypes.add(AUDIO_AMR);
+ sSupportedAudioTypes.add(AUDIO_IMELODY);
+ sSupportedAudioTypes.add(AUDIO_MID);
+ sSupportedAudioTypes.add(AUDIO_MIDI);
+ sSupportedAudioTypes.add(AUDIO_MP3);
+ sSupportedAudioTypes.add(AUDIO_MPEG3);
+ sSupportedAudioTypes.add(AUDIO_MPEG);
+ sSupportedAudioTypes.add(AUDIO_MPG);
+ sSupportedAudioTypes.add(AUDIO_MP4);
+ sSupportedAudioTypes.add(AUDIO_X_MID);
+ sSupportedAudioTypes.add(AUDIO_X_MIDI);
+ sSupportedAudioTypes.add(AUDIO_X_MP3);
+ sSupportedAudioTypes.add(AUDIO_X_MPEG3);
+ sSupportedAudioTypes.add(AUDIO_X_MPEG);
+ sSupportedAudioTypes.add(AUDIO_X_MPG);
+ sSupportedAudioTypes.add(AUDIO_3GPP);
+ sSupportedAudioTypes.add(AUDIO_OGG);
+
+ // add supported video types
+ sSupportedVideoTypes.add(VIDEO_3GPP);
+ sSupportedVideoTypes.add(VIDEO_3G2);
+ sSupportedVideoTypes.add(VIDEO_H263);
+ sSupportedVideoTypes.add(VIDEO_MP4);
+ }
+
+ // This class should never be instantiated.
+ private ContentType() {
+ }
+
+ public static boolean isSupportedType(String contentType) {
+ return (null != contentType) && sSupportedContentTypes.contains(contentType);
+ }
+
+ public static boolean isSupportedImageType(String contentType) {
+ return isImageType(contentType) && isSupportedType(contentType);
+ }
+
+ public static boolean isSupportedAudioType(String contentType) {
+ return isAudioType(contentType) && isSupportedType(contentType);
+ }
+
+ public static boolean isSupportedVideoType(String contentType) {
+ return isVideoType(contentType) && isSupportedType(contentType);
+ }
+
+ public static boolean isTextType(String contentType) {
+ return (null != contentType) && contentType.startsWith("text/");
+ }
+
+ public static boolean isImageType(String contentType) {
+ return (null != contentType) && contentType.startsWith("image/");
+ }
+
+ public static boolean isAudioType(String contentType) {
+ return (null != contentType) && contentType.startsWith("audio/");
+ }
+
+ public static boolean isVideoType(String contentType) {
+ return (null != contentType) && contentType.startsWith("video/");
+ }
+
+ public static boolean isDrmType(String contentType) {
+ return (null != contentType)
+ && (contentType.equals(APP_DRM_CONTENT)
+ || contentType.equals(APP_DRM_MESSAGE));
+ }
+
+ public static boolean isUnspecified(String contentType) {
+ return (null != contentType) && contentType.endsWith("*");
+ }
+
+ @SuppressWarnings("unchecked")
+ public static ArrayList<String> getImageTypes() {
+ return (ArrayList<String>) sSupportedImageTypes.clone();
+ }
+
+ @SuppressWarnings("unchecked")
+ public static ArrayList<String> getAudioTypes() {
+ return (ArrayList<String>) sSupportedAudioTypes.clone();
+ }
+
+ @SuppressWarnings("unchecked")
+ public static ArrayList<String> getVideoTypes() {
+ return (ArrayList<String>) sSupportedVideoTypes.clone();
+ }
+
+ @SuppressWarnings("unchecked")
+ public static ArrayList<String> getSupportedTypes() {
+ return (ArrayList<String>) sSupportedContentTypes.clone();
+ }
+}
diff --git a/core/java/com/google/android/mms/pdu/AcknowledgeInd.java b/mms-common/java/com/android/mmscommon/mms/pdu/AcknowledgeInd.java
index 0e96c60bd096..d1243b22b6ac 100644
--- a/core/java/com/google/android/mms/pdu/AcknowledgeInd.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/AcknowledgeInd.java
@@ -15,9 +15,10 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* M-Acknowledge.ind PDU.
diff --git a/core/java/com/google/android/mms/pdu/Base64.java b/mms-common/java/com/android/mmscommon/mms/pdu/Base64.java
index 604bee0d50fe..4c95dec72dd0 100644
--- a/core/java/com/google/android/mms/pdu/Base64.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/Base64.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
public class Base64 {
/**
diff --git a/core/java/com/google/android/mms/pdu/DeliveryInd.java b/mms-common/java/com/android/mmscommon/mms/pdu/DeliveryInd.java
index dafa8d11b871..e83729b8b109 100644
--- a/core/java/com/google/android/mms/pdu/DeliveryInd.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/DeliveryInd.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* M-Delivery.Ind Pdu.
diff --git a/core/java/com/google/android/mms/pdu/GenericPdu.java b/mms-common/java/com/android/mmscommon/mms/pdu/GenericPdu.java
index 705de6afb8b6..c38e502504ab 100644
--- a/core/java/com/google/android/mms/pdu/GenericPdu.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/GenericPdu.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
public class GenericPdu {
/**
diff --git a/core/java/com/google/android/mms/pdu/MultimediaMessagePdu.java b/mms-common/java/com/android/mmscommon/mms/pdu/MultimediaMessagePdu.java
index 5a85e0e79ddc..04fde2d453ec 100644
--- a/core/java/com/google/android/mms/pdu/MultimediaMessagePdu.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/MultimediaMessagePdu.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* Multimedia message PDU.
diff --git a/core/java/com/google/android/mms/pdu/NotificationInd.java b/mms-common/java/com/android/mmscommon/mms/pdu/NotificationInd.java
index c56cba6d14bf..24f17b09ae7f 100644
--- a/core/java/com/google/android/mms/pdu/NotificationInd.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/NotificationInd.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* M-Notification.ind PDU.
diff --git a/core/java/com/google/android/mms/pdu/NotifyRespInd.java b/mms-common/java/com/android/mmscommon/mms/pdu/NotifyRespInd.java
index 2cc2fce0812d..c2e2b26535e3 100644
--- a/core/java/com/google/android/mms/pdu/NotifyRespInd.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/NotifyRespInd.java
@@ -15,9 +15,10 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* M-NofifyResp.ind PDU.
diff --git a/core/java/com/google/android/mms/pdu/PduBody.java b/mms-common/java/com/android/mmscommon/mms/pdu/PduBody.java
index fa0416c6be6a..cc28d80eb06b 100644
--- a/core/java/com/google/android/mms/pdu/PduBody.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/PduBody.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
import java.util.HashMap;
import java.util.Map;
diff --git a/core/java/com/google/android/mms/pdu/PduComposer.java b/mms-common/java/com/android/mmscommon/mms/pdu/PduComposer.java
index 8940945a605a..bb3116d69ef0 100644
--- a/core/java/com/google/android/mms/pdu/PduComposer.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/PduComposer.java
@@ -15,7 +15,10 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
+
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.PduHeaders;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/com/google/android/mms/pdu/PduContentTypes.java b/mms-common/java/com/android/mmscommon/mms/pdu/PduContentTypes.java
index 7799e0e834af..3f971fd98d04 100644
--- a/core/java/com/google/android/mms/pdu/PduContentTypes.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/PduContentTypes.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
public class PduContentTypes {
/**
diff --git a/core/java/com/google/android/mms/pdu/PduParser.java b/mms-common/java/com/android/mmscommon/mms/pdu/PduParser.java
index d465c5aafb3b..9253f8373efb 100644
--- a/core/java/com/google/android/mms/pdu/PduParser.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/PduParser.java
@@ -15,10 +15,13 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.ContentType;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.ContentType;
+import com.android.mmscommon.CharacterSets;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
import android.util.Config;
import android.util.Log;
@@ -157,9 +160,11 @@ public class PduParser {
}
String ctTypeStr = new String(contentType);
if (ctTypeStr.equals(ContentType.MULTIPART_MIXED)
- || ctTypeStr.equals(ContentType.MULTIPART_RELATED)) {
+ || ctTypeStr.equals(ContentType.MULTIPART_RELATED)
+ || ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
// The MMS content type must be "application/vnd.wap.multipart.mixed"
// or "application/vnd.wap.multipart.related"
+ // or "application/vnd.wap.multipart.alternative"
return retrieveConf;
}
return null;
diff --git a/core/java/com/google/android/mms/pdu/PduPart.java b/mms-common/java/com/android/mmscommon/mms/pdu/PduPart.java
index b43e388b6517..7d51b86e9af1 100644
--- a/core/java/com/google/android/mms/pdu/PduPart.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/PduPart.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
import android.net.Uri;
diff --git a/core/java/com/google/android/mms/pdu/PduPersister.java b/mms-common/java/com/android/mmscommon/mms/pdu/PduPersister.java
index 1f754bc3483d..46f28c7f0385 100644
--- a/core/java/com/google/android/mms/pdu/PduPersister.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/PduPersister.java
@@ -15,14 +15,19 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.ContentType;
-import com.google.android.mms.InvalidHeaderValueException;
-import com.google.android.mms.MmsException;
-import com.google.android.mms.util.PduCache;
-import com.google.android.mms.util.PduCacheEntry;
-import com.google.android.mms.util.SqliteWrapper;
+import com.android.mmscommon.mms.pdu.PduPersister;
+
+import com.android.mmscommon.ContentType;
+import com.android.mmscommon.CharacterSets;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.MmsException;
+import com.android.mmscommon.PduHeaders;
+import com.android.mmscommon.mms.util.PduCache;
+import com.android.mmscommon.mms.util.PduCacheEntry;
+import android.database.sqlite.SqliteWrapper;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -31,13 +36,13 @@ import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
-import android.provider.Telephony;
-import android.provider.Telephony.Mms;
-import android.provider.Telephony.MmsSms;
-import android.provider.Telephony.Threads;
-import android.provider.Telephony.Mms.Addr;
-import android.provider.Telephony.Mms.Part;
-import android.provider.Telephony.MmsSms.PendingMessages;
+import com.android.mmscommon.telephony.TelephonyProvider;
+import com.android.mmscommon.telephony.TelephonyProvider.Mms;
+import com.android.mmscommon.telephony.TelephonyProvider.MmsSms;
+import com.android.mmscommon.telephony.TelephonyProvider.Threads;
+import com.android.mmscommon.telephony.TelephonyProvider.Mms.Addr;
+import com.android.mmscommon.telephony.TelephonyProvider.Mms.Part;
+import com.android.mmscommon.telephony.TelephonyProvider.MmsSms.PendingMessages;
import android.text.TextUtils;
import android.util.Config;
import android.util.Log;
@@ -55,7 +60,6 @@ import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
-import com.google.android.mms.pdu.EncodedStringValue;
/**
* This class is the high-level manager of PDU storage.
@@ -422,7 +426,8 @@ public class PduPersister {
// Store simple string values directly in the database instead of an
// external file. This makes the text searchable and retrieval slightly
// faster.
- if ("text/plain".equals(type) || "application/smil".equals(type)) {
+ if (ContentType.TEXT_PLAIN.equals(type) || ContentType.APP_SMIL.equals(type)
+ || ContentType.TEXT_HTML.equals(type)) {
String text = c.getString(PART_COLUMN_TEXT);
if (text == null) {
text = "";
@@ -738,9 +743,11 @@ public class PduPersister {
try {
byte[] data = part.getData();
- if ("text/plain".equals(contentType) || "application/smil".equals(contentType)) {
+ if (ContentType.TEXT_PLAIN.equals(contentType)
+ || ContentType.APP_SMIL.equals(contentType)
+ || ContentType.TEXT_HTML.equals(contentType)) {
ContentValues cv = new ContentValues();
- cv.put(Telephony.Mms.Part.TEXT, new EncodedStringValue(data).getString());
+ cv.put(TelephonyProvider.Mms.Part.TEXT, new EncodedStringValue(data).getString());
if (mContentResolver.update(uri, cv, null, null) != 1) {
throw new MmsException("unable to update " + uri.toString());
}
diff --git a/core/java/com/google/android/mms/pdu/QuotedPrintable.java b/mms-common/java/com/android/mmscommon/mms/pdu/QuotedPrintable.java
index a34ed1263891..e9da7df1f3c6 100644
--- a/core/java/com/google/android/mms/pdu/QuotedPrintable.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/QuotedPrintable.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
import java.io.ByteArrayOutputStream;
diff --git a/core/java/com/google/android/mms/pdu/ReadOrigInd.java b/mms-common/java/com/android/mmscommon/mms/pdu/ReadOrigInd.java
index 1bfc0bb3e258..9678784861ca 100644
--- a/core/java/com/google/android/mms/pdu/ReadOrigInd.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/ReadOrigInd.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
public class ReadOrigInd extends GenericPdu {
/**
diff --git a/core/java/com/google/android/mms/pdu/ReadRecInd.java b/mms-common/java/com/android/mmscommon/mms/pdu/ReadRecInd.java
index 880e3ac3ddd4..c1efbbc37da9 100644
--- a/core/java/com/google/android/mms/pdu/ReadRecInd.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/ReadRecInd.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
public class ReadRecInd extends GenericPdu {
/**
diff --git a/core/java/com/google/android/mms/pdu/RetrieveConf.java b/mms-common/java/com/android/mmscommon/mms/pdu/RetrieveConf.java
index 98e67c068d98..442949e95b6b 100644
--- a/core/java/com/google/android/mms/pdu/RetrieveConf.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/RetrieveConf.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
/**
* M-Retrive.conf Pdu.
diff --git a/core/java/com/google/android/mms/pdu/SendConf.java b/mms-common/java/com/android/mmscommon/mms/pdu/SendConf.java
index 0568fe79c5ff..0a57b6b2d09d 100644
--- a/core/java/com/google/android/mms/pdu/SendConf.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/SendConf.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
public class SendConf extends GenericPdu {
/**
diff --git a/core/java/com/google/android/mms/pdu/SendReq.java b/mms-common/java/com/android/mmscommon/mms/pdu/SendReq.java
index 597cd00b9961..5da4719ae8a7 100644
--- a/core/java/com/google/android/mms/pdu/SendReq.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/SendReq.java
@@ -15,11 +15,13 @@
* limitations under the License.
*/
-package com.google.android.mms.pdu;
+package com.android.mmscommon.mms.pdu;
import android.util.Log;
-import com.google.android.mms.InvalidHeaderValueException;
+import com.android.mmscommon.EncodedStringValue;
+import com.android.mmscommon.InvalidHeaderValueException;
+import com.android.mmscommon.PduHeaders;
public class SendReq extends MultimediaMessagePdu {
private static final String TAG = "SendReq";
diff --git a/core/java/com/google/android/mms/util/AbstractCache.java b/mms-common/java/com/android/mmscommon/mms/util/AbstractCache.java
index 670439ca777b..10a6fcedc2ec 100644
--- a/core/java/com/google/android/mms/util/AbstractCache.java
+++ b/mms-common/java/com/android/mmscommon/mms/util/AbstractCache.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.google.android.mms.util;
+package com.android.mmscommon.mms.util;
import android.util.Config;
import android.util.Log;
diff --git a/core/java/com/google/android/mms/util/PduCache.java b/mms-common/java/com/android/mmscommon/mms/util/PduCache.java
index 7c3fad7b865c..ca5432f07986 100644
--- a/core/java/com/google/android/mms/util/PduCache.java
+++ b/mms-common/java/com/android/mmscommon/mms/util/PduCache.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package com.google.android.mms.util;
+package com.android.mmscommon.mms.util;
import android.content.ContentUris;
import android.content.UriMatcher;
import android.net.Uri;
-import android.provider.Telephony.Mms;
+import com.android.mmscommon.telephony.TelephonyProvider.Mms;
import android.util.Config;
import android.util.Log;
diff --git a/core/java/com/google/android/mms/util/PduCacheEntry.java b/mms-common/java/com/android/mmscommon/mms/util/PduCacheEntry.java
index 8b4138628113..aed741d2d7a3 100644
--- a/core/java/com/google/android/mms/util/PduCacheEntry.java
+++ b/mms-common/java/com/android/mmscommon/mms/util/PduCacheEntry.java
@@ -15,9 +15,9 @@
* limitations under the License.
*/
-package com.google.android.mms.util;
+package com.android.mmscommon.mms.util;
-import com.google.android.mms.pdu.GenericPdu;
+import com.android.mmscommon.mms.pdu.GenericPdu;
public final class PduCacheEntry {
private final GenericPdu mPdu;
diff --git a/mms-common/java/com/android/mmscommon/telephony/TelephonyProvider.java b/mms-common/java/com/android/mmscommon/telephony/TelephonyProvider.java
new file mode 100644
index 000000000000..0237bc2eb690
--- /dev/null
+++ b/mms-common/java/com/android/mmscommon/telephony/TelephonyProvider.java
@@ -0,0 +1,1790 @@
+/*
+ * 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 com.android.mmscommon.telephony;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.telephony.SmsMessage;
+import android.text.TextUtils;
+import android.util.Config;
+import android.util.Log;
+
+import com.android.common.Patterns;
+import android.database.sqlite.SqliteWrapper;
+
+/**
+ * The Telephony provider contains data related to phone operation.
+ *
+ * @hide
+ */
+
+// This is a copy of the private TelephoneProvider.java file found in:
+// com.android.providers.telephony
+// TODO: keep these files in sync.
+
+public final class TelephonyProvider {
+ private static final String TAG = "Telephony";
+ private static final boolean DEBUG = true;
+ private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
+
+// public static final Pattern EMAIL_ADDRESS
+// = Pattern.compile(
+// "[a-zA-Z0-9\\+\\.\\_\\%\\-]{1,256}" +
+// "\\@" +
+// "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
+// "(" +
+// "\\." +
+// "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
+// ")+"
+// );
+//
+// /**
+// * This pattern is intended for searching for things that look like they
+// * might be phone numbers in arbitrary text, not for validating whether
+// * something is in fact a phone number. It will miss many things that
+// * are legitimate phone numbers.
+// *
+// * <p> The pattern matches the following:
+// * <ul>
+// * <li>Optionally, a + sign followed immediately by one or more digits. Spaces, dots, or dashes
+// * may follow.
+// * <li>Optionally, sets of digits in parentheses, separated by spaces, dots, or dashes.
+// * <li>A string starting and ending with a digit, containing digits, spaces, dots, and/or dashes.
+// * </ul>
+// */
+// public static final Pattern PHONE
+// = Pattern.compile( // sdd = space, dot, or dash
+// "(\\+[0-9]+[\\- \\.]*)?" // +<digits><sdd>*
+// + "(\\([0-9]+\\)[\\- \\.]*)?" // (<digits>)<sdd>*
+// + "([0-9][0-9\\- \\.][0-9\\- \\.]+[0-9])"); // <digit><digit|sdd>+<digit>
+
+ // Constructor
+ public TelephonyProvider() {
+ }
+
+ /**
+ * Base columns for tables that contain text based SMSs.
+ */
+ public interface TextBasedSmsColumns {
+ /**
+ * The type of the message
+ * <P>Type: INTEGER</P>
+ */
+ public static final String TYPE = "type";
+
+ public static final int MESSAGE_TYPE_ALL = 0;
+ public static final int MESSAGE_TYPE_INBOX = 1;
+ public static final int MESSAGE_TYPE_SENT = 2;
+ public static final int MESSAGE_TYPE_DRAFT = 3;
+ public static final int MESSAGE_TYPE_OUTBOX = 4;
+ public static final int MESSAGE_TYPE_FAILED = 5; // for failed outgoing messages
+ public static final int MESSAGE_TYPE_QUEUED = 6; // for messages to send later
+
+
+ /**
+ * The thread ID of the message
+ * <P>Type: INTEGER</P>
+ */
+ public static final String THREAD_ID = "thread_id";
+
+ /**
+ * The address of the other party
+ * <P>Type: TEXT</P>
+ */
+ public static final String ADDRESS = "address";
+
+ /**
+ * The person ID of the sender
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String PERSON_ID = "person";
+
+ /**
+ * The date the message was sent
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DATE = "date";
+
+ /**
+ * Has the message been read
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String READ = "read";
+
+ /**
+ * The TP-Status value for the message, or -1 if no status has
+ * been received
+ */
+ public static final String STATUS = "status";
+
+ public static final int STATUS_NONE = -1;
+ public static final int STATUS_COMPLETE = 0;
+ public static final int STATUS_PENDING = 64;
+ public static final int STATUS_FAILED = 128;
+
+ /**
+ * The subject of the message, if present
+ * <P>Type: TEXT</P>
+ */
+ public static final String SUBJECT = "subject";
+
+ /**
+ * The body of the message
+ * <P>Type: TEXT</P>
+ */
+ public static final String BODY = "body";
+
+ /**
+ * The id of the sender of the conversation, if present
+ * <P>Type: INTEGER (reference to item in content://contacts/people)</P>
+ */
+ public static final String PERSON = "person";
+
+ /**
+ * The protocol identifier code
+ * <P>Type: INTEGER</P>
+ */
+ public static final String PROTOCOL = "protocol";
+
+ /**
+ * Whether the <code>TP-Reply-Path</code> bit was set on this message
+ * <P>Type: BOOLEAN</P>
+ */
+ public static final String REPLY_PATH_PRESENT = "reply_path_present";
+
+ /**
+ * The service center (SC) through which to send the message, if present
+ * <P>Type: TEXT</P>
+ */
+ public static final String SERVICE_CENTER = "service_center";
+
+ /**
+ * Has the message been locked?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String LOCKED = "locked";
+
+ /**
+ * Error code associated with sending or receiving this message
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR_CODE = "error_code";
+}
+
+ /**
+ * Contains all text based SMS messages.
+ */
+ public static final class Sms implements BaseColumns, TextBasedSmsColumns {
+ public static final Cursor query(ContentResolver cr, String[] projection) {
+ return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
+ }
+
+ public static final Cursor query(ContentResolver cr, String[] projection,
+ String where, String orderBy) {
+ return cr.query(CONTENT_URI, projection, where,
+ null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
+ }
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the given URI.
+ *
+ * @param resolver the content resolver to use
+ * @param uri the URI to add the message to
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @param deliveryReport true if a delivery report was requested, false if not
+ * @return the URI for the new message
+ */
+ public static Uri addMessageToUri(ContentResolver resolver,
+ Uri uri, String address, String body, String subject,
+ Long date, boolean read, boolean deliveryReport) {
+ return addMessageToUri(resolver, uri, address, body, subject,
+ date, read, deliveryReport, -1L);
+ }
+
+ /**
+ * Add an SMS to the given URI with thread_id specified.
+ *
+ * @param resolver the content resolver to use
+ * @param uri the URI to add the message to
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @param deliveryReport true if a delivery report was requested, false if not
+ * @param threadId the thread_id of the message
+ * @return the URI for the new message
+ */
+ public static Uri addMessageToUri(ContentResolver resolver,
+ Uri uri, String address, String body, String subject,
+ Long date, boolean read, boolean deliveryReport, long threadId) {
+ ContentValues values = new ContentValues(7);
+
+ values.put(ADDRESS, address);
+ if (date != null) {
+ values.put(DATE, date);
+ }
+ values.put(READ, read ? Integer.valueOf(1) : Integer.valueOf(0));
+ values.put(SUBJECT, subject);
+ values.put(BODY, body);
+ if (deliveryReport) {
+ values.put(STATUS, STATUS_PENDING);
+ }
+ if (threadId != -1L) {
+ values.put(THREAD_ID, threadId);
+ }
+ return resolver.insert(uri, values);
+ }
+
+ /**
+ * Move a message to the given folder.
+ *
+ * @param context the context to use
+ * @param uri the message to move
+ * @param folder the folder to move to
+ * @return true if the operation succeeded
+ */
+ public static boolean moveMessageToFolder(Context context,
+ Uri uri, int folder, int error) {
+ if (uri == null) {
+ return false;
+ }
+
+ boolean markAsUnread = false;
+ boolean markAsRead = false;
+ switch(folder) {
+ case MESSAGE_TYPE_INBOX:
+ case MESSAGE_TYPE_DRAFT:
+ break;
+ case MESSAGE_TYPE_OUTBOX:
+ case MESSAGE_TYPE_SENT:
+ markAsRead = true;
+ break;
+ case MESSAGE_TYPE_FAILED:
+ case MESSAGE_TYPE_QUEUED:
+ markAsUnread = true;
+ break;
+ default:
+ return false;
+ }
+
+ ContentValues values = new ContentValues(3);
+
+ values.put(TYPE, folder);
+ if (markAsUnread) {
+ values.put(READ, Integer.valueOf(0));
+ } else if (markAsRead) {
+ values.put(READ, Integer.valueOf(1));
+ }
+ values.put(ERROR_CODE, error);
+
+ return 1 == SqliteWrapper.update(context, context.getContentResolver(),
+ uri, values, null, null);
+ }
+
+ /**
+ * Returns true iff the folder (message type) identifies an
+ * outgoing message.
+ */
+ public static boolean isOutgoingFolder(int messageType) {
+ return (messageType == MESSAGE_TYPE_FAILED)
+ || (messageType == MESSAGE_TYPE_OUTBOX)
+ || (messageType == MESSAGE_TYPE_SENT)
+ || (messageType == MESSAGE_TYPE_QUEUED);
+ }
+
+ /**
+ * Contains all text based SMS messages in the SMS app's inbox.
+ */
+ public static final class Inbox implements BaseColumns, TextBasedSmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms/inbox");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the Draft box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param read true if the message has been read, false if not
+ * @return the URI for the new message
+ */
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date,
+ boolean read) {
+ return addMessageToUri(resolver, CONTENT_URI, address, body,
+ subject, date, read, false);
+ }
+ }
+
+ /**
+ * Contains all sent text based SMS messages in the SMS app's.
+ */
+ public static final class Sent implements BaseColumns, TextBasedSmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms/sent");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the Draft box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @return the URI for the new message
+ */
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date) {
+ return addMessageToUri(resolver, CONTENT_URI, address, body,
+ subject, date, true, false);
+ }
+ }
+
+ /**
+ * Contains all sent text based SMS messages in the SMS app's.
+ */
+ public static final class Draft implements BaseColumns, TextBasedSmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms/draft");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the Draft box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @return the URI for the new message
+ */
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date) {
+ return addMessageToUri(resolver, CONTENT_URI, address, body,
+ subject, date, true, false);
+ }
+
+ /**
+ * Save over an existing draft message.
+ *
+ * @param resolver the content resolver to use
+ * @param uri of existing message
+ * @param body the new body for the draft message
+ * @return true is successful, false otherwise
+ */
+ public static boolean saveMessage(ContentResolver resolver,
+ Uri uri, String body) {
+ ContentValues values = new ContentValues(2);
+ values.put(BODY, body);
+ values.put(DATE, System.currentTimeMillis());
+ return resolver.update(uri, values, null, null) == 1;
+ }
+ }
+
+ /**
+ * Contains all pending outgoing text based SMS messages.
+ */
+ public static final class Outbox implements BaseColumns, TextBasedSmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms/outbox");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * Add an SMS to the Out box.
+ *
+ * @param resolver the content resolver to use
+ * @param address the address of the sender
+ * @param body the body of the message
+ * @param subject the psuedo-subject of the message
+ * @param date the timestamp for the message
+ * @param deliveryReport whether a delivery report was requested for the message
+ * @return the URI for the new message
+ */
+ public static Uri addMessage(ContentResolver resolver,
+ String address, String body, String subject, Long date,
+ boolean deliveryReport, long threadId) {
+ return addMessageToUri(resolver, CONTENT_URI, address, body,
+ subject, date, true, deliveryReport, threadId);
+ }
+ }
+
+ /**
+ * Contains all sent text-based SMS messages in the SMS app's.
+ */
+ public static final class Conversations
+ implements BaseColumns, TextBasedSmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://sms/conversations");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * The first 45 characters of the body of the message
+ * <P>Type: TEXT</P>
+ */
+ public static final String SNIPPET = "snippet";
+
+ /**
+ * The number of messages in the conversation
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_COUNT = "msg_count";
+ }
+
+ /**
+ * Contains info about SMS related Intents that are broadcast.
+ */
+ public static final class Intents {
+ /**
+ * Set by BroadcastReceiver. Indicates the message was handled
+ * successfully.
+ */
+ public static final int RESULT_SMS_HANDLED = 1;
+
+ /**
+ * Set by BroadcastReceiver. Indicates a generic error while
+ * processing the message.
+ */
+ public static final int RESULT_SMS_GENERIC_ERROR = 2;
+
+ /**
+ * Set by BroadcastReceiver. Indicates insufficient memory to store
+ * the message.
+ */
+ public static final int RESULT_SMS_OUT_OF_MEMORY = 3;
+
+ /**
+ * Set by BroadcastReceiver. Indicates the message, while
+ * possibly valid, is of a format or encoding that is not
+ * supported.
+ */
+ public static final int RESULT_SMS_UNSUPPORTED = 4;
+
+ /**
+ * Broadcast Action: A new text based SMS message has been received
+ * by the device. The intent will have the following extra
+ * values:</p>
+ *
+ * <ul>
+ * <li><em>pdus</em> - An Object[] od byte[]s containing the PDUs
+ * that make up the message.</li>
+ * </ul>
+ *
+ * <p>The extra values can be extracted using
+ * {@link #getMessagesFromIntent(Intent)}.</p>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ */
+ public static final String SMS_RECEIVED_ACTION =
+ "android.provider.Telephony.SMS_RECEIVED";
+
+ /**
+ * Broadcast Action: A new data based SMS message has been received
+ * by the device. The intent will have the following extra
+ * values:</p>
+ *
+ * <ul>
+ * <li><em>pdus</em> - An Object[] od byte[]s containing the PDUs
+ * that make up the message.</li>
+ * </ul>
+ *
+ * <p>The extra values can be extracted using
+ * {@link #getMessagesFromIntent(Intent)}.</p>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ */
+ public static final String DATA_SMS_RECEIVED_ACTION =
+ "android.intent.action.DATA_SMS_RECEIVED";
+
+ /**
+ * Broadcast Action: A new WAP PUSH message has been received by the
+ * device. The intent will have the following extra
+ * values:</p>
+ *
+ * <ul>
+ * <li><em>transactionId (Integer)</em> - The WAP transaction
+ * ID</li>
+ * <li><em>pduType (Integer)</em> - The WAP PDU type</li>
+ * <li><em>header (byte[])</em> - The header of the message</li>
+ * <li><em>data (byte[])</em> - The data payload of the message</li>
+ * </ul>
+ *
+ * <p>If a BroadcastReceiver encounters an error while processing
+ * this intent it should set the result code appropriately.</p>
+ */
+ public static final String WAP_PUSH_RECEIVED_ACTION =
+ "android.provider.Telephony.WAP_PUSH_RECEIVED";
+
+ /**
+ * Broadcast Action: The SIM storage for SMS messages is full. If
+ * space is not freed, messages targeted for the SIM (class 2) may
+ * not be saved.
+ */
+ public static final String SIM_FULL_ACTION =
+ "android.provider.Telephony.SIM_FULL";
+
+ /**
+ * Broadcast Action: An incoming SMS has been rejected by the
+ * telephony framework. This intent is sent in lieu of any
+ * of the RECEIVED_ACTION intents. The intent will have the
+ * following extra value:</p>
+ *
+ * <ul>
+ * <li><em>result</em> - An int result code, eg,
+ * <code>{@link #RESULT_SMS_OUT_OF_MEMORY}</code>,
+ * indicating the error returned to the network.</li>
+ * </ul>
+
+ */
+ public static final String SMS_REJECTED_ACTION =
+ "android.provider.Telephony.SMS_REJECTED";
+
+ /**
+ * Broadcast Action: The phone service state has changed. The intent will have the following
+ * extra values:</p>
+ * <ul>
+ * <li><em>state</em> - An int with one of the following values:
+ * {@link android.telephony.ServiceState#STATE_IN_SERVICE},
+ * {@link android.telephony.ServiceState#STATE_OUT_OF_SERVICE},
+ * {@link android.telephony.ServiceState#STATE_EMERGENCY_ONLY}
+ * or {@link android.telephony.ServiceState#STATE_POWER_OFF}
+ * <li><em>roaming</em> - A boolean value indicating whether the phone is roaming.</li>
+ * <li><em>operator-alpha-long</em> - The carrier name as a string.</li>
+ * <li><em>operator-alpha-short</em> - A potentially shortened version of the carrier name,
+ * as a string.</li>
+ * <li><em>operator-numeric</em> - A number representing the carrier, as a string. This is
+ * a five or six digit number consisting of the MCC (Mobile Country Code, 3 digits)
+ * and MNC (Mobile Network code, 2-3 digits).</li>
+ * <li><em>manual</em> - A boolean, where true indicates that the user has chosen to select
+ * the network manually, and false indicates that network selection is handled by the
+ * phone.</li>
+ * </ul>
+ *
+ * <p class="note">
+ * Requires the READ_PHONE_STATE permission.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ */
+ public static final String ACTION_SERVICE_STATE_CHANGED =
+ "android.intent.action.SERVICE_STATE";
+
+ /**
+ * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
+ * {@link #DATA_SMS_RECEIVED_ACTION} intent.
+ *
+ * @param intent the intent to read from
+ * @return an array of SmsMessages for the PDUs
+ */
+ public static final SmsMessage[] getMessagesFromIntent(
+ Intent intent) {
+ Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
+ byte[][] pduObjs = new byte[messages.length][];
+
+ for (int i = 0; i < messages.length; i++) {
+ pduObjs[i] = (byte[]) messages[i];
+ }
+ byte[][] pdus = new byte[pduObjs.length][];
+ int pduCount = pdus.length;
+ SmsMessage[] msgs = new SmsMessage[pduCount];
+ for (int i = 0; i < pduCount; i++) {
+ pdus[i] = pduObjs[i];
+ msgs[i] = SmsMessage.createFromPdu(pdus[i]);
+ }
+ return msgs;
+ }
+ }
+ }
+
+ /**
+ * Base columns for tables that contain MMSs.
+ */
+ public interface BaseMmsColumns extends BaseColumns {
+
+ public static final int MESSAGE_BOX_ALL = 0;
+ public static final int MESSAGE_BOX_INBOX = 1;
+ public static final int MESSAGE_BOX_SENT = 2;
+ public static final int MESSAGE_BOX_DRAFTS = 3;
+ public static final int MESSAGE_BOX_OUTBOX = 4;
+
+ /**
+ * The date the message was sent.
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DATE = "date";
+
+ /**
+ * The box which the message belong to, for example, MESSAGE_BOX_INBOX.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_BOX = "msg_box";
+
+ /**
+ * Has the message been read.
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String READ = "read";
+
+ /**
+ * The Message-ID of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MESSAGE_ID = "m_id";
+
+ /**
+ * The subject of the message, if present.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SUBJECT = "sub";
+
+ /**
+ * The character set of the subject, if present.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SUBJECT_CHARSET = "sub_cs";
+
+ /**
+ * The Content-Type of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_TYPE = "ct_t";
+
+ /**
+ * The Content-Location of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_LOCATION = "ct_l";
+
+ /**
+ * The address of the sender.
+ * <P>Type: TEXT</P>
+ */
+ public static final String FROM = "from";
+
+ /**
+ * The address of the recipients.
+ * <P>Type: TEXT</P>
+ */
+ public static final String TO = "to";
+
+ /**
+ * The address of the cc. recipients.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CC = "cc";
+
+ /**
+ * The address of the bcc. recipients.
+ * <P>Type: TEXT</P>
+ */
+ public static final String BCC = "bcc";
+
+ /**
+ * The expiry time of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String EXPIRY = "exp";
+
+ /**
+ * The class of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MESSAGE_CLASS = "m_cls";
+
+ /**
+ * The type of the message defined by MMS spec.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_TYPE = "m_type";
+
+ /**
+ * The version of specification that this message conform.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MMS_VERSION = "v";
+
+ /**
+ * The size of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_SIZE = "m_size";
+
+ /**
+ * The priority of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PRIORITY = "pri";
+
+ /**
+ * The read-report of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String READ_REPORT = "rr";
+
+ /**
+ * Whether the report is allowed.
+ * <P>Type: TEXT</P>
+ */
+ public static final String REPORT_ALLOWED = "rpt_a";
+
+ /**
+ * The response-status of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RESPONSE_STATUS = "resp_st";
+
+ /**
+ * The status of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String STATUS = "st";
+
+ /**
+ * The transaction-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String TRANSACTION_ID = "tr_id";
+
+ /**
+ * The retrieve-status of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RETRIEVE_STATUS = "retr_st";
+
+ /**
+ * The retrieve-text of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RETRIEVE_TEXT = "retr_txt";
+
+ /**
+ * The character set of the retrieve-text.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RETRIEVE_TEXT_CHARSET = "retr_txt_cs";
+
+ /**
+ * The read-status of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String READ_STATUS = "read_status";
+
+ /**
+ * The content-class of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CONTENT_CLASS = "ct_cls";
+
+ /**
+ * The delivery-report of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String DELIVERY_REPORT = "d_rpt";
+
+ /**
+ * The delivery-time-token of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String DELIVERY_TIME_TOKEN = "d_tm_tok";
+
+ /**
+ * The delivery-time of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String DELIVERY_TIME = "d_tm";
+
+ /**
+ * The response-text of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RESPONSE_TEXT = "resp_txt";
+
+ /**
+ * The sender-visibility of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SENDER_VISIBILITY = "s_vis";
+
+ /**
+ * The reply-charging of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String REPLY_CHARGING = "r_chg";
+
+ /**
+ * The reply-charging-deadline-token of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String REPLY_CHARGING_DEADLINE_TOKEN = "r_chg_dl_tok";
+
+ /**
+ * The reply-charging-deadline of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String REPLY_CHARGING_DEADLINE = "r_chg_dl";
+
+ /**
+ * The reply-charging-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String REPLY_CHARGING_ID = "r_chg_id";
+
+ /**
+ * The reply-charging-size of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String REPLY_CHARGING_SIZE = "r_chg_sz";
+
+ /**
+ * The previously-sent-by of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String PREVIOUSLY_SENT_BY = "p_s_by";
+
+ /**
+ * The previously-sent-date of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String PREVIOUSLY_SENT_DATE = "p_s_d";
+
+ /**
+ * The store of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String STORE = "store";
+
+ /**
+ * The mm-state of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MM_STATE = "mm_st";
+
+ /**
+ * The mm-flags-token of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MM_FLAGS_TOKEN = "mm_flg_tok";
+
+ /**
+ * The mm-flags of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MM_FLAGS = "mm_flg";
+
+ /**
+ * The store-status of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String STORE_STATUS = "store_st";
+
+ /**
+ * The store-status-text of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String STORE_STATUS_TEXT = "store_st_txt";
+
+ /**
+ * The stored of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String STORED = "stored";
+
+ /**
+ * The totals of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String TOTALS = "totals";
+
+ /**
+ * The mbox-totals of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MBOX_TOTALS = "mb_t";
+
+ /**
+ * The mbox-totals-token of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MBOX_TOTALS_TOKEN = "mb_t_tok";
+
+ /**
+ * The quotas of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String QUOTAS = "qt";
+
+ /**
+ * The mbox-quotas of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String MBOX_QUOTAS = "mb_qt";
+
+ /**
+ * The mbox-quotas-token of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MBOX_QUOTAS_TOKEN = "mb_qt_tok";
+
+ /**
+ * The message-count of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_COUNT = "m_cnt";
+
+ /**
+ * The start of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String START = "start";
+
+ /**
+ * The distribution-indicator of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String DISTRIBUTION_INDICATOR = "d_ind";
+
+ /**
+ * The element-descriptor of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String ELEMENT_DESCRIPTOR = "e_des";
+
+ /**
+ * The limit of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String LIMIT = "limit";
+
+ /**
+ * The recommended-retrieval-mode of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RECOMMENDED_RETRIEVAL_MODE = "r_r_mod";
+
+ /**
+ * The recommended-retrieval-mode-text of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RECOMMENDED_RETRIEVAL_MODE_TEXT = "r_r_mod_txt";
+
+ /**
+ * The status-text of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String STATUS_TEXT = "st_txt";
+
+ /**
+ * The applic-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String APPLIC_ID = "apl_id";
+
+ /**
+ * The reply-applic-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String REPLY_APPLIC_ID = "r_apl_id";
+
+ /**
+ * The aux-applic-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String AUX_APPLIC_ID = "aux_apl_id";
+
+ /**
+ * The drm-content of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String DRM_CONTENT = "drm_c";
+
+ /**
+ * The adaptation-allowed of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String ADAPTATION_ALLOWED = "adp_a";
+
+ /**
+ * The replace-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String REPLACE_ID = "repl_id";
+
+ /**
+ * The cancel-id of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CANCEL_ID = "cl_id";
+
+ /**
+ * The cancel-status of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CANCEL_STATUS = "cl_st";
+
+ /**
+ * The thread ID of the message
+ * <P>Type: INTEGER</P>
+ */
+ public static final String THREAD_ID = "thread_id";
+
+ /**
+ * Has the message been locked?
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String LOCKED = "locked";
+ }
+
+ /**
+ * Columns for the "canonical_addresses" table used by MMS and
+ * SMS."
+ */
+ public interface CanonicalAddressesColumns extends BaseColumns {
+ /**
+ * An address used in MMS or SMS. Email addresses are
+ * converted to lower case and are compared by string
+ * equality. Other addresses are compared using
+ * PHONE_NUMBERS_EQUAL.
+ * <P>Type: TEXT</P>
+ */
+ public static final String ADDRESS = "address";
+ }
+
+ /**
+ * Columns for the "threads" table used by MMS and SMS.
+ */
+ public interface ThreadsColumns extends BaseColumns {
+ /**
+ * The date at which the thread was created.
+ *
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String DATE = "date";
+
+ /**
+ * A string encoding of the recipient IDs of the recipients of
+ * the message, in numerical order and separated by spaces.
+ * <P>Type: TEXT</P>
+ */
+ public static final String RECIPIENT_IDS = "recipient_ids";
+
+ /**
+ * The message count of the thread.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MESSAGE_COUNT = "message_count";
+ /**
+ * Indicates whether all messages of the thread have been read.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String READ = "read";
+ /**
+ * The snippet of the latest message in the thread.
+ * <P>Type: TEXT</P>
+ */
+ public static final String SNIPPET = "snippet";
+ /**
+ * The charset of the snippet.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SNIPPET_CHARSET = "snippet_cs";
+ /**
+ * Type of the thread, either Threads.COMMON_THREAD or
+ * Threads.BROADCAST_THREAD.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String TYPE = "type";
+ /**
+ * Indicates whether there is a transmission error in the thread.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR = "error";
+ /**
+ * Indicates whether this thread contains any attachments.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String HAS_ATTACHMENT = "has_attachment";
+ }
+
+ /**
+ * Helper functions for the "threads" table used by MMS and SMS.
+ */
+ public static final class Threads implements ThreadsColumns {
+ private static final String[] ID_PROJECTION = { BaseColumns._ID };
+ private static final String STANDARD_ENCODING = "UTF-8";
+ private static final Uri THREAD_ID_CONTENT_URI = Uri.parse(
+ "content://mms-sms/threadID");
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(
+ MmsSms.CONTENT_URI, "conversations");
+ public static final Uri OBSOLETE_THREADS_URI = Uri.withAppendedPath(
+ CONTENT_URI, "obsolete");
+
+ public static final int COMMON_THREAD = 0;
+ public static final int BROADCAST_THREAD = 1;
+
+ // No one should construct an instance of this class.
+ private Threads() {
+ }
+
+ /**
+ * This is a single-recipient version of
+ * getOrCreateThreadId. It's convenient for use with SMS
+ * messages.
+ */
+ public static long getOrCreateThreadId(Context context, String recipient) {
+ Set<String> recipients = new HashSet<String>();
+
+ recipients.add(recipient);
+ return getOrCreateThreadId(context, recipients);
+ }
+
+ /**
+ * Given the recipients list and subject of an unsaved message,
+ * return its thread ID. If the message starts a new thread,
+ * allocate a new thread ID. Otherwise, use the appropriate
+ * existing thread ID.
+ *
+ * Find the thread ID of the same set of recipients (in
+ * any order, without any additions). If one
+ * is found, return it. Otherwise, return a unique thread ID.
+ */
+ public static long getOrCreateThreadId(
+ Context context, Set<String> recipients) {
+ Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
+
+ for (String recipient : recipients) {
+ if (Mms.isEmailAddress(recipient)) {
+ recipient = Mms.extractAddrSpec(recipient);
+ }
+
+ uriBuilder.appendQueryParameter("recipient", recipient);
+ }
+
+ Uri uri = uriBuilder.build();
+ if (DEBUG) {
+ Log.v(TAG, "getOrCreateThreadId uri: " + uri);
+ }
+ Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(),
+ uri, ID_PROJECTION, null, null, null);
+ if (DEBUG) {
+ Log.v(TAG, "getOrCreateThreadId cursor cnt: " + cursor.getCount());
+ }
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ return cursor.getLong(0);
+ } else {
+ Log.e(TAG, "getOrCreateThreadId returned no rows!");
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+
+ Log.e(TAG, "getOrCreateThreadId failed with uri " + uri.toString());
+ throw new IllegalArgumentException("Unable to find or allocate a thread ID.");
+ }
+ }
+
+ /**
+ * Contains all MMS messages.
+ */
+ public static final class Mms implements BaseMmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://mms");
+
+ public static final Uri REPORT_REQUEST_URI = Uri.withAppendedPath(
+ CONTENT_URI, "report-request");
+
+ public static final Uri REPORT_STATUS_URI = Uri.withAppendedPath(
+ CONTENT_URI, "report-status");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+
+ /**
+ * mailbox = name-addr
+ * name-addr = [display-name] angle-addr
+ * angle-addr = [CFWS] "<" addr-spec ">" [CFWS]
+ */
+ public static final Pattern NAME_ADDR_EMAIL_PATTERN =
+ Pattern.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
+
+ /**
+ * quoted-string = [CFWS]
+ * DQUOTE *([FWS] qcontent) [FWS] DQUOTE
+ * [CFWS]
+ */
+ public static final Pattern QUOTED_STRING_PATTERN =
+ Pattern.compile("\\s*\"([^\"]*)\"\\s*");
+
+ public static final Cursor query(
+ ContentResolver cr, String[] projection) {
+ return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
+ }
+
+ public static final Cursor query(
+ ContentResolver cr, String[] projection,
+ String where, String orderBy) {
+ return cr.query(CONTENT_URI, projection,
+ where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
+ }
+
+ public static final String getMessageBoxName(int msgBox) {
+ switch (msgBox) {
+ case MESSAGE_BOX_ALL:
+ return "all";
+ case MESSAGE_BOX_INBOX:
+ return "inbox";
+ case MESSAGE_BOX_SENT:
+ return "sent";
+ case MESSAGE_BOX_DRAFTS:
+ return "drafts";
+ case MESSAGE_BOX_OUTBOX:
+ return "outbox";
+ default:
+ throw new IllegalArgumentException("Invalid message box: " + msgBox);
+ }
+ }
+
+ public static String extractAddrSpec(String address) {
+ Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(address);
+
+ if (match.matches()) {
+ return match.group(2);
+ }
+ return address;
+ }
+
+ /**
+ * Returns true if the address is an email address
+ *
+ * @param address the input address to be tested
+ * @return true if address is an email address
+ */
+ public static boolean isEmailAddress(String address) {
+ if (TextUtils.isEmpty(address)) {
+ return false;
+ }
+
+ String s = extractAddrSpec(address);
+ Matcher match = Patterns.EMAIL_ADDRESS.matcher(s);
+ return match.matches();
+ }
+
+ /**
+ * Returns true if the number is a Phone number
+ *
+ * @param number the input number to be tested
+ * @return true if number is a Phone number
+ */
+ public static boolean isPhoneNumber(String number) {
+ if (TextUtils.isEmpty(number)) {
+ return false;
+ }
+
+ Matcher match = Patterns.PHONE.matcher(number);
+ return match.matches();
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app's inbox.
+ */
+ public static final class Inbox implements BaseMmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/inbox");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app's sent box.
+ */
+ public static final class Sent implements BaseMmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/sent");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app's drafts box.
+ */
+ public static final class Draft implements BaseMmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/drafts");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ /**
+ * Contains all MMS messages in the MMS app's outbox.
+ */
+ public static final class Outbox implements BaseMmsColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri
+ CONTENT_URI = Uri.parse("content://mms/outbox");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date DESC";
+ }
+
+ public static final class Addr implements BaseColumns {
+ /**
+ * The ID of MM which this address entry belongs to.
+ */
+ public static final String MSG_ID = "msg_id";
+
+ /**
+ * The ID of contact entry in Phone Book.
+ */
+ public static final String CONTACT_ID = "contact_id";
+
+ /**
+ * The address text.
+ */
+ public static final String ADDRESS = "address";
+
+ /**
+ * Type of address, must be one of PduHeaders.BCC,
+ * PduHeaders.CC, PduHeaders.FROM, PduHeaders.TO.
+ */
+ public static final String TYPE = "type";
+
+ /**
+ * Character set of this entry.
+ */
+ public static final String CHARSET = "charset";
+ }
+
+ public static final class Part implements BaseColumns {
+ /**
+ * The identifier of the message which this part belongs to.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MSG_ID = "mid";
+
+ /**
+ * The order of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SEQ = "seq";
+
+ /**
+ * The content type of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_TYPE = "ct";
+
+ /**
+ * The name of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String NAME = "name";
+
+ /**
+ * The charset of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CHARSET = "chset";
+
+ /**
+ * The file name of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String FILENAME = "fn";
+
+ /**
+ * The content disposition of the part.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CONTENT_DISPOSITION = "cd";
+
+ /**
+ * The content ID of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CONTENT_ID = "cid";
+
+ /**
+ * The content location of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CONTENT_LOCATION = "cl";
+
+ /**
+ * The start of content-type of the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String CT_START = "ctt_s";
+
+ /**
+ * The type of content-type of the message.
+ * <P>Type: TEXT</P>
+ */
+ public static final String CT_TYPE = "ctt_t";
+
+ /**
+ * The location(on filesystem) of the binary data of the part.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String _DATA = "_data";
+
+ public static final String TEXT = "text";
+
+ }
+
+ public static final class Rate {
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(
+ Mms.CONTENT_URI, "rate");
+ /**
+ * When a message was successfully sent.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String SENT_TIME = "sent_time";
+ }
+
+ public static final class ScrapSpace {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://mms/scrapSpace");
+
+ /**
+ * This is the scrap file we use to store the media attachment when the user
+ * chooses to capture a photo to be attached . We pass {#link@Uri} to the Camera app,
+ * which streams the captured image to the uri. Internally we write the media content
+ * to this file. It's named '.temp.jpg' so Gallery won't pick it up.
+ */
+ public static final String SCRAP_FILE_PATH = "/sdcard/mms/scrapSpace/.temp.jpg";
+ }
+
+ public static final class Intents {
+ private Intents() {
+ // Non-instantiatable.
+ }
+
+ /**
+ * The extra field to store the contents of the Intent,
+ * which should be an array of Uri.
+ */
+ public static final String EXTRA_CONTENTS = "contents";
+ /**
+ * The extra field to store the type of the contents,
+ * which should be an array of String.
+ */
+ public static final String EXTRA_TYPES = "types";
+ /**
+ * The extra field to store the 'Cc' addresses.
+ */
+ public static final String EXTRA_CC = "cc";
+ /**
+ * The extra field to store the 'Bcc' addresses;
+ */
+ public static final String EXTRA_BCC = "bcc";
+ /**
+ * The extra field to store the 'Subject'.
+ */
+ public static final String EXTRA_SUBJECT = "subject";
+ /**
+ * Indicates that the contents of specified URIs were changed.
+ * The application which is showing or caching these contents
+ * should be updated.
+ */
+ public static final String
+ CONTENT_CHANGED_ACTION = "android.intent.action.CONTENT_CHANGED";
+ /**
+ * An extra field which stores the URI of deleted contents.
+ */
+ public static final String DELETED_CONTENTS = "deleted_contents";
+ }
+ }
+
+ /**
+ * Contains all MMS and SMS messages.
+ */
+ public static final class MmsSms implements BaseColumns {
+ /**
+ * The column to distinguish SMS &amp; MMS messages in query results.
+ */
+ public static final String TYPE_DISCRIMINATOR_COLUMN =
+ "transport_type";
+
+ public static final Uri CONTENT_URI = Uri.parse("content://mms-sms/");
+
+ public static final Uri CONTENT_CONVERSATIONS_URI = Uri.parse(
+ "content://mms-sms/conversations");
+
+ public static final Uri CONTENT_FILTER_BYPHONE_URI = Uri.parse(
+ "content://mms-sms/messages/byphone");
+
+ public static final Uri CONTENT_UNDELIVERED_URI = Uri.parse(
+ "content://mms-sms/undelivered");
+
+ public static final Uri CONTENT_DRAFT_URI = Uri.parse(
+ "content://mms-sms/draft");
+
+ public static final Uri CONTENT_LOCKED_URI = Uri.parse(
+ "content://mms-sms/locked");
+
+ /***
+ * Pass in a query parameter called "pattern" which is the text
+ * to search for.
+ * The sort order is fixed to be thread_id ASC,date DESC.
+ */
+ public static final Uri SEARCH_URI = Uri.parse(
+ "content://mms-sms/search");
+
+ // Constants for message protocol types.
+ public static final int SMS_PROTO = 0;
+ public static final int MMS_PROTO = 1;
+
+ // Constants for error types of pending messages.
+ public static final int NO_ERROR = 0;
+ public static final int ERR_TYPE_GENERIC = 1;
+ public static final int ERR_TYPE_SMS_PROTO_TRANSIENT = 2;
+ public static final int ERR_TYPE_MMS_PROTO_TRANSIENT = 3;
+ public static final int ERR_TYPE_TRANSPORT_FAILURE = 4;
+ public static final int ERR_TYPE_GENERIC_PERMANENT = 10;
+ public static final int ERR_TYPE_SMS_PROTO_PERMANENT = 11;
+ public static final int ERR_TYPE_MMS_PROTO_PERMANENT = 12;
+
+ public static final class PendingMessages implements BaseColumns {
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(
+ MmsSms.CONTENT_URI, "pending");
+ /**
+ * The type of transport protocol(MMS or SMS).
+ * <P>Type: INTEGER</P>
+ */
+ public static final String PROTO_TYPE = "proto_type";
+ /**
+ * The ID of the message to be sent or downloaded.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MSG_ID = "msg_id";
+ /**
+ * The type of the message to be sent or downloaded.
+ * This field is only valid for MM. For SM, its value is always
+ * set to 0.
+ */
+ public static final String MSG_TYPE = "msg_type";
+ /**
+ * The type of the error code.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR_TYPE = "err_type";
+ /**
+ * The error code of sending/retrieving process.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR_CODE = "err_code";
+ /**
+ * How many times we tried to send or download the message.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String RETRY_INDEX = "retry_index";
+ /**
+ * The time to do next retry.
+ */
+ public static final String DUE_TIME = "due_time";
+ /**
+ * The time we last tried to send or download the message.
+ */
+ public static final String LAST_TRY = "last_try";
+ }
+ }
+
+ public static final class Carriers implements BaseColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://telephony/carriers");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "name ASC";
+
+ public static final String NAME = "name";
+
+ public static final String APN = "apn";
+
+ public static final String PROXY = "proxy";
+
+ public static final String PORT = "port";
+
+ public static final String MMSPROXY = "mmsproxy";
+
+ public static final String MMSPORT = "mmsport";
+
+ public static final String SERVER = "server";
+
+ public static final String USER = "user";
+
+ public static final String PASSWORD = "password";
+
+ public static final String MMSC = "mmsc";
+
+ public static final String MCC = "mcc";
+
+ public static final String MNC = "mnc";
+
+ public static final String NUMERIC = "numeric";
+
+ public static final String AUTH_TYPE = "authtype";
+
+ public static final String TYPE = "type";
+
+ public static final String CURRENT = "current";
+ }
+
+ public static final class Intents {
+ private Intents() {
+ // Not instantiable
+ }
+
+ /**
+ * Broadcast Action: A "secret code" has been entered in the dialer. Secret codes are
+ * of the form *#*#<code>#*#*. The intent will have the data URI:</p>
+ *
+ * <p><code>android_secret_code://&lt;code&gt;</code></p>
+ */
+ public static final String SECRET_CODE_ACTION =
+ "android.provider.Telephony.SECRET_CODE";
+
+ /**
+ * Broadcast Action: The Service Provider string(s) have been updated. Activities or
+ * services that use these strings should update their display.
+ * The intent will have the following extra values:</p>
+ * <ul>
+ * <li><em>showPlmn</em> - Boolean that indicates whether the PLMN should be shown.</li>
+ * <li><em>plmn</em> - The operator name of the registered network, as a string.</li>
+ * <li><em>showSpn</em> - Boolean that indicates whether the SPN should be shown.</li>
+ * <li><em>spn</em> - The service provider name, as a string.</li>
+ * </ul>
+ * Note that <em>showPlmn</em> may indicate that <em>plmn</em> should be displayed, even
+ * though the value for <em>plmn</em> is null. This can happen, for example, if the phone
+ * has not registered to a network yet. In this case the receiver may substitute an
+ * appropriate placeholder string (eg, "No service").
+ *
+ * It is recommended to display <em>plmn</em> before / above <em>spn</em> if
+ * both are displayed.
+ *
+ * <p>Note this is a protected intent that can only be sent
+ * by the system.
+ */
+ public static final String SPN_STRINGS_UPDATED_ACTION =
+ "android.provider.Telephony.SPN_STRINGS_UPDATED";
+
+ public static final String EXTRA_SHOW_PLMN = "showPlmn";
+ public static final String EXTRA_PLMN = "plmn";
+ public static final String EXTRA_SHOW_SPN = "showSpn";
+ public static final String EXTRA_SPN = "spn";
+ }
+}
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 01a9c913626f..30b9325e651e 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -48,6 +48,12 @@ public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
Buffer _pointSizePointerOES = null;
Buffer _matrixIndexPointerOES = null;
Buffer _weightPointerOES = null;
+
+ private boolean haveCheckedExtensions;
+ private boolean have_OES_blend_equation_separate;
+ private boolean have_OES_blend_subtract;
+ private boolean have_OES_framebuffer_object;
+ private boolean have_OES_texture_cube_map;
public GLImpl() {
}
@@ -1935,7 +1941,7 @@ public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
int target
);
- // C function void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers )
+ // C function void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers )
public native void glDeleteFramebuffersOES(
int n,
@@ -1943,14 +1949,14 @@ public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
int offset
);
- // C function void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers )
+ // C function void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers )
public native void glDeleteFramebuffersOES(
int n,
java.nio.IntBuffer framebuffers
);
- // C function void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers )
+ // C function void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers )
public native void glDeleteRenderbuffersOES(
int n,
@@ -1958,7 +1964,7 @@ public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
int offset
);
- // C function void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers )
+ // C function void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers )
public native void glDeleteRenderbuffersOES(
int n,
@@ -1990,7 +1996,7 @@ public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
int target
);
- // C function void glGenFramebuffersOES ( GLint n, GLint *framebuffers )
+ // C function void glGenFramebuffersOES ( GLint n, GLuint *framebuffers )
public native void glGenFramebuffersOES(
int n,
@@ -1998,14 +2004,14 @@ public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
int offset
);
- // C function void glGenFramebuffersOES ( GLint n, GLint *framebuffers )
+ // C function void glGenFramebuffersOES ( GLint n, GLuint *framebuffers )
public native void glGenFramebuffersOES(
int n,
java.nio.IntBuffer framebuffers
);
- // C function void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers )
+ // C function void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers )
public native void glGenRenderbuffersOES(
int n,
@@ -2013,7 +2019,7 @@ public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
int offset
);
- // C function void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers )
+ // C function void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers )
public native void glGenRenderbuffersOES(
int n,
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index c2e9f312e55a..6cb146c06094 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -29,7 +29,7 @@ LOCAL_CFLAGS += -DLOG_TAG=\"libagl\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_CFLAGS += -fvisibility=hidden
-LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger
+LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger libETC1
LOCAL_LDLIBS := -lpthread -ldl
ifeq ($(TARGET_ARCH),arm)
diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp
index 0f1f27d8cfb6..1224a96b9d2d 100644
--- a/opengl/libagl/state.cpp
+++ b/opengl/libagl/state.cpp
@@ -51,6 +51,9 @@ static char const * const gExtensionsString =
// "GL_OES_point_size_array " // TODO
// "GL_OES_point_sprite " // TODO
"GL_OES_EGL_image " // OK
+#ifdef GL_OES_compressed_ETC1_RGB8_texture
+ "GL_OES_compressed_ETC1_RGB8_texture " // OK
+#endif
"GL_ARB_texture_compression " // OK
"GL_ARB_texture_non_power_of_two " // OK
"GL_ANDROID_user_clip_plane " // OK
@@ -386,6 +389,7 @@ const GLubyte* glGetString(GLenum string)
void glGetIntegerv(GLenum pname, GLint *params)
{
+ int i;
ogles_context_t* c = ogles_context_t::get();
switch (pname) {
case GL_ALIASED_POINT_SIZE_RANGE:
@@ -431,6 +435,10 @@ void glGetIntegerv(GLenum pname, GLint *params)
params[ 7] = GL_PALETTE8_R5_G6_B5_OES;
params[ 8] = GL_PALETTE8_RGBA4_OES;
params[ 9] = GL_PALETTE8_RGB5_A1_OES;
+ i = 10;
+#ifdef GL_OES_compressed_ETC1_RGB8_texture
+ params[i++] = GL_ETC1_RGB8_OES;
+#endif
break;
case GL_DEPTH_BITS:
params[0] = c->rasterizer.state.buffers.depth.format ? 0 : 16;
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index 2875c1372157..a1a776f99029 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -24,6 +24,7 @@
#include "TextureObjectManager.h"
#include <private/ui/android_natives_priv.h>
+#include <ETC1/etc1.h>
#ifdef LIBAGL_USE_GRALLOC_COPYBITS
#include "copybit.h"
@@ -1081,11 +1082,6 @@ void glCompressedTexImage2D(
ogles_error(c, GL_INVALID_ENUM);
return;
}
- if ((internalformat < GL_PALETTE4_RGB8_OES ||
- internalformat > GL_PALETTE8_RGB5_A1_OES)) {
- ogles_error(c, GL_INVALID_ENUM);
- return;
- }
if (width<0 || height<0 || border!=0) {
ogles_error(c, GL_INVALID_VALUE);
return;
@@ -1121,6 +1117,12 @@ void glCompressedTexImage2D(
format = GL_RGBA;
type = GL_UNSIGNED_SHORT_5_5_5_1;
break;
+#ifdef GL_OES_compressed_ETC1_RGB8_texture
+ case GL_ETC1_RGB8_OES:
+ format = GL_RGB;
+ type = GL_UNSIGNED_BYTE;
+ break;
+#endif
default:
ogles_error(c, GL_INVALID_ENUM);
return;
@@ -1133,6 +1135,30 @@ void glCompressedTexImage2D(
int32_t size;
GGLSurface* surface;
+
+#ifdef GL_OES_compressed_ETC1_RGB8_texture
+ if (internalformat == GL_ETC1_RGB8_OES) {
+ GLsizei compressedSize = etc1_get_encoded_data_size(width, height);
+ if (compressedSize > imageSize) {
+ ogles_error(c, GL_INVALID_VALUE);
+ return;
+ }
+ int error = createTextureSurface(c, &surface, &size,
+ level, format, type, width, height);
+ if (error) {
+ ogles_error(c, error);
+ return;
+ }
+ if (etc1_decode_image(
+ (const etc1_byte*)data,
+ (etc1_byte*)surface->data,
+ width, height, 3, surface->stride*3) != 0) {
+ ogles_error(c, GL_INVALID_OPERATION);
+ }
+ return;
+ }
+#endif
+
// all mipmap levels are specified at once.
const int numLevels = level<0 ? -level : 1;
@@ -1389,9 +1415,20 @@ void glCopyTexImage2D(
// (x,y) is the lower-left corner of colorBuffer
y = cbSurface.height - (y + height);
+ /* The GLES spec says:
+ * If any of the pixels within the specified rectangle are outside
+ * the framebuffer associated with the current rendering context,
+ * then the values obtained for those pixels are undefined.
+ */
+ if (x+width > GLint(cbSurface.width))
+ width = cbSurface.width - x;
+
+ if (y+height > GLint(cbSurface.height))
+ height = cbSurface.height - y;
+
int err = copyPixels(c,
txSurface, 0, 0,
- cbSurface, x, y, cbSurface.width, cbSurface.height);
+ cbSurface, x, y, width, height);
if (err) {
ogles_error(c, err);
}
@@ -1439,6 +1476,17 @@ void glCopyTexSubImage2D(
const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
y = cbSurface.height - (y + height);
+ /* The GLES spec says:
+ * If any of the pixels within the specified rectangle are outside
+ * the framebuffer associated with the current rendering context,
+ * then the values obtained for those pixels are undefined.
+ */
+ if (x+width > GLint(cbSurface.width))
+ width = cbSurface.width - x;
+
+ if (y+height > GLint(cbSurface.height))
+ height = cbSurface.height - y;
+
int err = copyPixels(c,
surface, xoffset, yoffset,
cbSurface, x, y, width, height);
diff --git a/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack b/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
index ca9e6d2c5e3e..d6012d946936 100644
--- a/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
+++ b/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
@@ -7,14 +7,14 @@ void glBlendFuncSeparate ( GLint srcRGB, GLint dstRGB, GLint srcAlpha, GLint dst
GLint glCheckFramebufferStatusOES ( GLint target )
void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data )
void glCopyTexImage2D ( GLint target, GLint level, GLint internalformat, GLint x, GLint y, GLint width, GLint height, GLint border )
-void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers )
-void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers )
+void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers )
+void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers )
void glEnable ( GLint cap )
void glFramebufferRenderbufferOES ( GLint target, GLint attachment, GLint renderbuffertarget, GLint renderbuffer )
void glFramebufferTexture2DOES ( GLint target, GLint attachment, GLint textarget, GLint texture, GLint level )
void glGenerateMipmapOES ( GLint target )
-void glGenFramebuffersOES ( GLint n, GLint *framebuffers )
-void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers )
+void glGenFramebuffersOES ( GLint n, GLuint *framebuffers )
+void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers )
void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params )
void glGetIntegerv ( GLint pname, GLint *params )
void glGetRenderbufferParameterivOES ( GLint target, GLint pname, GLint *params )
diff --git a/opengl/tools/glgen/specs/jsr239/glspec-checks b/opengl/tools/glgen/specs/jsr239/glspec-checks
index c28e403002e9..9f8a793cc32f 100644
--- a/opengl/tools/glgen/specs/jsr239/glspec-checks
+++ b/opengl/tools/glgen/specs/jsr239/glspec-checks
@@ -29,28 +29,28 @@ glDrawTexfvOES check coords 5
glDrawTexivOES check coords 5
glDrawTexsvOES check coords 5
glDrawTexxvOES check coords 5
-glBindFramebufferOES unsupported
-glBindRenderbufferOES unsupported
-glBlendEquation unsupported
-glBlendEquationSeparate unsupported
-glBlendFuncSeparate unsupported
-glCheckFramebufferStatusOES unsupported return 0
-glDeleteFramebuffersOES unsupported
-glDeleteRenderbuffersOES unsupported
-glFramebufferRenderbufferOES unsupported
-glFramebufferStorageOES unsupported
-glFramebufferTexture2DOES unsupported
-glGenFramebuffersOES unsupported
-glGenRenderbuffersOES unsupported
-glGenerateMipmapOES unsupported
+glBindFramebufferOES requires OES_framebuffer_object
+glBindRenderbufferOES requires OES_framebuffer_object
+glBlendEquation requires OES_blend_subtract
+glBlendEquationSeparate requires OES_blend_equation_separate
+glBlendFuncSeparate requires OES_blend_equation_separate
+glCheckFramebufferStatusOES requires OES_framebuffer_object return 0
+glDeleteFramebuffersOES requires OES_framebuffer_object check framebuffers n
+glDeleteRenderbuffersOES requires OES_framebuffer_object check renderbuffers n
+glFramebufferRenderbufferOES requires OES_framebuffer_object
+glFramebufferStorageOES requires OES_framebuffer_object
+glFramebufferTexture2DOES requires OES_framebuffer_object
+glGenFramebuffersOES requires OES_framebuffer_object check framebuffers n
+glGenRenderbuffersOES requires OES_framebuffer_object check renderbuffers n
+glGenerateMipmapOES requires OES_framebuffer_object
+glGetFramebufferAttachmentParameterivOES requires OES_framebuffer_object
+glGetRenderbufferParameterivOES requires OES_framebuffer_object
+glIsFramebufferOES requires OES_framebuffer_object return JNI_FALSE
+glIsRenderbufferOES requires OES_framebuffer_object return JNI_FALSE
+glRenderbufferStorageOES requires OES_framebuffer_object
+glGetTexGen requires OES_texture_cube_map
+glTexGen requires OES_texture_cube_map
+glTexGenf requires OES_texture_cube_map
+glTexGeni requires OES_texture_cube_map
+glTexGenx requires OES_texture_cube_map
glGetBufferParameter unsupported
-glGetFramebufferAttachmentParameterivOES unsupported
-glGetRenderbufferParameterivOES unsupported
-glGetTexGen unsupported
-glIsFramebufferOES unsupported return JNI_FALSE
-glIsRenderbufferOES unsupported return JNI_FALSE
-glRenderbufferStorageOES unsupported return false
-glTexGen unsupported
-glTexGenf unsupported
-glTexGeni unsupported
-glTexGenx unsupported
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index e79170a28a8b..2db4e8d2e243 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -211,6 +211,8 @@ public class JniCodeEmitter {
index += 5;
} else if (checks[index].equals("unsupported")) {
index += 1;
+ } else if (checks[index].equals("requires")) {
+ index += 2;
} else if (checks[index].equals("nullAllowed")) {
return true;
} else {
@@ -243,6 +245,8 @@ public class JniCodeEmitter {
index += 5;
} else if (checks[index].equals("unsupported")) {
index += 1;
+ } else if (checks[index].equals("requires")) {
+ index += 2;
} else if (checks[index].equals("nullAllowed")) {
index += 1;
} else {
@@ -263,6 +267,8 @@ public class JniCodeEmitter {
while (index < checks.length) {
if (checks[index].equals("unsupported")) {
return true;
+ } else if (checks[index].equals("requires")) {
+ index += 2;
} else if (checks[index].equals("return")) {
index += 2;
} else if (checks[index].startsWith("check")) {
@@ -280,7 +286,34 @@ public class JniCodeEmitter {
}
return false;
}
-
+
+ String isRequiresFunc(CFunc cfunc) {
+ String[] checks = mChecker.getChecks(cfunc.getName());
+ int index = 1;
+ if (checks != null) {
+ while (index < checks.length) {
+ if (checks[index].equals("unsupported")) {
+ index += 1;
+ } else if (checks[index].equals("requires")) {
+ return checks[index+1];
+ } else if (checks[index].equals("return")) {
+ index += 2;
+ } else if (checks[index].startsWith("check")) {
+ index += 3;
+ } else if (checks[index].equals("ifcheck")) {
+ index += 5;
+ } else if (checks[index].equals("nullAllowed")) {
+ index += 1;
+ } else {
+ System.out.println("Error: unknown keyword \"" +
+ checks[index] + "\"");
+ System.exit(0);
+ }
+ }
+ }
+ return null;
+ }
+
void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
@@ -365,6 +398,9 @@ public class JniCodeEmitter {
} else if (checks[index].equals("unsupported")) {
// ignore
index += 1;
+ } else if (checks[index].equals("requires")) {
+ // ignore
+ index += 2;
} else if (checks[index].equals("nullAllowed")) {
// ignore
index += 1;
@@ -776,7 +812,23 @@ public class JniCodeEmitter {
out.println();
return;
}
-
+
+ String requiresExtension = isRequiresFunc(cfunc);
+ if (requiresExtension != null) {
+ out.println(indent +
+ "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
+ out.println(indent + indent +
+ "_env->ThrowNew(UOEClass,");
+ out.println(indent + indent +
+ " \"" + cfunc.getName() + "\");");
+ if (isVoid) {
+ out.println(indent + indent + " return;");
+ } else {
+ String retval = getErrorReturnValue(cfunc);
+ out.println(indent + indent + " return " + retval + ";");
+ }
+ out.println(indent + "}");
+ }
if (mUseContextPointer) {
out.println(indent +
"android::gl::ogles_context_t *ctx = getContext(_env, _this);");
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index b3d1c6cb1512..c2464b05626e 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -23,6 +23,23 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
+// Work around differences between the generated name and the actual name.
+
+#define glBlendEquation glBlendEquationOES
+#define glBlendEquationSeparate glBlendEquationSeparateOES
+#define glBlendFuncSeparate glBlendFuncSeparateOES
+#define glGetTexGenfv glGetTexGenfvOES
+#define glGetTexGeniv glGetTexGenivOES
+#define glGetTexGenxv glGetTexGenxvOES
+#define glTexGenf glTexGenfOES
+#define glTexGenfv glTexGenfvOES
+#define glTexGeni glTexGeniOES
+#define glTexGeniv glTexGenivOES
+#define glTexGenx glTexGenxOES
+#define glTexGenxv glTexGenxvOES
+
+
+
/* special calls implemented in Android's GLES wrapper used to more
* efficiently bound-check passed arrays */
extern "C" {
@@ -58,6 +75,11 @@ static jmethodID allowIndirectBuffersID;
static jfieldID positionID;
static jfieldID limitID;
static jfieldID elementSizeShiftID;
+static jfieldID haveCheckedExtensionsID;
+static jfieldID have_OES_blend_equation_separateID;
+static jfieldID have_OES_blend_subtractID;
+static jfieldID have_OES_framebuffer_objectID;
+static jfieldID have_OES_texture_cube_mapID;
/* Cache method IDs each time the class is loaded. */
@@ -72,6 +94,11 @@ nativeClassInitBuffer(JNIEnv *_env)
jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
+ haveCheckedExtensionsID = _env->GetFieldID(G11ImplClass, "haveCheckedExtensions", "Z");
+ have_OES_blend_equation_separateID = _env->GetFieldID(G11ImplClass, "have_OES_blend_equation_separate", "Z");
+ have_OES_blend_subtractID = _env->GetFieldID(G11ImplClass, "have_OES_blend_subtract", "Z");
+ have_OES_framebuffer_objectID = _env->GetFieldID(G11ImplClass, "have_OES_framebuffer_object", "Z");
+ have_OES_texture_cube_mapID = _env->GetFieldID(G11ImplClass, "have_OES_texture_cube_map", "Z");
getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
"getBasePointer", "(Ljava/nio/Buffer;)J");
@@ -193,5 +220,63 @@ getNumCompressedTextureFormats() {
return numCompressedTextureFormats;
}
+// Check if the extension at the head of pExtensions is pExtension. Note that pExtensions is
+// terminated by either 0 or space, while pExtension is terminated by 0.
+
+static bool
+extensionEqual(const GLubyte* pExtensions, const GLubyte* pExtension) {
+ while (true) {
+ char a = *pExtensions++;
+ char b = *pExtension++;
+ bool aEnd = a == '\0' || a == ' ';
+ bool bEnd = b == '\0';
+ if ( aEnd || bEnd) {
+ return aEnd == bEnd;
+ }
+ if ( a != b ) {
+ return false;
+ }
+ }
+}
+
+static const GLubyte*
+nextExtension(const GLubyte* pExtensions) {
+ while (true) {
+ char a = *pExtensions++;
+ if ( a == '\0') {
+ return pExtensions-1;
+ } else if ( a == ' ') {
+ return pExtensions;
+ }
+ }
+}
+
+static bool
+checkForExtension(const GLubyte* pExtensions, const GLubyte* pExtension) {
+ for (;*pExtensions != '\0'; pExtensions = nextExtension(pExtensions)) {
+ if (extensionEqual(pExtensions, pExtension)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+supportsExtension(JNIEnv *_env, jobject impl, jfieldID fieldId) {
+ if (!_env->GetBooleanField(impl, haveCheckedExtensionsID)) {
+ _env->SetBooleanField(impl, haveCheckedExtensionsID, true);
+ const GLubyte* sExtensions = glGetString(GL_EXTENSIONS);
+ _env->SetBooleanField(impl, have_OES_blend_equation_separateID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_equation_separate"));
+ _env->SetBooleanField(impl, have_OES_blend_subtractID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_subtract"));
+ _env->SetBooleanField(impl, have_OES_framebuffer_objectID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_framebuffer_object"));
+ _env->SetBooleanField(impl, have_OES_texture_cube_mapID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_texture_cube_map"));
+ }
+ return _env->GetBooleanField(impl, fieldId);
+}
+
// --------------------------------------------------------------------------
diff --git a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
index 76fea3f6a648..372710625e4c 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
+++ b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
@@ -47,6 +47,12 @@ public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
Buffer _pointSizePointerOES = null;
Buffer _matrixIndexPointerOES = null;
Buffer _weightPointerOES = null;
+
+ private boolean haveCheckedExtensions;
+ private boolean have_OES_blend_equation_separate;
+ private boolean have_OES_blend_subtract;
+ private boolean have_OES_framebuffer_object;
+ private boolean have_OES_texture_cube_map;
public GLImpl() {
}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index d36207bfdc31..d23b7d09e340 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -7,6 +7,7 @@ import android.net.Uri;
import android.os.Debug;
import android.os.IBinder;
import android.os.IMountService;
+import android.os.MountServiceResultCode;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
@@ -96,11 +97,13 @@ public class DefaultContainerService extends Service {
int errCode = CREATE_FAILED;
// Create new container
if ((newCachePath = createSdDir(packageURI, newCacheId, key)) != null) {
+ if (localLOGV) Log.i(TAG, "Created container for " + newCacheId
+ + " at path : " + newCachePath);
File resFile = new File(newCachePath, resFileName);
errCode = COPY_FAILED;
- if (localLOGV) Log.i(TAG, "Trying to copy " + codePath + " to " + resFile);
// Copy file from codePath
if (FileUtils.copyFile(new File(codePath), resFile)) {
+ if (localLOGV) Log.i(TAG, "Copied " + codePath + " to " + resFile);
errCode = FINALIZE_FAILED;
if (finalizeSdDir(newCacheId)) {
errCode = PASS;
@@ -115,18 +118,23 @@ public class DefaultContainerService extends Service {
break;
case COPY_FAILED:
errMsg = "COPY_FAILED";
+ if (localLOGV) Log.i(TAG, "Destroying " + newCacheId +
+ " at path " + newCachePath + " after " + errMsg);
destroySdDir(newCacheId);
break;
case FINALIZE_FAILED:
errMsg = "FINALIZE_FAILED";
+ if (localLOGV) Log.i(TAG, "Destroying " + newCacheId +
+ " at path " + newCachePath + " after " + errMsg);
destroySdDir(newCacheId);
break;
default:
errMsg = "PASS";
+ if (localLOGV) Log.i(TAG, "Unmounting " + newCacheId +
+ " at path " + newCachePath + " after " + errMsg);
unMountSdDir(newCacheId);
break;
}
- Log.i(TAG, "Status: " + errMsg);
if (errCode != PASS) {
return null;
}
@@ -143,47 +151,39 @@ public class DefaultContainerService extends Service {
if ((len - (mbLen * 1024 * 1024)) > 0) {
mbLen++;
}
- if (localLOGV) Log.i(TAG, "mbLen="+mbLen);
+ if (localLOGV) Log.i(TAG, "mbLen=" + mbLen);
String cachePath = null;
int ownerUid = Process.myUid();
try {
- cachePath = mountService.createSecureContainer(containerId,
- mbLen,
- "vfat", sdEncKey, ownerUid);
+ int rc = mountService.createSecureContainer(
+ containerId, mbLen, "vfat", sdEncKey, ownerUid);
+
+ if (rc != MountServiceResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format("Container creation failed (%d)", rc));
+
+ // XXX: This destroy should not be necessary
+ rc = mountService.destroySecureContainer(containerId);
+ if (rc != MountServiceResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format("Container creation-cleanup failed (%d)", rc));
+ return null;
+ }
+
+ // XXX: Does this ever actually succeed?
+ rc = mountService.createSecureContainer(
+ containerId, mbLen, "vfat", sdEncKey, ownerUid);
+ if (rc != MountServiceResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format("Container creation retry failed (%d)", rc));
+ }
+ }
+
+ cachePath = mountService.getSecureContainerPath(containerId);
if (localLOGV) Log.i(TAG, "Trying to create secure container for "
+ containerId + ", cachePath =" + cachePath);
return cachePath;
- } catch(IllegalStateException e) {
- Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
} catch(RemoteException e) {
- Log.e(TAG, "MounteService not running?");
+ Log.e(TAG, "MountService not running?");
return null;
}
- // TODO just fail here and let the user delete later on.
- try {
- mountService.destroySecureContainer(containerId);
- if (localLOGV) Log.i(TAG, "Destroying cache for " + containerId
- + ", cachePath =" + cachePath);
- } catch(IllegalStateException e) {
- Log.e(TAG, "Failed to destroy existing cache: " + e);
- return null;
- } catch(RemoteException e) {
- Log.e(TAG, "MounteService not running?");
- return null;
- }
- try {
- cachePath = mountService.createSecureContainer(containerId,
- mbLen,
- "vfat", sdEncKey, ownerUid);
- if (localLOGV) Log.i(TAG, "Trying to install again " + containerId
- + ", cachePath =" + cachePath);
- return cachePath;
- } catch(IllegalStateException e) {
- Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
- } catch(RemoteException e) {
- Log.e(TAG, "MounteService not running?");
- }
- return null;
}
private boolean destroySdDir(String containerId) {
@@ -194,7 +194,7 @@ public class DefaultContainerService extends Service {
} catch (IllegalStateException e) {
Log.i(TAG, "Failed to destroy container : " + containerId);
} catch(RemoteException e) {
- Log.e(TAG, "MounteService not running?");
+ Log.e(TAG, "MountService not running?");
}
return false;
}
@@ -206,7 +206,7 @@ public class DefaultContainerService extends Service {
} catch (IllegalStateException e) {
Log.i(TAG, "Failed to finalize container for pkg : " + containerId);
} catch(RemoteException e) {
- Log.e(TAG, "MounteService not running?");
+ Log.e(TAG, "MountService not running?");
}
return false;
}
@@ -218,19 +218,21 @@ public class DefaultContainerService extends Service {
} catch (IllegalStateException e) {
Log.e(TAG, "Failed to unmount id: " + containerId + " with exception " + e);
} catch(RemoteException e) {
- Log.e(TAG, "MounteService not running?");
+ Log.e(TAG, "MountService not running?");
}
return false;
}
private String mountSdDir(String containerId, String key) {
try {
- return getMountService().mountSecureContainer(containerId, key, Process.myUid());
- } catch (IllegalStateException e) {
- Log.e(TAG, "Failed to mount id: " +
- containerId + " with exception " + e);
+ int rc = getMountService().mountSecureContainer(containerId, key, Process.myUid());
+ if (rc == MountServiceResultCode.OperationSucceeded) {
+ return getMountService().getSecureContainerPath(containerId);
+ } else {
+ Log.e(TAG, String.format("Failed to mount id %s with rc %d ", containerId, rc));
+ }
} catch(RemoteException e) {
- Log.e(TAG, "MounteService not running?");
+ Log.e(TAG, "MountService not running?");
}
return null;
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 979955c2d941..015b4877e4f3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -71,7 +71,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 = 47;
+ private static final int DATABASE_VERSION = 48;
private Context mContext;
@@ -595,8 +595,23 @@ public class DatabaseHelper extends SQLiteOpenHelper {
upgradeVersion = 47;
}
+
+ if (upgradeVersion == 47) {
+ /*
+ * The password mode constants have changed again; reset back to no
+ * password.
+ */
+ db.beginTransaction();
+ try {
+ db.execSQL("DELETE FROM system WHERE name='lockscreen.password_type';");
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ upgradeVersion = 48;
+ }
- if (upgradeVersion != currentVersion) {
+ if (upgradeVersion != currentVersion) {
Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
+ ", must wipe the settings provider");
db.execSQL("DROP TABLE IF EXISTS system");
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 265d13864136..4080a6ae7632 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -17,9 +17,10 @@
package com.android.providers.settings;
import java.io.FileNotFoundException;
-import java.util.Random;
-import java.security.SecureRandom;
+import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Random;
import android.backup.BackupManager;
import android.content.ContentProvider;
@@ -197,6 +198,14 @@ public class SettingsProvider extends ContentProvider {
final String value = c.moveToNext() ? c.getString(0) : null;
if (value == null) {
final SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+ String serial = SystemProperties.get("ro.serialno");
+ if (serial != null) {
+ try {
+ random.setSeed(serial.getBytes("UTF-8"));
+ } catch (UnsupportedEncodingException ignore) {
+ // stick with default seed
+ }
+ }
final String newAndroidIdValue = Long.toHexString(random.nextLong());
Log.d(TAG, "Generated and saved new ANDROID_ID");
final ContentValues values = new ContentValues();
diff --git a/preloaded-classes b/preloaded-classes
index d108883a4782..0c849047af9c 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -686,10 +686,6 @@ com.android.internal.widget.Smileys
com.google.android.gles_jni.EGLDisplayImpl
com.google.android.gles_jni.EGLImpl
com.google.android.gles_jni.GLImpl
-com.google.android.mms.ContentType
-com.google.android.mms.pdu.CharacterSets
-com.google.android.mms.pdu.PduPart
-com.google.android.mms.pdu.PduPersister
com.ibm.icu4jni.charset.CharsetDecoderICU
com.ibm.icu4jni.charset.CharsetEncoderICU
com.ibm.icu4jni.charset.CharsetICU
diff --git a/sax/tests/saxtests/Android.mk b/sax/tests/saxtests/Android.mk
new file mode 100644
index 000000000000..836711b13dde
--- /dev/null
+++ b/sax/tests/saxtests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PACKAGE_NAME := FrameworksSaxTests
+
+include $(BUILD_PACKAGE)
+
diff --git a/sax/tests/saxtests/AndroidManifest.xml b/sax/tests/saxtests/AndroidManifest.xml
new file mode 100644
index 000000000000..c66844d819fd
--- /dev/null
+++ b/sax/tests/saxtests/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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.
+ 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.saxtests">
+ <uses-permission android:name="android.permission.RECEIVE_SMS"/>
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
+ <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
+ <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.frameworks.saxtests"
+ android:label="Frameworks Sax Tests" />
+</manifest>
diff --git a/tests/AndroidTests/res/raw/youtube.xml b/sax/tests/saxtests/res/raw/youtube.xml
index fedaeacc1669..fedaeacc1669 100644
--- a/tests/AndroidTests/res/raw/youtube.xml
+++ b/sax/tests/saxtests/res/raw/youtube.xml
diff --git a/tests/AndroidTests/src/com/android/unit_tests/ExpatPerformanceTest.java b/sax/tests/saxtests/src/android/sax/ExpatPerformanceTest.java
index 0d51047224e2..892c49052533 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/ExpatPerformanceTest.java
+++ b/sax/tests/saxtests/src/android/sax/ExpatPerformanceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.sax;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
@@ -31,6 +31,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import com.android.frameworks.saxtests.R;
+
public class ExpatPerformanceTest extends AndroidTestCase {
private static final String TAG = ExpatPerformanceTest.class.getSimpleName();
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SafeSaxTest.java b/sax/tests/saxtests/src/android/sax/SafeSaxTest.java
index 8ccd26e733c2..bee393863dfe 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SafeSaxTest.java
+++ b/sax/tests/saxtests/src/android/sax/SafeSaxTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.sax;
import android.graphics.Bitmap;
import android.sax.Element;
@@ -40,6 +40,8 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import com.android.frameworks.saxtests.R;
+
public class SafeSaxTest extends AndroidTestCase {
private static final String TAG = SafeSaxTest.class.getName();
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index f67a7aec48cc..b56b13b3fb0d 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -174,6 +174,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
packageFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
packageFilter.addDataScheme("package");
context.registerReceiver(broadcastReceiver, packageFilter);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(broadcastReceiver, sdFilter);
// boot completed
IntentFilter bootFiler = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 18a5615af44b..f3306513d815 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -772,16 +772,33 @@ class AlarmManagerService extends IAlarmManager.Stub {
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addDataScheme("package");
mContext.registerReceiver(this, filter);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(this, sdFilter);
}
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
- Uri data = intent.getData();
- if (data != null) {
- String pkg = data.getSchemeSpecificPart();
- removeLocked(pkg);
- mBroadcastStats.remove(pkg);
+ String action = intent.getAction();
+ String pkgList[] = null;
+ if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ } else {
+ Uri data = intent.getData();
+ if (data != null) {
+ String pkg = data.getSchemeSpecificPart();
+ if (pkg != null) {
+ pkgList = new String[]{pkg};
+ }
+ }
+ }
+ if (pkgList != null && (pkgList.length > 0)) {
+ for (String pkg : pkgList) {
+ removeLocked(pkg);
+ mBroadcastStats.remove(pkg);
+ }
}
}
}
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 8797a422ea04..684f117913ad 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -145,6 +145,11 @@ class AppWidgetService extends IAppWidgetService.Stub
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
mContext.registerReceiver(mBroadcastReceiver, filter);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(mBroadcastReceiver, sdFilter);
}
@Override
@@ -1070,36 +1075,55 @@ class AppWidgetService extends IAppWidgetService.Stub
}
}
} else {
- Uri uri = intent.getData();
- if (uri == null) {
- return;
+ boolean added = false;
+ String pkgList[] = null;
+ if (Intent.ACTION_MEDIA_RESOURCES_AVAILABLE.equals(action)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ added = true;
+ } if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ added = false;
+ } else {
+ Uri uri = intent.getData();
+ if (uri == null) {
+ return;
+ }
+ String pkgName = uri.getSchemeSpecificPart();
+ if (pkgName == null) {
+ return;
+ }
+ pkgList = new String[] { pkgName };
+ added = Intent.ACTION_PACKAGE_ADDED.equals(action);
}
- String pkgName = uri.getSchemeSpecificPart();
- if (pkgName == null) {
+ if (pkgList == null || pkgList.length == 0) {
return;
}
-
- if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ if (added) {
synchronized (mAppWidgetIds) {
Bundle extras = intent.getExtras();
if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
- // The package was just upgraded
- updateProvidersForPackageLocked(pkgName);
+ for (String pkgName : pkgList) {
+ // The package was just upgraded
+ updateProvidersForPackageLocked(pkgName);
+ }
} else {
// The package was just added
- addProvidersForPackageLocked(pkgName);
+ for (String pkgName : pkgList) {
+ addProvidersForPackageLocked(pkgName);
+ }
}
saveStateLocked();
}
- }
- else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ } else {
Bundle extras = intent.getExtras();
if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
// The package is being updated. We'll receive a PACKAGE_ADDED shortly.
} else {
synchronized (mAppWidgetIds) {
- removeProvidersForPackageLocked(pkgName);
- saveStateLocked();
+ for (String pkgName : pkgList) {
+ removeProvidersForPackageLocked(pkgName);
+ saveStateLocked();
+ }
}
}
}
@@ -1107,10 +1131,9 @@ class AppWidgetService extends IAppWidgetService.Stub
}
};
- // TODO: If there's a better way of matching an intent filter against the
- // packages for a given package, use that.
void addProvidersForPackageLocked(String pkgName) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
+ intent.setPackage(pkgName);
List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
PackageManager.GET_META_DATA);
@@ -1125,11 +1148,10 @@ class AppWidgetService extends IAppWidgetService.Stub
}
}
- // TODO: If there's a better way of matching an intent filter against the
- // packages for a given package, use that.
void updateProvidersForPackageLocked(String pkgName) {
HashSet<String> keep = new HashSet<String>();
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
+ intent.setPackage(pkgName);
List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
PackageManager.GET_META_DATA);
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 72e26f8775ae..0562c5535a13 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -43,18 +43,20 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.provider.Settings;
import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import com.android.internal.backup.BackupConstants;
import com.android.internal.backup.IBackupTransport;
@@ -98,20 +100,27 @@ class BackupManagerService extends IBackupManager.Stub {
private static final int MSG_RUN_RESTORE = 3;
private static final int MSG_RUN_CLEAR = 4;
private static final int MSG_RUN_INITIALIZE = 5;
+ private static final int MSG_TIMEOUT = 6;
// Timeout interval for deciding that a bind or clear-data has taken too long
static final long TIMEOUT_INTERVAL = 10 * 1000;
+ // Timeout intervals for agent backup & restore operations
+ static final long TIMEOUT_BACKUP_INTERVAL = 30 * 1000;
+ static final long TIMEOUT_RESTORE_INTERVAL = 60 * 1000;
+
private Context mContext;
private PackageManager mPackageManager;
private IActivityManager mActivityManager;
private PowerManager mPowerManager;
private AlarmManager mAlarmManager;
+ IBackupManager mBackupManagerBinder;
boolean mEnabled; // access to this is synchronized on 'this'
boolean mProvisioned;
PowerManager.WakeLock mWakelock;
- final BackupHandler mBackupHandler = new BackupHandler();
+ HandlerThread mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
+ BackupHandler mBackupHandler;
PendingIntent mRunBackupIntent, mRunInitIntent;
BroadcastReceiver mRunBackupReceiver, mRunInitReceiver;
// map UIDs to the set of backup client services within that UID's app set
@@ -148,7 +157,6 @@ class BackupManagerService extends IBackupManager.Stub {
final Object mAgentConnectLock = new Object();
IBackupAgent mConnectedAgent;
volatile boolean mConnecting;
- volatile boolean mBackupOrRestoreInProgress = false;
volatile long mLastBackupPass;
volatile long mNextBackupPass;
@@ -185,6 +193,16 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
+ // Bookkeeping of in-flight operations for timeout etc. purposes. The operation
+ // token is the index of the entry in the pending-operations list.
+ static final int OP_PENDING = 0;
+ static final int OP_ACKNOWLEDGED = 1;
+ static final int OP_TIMEOUT = -1;
+
+ final SparseIntArray mCurrentOperations = new SparseIntArray();
+ final Object mCurrentOpLock = new Object();
+ final Random mTokenGenerator = new Random();
+
// Where we keep our journal files and other bookkeeping
File mBaseStateDir;
File mDataDir;
@@ -198,7 +216,109 @@ class BackupManagerService extends IBackupManager.Stub {
// Persistently track the need to do a full init
static final String INIT_SENTINEL_FILE_NAME = "_need_init_";
HashSet<String> mPendingInits = new HashSet<String>(); // transport names
- volatile boolean mInitInProgress = false;
+
+ // ----- Asynchronous backup/restore handler thread -----
+
+ private class BackupHandler extends Handler {
+ public BackupHandler(Looper looper) {
+ super(looper);
+ }
+
+ public void handleMessage(Message msg) {
+
+ switch (msg.what) {
+ case MSG_RUN_BACKUP:
+ {
+ mLastBackupPass = System.currentTimeMillis();
+ mNextBackupPass = mLastBackupPass + BACKUP_INTERVAL;
+
+ IBackupTransport transport = getTransport(mCurrentTransport);
+ if (transport == null) {
+ Log.v(TAG, "Backup requested but no transport available");
+ mWakelock.release();
+ break;
+ }
+
+ // snapshot the pending-backup set and work on that
+ ArrayList<BackupRequest> queue = new ArrayList<BackupRequest>();
+ synchronized (mQueueLock) {
+ // Do we have any work to do?
+ if (mPendingBackups.size() > 0) {
+ for (BackupRequest b: mPendingBackups.values()) {
+ queue.add(b);
+ }
+ if (DEBUG) Log.v(TAG, "clearing pending backups");
+ mPendingBackups.clear();
+
+ // Start a new backup-queue journal file too
+ File oldJournal = mJournal;
+ mJournal = null;
+
+ // At this point, we have started a new journal file, and the old
+ // file identity is being passed to the backup processing thread.
+ // When it completes successfully, that old journal file will be
+ // deleted. If we crash prior to that, the old journal is parsed
+ // at next boot and the journaled requests fulfilled.
+ (new PerformBackupTask(transport, queue, oldJournal)).run();
+ } else {
+ Log.v(TAG, "Backup requested but nothing pending");
+ mWakelock.release();
+ }
+ }
+ break;
+ }
+
+ case MSG_RUN_FULL_BACKUP:
+ break;
+
+ case MSG_RUN_RESTORE:
+ {
+ RestoreParams params = (RestoreParams)msg.obj;
+ Log.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
+ (new PerformRestoreTask(params.transport, params.observer,
+ params.token)).run();
+ break;
+ }
+
+ case MSG_RUN_CLEAR:
+ {
+ ClearParams params = (ClearParams)msg.obj;
+ (new PerformClearTask(params.transport, params.packageInfo)).run();
+ break;
+ }
+
+ case MSG_RUN_INITIALIZE:
+ {
+ HashSet<String> queue;
+
+ // Snapshot the pending-init queue and work on that
+ synchronized (mQueueLock) {
+ queue = new HashSet<String>(mPendingInits);
+ mPendingInits.clear();
+ }
+
+ (new PerformInitializeTask(queue)).run();
+ break;
+ }
+
+ case MSG_TIMEOUT:
+ {
+ synchronized (mCurrentOpLock) {
+ final int token = msg.arg1;
+ int state = mCurrentOperations.get(token, OP_TIMEOUT);
+ if (state == OP_PENDING) {
+ if (DEBUG) Log.v(TAG, "TIMEOUT: token=" + token);
+ mCurrentOperations.put(token, OP_TIMEOUT);
+ }
+ mCurrentOpLock.notifyAll();
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // ----- Main service implementation -----
public BackupManagerService(Context context) {
mContext = context;
@@ -208,6 +328,13 @@ class BackupManagerService extends IBackupManager.Stub {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mBackupManagerBinder = asInterface(asBinder());
+
+ // spin up the backup/restore handler thread
+ mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
+ mHandlerThread.start();
+ mBackupHandler = new BackupHandler(mHandlerThread.getLooper());
+
// Set up our bookkeeping
boolean areEnabled = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.BACKUP_ENABLED, 0) != 0;
@@ -305,13 +432,10 @@ class BackupManagerService extends IBackupManager.Stub {
// can't really do more than bail here
}
} else {
- // Don't run backups now if we're disabled, not yet
- // fully set up, in the middle of a backup already,
- // or racing with an initialize pass.
- if (mEnabled && mProvisioned
- && !mBackupOrRestoreInProgress && !mInitInProgress) {
+ // Don't run backups now if we're disabled or not yet
+ // fully set up.
+ if (mEnabled && mProvisioned) {
if (DEBUG) Log.v(TAG, "Running a backup pass");
- mBackupOrRestoreInProgress = true;
// Acquire the wakelock and pass it to the backup thread. it will
// be released once backup concludes.
@@ -320,8 +444,7 @@ class BackupManagerService extends IBackupManager.Stub {
Message msg = mBackupHandler.obtainMessage(MSG_RUN_BACKUP);
mBackupHandler.sendMessage(msg);
} else {
- Log.w(TAG, "Backup pass but e=" + mEnabled + " p=" + mProvisioned
- + " b=" + mBackupOrRestoreInProgress + " i=" + mInitInProgress);
+ Log.w(TAG, "Backup pass but e=" + mEnabled + " p=" + mProvisioned);
}
}
}
@@ -334,7 +457,6 @@ class BackupManagerService extends IBackupManager.Stub {
if (RUN_INITIALIZE_ACTION.equals(intent.getAction())) {
synchronized (mQueueLock) {
if (DEBUG) Log.v(TAG, "Running a device init");
- mInitInProgress = true;
// Acquire the wakelock and pass it to the init thread. it will
// be released once init concludes.
@@ -407,6 +529,11 @@ class BackupManagerService extends IBackupManager.Stub {
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
mContext.registerReceiver(mBroadcastReceiver, filter);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(mBroadcastReceiver, sdFilter);
}
private void parseLeftoverJournals() {
@@ -506,7 +633,7 @@ class BackupManagerService extends IBackupManager.Stub {
mTransports.put(name, transport);
} else {
mTransports.remove(name);
- if (mCurrentTransport.equals(name)) {
+ if ((mCurrentTransport != null) && mCurrentTransport.equals(name)) {
mCurrentTransport = null;
}
// Nothing further to do in the unregistration case
@@ -543,35 +670,53 @@ class BackupManagerService extends IBackupManager.Stub {
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.d(TAG, "Received broadcast " + intent);
- Uri uri = intent.getData();
- if (uri == null) {
- return;
+ String action = intent.getAction();
+ boolean replacing = false;
+ boolean added = false;
+ Bundle extras = intent.getExtras();
+ String pkgList[] = null;
+ if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
+ Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ Uri uri = intent.getData();
+ if (uri == null) {
+ return;
+ }
+ String pkgName = uri.getSchemeSpecificPart();
+ if (pkgName != null) {
+ pkgList = new String[] { pkgName };
+ }
+ added = Intent.ACTION_PACKAGE_ADDED.equals(action);
+ replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
+ } else if (Intent.ACTION_MEDIA_RESOURCES_AVAILABLE.equals(action)) {
+ added = true;
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ } else if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
+ added = false;
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
}
- String pkgName = uri.getSchemeSpecificPart();
- if (pkgName == null) {
+ if (pkgList == null || pkgList.length == 0) {
return;
}
-
- String action = intent.getAction();
- if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ if (added) {
synchronized (mBackupParticipants) {
- Bundle extras = intent.getExtras();
- if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
- // The package was just upgraded
- updatePackageParticipantsLocked(pkgName);
- } else {
- // The package was just added
- addPackageParticipantsLocked(pkgName);
+ for (String pkgName : pkgList) {
+ if (replacing) {
+ // The package was just upgraded
+ updatePackageParticipantsLocked(pkgName);
+ } else {
+ // The package was just added
+ addPackageParticipantsLocked(pkgName);
+ }
}
}
- }
- else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
- Bundle extras = intent.getExtras();
- if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
+ } else {
+ if (replacing) {
// The package is being updated. We'll receive a PACKAGE_ADDED shortly.
} else {
synchronized (mBackupParticipants) {
- removePackageParticipantsLocked(pkgName);
+ for (String pkgName : pkgList) {
+ removePackageParticipantsLocked(pkgName);
+ }
}
}
}
@@ -593,95 +738,6 @@ class BackupManagerService extends IBackupManager.Stub {
}
};
- // ----- Run the actual backup process asynchronously -----
-
- private class BackupHandler extends Handler {
- public void handleMessage(Message msg) {
-
- switch (msg.what) {
- case MSG_RUN_BACKUP:
- {
- mLastBackupPass = System.currentTimeMillis();
- mNextBackupPass = mLastBackupPass + BACKUP_INTERVAL;
-
- IBackupTransport transport = getTransport(mCurrentTransport);
- if (transport == null) {
- Log.v(TAG, "Backup requested but no transport available");
- synchronized (mQueueLock) {
- mBackupOrRestoreInProgress = false;
- }
- mWakelock.release();
- break;
- }
-
- // snapshot the pending-backup set and work on that
- ArrayList<BackupRequest> queue = new ArrayList<BackupRequest>();
- synchronized (mQueueLock) {
- // Do we have any work to do?
- if (mPendingBackups.size() > 0) {
- for (BackupRequest b: mPendingBackups.values()) {
- queue.add(b);
- }
- Log.v(TAG, "clearing pending backups");
- mPendingBackups.clear();
-
- // Start a new backup-queue journal file too
- File oldJournal = mJournal;
- mJournal = null;
-
- // At this point, we have started a new journal file, and the old
- // file identity is being passed to the backup processing thread.
- // When it completes successfully, that old journal file will be
- // deleted. If we crash prior to that, the old journal is parsed
- // at next boot and the journaled requests fulfilled.
- (new PerformBackupThread(transport, queue, oldJournal)).start();
- } else {
- Log.v(TAG, "Backup requested but nothing pending");
- synchronized (mQueueLock) {
- mBackupOrRestoreInProgress = false;
- }
- mWakelock.release();
- }
- }
- break;
- }
-
- case MSG_RUN_FULL_BACKUP:
- break;
-
- case MSG_RUN_RESTORE:
- {
- RestoreParams params = (RestoreParams)msg.obj;
- Log.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
- (new PerformRestoreThread(params.transport, params.observer,
- params.token)).start();
- break;
- }
-
- case MSG_RUN_CLEAR:
- {
- ClearParams params = (ClearParams)msg.obj;
- (new PerformClearThread(params.transport, params.packageInfo)).start();
- break;
- }
-
- case MSG_RUN_INITIALIZE:
- {
- HashSet<String> queue;
-
- // Snapshot the pending-init queue and work on that
- synchronized (mQueueLock) {
- queue = new HashSet<String>(mPendingInits);
- mPendingInits.clear();
- }
-
- (new PerformInitializeThread(queue)).start();
- break;
- }
- }
- }
- }
-
// Add the backup agents in the given package to our set of known backup participants.
// If 'packageName' is null, adds all backup agents in the whole system.
void addPackageParticipantsLocked(String packageName) {
@@ -978,16 +1034,44 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
+ // -----
+ // Utility methods used by the asynchronous-with-timeout backup/restore operations
+ boolean waitUntilOperationComplete(int token) {
+ int finalState = OP_PENDING;
+ synchronized (mCurrentOpLock) {
+ try {
+ while ((finalState = mCurrentOperations.get(token, OP_TIMEOUT)) == OP_PENDING) {
+ try {
+ mCurrentOpLock.wait();
+ } catch (InterruptedException e) {}
+ }
+ } catch (IndexOutOfBoundsException e) {
+ // the operation has been mysteriously cleared from our
+ // bookkeeping -- consider this a success and ignore it.
+ }
+ }
+ mBackupHandler.removeMessages(MSG_TIMEOUT);
+ if (DEBUG) Log.v(TAG, "operation " + token + " complete: finalState=" + finalState);
+ return finalState == OP_ACKNOWLEDGED;
+ }
+
+ void prepareOperationTimeout(int token, long interval) {
+ if (DEBUG) Log.v(TAG, "starting timeout: token=" + token + " interval=" + interval);
+ mCurrentOperations.put(token, OP_PENDING);
+ Message msg = mBackupHandler.obtainMessage(MSG_TIMEOUT, token, 0);
+ mBackupHandler.sendMessageDelayed(msg, interval);
+ }
+
// ----- Back up a set of applications via a worker thread -----
- class PerformBackupThread extends Thread {
+ class PerformBackupTask implements Runnable {
private static final String TAG = "PerformBackupThread";
IBackupTransport mTransport;
ArrayList<BackupRequest> mQueue;
File mStateDir;
File mJournal;
- public PerformBackupThread(IBackupTransport transport, ArrayList<BackupRequest> queue,
+ public PerformBackupTask(IBackupTransport transport, ArrayList<BackupRequest> queue,
File journal) {
mTransport = transport;
mQueue = queue;
@@ -1000,7 +1084,6 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
- @Override
public void run() {
int status = BackupConstants.TRANSPORT_OK;
long startRealtime = SystemClock.elapsedRealtime();
@@ -1060,7 +1143,7 @@ class BackupManagerService extends IBackupManager.Stub {
if (status == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
// The backend reports that our dataset has been wiped. We need to
// reset all of our bookkeeping and instead run a new backup pass for
- // everything. This must come after mBackupOrRestoreInProgress is cleared.
+ // everything.
EventLog.writeEvent(EventLogTags.BACKUP_RESET, mTransport.transportDirName());
resetBackupState(mStateDir);
}
@@ -1093,14 +1176,8 @@ class BackupManagerService extends IBackupManager.Stub {
Log.e(TAG, "Unable to remove backup journal file " + mJournal);
}
- // Only once we're entirely finished do we indicate our completion
- // and release the wakelock
- synchronized (mQueueLock) {
- mBackupOrRestoreInProgress = false;
- }
-
+ // Only once we're entirely finished do we release the wakelock
if (status == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
- // This must come after mBackupOrRestoreInProgress is cleared.
backupNow();
}
@@ -1158,6 +1235,7 @@ class BackupManagerService extends IBackupManager.Stub {
ParcelFileDescriptor newState = null;
PackageInfo packInfo;
+ int token = mTokenGenerator.nextInt();
try {
// Look up the package info & signatures. This is first so that if it
// throws an exception, there's no file setup yet that would need to
@@ -1189,8 +1267,16 @@ class BackupManagerService extends IBackupManager.Stub {
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE);
- // Run the target's backup pass
- agent.doBackup(savedState, backupData, newState);
+ // Initiate the target's backup pass
+ prepareOperationTimeout(token, TIMEOUT_BACKUP_INTERVAL);
+ agent.doBackup(savedState, backupData, newState, token, mBackupManagerBinder);
+ boolean success = waitUntilOperationComplete(token);
+
+ if (!success) {
+ // timeout -- bail out into the failed-transaction logic
+ throw new RuntimeException("Backup timeout");
+ }
+
logBackupComplete(packageName);
if (DEBUG) Log.v(TAG, "doBackup() success");
} catch (Exception e) {
@@ -1204,6 +1290,9 @@ class BackupManagerService extends IBackupManager.Stub {
try { if (backupData != null) backupData.close(); } catch (IOException e) {}
try { if (newState != null) newState.close(); } catch (IOException e) {}
savedState = backupData = newState = null;
+ synchronized (mCurrentOpLock) {
+ mCurrentOperations.clear();
+ }
}
// Now propagate the newly-backed-up data to the transport
@@ -1299,7 +1388,7 @@ class BackupManagerService extends IBackupManager.Stub {
return true;
}
- class PerformRestoreThread extends Thread {
+ class PerformRestoreTask implements Runnable {
private IBackupTransport mTransport;
private IRestoreObserver mObserver;
private long mToken;
@@ -1315,7 +1404,7 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
- PerformRestoreThread(IBackupTransport transport, IRestoreObserver observer,
+ PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer,
long restoreSetToken) {
mTransport = transport;
Log.d(TAG, "PerformRestoreThread mObserver=" + mObserver);
@@ -1329,7 +1418,6 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
- @Override
public void run() {
long startRealtime = SystemClock.elapsedRealtime();
if (DEBUG) Log.v(TAG, "Beginning restore process mTransport=" + mTransport
@@ -1551,9 +1639,6 @@ class BackupManagerService extends IBackupManager.Stub {
}
// done; we can finally release the wakelock
- synchronized (mQueueLock) {
- mBackupOrRestoreInProgress = false;
- }
mWakelock.release();
}
}
@@ -1579,6 +1664,7 @@ class BackupManagerService extends IBackupManager.Stub {
ParcelFileDescriptor backupData = null;
ParcelFileDescriptor newState = null;
+ int token = mTokenGenerator.nextInt();
try {
// Run the transport's restore pass
backupData = ParcelFileDescriptor.open(backupDataName,
@@ -1602,7 +1688,14 @@ class BackupManagerService extends IBackupManager.Stub {
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE);
- agent.doRestore(backupData, appVersionCode, newState);
+ // Kick off the restore, checking for hung agents
+ prepareOperationTimeout(token, TIMEOUT_RESTORE_INTERVAL);
+ agent.doRestore(backupData, appVersionCode, newState, token, mBackupManagerBinder);
+ boolean success = waitUntilOperationComplete(token);
+
+ if (!success) {
+ throw new RuntimeException("restore timeout");
+ }
// if everything went okay, remember the recorded state now
//
@@ -1635,20 +1728,20 @@ class BackupManagerService extends IBackupManager.Stub {
try { if (backupData != null) backupData.close(); } catch (IOException e) {}
try { if (newState != null) newState.close(); } catch (IOException e) {}
backupData = newState = null;
+ mCurrentOperations.delete(token);
}
}
}
- class PerformClearThread extends Thread {
+ class PerformClearTask implements Runnable {
IBackupTransport mTransport;
PackageInfo mPackage;
- PerformClearThread(IBackupTransport transport, PackageInfo packageInfo) {
+ PerformClearTask(IBackupTransport transport, PackageInfo packageInfo) {
mTransport = transport;
mPackage = packageInfo;
}
- @Override
public void run() {
try {
// Clear the on-device backup state to ensure a full backup next time
@@ -1670,22 +1763,18 @@ class BackupManagerService extends IBackupManager.Stub {
}
// Last but not least, release the cpu
- synchronized (mQueueLock) {
- mBackupOrRestoreInProgress = false;
- }
mWakelock.release();
}
}
}
- class PerformInitializeThread extends Thread {
+ class PerformInitializeTask implements Runnable {
HashSet<String> mQueue;
- PerformInitializeThread(HashSet<String> transportNames) {
+ PerformInitializeTask(HashSet<String> transportNames) {
mQueue = transportNames;
}
- @Override
public void run() {
try {
for (String transportName : mQueue) {
@@ -1735,10 +1824,7 @@ class BackupManagerService extends IBackupManager.Stub {
} catch (Exception e) {
Log.e(TAG, "Unexpected error performing init", e);
} finally {
- // Done; indicate that we're finished and release the wakelock
- synchronized (mQueueLock) {
- mInitInProgress = false;
- }
+ // Done; release the wakelock
mWakelock.release();
}
}
@@ -2073,6 +2159,16 @@ class BackupManagerService extends IBackupManager.Stub {
return mActiveRestoreSession;
}
+ // Note that a currently-active backup agent has notified us that it has
+ // completed the given outstanding asynchronous backup/restore operation.
+ public void opComplete(int token) {
+ synchronized (mCurrentOpLock) {
+ if (DEBUG) Log.v(TAG, "opComplete: " + token);
+ mCurrentOperations.put(token, OP_ACKNOWLEDGED);
+ mCurrentOpLock.notifyAll();
+ }
+ }
+
// ----- Restore session -----
class ActiveRestoreSession extends IRestoreSession.Stub {
@@ -2119,16 +2215,9 @@ class BackupManagerService extends IBackupManager.Stub {
}
synchronized (mQueueLock) {
- if (mBackupOrRestoreInProgress) {
- Log.e(TAG, "Backup pass in progress, restore aborted");
- return -1;
- }
-
for (int i = 0; i < mRestoreSets.length; i++) {
if (token == mRestoreSets[i].token) {
long oldId = Binder.clearCallingIdentity();
- // Suppress backups until the restore operation is finished
- mBackupOrRestoreInProgress = true;
mWakelock.acquire();
Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
msg.obj = new RestoreParams(mRestoreTransport, observer, token);
@@ -2175,9 +2264,7 @@ class BackupManagerService extends IBackupManager.Stub {
synchronized (mQueueLock) {
pw.println("Backup Manager is " + (mEnabled ? "enabled" : "disabled")
+ " / " + (!mProvisioned ? "not " : "") + "provisioned / "
- + (!mBackupOrRestoreInProgress ? "not " : "") + "in progress / "
- + (this.mPendingInits.size() == 0 ? "not " : "") + "pending init / "
- + (!mInitInProgress ? "not " : "") + "initializing");
+ + (this.mPendingInits.size() == 0 ? "not " : "") + "pending init");
pw.println("Last backup pass: " + mLastBackupPass
+ " (now = " + System.currentTimeMillis() + ')');
pw.println(" next scheduled: " + mNextBackupPass);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 0aad05681193..aa4956f1573e 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -828,12 +828,15 @@ public class ConnectivityService extends IConnectivityManager.Stub {
info.getExtraInfo());
}
- NetworkStateTracker newNet = tryFailover(prevNetType);
- if (newNet != null) {
- NetworkInfo switchTo = newNet.getNetworkInfo();
- intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
- } else {
- intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
+ NetworkStateTracker newNet = null;
+ if (mNetAttributes[prevNetType].isDefault()) {
+ newNet = tryFailover(prevNetType);
+ if (newNet != null) {
+ NetworkInfo switchTo = newNet.getNetworkInfo();
+ intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
+ } else {
+ intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
+ }
}
// do this before we broadcast the change
handleConnectivityChange();
@@ -848,7 +851,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
- // returns -1 if no failover available
+ // returns null if no failover available
private NetworkStateTracker tryFailover(int prevNetType) {
/*
* If this is a default network, check if other defaults are available
@@ -970,13 +973,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
info.setFailover(false);
}
- NetworkStateTracker newNet = tryFailover(info.getType());
- if (newNet != null) {
- NetworkInfo switchTo = newNet.getNetworkInfo();
- intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
- } else {
- intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
+ NetworkStateTracker newNet = null;
+ if (mNetAttributes[info.getType()].isDefault()) {
+ newNet = tryFailover(info.getType());
+ if (newNet != null) {
+ NetworkInfo switchTo = newNet.getNetworkInfo();
+ intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
+ } else {
+ intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
+ }
}
+
// do this before we broadcast the change
handleConnectivityChange();
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 17a3ab847f81..e4ee4aee9f14 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -64,7 +64,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
IPowerManager mIPowerManager;
- int mActivePasswordMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+ int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
int mActivePasswordLength = 0;
int mFailedPasswordAttempts = 0;
@@ -76,7 +76,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
static class ActiveAdmin {
final DeviceAdminInfo info;
- int passwordMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+ int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
int minimumPasswordLength = 0;
long maximumTimeToUnlock = 0;
int maximumFailedPasswordsForWipe = 0;
@@ -89,17 +89,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
void writeToXml(XmlSerializer out)
throws IllegalArgumentException, IllegalStateException, IOException {
- if (passwordMode != DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED) {
- out.startTag(null, "password-mode");
- out.attribute(null, "value", Integer.toString(passwordMode));
- out.endTag(null, "password-mode");
+ if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+ out.startTag(null, "password-quality");
+ out.attribute(null, "value", Integer.toString(passwordQuality));
+ out.endTag(null, "password-quality");
if (minimumPasswordLength > 0) {
out.startTag(null, "min-password-length");
out.attribute(null, "value", Integer.toString(minimumPasswordLength));
out.endTag(null, "mn-password-length");
}
}
- if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED) {
+ if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
out.startTag(null, "max-time-to-unlock");
out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
out.endTag(null, "max-time-to-unlock");
@@ -121,8 +121,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
continue;
}
String tag = parser.getName();
- if ("password-mode".equals(tag)) {
- passwordMode = Integer.parseInt(
+ if ("password-quality".equals(tag)) {
+ passwordQuality = Integer.parseInt(
parser.getAttributeValue(null, "value"));
} else if ("min-password-length".equals(tag)) {
minimumPasswordLength = Integer.parseInt(
@@ -435,34 +435,34 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setPasswordMode(ComponentName who, int mode) {
+ public void setPasswordQuality(ComponentName who, int mode) {
synchronized (this) {
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
- if (ap.passwordMode != mode) {
- ap.passwordMode = mode;
+ if (ap.passwordQuality != mode) {
+ ap.passwordQuality = mode;
saveSettingsLocked();
}
}
}
- public int getPasswordMode(ComponentName who) {
+ public int getPasswordQuality(ComponentName who) {
synchronized (this) {
- int mode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
+ int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
- return admin != null ? admin.passwordMode : mode;
+ return admin != null ? admin.passwordQuality : mode;
}
final int N = mAdminList.size();
for (int i=0; i<N; i++) {
ActiveAdmin admin = mAdminList.get(i);
- if (mode < admin.passwordMode) {
- mode = admin.passwordMode;
+ if (mode < admin.passwordQuality) {
+ mode = admin.passwordQuality;
}
}
return mode;
@@ -509,7 +509,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
- return mActivePasswordMode >= getPasswordMode(null)
+ return mActivePasswordQuality >= getPasswordQuality(null)
&& mActivePasswordLength >= getPasswordMinimumLength(null);
}
}
@@ -563,14 +563,24 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
public boolean resetPassword(String password) {
- int mode;
+ int quality;
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
- mode = getPasswordMode(null);
- if (password.length() < getPasswordMinimumLength(null)) {
+ quality = getPasswordQuality(null);
+ if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+ int adjQuality = LockPatternUtils.adjustPasswordMode(password, quality);
+ if (adjQuality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+ Log.w(TAG, "resetPassword: password does not meet quality " + quality);
+ return false;
+ }
+ quality = adjQuality;
+ }
+ int length = getPasswordMinimumLength(null);
+ if (password.length() < length) {
+ Log.w(TAG, "resetPassword: password does not meet length " + length);
return false;
}
}
@@ -580,7 +590,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
LockPatternUtils utils = new LockPatternUtils(mContext);
- utils.saveLockPassword(password, mode);
+ utils.saveLockPassword(password, quality);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -709,16 +719,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- public void setActivePasswordState(int mode, int length) {
+ public void setActivePasswordState(int quality, int length) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
synchronized (this) {
- if (mActivePasswordMode != mode || mActivePasswordLength != length
+ if (mActivePasswordQuality != quality || mActivePasswordLength != length
|| mFailedPasswordAttempts != 0) {
long ident = Binder.clearCallingIdentity();
try {
- mActivePasswordMode = mode;
+ mActivePasswordQuality = quality;
mActivePasswordLength = length;
if (mFailedPasswordAttempts != 0) {
mFailedPasswordAttempts = 0;
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 405dc2e34ca0..dc942a293427 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -335,6 +335,22 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
class PackageReceiver extends android.content.BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ String pkgList[] = null;
+ if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
+ Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ Uri uri = intent.getData();
+ String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
+ if (pkg != null) {
+ pkgList = new String[] { pkg };
+ }
+ } else if (Intent.ACTION_MEDIA_RESOURCES_AVAILABLE.equals(action) ||
+ Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ }
+ if (pkgList == null || pkgList.length == 0) {
+ return;
+ }
synchronized (mMethodMap) {
buildInputMethodListLocked(mMethodList, mMethodMap);
@@ -352,38 +368,45 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
boolean changed = false;
- Uri uri = intent.getData();
- String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
- if (curIm != null && curIm.getPackageName().equals(pkg)) {
- ServiceInfo si = null;
- try {
- si = mContext.getPackageManager().getServiceInfo(
- curIm.getComponent(), 0);
- } catch (PackageManager.NameNotFoundException ex) {
- }
- if (si == null) {
- // Uh oh, current input method is no longer around!
- // Pick another one...
- Log.i(TAG, "Current input method removed: " + curInputMethodId);
- if (!chooseNewDefaultIME()) {
- changed = true;
- curIm = null;
- curInputMethodId = "";
- Log.i(TAG, "Unsetting current input method");
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.DEFAULT_INPUT_METHOD,
- curInputMethodId);
+ if (curIm != null) {
+ boolean foundPkg = false;
+ for (String pkg : pkgList) {
+ if (curIm.getPackageName().equals(pkg)) {
+ foundPkg = true;
+ break;
}
}
+ if (foundPkg) {
+ ServiceInfo si = null;
+ try {
+ si = mContext.getPackageManager().getServiceInfo(
+ curIm.getComponent(), 0);
+ } catch (PackageManager.NameNotFoundException ex) {
+ }
+ if (si == null) {
+ // Uh oh, current input method is no longer around!
+ // Pick another one...
+ Log.i(TAG, "Current input method removed: " + curInputMethodId);
+ if (!chooseNewDefaultIME()) {
+ changed = true;
+ curIm = null;
+ curInputMethodId = "";
+ Log.i(TAG, "Unsetting current input method");
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.DEFAULT_INPUT_METHOD,
+ curInputMethodId);
+ }
+ }
- } else if (curIm == null) {
- // We currently don't have a default input method... is
- // one now available?
- changed = chooseNewDefaultIME();
- }
+ } else if (curIm == null) {
+ // We currently don't have a default input method... is
+ // one now available?
+ changed = chooseNewDefaultIME();
+ }
- if (changed) {
- updateFromSettingsLocked();
+ if (changed) {
+ updateFromSettingsLocked();
+ }
}
}
}
@@ -415,13 +438,19 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
});
+ PackageReceiver mBroadcastReceiver = new PackageReceiver();
IntentFilter packageFilt = new IntentFilter();
packageFilt.addAction(Intent.ACTION_PACKAGE_ADDED);
packageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED);
packageFilt.addAction(Intent.ACTION_PACKAGE_REMOVED);
packageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED);
packageFilt.addDataScheme("package");
- mContext.registerReceiver(new PackageReceiver(), packageFilt);
+ mContext.registerReceiver(mBroadcastReceiver, packageFilt);
+ // Register for events related to sdcard installation.
+ IntentFilter sdFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_AVAILABLE);
+ sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(mBroadcastReceiver, sdFilter);
IntentFilter screenOnOffFilt = new IntentFilter();
screenOnOffFilt.addAction(Intent.ACTION_SCREEN_ON);
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 1c82c94e77ae..3a42b37aafc1 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -484,6 +484,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+ IntentFilter sdFilter = new IntentFilter(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(mBroadcastReceiver, sdFilter);
// listen for settings changes
ContentResolver resolver = mContext.getContentResolver();
@@ -1549,43 +1551,54 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
String action = intent.getAction();
if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
- || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {
+ || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
+ || action.equals(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE)) {
synchronized (mLock) {
- int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
- if (uid >= 0) {
- ArrayList<Receiver> removedRecs = null;
- for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) {
- for (int j=i.size()-1; j>=0; j--) {
- UpdateRecord ur = i.get(j);
- if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) {
- if (removedRecs == null) {
- removedRecs = new ArrayList<Receiver>();
- }
- if (!removedRecs.contains(ur.mReceiver)) {
- removedRecs.add(ur.mReceiver);
+ int uidList[] = null;
+ if (action.equals(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE)) {
+ uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
+ } else {
+ uidList = new int[]{intent.getIntExtra(Intent.EXTRA_UID, -1)};
+ }
+ if (uidList == null || uidList.length == 0) {
+ return;
+ }
+ for (int uid : uidList) {
+ if (uid >= 0) {
+ ArrayList<Receiver> removedRecs = null;
+ for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) {
+ for (int j=i.size()-1; j>=0; j--) {
+ UpdateRecord ur = i.get(j);
+ if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) {
+ if (removedRecs == null) {
+ removedRecs = new ArrayList<Receiver>();
+ }
+ if (!removedRecs.contains(ur.mReceiver)) {
+ removedRecs.add(ur.mReceiver);
+ }
}
}
}
- }
- ArrayList<ProximityAlert> removedAlerts = null;
- for (ProximityAlert i : mProximityAlerts.values()) {
- if (i.mUid == uid) {
- if (removedAlerts == null) {
- removedAlerts = new ArrayList<ProximityAlert>();
- }
- if (!removedAlerts.contains(i)) {
- removedAlerts.add(i);
+ ArrayList<ProximityAlert> removedAlerts = null;
+ for (ProximityAlert i : mProximityAlerts.values()) {
+ if (i.mUid == uid) {
+ if (removedAlerts == null) {
+ removedAlerts = new ArrayList<ProximityAlert>();
+ }
+ if (!removedAlerts.contains(i)) {
+ removedAlerts.add(i);
+ }
}
}
- }
- if (removedRecs != null) {
- for (int i=removedRecs.size()-1; i>=0; i--) {
- removeUpdatesLocked(removedRecs.get(i));
+ if (removedRecs != null) {
+ for (int i=removedRecs.size()-1; i>=0; i--) {
+ removeUpdatesLocked(removedRecs.get(i));
+ }
}
- }
- if (removedAlerts != null) {
- for (int i=removedAlerts.size()-1; i>=0; i--) {
- removeProximityAlertLocked(removedAlerts.get(i).mIntent);
+ if (removedAlerts != null) {
+ for (int i=removedAlerts.size()-1; i>=0; i--) {
+ removeProximityAlertLocked(removedAlerts.get(i).mIntent);
+ }
}
}
}
@@ -1599,7 +1612,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
}
NetworkInfo info =
- (NetworkInfo)intent.getExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
+ (NetworkInfo)intent.getExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
// Notify location providers of current network state
synchronized (mLock) {
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 9a1f8a6b07e3..638264606a0e 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -16,9 +16,6 @@
package com.android.server;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -27,6 +24,10 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.IMountService;
+import android.os.IMountServiceListener;
+import android.os.MountServiceResultCode;
+import android.os.RemoteException;
+import android.os.IBinder;
import android.os.Environment;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -36,13 +37,8 @@ import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
-import android.provider.Settings;
-import android.content.ContentResolver;
-import android.database.ContentObserver;
-
import java.io.File;
import java.io.FileReader;
-import java.lang.IllegalStateException;
/**
* MountService implements an to the mount service daemon
@@ -53,6 +49,9 @@ class MountService extends IMountService.Stub
private static final String TAG = "MountService";
+ /*
+ * Internal vold volume state constants
+ */
class VolumeState {
public static final int Init = -1;
public static final int NoMedia = 0;
@@ -66,73 +65,50 @@ class MountService extends IMountService.Stub
public static final int SharedMnt = 8;
}
+ /*
+ * Internal vold response code constants
+ */
class VoldResponseCode {
+ /*
+ * 100 series - Requestion action was initiated; expect another reply
+ * before proceeding with a new command.
+ */
public static final int VolumeListResult = 110;
public static final int AsecListResult = 111;
- public static final int ShareAvailabilityResult = 210;
+ /*
+ * 200 series - Requestion action has been successfully completed.
+ */
+ public static final int ShareStatusResult = 210;
public static final int AsecPathResult = 211;
+ public static final int ShareEnabledResult = 212;
+ /*
+ * 400 series - Command was accepted, but the requested action
+ * did not take place.
+ */
+ public static final int OpFailedNoMedia = 401;
+ public static final int OpFailedMediaBlank = 402;
+ public static final int OpFailedMediaCorrupt = 403;
+ public static final int OpFailedVolNotMounted = 404;
+ public static final int OpFailedVolBusy = 405;
+
+ /*
+ * 600 series - Unsolicited broadcasts.
+ */
public static final int VolumeStateChange = 605;
- public static final int VolumeMountFailedBlank = 610;
- public static final int VolumeMountFailedDamaged = 611;
- public static final int VolumeMountFailedNoMedia = 612;
public static final int ShareAvailabilityChange = 620;
public static final int VolumeDiskInserted = 630;
public static final int VolumeDiskRemoved = 631;
public static final int VolumeBadRemoval = 632;
}
-
- /**
- * Binder context for this service
- */
- private Context mContext;
-
- /**
- * connectorr object for communicating with vold
- */
- private NativeDaemonConnector mConnector;
-
- /**
- * The notification that is shown when a USB mass storage host
- * is connected.
- * <p>
- * This is lazily created, so use {@link #setUsbStorageNotification()}.
- */
- private Notification mUsbStorageNotification;
-
-
- /**
- * The notification that is shown when the following media events occur:
- * - Media is being checked
- * - Media is blank (or unknown filesystem)
- * - Media is corrupt
- * - Media is safe to unmount
- * - Media is missing
- * <p>
- * This is lazily created, so use {@link #setMediaStorageNotification()}.
- */
- private Notification mMediaStorageNotification;
-
- private boolean mShowSafeUnmountNotificationWhenUnmounted;
-
- private boolean mPlaySounds;
-
- private boolean mMounted;
-
- private SettingsWatcher mSettingsWatcher;
- private boolean mAutoStartUms;
- private boolean mPromptUms;
- private boolean mUmsActiveNotify;
-
- private boolean mUmsConnected = false;
- private boolean mUmsEnabled = false;
- private boolean mUmsEnabling = false;
-
- private String mLegacyState = Environment.MEDIA_REMOVED;
-
- private PackageManagerService mPms;
+ private Context mContext;
+ private NativeDaemonConnector mConnector;
+ private String mLegacyState = Environment.MEDIA_REMOVED;
+ private PackageManagerService mPms;
+ private boolean mUmsEnabling;
+ private ArrayList<MountServiceBinderListener> mListeners;
/**
* Constructs a new MountService instance
@@ -142,7 +118,9 @@ class MountService extends IMountService.Stub
public MountService(Context context) {
mContext = context;
+ // XXX: This will go away soon in favor of IMountServiceObserver
mPms = (PackageManagerService) ServiceManager.getService("package");
+
// Register a BOOT_COMPLETED handler so that we can start
// our NativeDaemonConnector. We defer the startup so that we don't
// start processing events before we ought-to
@@ -150,78 +128,9 @@ class MountService extends IMountService.Stub
new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
mConnector = new NativeDaemonConnector(this, "vold", 10, "VoldConnector");
- mShowSafeUnmountNotificationWhenUnmounted = false;
-
- mPlaySounds = SystemProperties.get("persist.service.mount.playsnd", "1").equals("1");
-
- ContentResolver cr = mContext.getContentResolver();
- mAutoStartUms = (Settings.Secure.getInt(
- cr, Settings.Secure.MOUNT_UMS_AUTOSTART, 0) == 1);
- mPromptUms = (Settings.Secure.getInt(
- cr, Settings.Secure.MOUNT_UMS_PROMPT, 1) == 1);
- mUmsActiveNotify = (Settings.Secure.getInt(
- cr, Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED, 1) == 1);
-
- mSettingsWatcher = new SettingsWatcher(new Handler());
+ mListeners = new ArrayList<MountServiceBinderListener>();
}
- private class SettingsWatcher extends ContentObserver {
- public SettingsWatcher(Handler handler) {
- super(handler);
- ContentResolver cr = mContext.getContentResolver();
- cr.registerContentObserver(Settings.System.getUriFor(
- Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND), false, this);
- cr.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.MOUNT_UMS_AUTOSTART), false, this);
- cr.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.MOUNT_UMS_PROMPT), false, this);
- cr.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED), false, this);
- }
-
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- ContentResolver cr = mContext.getContentResolver();
-
- boolean newPlayNotificationSounds = (Settings.Secure.getInt(
- cr, Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND, 1) == 1);
-
- boolean newUmsAutostart = (Settings.Secure.getInt(
- cr, Settings.Secure.MOUNT_UMS_AUTOSTART, 0) == 1);
-
- if (newUmsAutostart != mAutoStartUms) {
- mAutoStartUms = newUmsAutostart;
- }
-
- boolean newUmsPrompt = (Settings.Secure.getInt(
- cr, Settings.Secure.MOUNT_UMS_PROMPT, 1) == 1);
-
- if (newUmsPrompt != mPromptUms) {
- mPromptUms = newUmsAutostart;
- }
-
- boolean newUmsNotifyEnabled = (Settings.Secure.getInt(
- cr, Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED, 1) == 1);
-
- if (mUmsEnabled) {
- if (newUmsNotifyEnabled) {
- Intent intent = new Intent();
- intent.setClass(mContext, com.android.internal.app.UsbStorageStopActivity.class);
- PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
- setUsbStorageNotification(com.android.internal.R.string.usb_storage_stop_notification_title,
- com.android.internal.R.string.usb_storage_stop_notification_message,
- com.android.internal.R.drawable.stat_sys_warning,
- false, true, pi);
- } else {
- setUsbStorageNotification(0, 0, 0, false, false, null);
- }
- }
- if (newUmsNotifyEnabled != mUmsActiveNotify) {
- mUmsActiveNotify = newUmsNotifyEnabled;
- }
- }
- }
-
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -232,8 +141,7 @@ class MountService extends IMountService.Stub
* event to trigger MediaScanner
*/
if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
- notifyMediaMounted(
- Environment.getExternalStorageDirectory().getPath(), false);
+ updatePublicVolumeState("/sdcard", Environment.MEDIA_MOUNTED);
return;
}
@@ -244,280 +152,89 @@ class MountService extends IMountService.Stub
}
};
- public void shutdown() {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.SHUTDOWN)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires SHUTDOWN permission");
- }
-
- Log.d(TAG, "Shutting down");
- String state = Environment.getExternalStorageState();
+ private final class MountServiceBinderListener implements IBinder.DeathRecipient {
+ final IMountServiceListener mListener;
- if (state.equals(Environment.MEDIA_SHARED)) {
- /*
- * If the media is currently shared, unshare it.
- * XXX: This is still dangerous!. We should not
- * be rebooting at *all* if UMS is enabled, since
- * the UMS host could have dirty FAT cache entries
- * yet to flush.
- */
- try {
- setMassStorageEnabled(false);
- } catch (Exception e) {
- Log.e(TAG, "ums disable failed", e);
- }
- } else if (state.equals(Environment.MEDIA_CHECKING)) {
- /*
- * If the media is being checked, then we need to wait for
- * it to complete before being able to proceed.
- */
- // XXX: @hackbod - Should we disable the ANR timer here?
- int retries = 30;
- while (state.equals(Environment.MEDIA_CHECKING) && (retries-- >=0)) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException iex) {
- Log.e(TAG, "Interrupted while waiting for media", iex);
- break;
- }
- state = Environment.getExternalStorageState();
- }
- if (retries == 0) {
- Log.e(TAG, "Timed out waiting for media to check");
- }
+ MountServiceBinderListener(IMountServiceListener listener) {
+ mListener = listener;
+
}
- if (state.equals(Environment.MEDIA_MOUNTED)) {
- /*
- * If the media is mounted, then gracefully unmount it.
- */
- try {
- String m = Environment.getExternalStorageDirectory().toString();
- unmountVolume(m);
-
- int retries = 12;
- while (!state.equals(Environment.MEDIA_UNMOUNTED) && (retries-- >=0)) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException iex) {
- Log.e(TAG, "Interrupted while waiting for media", iex);
- break;
- }
- state = Environment.getExternalStorageState();
- }
- if (retries == 0) {
- Log.e(TAG, "Timed out waiting for media to unmount");
- }
- } catch (Exception e) {
- Log.e(TAG, "external storage unmount failed", e);
+ public void binderDied() {
+ Log.d(TAG, "An IMountServiceListener has died!");
+ synchronized(mListeners) {
+ mListeners.remove(this);
+ mListener.asBinder().unlinkToDeath(this, 0);
}
}
}
- /**
- * @return true if USB mass storage support is enabled.
- */
- public boolean getMassStorageEnabled() {
- return mUmsEnabled;
- }
+ int doShareUnshareVolume(String path, String method, boolean enable) {
+ validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- /**
- * Enables or disables USB mass storage support.
- *
- * @param enable true to enable USB mass storage support
- */
- public void setMassStorageEnabled(boolean enable) throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires MOUNT_UNMOUNT_FILESYSTEMS permission");
- }
- try {
- String vp = Environment.getExternalStorageDirectory().getPath();
- String vs = getVolumeState(vp);
-
- mUmsEnabling = enable;
- if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
- unmountVolume(vp);
- mUmsEnabling = false;
- updateUsbMassStorageNotification(true, false);
- }
-
- setShareMethodEnabled(vp, "ums", enable);
- mUmsEnabled = enable;
- mUmsEnabling = false;
- if (!enable) {
- mountVolume(vp);
- if (mPromptUms) {
- updateUsbMassStorageNotification(false, false);
- } else {
- updateUsbMassStorageNotification(true, false);
- }
- }
- } catch (IllegalStateException rex) {
- Log.e(TAG, "Failed to set ums enable {" + enable + "}");
- return;
+ // TODO: Add support for multiple share methods
+ if (!method.equals("ums")) {
+ throw new IllegalArgumentException(String.format("Method %s not supported", method));
}
- }
- /**
- * @return true if USB mass storage is connected.
- */
- public boolean getMassStorageConnected() {
- return mUmsConnected;
- }
-
- /**
- * @return state of the volume at the specified mount point
- */
- public String getVolumeState(String mountPoint) throws IllegalStateException {
/*
- * XXX: Until we have multiple volume discovery, just hardwire
- * this to /sdcard
+ * If the volume is mounted and we're enabling then unmount it
*/
- if (!mountPoint.equals(Environment.getExternalStorageDirectory().getPath())) {
- Log.w(TAG, "getVolumeState(" + mountPoint + "): Unknown volume");
- throw new IllegalArgumentException();
- }
-
- return mLegacyState;
- }
-
-
- /**
- * Attempt to mount external media
- */
- public void mountVolume(String mountPath) throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires MOUNT_UNMOUNT_FILESYSTEMS permission");
- }
- mConnector.doCommand(String.format("mount %s", mountPath));
- }
-
- /**
- * Attempt to unmount external media to prepare for eject
- */
- public void unmountVolume(String mountPath) throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires MOUNT_UNMOUNT_FILESYSTEMS permission");
+ String vs = getVolumeState(path);
+ if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
+ mUmsEnabling = enable; // Supress unmounted events
+ unmountVolume(path);
+ mUmsEnabling = false; // Unsupress unmounted events
}
- // Set a flag so that when we get the unmounted event, we know
- // to display the notification
- mShowSafeUnmountNotificationWhenUnmounted = true;
-
- mConnector.doCommand(String.format("unmount %s", mountPath));
- }
-
- /**
- * Attempt to format external media
- */
- public void formatVolume(String formatPath) throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires MOUNT_FORMAT_FILESYSTEMS permission");
+ try {
+ mConnector.doCommand(String.format(
+ "volume %sshare %s %s", (enable ? "" : "un"), path, method));
+ } catch (NativeDaemonConnectorException e) {
+ Log.e(TAG, "Failed to share/unshare", e);
+ return MountServiceResultCode.OperationFailedInternalError;
}
- mConnector.doCommand(String.format("format %s", formatPath));
- }
-
- boolean getShareAvailable(String method) throws IllegalStateException {
- ArrayList<String> rsp = mConnector.doCommand("share_available " + method);
-
- for (String line : rsp) {
- String []tok = line.split(" ");
- int code = Integer.parseInt(tok[0]);
- if (code == VoldResponseCode.ShareAvailabilityResult) {
- if (tok[2].equals("available"))
- return true;
- return false;
- } else {
- throw new IllegalStateException(String.format("Unexpected response code %d", code));
+ /*
+ * If we disabled UMS then mount the volume
+ */
+ if (!enable) {
+ if (mountVolume(path) != MountServiceResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format(
+ "Failed to remount %s after disabling share method %s", path, method));
+ /*
+ * Even though the mount failed, the unshare didn't so don't indicate an error.
+ * The mountVolume() call will have set the storage state and sent the necessary
+ * broadcasts.
+ */
}
}
- throw new IllegalStateException("Got an empty response");
- }
-
- /**
- * Enables or disables USB mass storage support.
- *
- * @param enable true to enable USB mass storage support
- */
- void setShareMethodEnabled(String mountPoint, String method,
- boolean enable) throws IllegalStateException {
- mConnector.doCommand(String.format(
- "%sshare %s %s", (enable ? "" : "un"), mountPoint, method));
- }
-
- /**
- * Returns true if we're playing media notification sounds.
- */
- public boolean getPlayNotificationSounds() {
- return mPlaySounds;
- }
-
- /**
- * Set whether or not we're playing media notification sounds.
- */
- public void setPlayNotificationSounds(boolean enabled) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SETTINGS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires WRITE_SETTINGS permission");
- }
- mPlaySounds = enabled;
- SystemProperties.set("persist.service.mount.playsnd", (enabled ? "1" : "0"));
+ return MountServiceResultCode.OperationSucceeded;
}
- void updatePublicVolumeState(String mountPoint, String state) {
- if (!mountPoint.equals(Environment.getExternalStorageDirectory().getPath())) {
+ void updatePublicVolumeState(String path, String state) {
+ if (!path.equals(Environment.getExternalStorageDirectory().getPath())) {
Log.w(TAG, "Multiple volumes not currently supported");
return;
}
- Log.i(TAG, "State for {" + mountPoint + "} = {" + state + "}");
- mLegacyState = state;
- }
+ Log.i(TAG, "State for {" + path + "} = {" + state + "}");
- /**
- * Update the state of the USB mass storage notification
- */
- void updateUsbMassStorageNotification(boolean suppressIfConnected, boolean sound) {
-
- try {
+ String oldState = mLegacyState;
+ mLegacyState = state;
- if (getMassStorageConnected() && !suppressIfConnected) {
- Intent intent = new Intent();
- intent.setClass(mContext, com.android.internal.app.UsbStorageActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
- setUsbStorageNotification(
- com.android.internal.R.string.usb_storage_notification_title,
- com.android.internal.R.string.usb_storage_notification_message,
- com.android.internal.R.drawable.stat_sys_data_usb,
- sound, true, pi);
- } else {
- setUsbStorageNotification(0, 0, 0, false, false, null);
+ synchronized (mListeners) {
+ for (int i = mListeners.size() -1; i >= 0; i--) {
+ MountServiceBinderListener bl = mListeners.get(i);
+ try {
+ bl.mListener.onVolumeStateChanged("", path, oldState, state);
+ } catch (RemoteException rex) {
+ Log.e(TAG, "Listener dead");
+ mListeners.remove(i);
+ } catch (Exception ex) {
+ Log.e(TAG, "Listener failed", ex);
+ }
}
- } catch (IllegalStateException e) {
- // Nothing to do
- }
- }
-
- void handlePossibleExplicitUnmountBroadcast(String path) {
- if (mMounted) {
- mMounted = false;
- // Update media status on PackageManagerService to unmount packages on sdcard
- mPms.updateExternalMediaStatus(false);
- Intent intent = new Intent(Intent.ACTION_MEDIA_UNMOUNTED,
- Uri.parse("file://" + path));
- mContext.sendBroadcast(intent);
}
}
@@ -540,7 +257,7 @@ class MountService extends IMountService.Stub
try {
String[] vols = mConnector.doListCommand(
- "list_volumes", VoldResponseCode.VolumeListResult);
+ "volume list", VoldResponseCode.VolumeListResult);
for (String volstr : vols) {
String[] tok = volstr.split(" ");
// FMT: <label> <mountpoint> <state>
@@ -554,10 +271,9 @@ class MountService extends IMountService.Stub
state = Environment.MEDIA_REMOVED;
} else if (st == VolumeState.Idle) {
state = null;
- try {
- mountVolume(path);
- } catch (Exception ex) {
- Log.e(TAG, "Connection-mount failed", ex);
+ int rc = mountVolume(path);
+ if (rc != MountServiceResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format("Connection-mount failed (%d)", rc));
}
} else if (st == VolumeState.Mounted) {
state = Environment.MEDIA_MOUNTED;
@@ -578,7 +294,7 @@ class MountService extends IMountService.Stub
}
try {
- boolean avail = getShareAvailable("ums");
+ boolean avail = getShareMethodAvailable("ums");
notifyShareAvailabilityChange("ums", avail);
} catch (Exception ex) {
Log.w(TAG, "Failed to get share availability");
@@ -592,22 +308,18 @@ class MountService extends IMountService.Stub
* Callback from NativeDaemonConnector
*/
public boolean onEvent(int code, String raw, String[] cooked) {
+ Intent in = null;
+
// Log.d(TAG, "event {" + raw + "}");
if (code == VoldResponseCode.VolumeStateChange) {
- // FMT: NNN Volume <label> <mountpoint> state changed
- // from <old_#> (<old_str>) to <new_#> (<new_str>)
+ /*
+ * One of the volumes we're managing has changed state.
+ * Format: "NNN Volume <label> <path> state changed
+ * from <old_#> (<old_str>) to <new_#> (<new_str>)"
+ */
notifyVolumeStateChange(
cooked[2], cooked[3], Integer.parseInt(cooked[7]),
Integer.parseInt(cooked[10]));
- } else if (code == VoldResponseCode.VolumeMountFailedBlank) {
- // FMT: NNN Volume <label> <mountpoint> mount failed - no supported file-systems
- notifyMediaNoFs(cooked[3]);
- // FMT: NNN Volume <label> <mountpoint> mount failed - no media
- } else if (code == VoldResponseCode.VolumeMountFailedNoMedia) {
- notifyMediaRemoved(cooked[3]);
- } else if (code == VoldResponseCode.VolumeMountFailedDamaged) {
- // FMT: NNN Volume <label> <mountpoint> mount failed - filesystem check failed
- notifyMediaUnmountable(cooked[3]);
} else if (code == VoldResponseCode.ShareAvailabilityChange) {
// FMT: NNN Share method <method> now <available|unavailable>
boolean avail = false;
@@ -615,24 +327,100 @@ class MountService extends IMountService.Stub
avail = true;
}
notifyShareAvailabilityChange(cooked[3], avail);
- } else if (code == VoldResponseCode.VolumeDiskInserted) {
+ } else if ((code == VoldResponseCode.VolumeDiskInserted) ||
+ (code == VoldResponseCode.VolumeDiskRemoved) ||
+ (code == VoldResponseCode.VolumeBadRemoval)) {
// FMT: NNN Volume <label> <mountpoint> disk inserted (<major>:<minor>)
- notifyMediaInserted(cooked[3]);
- } else if (code == VoldResponseCode.VolumeDiskRemoved) {
// FMT: NNN Volume <label> <mountpoint> disk removed (<major>:<minor>)
- notifyMediaRemoved(cooked[3]);
- } else if (code == VoldResponseCode.VolumeBadRemoval) {
// FMT: NNN Volume <label> <mountpoint> bad removal (<major>:<minor>)
- notifyMediaBadRemoval(cooked[3]);
+ final String label = cooked[2];
+ final String path = cooked[3];
+ int major = -1;
+ int minor = -1;
+
+ try {
+ String devComp = cooked[6].substring(1, cooked[6].length() -1);
+ String[] devTok = devComp.split(":");
+ major = Integer.parseInt(devTok[0]);
+ minor = Integer.parseInt(devTok[1]);
+ } catch (Exception ex) {
+ Log.e(TAG, "Failed to parse major/minor", ex);
+ }
+
+ synchronized (mListeners) {
+ for (int i = mListeners.size() -1; i >= 0; i--) {
+ MountServiceBinderListener bl = mListeners.get(i);
+ try {
+ if (code == VoldResponseCode.VolumeDiskInserted) {
+ bl.mListener.onMediaInserted(label, path, major, minor);
+ } else if (code == VoldResponseCode.VolumeDiskRemoved) {
+ bl.mListener.onMediaRemoved(label, path, major, minor, true);
+ } else if (code == VoldResponseCode.VolumeBadRemoval) {
+ bl.mListener.onMediaRemoved(label, path, major, minor, false);
+ } else {
+ Log.e(TAG, String.format("Unknown code {%d}", code));
+ }
+ } catch (RemoteException rex) {
+ Log.e(TAG, "Listener dead");
+ mListeners.remove(i);
+ } catch (Exception ex) {
+ Log.e(TAG, "Listener failed", ex);
+ }
+ }
+ }
+
+ if (code == VoldResponseCode.VolumeDiskInserted) {
+ new Thread() {
+ public void run() {
+ try {
+ int rc;
+ if ((rc = mountVolume(path)) != MountServiceResultCode.OperationSucceeded) {
+ Log.w(TAG, String.format("Insertion mount failed (%d)", rc));
+ }
+ } catch (Exception ex) {
+ Log.w(TAG, "Failed to mount media on insertion", ex);
+ }
+ }
+ }.start();
+ } else if (code == VoldResponseCode.VolumeDiskRemoved) {
+ /*
+ * This event gets trumped if we're already in BAD_REMOVAL state
+ */
+ if (getVolumeState(path).equals(Environment.MEDIA_BAD_REMOVAL)) {
+ return true;
+ }
+ /* Send the media unmounted event first */
+ updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
+ in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
+ mContext.sendBroadcast(in);
+
+ updatePublicVolumeState(path, Environment.MEDIA_REMOVED);
+ in = new Intent(Intent.ACTION_MEDIA_REMOVED, Uri.parse("file://" + path));
+ } else if (code == VoldResponseCode.VolumeBadRemoval) {
+ /* Send the media unmounted event first */
+ updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
+ in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
+ mContext.sendBroadcast(in);
+
+ updatePublicVolumeState(path, Environment.MEDIA_BAD_REMOVAL);
+ in = new Intent(Intent.ACTION_MEDIA_BAD_REMOVAL, Uri.parse("file://" + path));
+ } else {
+ Log.e(TAG, String.format("Unknown code {%d}", code));
+ }
} else {
return false;
}
+
+ if (in != null) {
+ mContext.sendBroadcast(in);
+ }
return true;
}
- void notifyVolumeStateChange(String label, String mountPoint, int oldState,
- int newState) throws IllegalStateException {
- String vs = getVolumeState(mountPoint);
+ void notifyVolumeStateChange(String label, String path, int oldState, int newState) {
+ String vs = getVolumeState(path);
+
+ Intent in = null;
if (newState == VolumeState.Init) {
} else if (newState == VolumeState.NoMedia) {
@@ -642,53 +430,45 @@ class MountService extends IMountService.Stub
* Don't notify if we're in BAD_REMOVAL, NOFS, UNMOUNTABLE, or
* if we're in the process of enabling UMS
*/
- if (!vs.equals(Environment.MEDIA_BAD_REMOVAL) &&
- !vs.equals(Environment.MEDIA_NOFS) &&
- !vs.equals(Environment.MEDIA_UNMOUNTABLE) &&
- !mUmsEnabling) {
- notifyMediaUnmounted(mountPoint);
+ if (!vs.equals(
+ Environment.MEDIA_BAD_REMOVAL) && !vs.equals(
+ Environment.MEDIA_NOFS) && !vs.equals(
+ Environment.MEDIA_UNMOUNTABLE) && !mUmsEnabling) {
+ updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
+ in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
}
} else if (newState == VolumeState.Pending) {
} else if (newState == VolumeState.Checking) {
- notifyMediaChecking(mountPoint);
+ updatePublicVolumeState(path, Environment.MEDIA_CHECKING);
+ in = new Intent(Intent.ACTION_MEDIA_CHECKING, Uri.parse("file://" + path));
} else if (newState == VolumeState.Mounted) {
- notifyMediaMounted(mountPoint, false);
+ updatePublicVolumeState(path, Environment.MEDIA_MOUNTED);
+ // Update media status on PackageManagerService to mount packages on sdcard
+ mPms.updateExternalMediaStatus(true);
+ in = new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + path));
+ in.putExtra("read-only", false);
} else if (newState == VolumeState.Unmounting) {
- notifyMediaUnmounting(mountPoint);
+ mPms.updateExternalMediaStatus(false);
+ in = new Intent(Intent.ACTION_MEDIA_EJECT, Uri.parse("file://" + path));
} else if (newState == VolumeState.Formatting) {
} else if (newState == VolumeState.Shared) {
- notifyMediaShared(mountPoint, false);
+ /* Send the media unmounted event first */
+ updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
+ in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
+ mContext.sendBroadcast(in);
+
+ updatePublicVolumeState(path, Environment.MEDIA_SHARED);
+ in = new Intent(Intent.ACTION_MEDIA_SHARED, Uri.parse("file://" + path));
} else if (newState == VolumeState.SharedMnt) {
- notifyMediaShared(mountPoint, true);
+ Log.e(TAG, "Live shared mounts not supported yet!");
+ return;
} else {
Log.e(TAG, "Unhandled VolumeState {" + newState + "}");
}
- }
-
- /**
- * Broadcasts the USB mass storage connected event to all clients.
- */
- void notifyUmsConnected() {
- mUmsConnected = true;
-
- String storageState = Environment.getExternalStorageState();
- if (!storageState.equals(Environment.MEDIA_REMOVED) &&
- !storageState.equals(Environment.MEDIA_BAD_REMOVAL) &&
- !storageState.equals(Environment.MEDIA_CHECKING)) {
-
- if (mAutoStartUms) {
- try {
- setMassStorageEnabled(true);
- } catch (IllegalStateException e) {
- }
- } else if (mPromptUms) {
- updateUsbMassStorageNotification(false, true);
- }
+ if (in != null) {
+ mContext.sendBroadcast(in);
}
-
- Intent intent = new Intent(Intent.ACTION_UMS_CONNECTED);
- mContext.sendBroadcast(intent);
}
void notifyShareAvailabilityChange(String method, final boolean avail) {
@@ -697,446 +477,377 @@ class MountService extends IMountService.Stub
return;
}
- /*
- * Notification needs to run in a different thread as
- * it may need to call back into vold
- */
- new Thread() {
- public void run() {
+ synchronized (mListeners) {
+ for (int i = mListeners.size() -1; i >= 0; i--) {
+ MountServiceBinderListener bl = mListeners.get(i);
try {
- if (avail) {
- notifyUmsConnected();
- } else {
- notifyUmsDisconnected();
- }
+ bl.mListener.onShareAvailabilityChanged(method, avail);
+ } catch (RemoteException rex) {
+ Log.e(TAG, "Listener dead");
+ mListeners.remove(i);
} catch (Exception ex) {
- Log.w(TAG, "Failed to mount media on insertion");
+ Log.e(TAG, "Listener failed", ex);
}
}
- }.start();
- }
+ }
- /**
- * Broadcasts the USB mass storage disconnected event to all clients.
- */
- void notifyUmsDisconnected() {
- mUmsConnected = false;
- if (mUmsEnabled) {
- try {
- Log.w(TAG, "UMS disconnected while enabled!");
- setMassStorageEnabled(false);
- } catch (Exception ex) {
- Log.e(TAG, "Error disabling UMS on unsafe UMS disconnect", ex);
- }
+ Intent intent;
+ if (avail) {
+ intent = new Intent(Intent.ACTION_UMS_CONNECTED);
+ } else {
+ intent = new Intent(Intent.ACTION_UMS_DISCONNECTED);
}
- updateUsbMassStorageNotification(false, false);
- Intent intent = new Intent(Intent.ACTION_UMS_DISCONNECTED);
mContext.sendBroadcast(intent);
}
- void notifyMediaInserted(final String path) throws IllegalStateException {
- new Thread() {
- public void run() {
- try {
- mountVolume(path);
- } catch (Exception ex) {
- Log.w(TAG, "Failed to mount media on insertion", ex);
- }
- }
- }.start();
+ void validatePermission(String perm) {
+ if (mContext.checkCallingOrSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException(String.format("Requires %s permission", perm));
+ }
}
/**
- * Broadcasts the media removed event to all clients.
+ * Exposed API calls below here
*/
- void notifyMediaRemoved(String path) throws IllegalStateException {
- // Suppress this on bad removal
- if (getVolumeState(path).equals(Environment.MEDIA_BAD_REMOVAL)) {
- return;
+ public void registerListener(IMountServiceListener listener) {
+ synchronized (mListeners) {
+ MountServiceBinderListener bl = new MountServiceBinderListener(listener);
+ try {
+ listener.asBinder().linkToDeath(bl, 0);
+ mListeners.add(bl);
+ } catch (RemoteException rex) {
+ Log.e(TAG, "Failed to link to listener death");
+ }
}
-
- updatePublicVolumeState(path, Environment.MEDIA_REMOVED);
-
- updateUsbMassStorageNotification(true, false);
-
- setMediaStorageNotification(
- com.android.internal.R.string.ext_media_nomedia_notification_title,
- com.android.internal.R.string.ext_media_nomedia_notification_message,
- com.android.internal.R.drawable.stat_notify_sdcard_usb,
- true, false, null);
- handlePossibleExplicitUnmountBroadcast(path);
-
- Intent intent = new Intent(Intent.ACTION_MEDIA_REMOVED,
- Uri.parse("file://" + path));
- mContext.sendBroadcast(intent);
}
- /**
- * Broadcasts the media unmounted event to all clients.
- */
- void notifyMediaUnmounted(String path) {
-
- updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
-
- // Update media status on PackageManagerService to unmount packages on sdcard
- mPms.updateExternalMediaStatus(false);
- if (mShowSafeUnmountNotificationWhenUnmounted) {
- setMediaStorageNotification(
- com.android.internal.R.string.ext_media_safe_unmount_notification_title,
- com.android.internal.R.string.ext_media_safe_unmount_notification_message,
- com.android.internal.R.drawable.stat_notify_sdcard,
- true, true, null);
- mShowSafeUnmountNotificationWhenUnmounted = false;
- } else {
- setMediaStorageNotification(0, 0, 0, false, false, null);
+ public void unregisterListener(IMountServiceListener listener) {
+ synchronized (mListeners) {
+ for(MountServiceBinderListener bl : mListeners) {
+ if (bl.mListener == listener) {
+ mListeners.remove(mListeners.indexOf(bl));
+ return;
+ }
+ }
}
- updateUsbMassStorageNotification(false, false);
-
- Intent intent = new Intent(Intent.ACTION_MEDIA_UNMOUNTED,
- Uri.parse("file://" + path));
- mContext.sendBroadcast(intent);
}
- /**
- * Broadcasts the media checking event to all clients.
- */
- void notifyMediaChecking(String path) {
- updatePublicVolumeState(path, Environment.MEDIA_CHECKING);
-
- setMediaStorageNotification(
- com.android.internal.R.string.ext_media_checking_notification_title,
- com.android.internal.R.string.ext_media_checking_notification_message,
- com.android.internal.R.drawable.stat_notify_sdcard_prepare,
- true, false, null);
-
- updateUsbMassStorageNotification(true, false);
- Intent intent = new Intent(Intent.ACTION_MEDIA_CHECKING,
- Uri.parse("file://" + path));
- mContext.sendBroadcast(intent);
- }
+ public void shutdown() {
+ validatePermission(android.Manifest.permission.SHUTDOWN);
- /**
- * Broadcasts the media nofs event to all clients.
- */
- void notifyMediaNoFs(String path) {
- updatePublicVolumeState(path, Environment.MEDIA_NOFS);
-
- Intent intent = new Intent();
- intent.setClass(mContext, com.android.internal.app.ExternalMediaFormatActivity.class);
- PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
-
- setMediaStorageNotification(com.android.internal.R.string.ext_media_nofs_notification_title,
- com.android.internal.R.string.ext_media_nofs_notification_message,
- com.android.internal.R.drawable.stat_notify_sdcard_usb,
- true, false, pi);
- updateUsbMassStorageNotification(false, false);
- intent = new Intent(Intent.ACTION_MEDIA_NOFS,
- Uri.parse("file://" + path));
- mContext.sendBroadcast(intent);
- }
+ Log.i(TAG, "Shutting down");
- /**
- * Broadcasts the media mounted event to all clients.
- */
- void notifyMediaMounted(String path, boolean readOnly) {
- updatePublicVolumeState(path, Environment.MEDIA_MOUNTED);
-
- // Update media status on PackageManagerService to mount packages on sdcard
- mPms.updateExternalMediaStatus(true);
- setMediaStorageNotification(0, 0, 0, false, false, null);
- updateUsbMassStorageNotification(false, false);
- Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED,
- Uri.parse("file://" + path));
- intent.putExtra("read-only", readOnly);
- mMounted = true;
- mContext.sendBroadcast(intent);
- }
+ String path = Environment.getExternalStorageDirectory().getPath();
+ String state = getVolumeState(path);
- /**
- * Broadcasts the media shared event to all clients.
- */
- void notifyMediaShared(String path, boolean mounted) {
- if (mounted) {
- Log.e(TAG, "Live shared mounts not supported yet!");
- return;
+ if (state.equals(Environment.MEDIA_SHARED)) {
+ /*
+ * If the media is currently shared, unshare it.
+ * XXX: This is still dangerous!. We should not
+ * be rebooting at *all* if UMS is enabled, since
+ * the UMS host could have dirty FAT cache entries
+ * yet to flush.
+ */
+ if (unshareVolume(path, "ums") != MountServiceResultCode.OperationSucceeded) {
+ Log.e(TAG, "UMS disable on shutdown failed");
+ }
+ } else if (state.equals(Environment.MEDIA_CHECKING)) {
+ /*
+ * If the media is being checked, then we need to wait for
+ * it to complete before being able to proceed.
+ */
+ // XXX: @hackbod - Should we disable the ANR timer here?
+ int retries = 30;
+ while (state.equals(Environment.MEDIA_CHECKING) && (retries-- >=0)) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException iex) {
+ Log.e(TAG, "Interrupted while waiting for media", iex);
+ break;
+ }
+ state = Environment.getExternalStorageState();
+ }
+ if (retries == 0) {
+ Log.e(TAG, "Timed out waiting for media to check");
+ }
}
- updatePublicVolumeState(path, Environment.MEDIA_SHARED);
-
- if (mUmsActiveNotify) {
- Intent intent = new Intent();
- intent.setClass(mContext, com.android.internal.app.UsbStorageStopActivity.class);
- PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
- setUsbStorageNotification(com.android.internal.R.string.usb_storage_stop_notification_title,
- com.android.internal.R.string.usb_storage_stop_notification_message,
- com.android.internal.R.drawable.stat_sys_warning,
- false, true, pi);
+ if (state.equals(Environment.MEDIA_MOUNTED)) {
+ /*
+ * If the media is mounted, then gracefully unmount it.
+ */
+ if (unmountVolume(path) != MountServiceResultCode.OperationSucceeded) {
+ Log.e(TAG, "Failed to unmount media for shutdown");
+ }
}
- handlePossibleExplicitUnmountBroadcast(path);
- Intent intent = new Intent(Intent.ACTION_MEDIA_SHARED,
- Uri.parse("file://" + path));
- mContext.sendBroadcast(intent);
}
- /**
- * Broadcasts the media bad removal event to all clients.
- */
- void notifyMediaBadRemoval(String path) {
- updatePublicVolumeState(path, Environment.MEDIA_BAD_REMOVAL);
-
- updateUsbMassStorageNotification(true, false);
- setMediaStorageNotification(com.android.internal.R.string.ext_media_badremoval_notification_title,
- com.android.internal.R.string.ext_media_badremoval_notification_message,
- com.android.internal.R.drawable.stat_sys_warning,
- true, true, null);
-
- handlePossibleExplicitUnmountBroadcast(path);
- Intent intent = new Intent(Intent.ACTION_MEDIA_BAD_REMOVAL,
- Uri.parse("file://" + path));
- mContext.sendBroadcast(intent);
+ public String[] getShareMethodList() {
+ String[] rdata = new String[1];
+ rdata[0] = "ums";
+ return rdata;
}
- /**
- * Broadcasts the media unmountable event to all clients.
- */
- void notifyMediaUnmountable(String path) {
- updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTABLE);
+ public boolean getShareMethodAvailable(String method) {
+ ArrayList<String> rsp = mConnector.doCommand("share status " + method);
+
+ for (String line : rsp) {
+ String []tok = line.split(" ");
+ int code;
+ try {
+ code = Integer.parseInt(tok[0]);
+ } catch (NumberFormatException nfe) {
+ Log.e(TAG, String.format("Error parsing code %s", tok[0]));
+ return false;
+ }
+ if (code == VoldResponseCode.ShareStatusResult) {
+ if (tok[2].equals("available"))
+ return true;
+ return false;
+ } else {
+ Log.e(TAG, String.format("Unexpected response code %d", code));
+ return false;
+ }
+ }
+ Log.e(TAG, "Got an empty response");
+ return false;
+ }
- Intent intent = new Intent();
- intent.setClass(mContext, com.android.internal.app.ExternalMediaFormatActivity.class);
- PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
+ public int shareVolume(String path, String method) {
+ return doShareUnshareVolume(path, method, true);
+ }
- setMediaStorageNotification(com.android.internal.R.string.ext_media_unmountable_notification_title,
- com.android.internal.R.string.ext_media_unmountable_notification_message,
- com.android.internal.R.drawable.stat_notify_sdcard_usb,
- true, false, pi);
- updateUsbMassStorageNotification(false, false);
+ public int unshareVolume(String path, String method) {
+ return doShareUnshareVolume(path, method, false);
+ }
- handlePossibleExplicitUnmountBroadcast(path);
+ public boolean getVolumeShared(String path, String method) {
+ String cmd = String.format("volume shared %s %s", path, method);
+ ArrayList<String> rsp = mConnector.doCommand(cmd);
- intent = new Intent(Intent.ACTION_MEDIA_UNMOUNTABLE,
- Uri.parse("file://" + path));
- mContext.sendBroadcast(intent);
+ for (String line : rsp) {
+ String []tok = line.split(" ");
+ int code;
+ try {
+ code = Integer.parseInt(tok[0]);
+ } catch (NumberFormatException nfe) {
+ Log.e(TAG, String.format("Error parsing code %s", tok[0]));
+ return false;
+ }
+ if (code == VoldResponseCode.ShareEnabledResult) {
+ if (tok[2].equals("enabled"))
+ return true;
+ return false;
+ } else {
+ Log.e(TAG, String.format("Unexpected response code %d", code));
+ return false;
+ }
+ }
+ Log.e(TAG, "Got an empty response");
+ return false;
}
/**
- * Broadcasts the media eject event to all clients.
+ * @return state of the volume at the specified mount point
*/
- void notifyMediaUnmounting(String path) {
- Intent intent = new Intent(Intent.ACTION_MEDIA_EJECT,
- Uri.parse("file://" + path));
- mContext.sendBroadcast(intent);
+ public String getVolumeState(String mountPoint) {
+ /*
+ * XXX: Until we have multiple volume discovery, just hardwire
+ * this to /sdcard
+ */
+ if (!mountPoint.equals(Environment.getExternalStorageDirectory().getPath())) {
+ Log.w(TAG, "getVolumeState(" + mountPoint + "): Unknown volume");
+ throw new IllegalArgumentException();
+ }
+
+ return mLegacyState;
}
+
/**
- * Sets the USB storage notification.
+ * Attempt to mount external media
*/
- private synchronized void setUsbStorageNotification(int titleId, int messageId, int icon, boolean sound, boolean visible,
- PendingIntent pi) {
+ public int mountVolume(String path) {
+ validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- if (!visible && mUsbStorageNotification == null) {
- return;
- }
-
- NotificationManager notificationManager = (NotificationManager) mContext
- .getSystemService(Context.NOTIFICATION_SERVICE);
-
- if (notificationManager == null) {
- return;
- }
-
- if (visible) {
- Resources r = Resources.getSystem();
- CharSequence title = r.getText(titleId);
- CharSequence message = r.getText(messageId);
-
- if (mUsbStorageNotification == null) {
- mUsbStorageNotification = new Notification();
- mUsbStorageNotification.icon = icon;
- mUsbStorageNotification.when = 0;
- }
+ int rc = MountServiceResultCode.OperationSucceeded;
- if (sound && mPlaySounds) {
- mUsbStorageNotification.defaults |= Notification.DEFAULT_SOUND;
+ try {
+ mConnector.doCommand(String.format("volume mount %s", path));
+ } catch (NativeDaemonConnectorException e) {
+ /*
+ * Mount failed for some reason
+ */
+ Intent in = null;
+ int code = e.getCode();
+ if (code == VoldResponseCode.OpFailedNoMedia) {
+ /*
+ * Attempt to mount but no media inserted
+ */
+ rc = MountServiceResultCode.OperationFailedNoMedia;
+ } else if (code == VoldResponseCode.OpFailedMediaBlank) {
+ /*
+ * Media is blank or does not contain a supported filesystem
+ */
+ updatePublicVolumeState(path, Environment.MEDIA_NOFS);
+ in = new Intent(Intent.ACTION_MEDIA_NOFS, Uri.parse("file://" + path));
+ rc = MountServiceResultCode.OperationFailedMediaBlank;
+ } else if (code == VoldResponseCode.OpFailedMediaCorrupt) {
+ /*
+ * Volume consistency check failed
+ */
+ updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTABLE);
+ in = new Intent(Intent.ACTION_MEDIA_UNMOUNTABLE, Uri.parse("file://" + path));
+ rc = MountServiceResultCode.OperationFailedMediaCorrupt;
} else {
- mUsbStorageNotification.defaults &= ~Notification.DEFAULT_SOUND;
+ rc = MountServiceResultCode.OperationFailedInternalError;
}
-
- mUsbStorageNotification.flags = Notification.FLAG_ONGOING_EVENT;
- mUsbStorageNotification.tickerText = title;
- if (pi == null) {
- Intent intent = new Intent();
- pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+ /*
+ * Send broadcast intent (if required for the failure)
+ */
+ if (in != null) {
+ mContext.sendBroadcast(in);
}
-
- mUsbStorageNotification.setLatestEventInfo(mContext, title, message, pi);
- }
-
- final int notificationId = mUsbStorageNotification.icon;
- if (visible) {
- notificationManager.notify(notificationId, mUsbStorageNotification);
- } else {
- notificationManager.cancel(notificationId);
}
- }
-
- private synchronized boolean getMediaStorageNotificationDismissable() {
- if ((mMediaStorageNotification != null) &&
- ((mMediaStorageNotification.flags & Notification.FLAG_AUTO_CANCEL) ==
- Notification.FLAG_AUTO_CANCEL))
- return true;
- return false;
+ return rc;
}
/**
- * Sets the media storage notification.
+ * Attempt to unmount external media to prepare for eject
*/
- private synchronized void setMediaStorageNotification(int titleId, int messageId, int icon, boolean visible,
- boolean dismissable, PendingIntent pi) {
+ public int unmountVolume(String path) {
+ validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- if (!visible && mMediaStorageNotification == null) {
- return;
- }
-
- NotificationManager notificationManager = (NotificationManager) mContext
- .getSystemService(Context.NOTIFICATION_SERVICE);
-
- if (notificationManager == null) {
- return;
- }
-
- if (mMediaStorageNotification != null && visible) {
- /*
- * Dismiss the previous notification - we're about to
- * re-use it.
- */
- final int notificationId = mMediaStorageNotification.icon;
- notificationManager.cancel(notificationId);
- }
-
- if (visible) {
- Resources r = Resources.getSystem();
- CharSequence title = r.getText(titleId);
- CharSequence message = r.getText(messageId);
-
- if (mMediaStorageNotification == null) {
- mMediaStorageNotification = new Notification();
- mMediaStorageNotification.when = 0;
- }
-
- if (mPlaySounds) {
- mMediaStorageNotification.defaults |= Notification.DEFAULT_SOUND;
+ try {
+ mConnector.doCommand(String.format("volume unmount %s", path));
+ return MountServiceResultCode.OperationSucceeded;
+ } catch (NativeDaemonConnectorException e) {
+ int code = e.getCode();
+ if (code == VoldResponseCode.OpFailedVolNotMounted) {
+ return MountServiceResultCode.OperationFailedVolumeNotMounted;
} else {
- mMediaStorageNotification.defaults &= ~Notification.DEFAULT_SOUND;
+ return MountServiceResultCode.OperationFailedInternalError;
}
+ }
+ }
- if (dismissable) {
- mMediaStorageNotification.flags = Notification.FLAG_AUTO_CANCEL;
- } else {
- mMediaStorageNotification.flags = Notification.FLAG_ONGOING_EVENT;
- }
+ /**
+ * Synchronously formats a volume
+ *
+ * @param path The volume path to format
+ * @return Error code from MountServiceResultCode
+ */
+ public int formatVolume(String path) {
+ validatePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
- mMediaStorageNotification.tickerText = title;
- if (pi == null) {
- Intent intent = new Intent();
- pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+ try {
+ String cmd = String.format("volume format %s", path);
+ mConnector.doCommand(cmd);
+ return MountServiceResultCode.OperationSucceeded;
+ } catch (NativeDaemonConnectorException e) {
+ int code = e.getCode();
+ if (code == VoldResponseCode.OpFailedNoMedia) {
+ return MountServiceResultCode.OperationFailedNoMedia;
+ } else if (code == VoldResponseCode.OpFailedMediaCorrupt) {
+ return MountServiceResultCode.OperationFailedMediaCorrupt;
+ } else {
+ return MountServiceResultCode.OperationFailedInternalError;
}
-
- mMediaStorageNotification.icon = icon;
- mMediaStorageNotification.setLatestEventInfo(mContext, title, message, pi);
- }
-
- final int notificationId = mMediaStorageNotification.icon;
- if (visible) {
- notificationManager.notify(notificationId, mMediaStorageNotification);
- } else {
- notificationManager.cancel(notificationId);
}
}
- public String[] getSecureContainerList() throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.ASEC_ACCESS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires ASEC_ACCESS permission");
+ public String[] getSecureContainerList() {
+ validatePermission(android.Manifest.permission.ASEC_ACCESS);
+ try {
+ return mConnector.doListCommand("asec list", VoldResponseCode.AsecListResult);
+ } catch (NativeDaemonConnectorException e) {
+ return new String[0];
}
- return mConnector.doListCommand("list_asec", VoldResponseCode.AsecListResult);
}
- public String createSecureContainer(String id, int sizeMb, String fstype,
- String key, int ownerUid) throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.ASEC_CREATE)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires ASEC_CREATE permission");
+ public int createSecureContainer(String id, int sizeMb, String fstype,
+ String key, int ownerUid) {
+ validatePermission(android.Manifest.permission.ASEC_CREATE);
+
+ int rc = MountServiceResultCode.OperationSucceeded;
+ String cmd = String.format("asec create %s %d %s %s %d", id, sizeMb, fstype, key, ownerUid);
+ try {
+ mConnector.doCommand(cmd);
+ } catch (NativeDaemonConnectorException e) {
+ rc = MountServiceResultCode.OperationFailedInternalError;
}
- String cmd = String.format("create_asec %s %d %s %s %d",
- id, sizeMb, fstype, key, ownerUid);
- mConnector.doCommand(cmd);
- return getSecureContainerPath(id);
+ return rc;
}
- public void finalizeSecureContainer(String id) throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.ASEC_CREATE)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires ASEC_CREATE permission");
+ public int finalizeSecureContainer(String id) {
+ validatePermission(android.Manifest.permission.ASEC_CREATE);
+
+ int rc = MountServiceResultCode.OperationSucceeded;
+ try {
+ mConnector.doCommand(String.format("asec finalize %s", id));
+ } catch (NativeDaemonConnectorException e) {
+ rc = MountServiceResultCode.OperationFailedInternalError;
}
- mConnector.doCommand(String.format("finalize_asec %s", id));
+ return rc;
}
- public void destroySecureContainer(String id) throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.ASEC_DESTROY)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires ASEC_DESTROY permission");
+ public int destroySecureContainer(String id) {
+ validatePermission(android.Manifest.permission.ASEC_DESTROY);
+
+ int rc = MountServiceResultCode.OperationSucceeded;
+ try {
+ mConnector.doCommand(String.format("asec destroy %s", id));
+ } catch (NativeDaemonConnectorException e) {
+ rc = MountServiceResultCode.OperationFailedInternalError;
}
- mConnector.doCommand(String.format("destroy_asec %s", id));
+ return rc;
}
- public String mountSecureContainer(String id, String key,
- int ownerUid) throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.ASEC_MOUNT_UNMOUNT)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires ASEC_MOUNT_UNMOUNT permission");
+ public int mountSecureContainer(String id, String key, int ownerUid) {
+ validatePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
+
+ int rc = MountServiceResultCode.OperationSucceeded;
+ String cmd = String.format("asec mount %s %s %d", id, key, ownerUid);
+ try {
+ mConnector.doCommand(cmd);
+ } catch (NativeDaemonConnectorException e) {
+ rc = MountServiceResultCode.OperationFailedInternalError;
}
- String cmd = String.format("mount_asec %s %s %d",
- id, key, ownerUid);
- mConnector.doCommand(cmd);
- return getSecureContainerPath(id);
+ return rc;
}
- public void unmountSecureContainer(String id) throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.ASEC_MOUNT_UNMOUNT)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires ASEC_MOUNT_UNMOUNT permission");
+ public int unmountSecureContainer(String id) {
+ validatePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
+
+ int rc = MountServiceResultCode.OperationSucceeded;
+ String cmd = String.format("asec unmount %s", id);
+ try {
+ mConnector.doCommand(cmd);
+ } catch (NativeDaemonConnectorException e) {
+ rc = MountServiceResultCode.OperationFailedInternalError;
}
- String cmd = String.format("unmount_asec %s", id);
- mConnector.doCommand(cmd);
+ return rc;
}
- public void renameSecureContainer(String oldId, String newId) throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.ASEC_RENAME)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires ASEC_RENAME permission");
+ public int renameSecureContainer(String oldId, String newId) {
+ validatePermission(android.Manifest.permission.ASEC_RENAME);
+
+ int rc = MountServiceResultCode.OperationSucceeded;
+ String cmd = String.format("asec rename %s %s", oldId, newId);
+ try {
+ mConnector.doCommand(cmd);
+ } catch (NativeDaemonConnectorException e) {
+ rc = MountServiceResultCode.OperationFailedInternalError;
}
- String cmd = String.format("rename_asec %s %s", oldId, newId);
- mConnector.doCommand(cmd);
+ return rc;
}
- public String getSecureContainerPath(String id) throws IllegalStateException {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.ASEC_ACCESS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires ASEC_ACCESS permission");
- }
- ArrayList<String> rsp = mConnector.doCommand("asec_path " + id);
+ public String getSecureContainerPath(String id) {
+ validatePermission(android.Manifest.permission.ASEC_ACCESS);
+ ArrayList<String> rsp = mConnector.doCommand("asec path " + id);
for (String line : rsp) {
String []tok = line.split(" ");
@@ -1144,10 +855,13 @@ class MountService extends IMountService.Stub
if (code == VoldResponseCode.AsecPathResult) {
return tok[1];
} else {
- throw new IllegalStateException(String.format("Unexpected response code %d", code));
+ Log.e(TAG, String.format("Unexpected response code %d", code));
+ return "";
}
}
- throw new IllegalStateException("Got an empty response");
+
+ Log.e(TAG, "Got an empty response");
+ return "";
}
}
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index 92ba5f80d554..016aa52ac7a6 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -28,7 +28,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
-import java.lang.IllegalStateException;
import java.util.List;
import java.util.ArrayList;
@@ -82,12 +81,12 @@ final class NativeDaemonConnector implements Runnable {
listenToSocket();
} catch (Exception e) {
Log.e(TAG, "Error in NativeDaemonConnector", e);
- SystemClock.sleep(1000);
+ SystemClock.sleep(5000);
}
}
}
- private void listenToSocket() {
+ private void listenToSocket() throws IOException {
LocalSocket socket = null;
try {
@@ -143,31 +142,27 @@ final class NativeDaemonConnector implements Runnable {
}
} catch (IOException ex) {
Log.e(TAG, "Communications error", ex);
- }
-
- synchronized (this) {
- if (mOutputStream != null) {
- try {
- mOutputStream.close();
- } catch (IOException e) {
- Log.w(TAG, "Failed closing output stream", e);
+ throw ex;
+ } finally {
+ synchronized (this) {
+ if (mOutputStream != null) {
+ try {
+ mOutputStream.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Failed closing output stream", e);
+ }
+ mOutputStream = null;
}
-
- mOutputStream = null;
}
- }
- try {
- if (socket != null) {
- socket.close();
+ try {
+ if (socket != null) {
+ socket.close();
+ }
+ } catch (IOException ex) {
+ Log.w(TAG, "Failed closing socket", ex);
}
- } catch (IOException ex) {
- Log.w(TAG, "Failed closing socket", ex);
}
-
- Log.e(TAG, "Failed to connect to native daemon",
- new IllegalStateException());
- SystemClock.sleep(5000);
}
private void sendCommand(String command) {
@@ -204,7 +199,8 @@ final class NativeDaemonConnector implements Runnable {
/**
* Issue a command to the native daemon and return the responses
*/
- public synchronized ArrayList<String> doCommand(String cmd) throws IllegalStateException {
+ public synchronized ArrayList<String> doCommand(String cmd)
+ throws NativeDaemonConnectorException {
sendCommand(cmd);
ArrayList<String> response = new ArrayList<String>();
@@ -214,12 +210,12 @@ final class NativeDaemonConnector implements Runnable {
while (!complete) {
try {
String line = mResponseQueue.take();
-// Log.d(TAG, "Removed off queue -> " + line);
+ Log.d(TAG, String.format("RSP -> {%s}", line));
String[] tokens = line.split(" ");
try {
code = Integer.parseInt(tokens[0]);
} catch (NumberFormatException nfe) {
- throw new IllegalStateException(
+ throw new NativeDaemonConnectorException(
String.format("Invalid response from daemon (%s)", line));
}
@@ -233,7 +229,7 @@ final class NativeDaemonConnector implements Runnable {
if (code >= ResponseCode.FailedRangeStart &&
code <= ResponseCode.FailedRangeEnd) {
- throw new IllegalStateException(String.format(
+ throw new NativeDaemonConnectorException(code, String.format(
"Command %s failed with code %d",
cmd, code));
}
@@ -244,7 +240,7 @@ final class NativeDaemonConnector implements Runnable {
* Issues a list command and returns the cooked list
*/
public String[] doListCommand(String cmd, int expectedResponseCode)
- throws IllegalStateException {
+ throws NativeDaemonConnectorException {
ArrayList<String> rsp = doCommand(cmd);
String[] rdata = new String[rsp.size()-1];
@@ -259,14 +255,15 @@ final class NativeDaemonConnector implements Runnable {
} else if (code == NativeDaemonConnector.ResponseCode.CommandOkay) {
return rdata;
} else {
- throw new IllegalStateException(
+ throw new NativeDaemonConnectorException(
String.format("Expected list response %d, but got %d",
expectedResponseCode, code));
}
} catch (NumberFormatException nfe) {
- throw new IllegalStateException(String.format("Error reading code '%s'", line));
+ throw new NativeDaemonConnectorException(
+ String.format("Error reading code '%s'", line));
}
}
- throw new IllegalStateException("Got an empty response");
+ throw new NativeDaemonConnectorException("Got an empty response");
}
}
diff --git a/services/java/com/android/server/NativeDaemonConnectorException.java b/services/java/com/android/server/NativeDaemonConnectorException.java
new file mode 100644
index 000000000000..e60aaf86858d
--- /dev/null
+++ b/services/java/com/android/server/NativeDaemonConnectorException.java
@@ -0,0 +1,42 @@
+/*
+ * 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 com.android.server;
+
+/**
+ * An exception that indicates there was an error with a NativeDaemonConnector operation
+ */
+public class NativeDaemonConnectorException extends RuntimeException
+{
+ private int mCode = -1;
+
+ public NativeDaemonConnectorException() {}
+
+ public NativeDaemonConnectorException(String error)
+ {
+ super(error);
+ }
+
+ public NativeDaemonConnectorException(int code, String error)
+ {
+ super(error);
+ mCode = code;
+ }
+
+ public int getCode() {
+ return mCode;
+ }
+}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index fc89ec8482a8..02a0401b23cb 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -329,16 +329,27 @@ class NotificationManagerService extends INotificationManager.Stub
mUsbConnected = false;
updateAdbNotification();
} else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
- || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {
- Uri uri = intent.getData();
- if (uri == null) {
- return;
+ || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
+ || action.equals(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE)) {
+ String pkgList[] = null;
+ if (action.equals(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE)) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ } else {
+ Uri uri = intent.getData();
+ if (uri == null) {
+ return;
+ }
+ String pkgName = uri.getSchemeSpecificPart();
+ if (pkgName == null) {
+ return;
+ }
+ pkgList = new String[]{pkgName};
}
- String pkgName = uri.getSchemeSpecificPart();
- if (pkgName == null) {
- return;
+ if (pkgList != null && (pkgList.length > 0)) {
+ for (String pkgName : pkgList) {
+ cancelAllNotificationsInt(pkgName, 0, 0);
+ }
}
- cancelAllNotificationsInt(pkgName, 0, 0);
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
mScreenOn = true;
updateNotificationPulse();
@@ -429,6 +440,8 @@ class NotificationManagerService extends INotificationManager.Stub
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
mContext.registerReceiver(mIntentReceiver, filter);
+ IntentFilter sdFilter = new IntentFilter(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(mIntentReceiver, sdFilter);
SettingsObserver observer = new SettingsObserver(mHandler);
observer.observe();
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 3ffb8bf8351d..238403c39143 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -63,6 +63,7 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.Debug;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
@@ -73,6 +74,7 @@ import android.os.Environment;
import android.os.FileObserver;
import android.os.FileUtils;
import android.os.Handler;
+import android.os.MountServiceResultCode;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.ServiceManager;
@@ -2178,21 +2180,32 @@ class PackageManagerService extends IPackageManager.Stub {
parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
}
+ String codePath = null;
+ String resPath = null;
if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
if (ps != null && ps.resourcePathString != null) {
- pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
+ resPath = ps.resourcePathString;
} else {
// Should not happen at all. Just log an error.
Log.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
}
} else {
- pkg.applicationInfo.publicSourceDir = pkg.mScanPath;
+ resPath = pkg.mScanPath;
}
- pkg.applicationInfo.sourceDir = pkg.mScanPath;
+ codePath = pkg.mScanPath;
+ // Set application objects path explicitly.
+ setApplicationInfoPaths(pkg, codePath, resPath);
// Note that we invoke the following method only if we are about to unpack an application
return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
}
+ private static void setApplicationInfoPaths(PackageParser.Package pkg,
+ String destCodePath, String destResPath) {
+ pkg.mPath = pkg.mScanPath = destCodePath;
+ pkg.applicationInfo.sourceDir = destCodePath;
+ pkg.applicationInfo.publicSourceDir = destResPath;
+ }
+
private static String fixProcessName(String defProcessName,
String processName, int uid) {
if (processName == null) {
@@ -4024,7 +4037,7 @@ class PackageManagerService extends IPackageManager.Stub {
if (res.removedInfo.args != null) {
// Remove the replaced package's older resources safely now
synchronized (mInstallLock) {
- res.removedInfo.args.cleanUpResourcesLI();
+ res.removedInfo.args.doPostDeleteLI(true);
}
}
}
@@ -4050,13 +4063,14 @@ class PackageManagerService extends IPackageManager.Stub {
abstract void createCopyFile();
abstract int copyApk(IMediaContainerService imcs);
- abstract void doPreInstall(int status);
+ abstract int doPreInstall(int status);
abstract boolean doRename(int status, String pkgName, String oldCodePath);
- abstract void doPostInstall(int status);
+ abstract int doPostInstall(int status);
abstract String getCodePath();
abstract String getResourcePath();
// Need installer lock especially for dex file removal.
abstract void cleanUpResourcesLI();
+ abstract boolean doPostDeleteLI(boolean delete);
}
class FileInstallArgs extends InstallArgs {
@@ -4113,10 +4127,11 @@ class PackageManagerService extends IPackageManager.Stub {
return ret;
}
- void doPreInstall(int status) {
+ int doPreInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
cleanUp();
}
+ return status;
}
boolean doRename(int status, final String pkgName, String oldCodePath) {
@@ -4143,10 +4158,11 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
- void doPostInstall(int status) {
+ int doPostInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
cleanUp();
}
+ return status;
}
String getResourcePath() {
@@ -4219,6 +4235,11 @@ class PackageManagerService extends IPackageManager.Stub {
}
return true;
}
+
+ boolean doPostDeleteLI(boolean delete) {
+ cleanUpResourcesLI();
+ return true;
+ }
}
class SdInstallArgs extends InstallArgs {
@@ -4233,7 +4254,7 @@ class PackageManagerService extends IPackageManager.Stub {
}
SdInstallArgs(String fullCodePath, String fullResourcePath) {
- super(null, null, 0, null);
+ super(null, null, ApplicationInfo.FLAG_ON_SDCARD, null);
// Extract cid from fullCodePath
int eidx = fullCodePath.lastIndexOf("/");
String subStr1 = fullCodePath.substring(0, eidx);
@@ -4242,6 +4263,11 @@ class PackageManagerService extends IPackageManager.Stub {
cachePath = subStr1;
}
+ SdInstallArgs(String cid) {
+ super(null, null, ApplicationInfo.FLAG_ON_SDCARD, null);
+ this.cid = cid;
+ }
+
void createCopyFile() {
cid = getTempContainerId();
}
@@ -4253,16 +4279,8 @@ class PackageManagerService extends IPackageManager.Stub {
getEncryptKey(), RES_FILE_NAME);
} catch (RemoteException e) {
}
-
- if (cachePath != null) {
- // Mount container once its created with system_uid
- cachePath = mountSdDir(cid, Process.SYSTEM_UID);
- }
- if (cachePath == null) {
- return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
- } else {
- return PackageManager.INSTALL_SUCCEEDED;
- }
+ return (cachePath == null) ? PackageManager.INSTALL_FAILED_CONTAINER_ERROR :
+ PackageManager.INSTALL_SUCCEEDED;
}
@Override
@@ -4275,25 +4293,81 @@ class PackageManagerService extends IPackageManager.Stub {
return cachePath + "/" + RES_FILE_NAME;
}
- void doPreInstall(int status) {
+ int doPreInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
// Destroy container
destroySdDir(cid);
+ } else {
+ // STOPSHIP Remove once new api is added in MountService
+ //boolean mounted = isContainerMounted(cid);
+ boolean mounted = false;
+ if (!mounted) {
+ cachePath = mountSdDir(cid, Process.SYSTEM_UID);
+ if (cachePath == null) {
+ return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
+ }
+ }
}
+ return status;
}
boolean doRename(int status, final String pkgName,
String oldCodePath) {
String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
+ String newCachePath = null;
+ /*final int RENAME_FAILED = 1;
+ final int MOUNT_FAILED = 2;
+ final int DESTROY_FAILED = 3;
+ final int PASS = 4;
+ int errCode = RENAME_FAILED;
+ if (mounted) {
+ // Unmount the container
+ if (!unMountSdDir(cid)) {
+ Log.i(TAG, "Failed to unmount " + cid + " before renaming");
+ return false;
+ }
+ mounted = false;
+ }
+ if (renameSdDir(cid, newCacheId)) {
+ errCode = MOUNT_FAILED;
+ if ((newCachePath = mountSdDir(newCacheId, Process.SYSTEM_UID)) != null) {
+ errCode = PASS;
+ }
+ }
+ String errMsg = "";
+ switch (errCode) {
+ case RENAME_FAILED:
+ errMsg = "RENAME_FAILED";
+ break;
+ case MOUNT_FAILED:
+ errMsg = "MOUNT_FAILED";
+ break;
+ case DESTROY_FAILED:
+ errMsg = "DESTROY_FAILED";
+ break;
+ default:
+ errMsg = "PASS";
+ break;
+ }
+ Log.i(TAG, "Status: " + errMsg);
+ if (errCode != PASS) {
+ return false;
+ }
+ Log.i(TAG, "Succesfully renamed " + cid + " to " +newCacheId +
+ " at path: " + cachePath + " to new path: " + newCachePath);
+ cid = newCacheId;
+ cachePath = newCachePath;
+ return true;
+ */
// STOPSHIP TEMPORARY HACK FOR RENAME
// Create new container at newCachePath
String codePath = getCodePath();
- String newCachePath = null;
final int CREATE_FAILED = 1;
final int COPY_FAILED = 3;
final int FINALIZE_FAILED = 5;
final int PASS = 7;
int errCode = CREATE_FAILED;
+
if ((newCachePath = createSdDir(new File(codePath), newCacheId)) != null) {
errCode = COPY_FAILED;
// Copy file from codePath
@@ -4334,13 +4408,18 @@ class PackageManagerService extends IPackageManager.Stub {
return true;
}
- void doPostInstall(int status) {
+ int doPostInstall(int status) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
cleanUp();
} else {
- // Unmount container
- // Rename and remount based on package name and new uid
+ // STOP SHIP Change this once new api is added.
+ //boolean mounted = isContainerMounted(cid);
+ boolean mounted = false;
+ if (!mounted) {
+ mountSdDir(cid, Process.SYSTEM_UID);
+ }
}
+ return status;
}
private void cleanUp() {
@@ -4362,37 +4441,66 @@ class PackageManagerService extends IPackageManager.Stub {
}
cleanUp();
}
+
+ boolean matchContainer(String app) {
+ if (cid.startsWith(app)) {
+ return true;
+ }
+ return false;
+ }
+
+ String getPackageName() {
+ int idx = cid.lastIndexOf("-");
+ if (idx == -1) {
+ return cid;
+ }
+ return cid.substring(0, idx);
+ }
+
+ boolean doPostDeleteLI(boolean delete) {
+ boolean ret = false;
+ boolean mounted = isContainerMounted(cid);
+ if (mounted) {
+ // Unmount first
+ ret = unMountSdDir(cid);
+ }
+ if (ret && delete) {
+ cleanUpResourcesLI();
+ }
+ return ret;
+ }
};
// Utility method used to create code paths based on package name and available index.
private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
String idxStr = "";
int idx = 1;
+ // Fall back to default value of idx=1 if prefix is not
+ // part of oldCodePath
if (oldCodePath != null) {
- int eidx = -1;
- if (suffix != null) {
- eidx = oldCodePath.indexOf(suffix);
- }
- if (eidx == -1) {
- eidx = oldCodePath.length();
- }
- int sidx = oldCodePath.indexOf(prefix);
- if (sidx == -1) {
- sidx = 0;
- }
- String subStr = oldCodePath.substring(sidx + prefix.length(), eidx);
- if (subStr != null) {
- if (subStr.startsWith("-")) {
- subStr = subStr.substring(1);
- }
- try {
- idx = Integer.parseInt(subStr);
- if (idx <= 1) {
- idx++;
- } else {
- idx--;
+ String subStr = oldCodePath;
+ // Drop the suffix right away
+ if (subStr.endsWith(suffix)) {
+ subStr = subStr.substring(0, subStr.length() - suffix.length());
+ }
+ // If oldCodePath already contains prefix find out the
+ // ending index to either increment or decrement.
+ int sidx = subStr.lastIndexOf(prefix);
+ if (sidx != -1) {
+ subStr = subStr.substring(sidx + prefix.length());
+ if (subStr != null) {
+ if (subStr.startsWith("-")) {
+ subStr = subStr.substring(1);
+ }
+ try {
+ idx = Integer.parseInt(subStr);
+ if (idx <= 1) {
+ idx++;
+ } else {
+ idx--;
+ }
+ } catch(NumberFormatException e) {
}
- } catch(NumberFormatException e) {
}
}
}
@@ -4757,6 +4865,9 @@ class PackageManagerService extends IPackageManager.Stub {
if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
&& mPackages.containsKey(pkgName)) {
replacingExistingPackage = true;
+ }
+ PackageSetting ps = mSettings.mPackages.get(pkgName);
+ if (ps != null) {
oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
}
}
@@ -4765,9 +4876,8 @@ class PackageManagerService extends IPackageManager.Stub {
res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
break main_flow;
}
- // TODO rename pkg.mScanPath In scanPackageLI let it just set values based on mScanPath
- pkg.applicationInfo.sourceDir = pkg.mScanPath= pkg.mPath = args.getCodePath();
- pkg.applicationInfo.publicSourceDir = args.getResourcePath();
+ // Set application objects path explicitly after the rename
+ setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
if(replacingExistingPackage) {
replacePackageLI(pkg, parseFlags, scanMode,
installerPackageName, res);
@@ -4981,9 +5091,9 @@ class PackageManagerService extends IPackageManager.Stub {
}
// Delete the resources here after sending the broadcast to let
// other processes clean up before deleting resources.
- synchronized (mInstallLock) {
- if (info.args != null) {
- info.args.cleanUpResourcesLI();
+ if (info.args != null) {
+ synchronized (mInstallLock) {
+ info.args.doPostDeleteLI(deleteCodeAndResources);
}
}
return res;
@@ -6952,6 +7062,17 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
+ private Set<String> findPackagesWithFlag(int flag) {
+ Set<String> ret = new HashSet<String>();
+ for (PackageSetting ps : mPackages.values()) {
+ // Has to match atleast all the flag bits set on flag
+ if ((ps.pkgFlags & flag) == flag) {
+ ret.add(ps.name);
+ }
+ }
+ return ret;
+ }
+
private void removeUserIdLP(int uid) {
if (uid >= FIRST_APPLICATION_UID) {
int N = mUserIds.size();
@@ -7945,33 +8066,28 @@ class PackageManagerService extends IPackageManager.Stub {
Log.e(TAG, "Failed to create encryption keys with exception: " + nsae);
return null;
}
- try {
- cachePath = mountService.createSecureContainer(pkgName,
- mbLen,
- "vfat", sdEncKey, Process.SYSTEM_UID);
- if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install " + pkgName + ", cachePath =" + cachePath);
- return cachePath;
- } catch(IllegalStateException e) {
- Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
+
+ int rc = mountService.createSecureContainer(
+ pkgName, mbLen, "vfat", sdEncKey, Process.SYSTEM_UID);
+ if (rc != MountServiceResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format("Failed to create container (%d)", rc));
+
+ rc = mountService.destroySecureContainer(pkgName);
+ if (rc != MountServiceResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format("Failed to cleanup container (%d)", rc));
+ return null;
+ }
+ rc = mountService.createSecureContainer(
+ pkgName, mbLen, "vfat", sdEncKey, Process.SYSTEM_UID);
+ if (rc != MountServiceResultCode.OperationSucceeded) {
+ Log.e(TAG, String.format("Failed to create container (2nd try) (%d)", rc));
+ return null;
+ }
}
- // TODO just fail here and let the user delete later on.
- try {
- mountService.destroySecureContainer(pkgName);
- if (DEBUG_SD_INSTALL) Log.i(TAG, "Destroying cache for " + pkgName + ", cachePath =" + cachePath);
- } catch(IllegalStateException e) {
- Log.e(TAG, "Failed to destroy existing cache: " + e);
- return null;
- }
- try {
- cachePath = mountService.createSecureContainer(pkgName,
- mbLen,
- "vfat", sdEncKey, Process.SYSTEM_UID);
- if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install again " + pkgName + ", cachePath =" + cachePath);
+
+ cachePath = mountService.getSecureContainerPath(pkgName);
+ if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install " + pkgName + ", cachePath =" + cachePath);
return cachePath;
- } catch(IllegalStateException e) {
- Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
- return null;
- }
}
private String mountSdDir(String pkgName, int ownerUid) {
@@ -7980,63 +8096,73 @@ class PackageManagerService extends IPackageManager.Stub {
Log.e(TAG, "Failed to retrieve encryption keys to mount package code: " + pkgName + ".");
return null;
}
- try {
- return getMountService().mountSecureContainer(pkgName, sdEncKey, ownerUid);
- } catch (IllegalStateException e) {
- Log.i(TAG, "Failed to mount container for pkg : " + pkgName + " exception : " + e);
+
+ int rc = getMountService().mountSecureContainer(pkgName, sdEncKey, ownerUid);
+
+ if (rc != MountServiceResultCode.OperationSucceeded) {
+ Log.i(TAG, "Failed to mount container for pkg : " + pkgName + " rc : " + rc);
+ return null;
}
- return null;
+
+ return getMountService().getSecureContainerPath(pkgName);
}
private boolean unMountSdDir(String pkgName) {
// STOPSHIP unmount directory
+ int rc = getMountService().unmountSecureContainer(pkgName);
+ if (rc != MountServiceResultCode.OperationSucceeded) {
+ Log.e(TAG, "Failed to unmount : " + pkgName + " with rc " + rc);
+ return false;
+ }
+ return true;
+ }
+
+ private boolean renameSdDir(String oldId, String newId) {
try {
- getMountService().unmountSecureContainer(pkgName);
+ getMountService().renameSecureContainer(oldId, newId);
return true;
} catch (IllegalStateException e) {
- Log.e(TAG, "Failed to unmount : " + pkgName + " with exception " + e);
+ Log.i(TAG, "Failed ot rename " + oldId + " to " + newId +
+ " with exception : " + e);
}
return false;
}
private String getSdDir(String pkgName) {
- String cachePath = null;
- try {
- cachePath = getMountService().getSecureContainerPath(pkgName);
- } catch (IllegalStateException e) {
- Log.e(TAG, "Failed to retrieve secure container path for pkg : " + pkgName + " with exception " + e);
- }
- return cachePath;
+ return getMountService().getSecureContainerPath(pkgName);
}
- private boolean finalizeSdDir(String pkgName) {
- try {
- getMountService().finalizeSecureContainer(pkgName);
- return true;
- } catch (IllegalStateException e) {
- Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
- return false;
- }
- }
+ private boolean finalizeSdDir(String pkgName) {
+ int rc = getMountService().finalizeSecureContainer(pkgName);
+ if (rc != MountServiceResultCode.OperationSucceeded) {
+ Log.i(TAG, "Failed to finalize container for pkg : " + pkgName);
+ return false;
+ }
+ return true;
+ }
- private boolean destroySdDir(String pkgName) {
- try {
- // We need to destroy right away
- getMountService().destroySecureContainer(pkgName);
- return true;
- } catch (IllegalStateException e) {
- Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
- return false;
- }
- }
+ private boolean destroySdDir(String pkgName) {
+ int rc = getMountService().destroySecureContainer(pkgName);
+ if (rc != MountServiceResultCode.OperationSucceeded) {
+ Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
+ return false;
+ }
+ return true;
+ }
- static String[] getSecureContainerList() {
+ static String[] getSecureContainerList() {
+ String[] list = getMountService().getSecureContainerList();
+ return list.length == 0 ? null : list;
+ }
+
+ static boolean isContainerMounted(String cid) {
+ // STOPSHIP
+ // New api from MountService
try {
- return getMountService().getSecureContainerList();
+ return (getMountService().getSecureContainerPath(cid) != null);
} catch (IllegalStateException e) {
- Log.i(TAG, "Failed to getSecureContainerList");
}
- return null;
+ return false;
}
static String getTempContainerId() {
@@ -8083,6 +8209,8 @@ class PackageManagerService extends IPackageManager.Stub {
}
public void updateExternalMediaStatus(final boolean mediaStatus) {
+ final boolean DEBUG = true;
+ if (DEBUG) Log.i(TAG, "updateExterMediaStatus::");
if (mediaStatus == mMediaMounted) {
return;
}
@@ -8091,54 +8219,155 @@ class PackageManagerService extends IPackageManager.Stub {
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- final String list[] = getSecureContainerList();
- if (list == null || list.length == 0) {
- return;
+ updateExternalMediaStatusInner(mediaStatus);
+ }
+ });
+ }
+
+ void updateExternalMediaStatusInner(boolean mediaStatus) {
+ final String list[] = getSecureContainerList();
+ if (list == null || list.length == 0) {
+ return;
+ }
+ HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
+ int uidList[] = new int[list.length];
+ int num = 0;
+ for (int i = 0; i < uidList.length; i++) {
+ uidList[i] = Process.LAST_APPLICATION_UID;
+ }
+ synchronized (mPackages) {
+ Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_ON_SDCARD);
+ for (String cid : list) {
+ SdInstallArgs args = new SdInstallArgs(cid);
+ String removeEntry = null;
+ for (String app : appList) {
+ if (args.matchContainer(app)) {
+ removeEntry = app;
+ break;
+ }
+ }
+ if (removeEntry == null) {
+ // No matching app on device. Skip entry or may be cleanup?
+ // Ignore default package
+ continue;
+ }
+ appList.remove(removeEntry);
+ PackageSetting ps = mSettings.mPackages.get(removeEntry);
+ processCids.put(args, ps.codePathString);
+ int uid = ps.userId;
+ if (uid != -1) {
+ int idx = Arrays.binarySearch(uidList, uid);
+ if (idx < 0) {
+ uidList[-idx] = uid;
+ num++;
+ }
}
- for (int i = 0; i < list.length; i++) {
- String mountPkg = list[i];
- // TODO compare with default package
+ }
+ }
+ int uidArr[] = uidList;
+ if ((num > 0) && (num < uidList.length)) {
+ uidArr = new int[num];
+ for (int i = 0; i < num; i++) {
+ uidArr[i] = uidList[i];
+ }
+ }
+ if (mediaStatus) {
+ loadMediaPackages(processCids, uidArr);
+ } else {
+ unloadMediaPackages(processCids, uidArr);
+ }
+ }
+
+ private void sendResourcesChangedBroadcast(boolean mediaStatus,
+ ArrayList<String> pkgList, int uidArr[]) {
+ int size = pkgList.size();
+ if (size > 0) {
+ // Send broadcasts here
+ Bundle extras = new Bundle();
+ extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
+ pkgList.toArray(new String[size]));
+ extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
+ String action = mediaStatus ? Intent.ACTION_MEDIA_RESOURCES_AVAILABLE
+ : Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE;
+ sendPackageBroadcast(action, null, extras);
+ }
+ }
+
+ void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
+ ArrayList<String> pkgList = new ArrayList<String>();
+ Set<SdInstallArgs> keys = processCids.keySet();
+ for (SdInstallArgs args : keys) {
+ String cid = args.cid;
+ String codePath = processCids.get(args);
+ if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
+ Log.i(TAG, "Failed to install package: " + codePath + " from sdcard");
+ continue;
+ }
+ // Parse package
+ int parseFlags = PackageParser.PARSE_CHATTY |
+ PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
+ PackageParser pp = new PackageParser(codePath);
+ pp.setSeparateProcesses(mSeparateProcesses);
+ final PackageParser.Package pkg = pp.parsePackage(new File(codePath),
+ codePath, mMetrics, parseFlags);
+ if (pkg == null) {
+ Log.w(TAG, "Failed to install package : " + cid + " from sd card");
+ continue;
+ }
+ setApplicationInfoPaths(pkg, codePath, codePath);
+ int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
+ synchronized (mInstallLock) {
+ // Scan the package
+ if (scanPackageLI(pkg, parseFlags, SCAN_MONITOR) != null) {
synchronized (mPackages) {
- PackageSetting ps = mSettings.mPackages.get(mountPkg);
- if (ps != null && (ps.pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) != 0) {
- if (mediaStatus) {
- String pkgPath = getSdDir(mountPkg);
- if (pkgPath == null) {
- continue;
- }
- pkgPath = ps.codePathString;
- int parseFlags = PackageParser.PARSE_CHATTY |
- PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
- PackageParser pp = new PackageParser(pkgPath);
- pp.setSeparateProcesses(mSeparateProcesses);
- final PackageParser.Package pkg = pp.parsePackage(new File(pkgPath),
- null, mMetrics, parseFlags);
- if (pkg == null) {
- Log.w(TAG, "Failed to install package : " + mountPkg + " from sd card");
- continue;
- }
- int scanMode = SCAN_MONITOR;
- // Scan the package
- if (scanPackageLI(pkg, parseFlags, scanMode) != null) {
- // Grant permissions
- grantPermissionsLP(pkg, false);
- // Persist settings
- mSettings.writeLP();
- } else {
- Log.i(TAG, "Failed to install package: " + mountPkg + " from sdcard");
- }
- } else {
- // Delete package
- PackageRemovedInfo outInfo = new PackageRemovedInfo();
- boolean res = deletePackageLI(mountPkg, false, PackageManager.DONT_DELETE_DATA, outInfo);
- if (!res) {
- Log.e(TAG, "Failed to delete pkg from sdcard : " + mountPkg);
- }
- }
- }
+ // Grant permissions
+ grantPermissionsLP(pkg, false);
+ // Persist settings
+ mSettings.writeLP();
+ retCode = PackageManager.INSTALL_SUCCEEDED;
+ pkgList.add(pkg.packageName);
}
+ } else {
+ Log.i(TAG, "Failed to install package: " + pkg.packageName + " from sdcard");
}
}
- });
+ args.doPostInstall(retCode);
+ pkgList.add(pkg.packageName);
+ }
+ // Send broadcasts first
+ sendResourcesChangedBroadcast(true, pkgList, uidArr);
+ Runtime.getRuntime().gc();
+ // If something failed do we clean up here or next install?
+ }
+
+ void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
+ ArrayList<String> pkgList = new ArrayList<String>();
+ Set<SdInstallArgs> keys = processCids.keySet();
+ for (SdInstallArgs args : keys) {
+ String cid = args.cid;
+ String pkgName = args.getPackageName();
+ // STOPSHIP Send broadcast to apps to remove references
+ // STOPSHIP Unmount package
+ // Delete package internally
+ PackageRemovedInfo outInfo = new PackageRemovedInfo();
+ synchronized (mInstallLock) {
+ boolean res = deletePackageLI(pkgName, false,
+ PackageManager.DONT_DELETE_DATA, outInfo);
+ if (res) {
+ pkgList.add(pkgName);
+ } else {
+ Log.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
+ }
+ }
+ }
+ // Send broadcasts
+ sendResourcesChangedBroadcast(false, pkgList, uidArr);
+ Runtime.getRuntime().gc();
+ // Do clean up. Just unmount
+ for (SdInstallArgs args : keys) {
+ synchronized (mInstallLock) {
+ args.doPostDeleteLI(false);
+ }
+ }
}
}
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index cefd3124f80d..e14a9734c8c9 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2011,6 +2011,10 @@ class PowerManagerService extends IPowerManager.Stub
}
}
}
+
+ if (mPolicy != null) {
+ mPolicy.userActivity();
+ }
}
private int getAutoBrightnessValue(int sensorValue, int[] values) {
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index d5de1f0be1c1..7951fb71b084 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -923,7 +923,7 @@ public class WifiService extends IWifiManager.Stub {
String value = field.value();
if (value != null) {
if (field != config.eap) {
- value = convertToQuotedString(value);
+ value = (value.length() == 0) ? "NULL" : convertToQuotedString(value);
}
if (!WifiNative.setNetworkVariableCommand(
netId,
diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java
index 9443a958199a..f2347edebf67 100644
--- a/services/java/com/android/server/WifiWatchdogService.java
+++ b/services/java/com/android/server/WifiWatchdogService.java
@@ -739,6 +739,8 @@ public class WifiWatchdogService {
// Black list this "bad" AP, this will cause an attempt to connect to another
blacklistAp(ap.bssid);
+ // Initiate an association to an alternate AP
+ mWifiStateTracker.reassociate();
}
private void blacklistAp(String bssid) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 1d14e5e65684..88aadbd665ce 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -2385,7 +2385,8 @@ public class WindowManagerService extends IWindowManager.Stub
// to provide the correct semantics while starting.
final int mask =
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
- | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
+ | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+ | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c2c6e76e7d99..5e6881cc923a 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1196,7 +1196,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
int uid = msg.arg1;
boolean restart = (msg.arg2 == 1);
String pkg = (String) msg.obj;
- forceStopPackageLocked(pkg, uid, restart);
+ forceStopPackageLocked(pkg, uid, restart, false);
}
} break;
}
@@ -4998,7 +4998,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
private void forceStopPackageLocked(final String packageName, int uid) {
- forceStopPackageLocked(packageName, uid, false);
+ forceStopPackageLocked(packageName, uid, false, false);
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
intent.putExtra(Intent.EXTRA_UID, uid);
@@ -5037,9 +5037,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
removeProcessLocked(procs.get(i), callerWillRestart);
}
}
-
+
private final void forceStopPackageLocked(String name, int uid,
- boolean callerWillRestart) {
+ boolean callerWillRestart, boolean purgeCache) {
int i, N;
if (uid < 0) {
@@ -5091,6 +5091,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
resumeTopActivityLocked(null);
+ if (purgeCache) {
+ AttributeCache ac = AttributeCache.instance();
+ if (ac != null) {
+ ac.removePackage(name);
+ }
+ }
}
private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
@@ -8054,7 +8060,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
mDebugTransient = !persistent;
if (packageName != null) {
final long origId = Binder.clearCallingIdentity();
- forceStopPackageLocked(packageName, -1, false);
+ forceStopPackageLocked(packageName, -1, false, false);
Binder.restoreCallingIdentity(origId);
}
}
@@ -8081,6 +8087,14 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
+ public boolean isUserAMonkey() {
+ // For now the fact that there is a controller implies
+ // we have a monkey.
+ synchronized (this) {
+ return mController != null;
+ }
+ }
+
public void registerActivityWatcher(IActivityWatcher watcher) {
mWatchers.register(watcher);
}
@@ -11927,6 +11941,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
intent.getAction());
if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
|| intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
+ || Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(intent.getAction())
|| uidRemoved) {
if (checkComponentPermission(
android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
@@ -11943,15 +11958,22 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
} else {
- Uri data = intent.getData();
- String ssp;
- if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
- if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
- forceStopPackageLocked(ssp,
- intent.getIntExtra(Intent.EXTRA_UID, -1), false);
- AttributeCache ac = AttributeCache.instance();
- if (ac != null) {
- ac.removePackage(ssp);
+ // If resources are unvailble just force stop all
+ // those packages and flush the attribute cache as well.
+ if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(intent.getAction())) {
+ String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ if (list != null && (list.length > 0)) {
+ for (String pkg : list) {
+ forceStopPackageLocked(pkg, -1, false, true);
+ }
+ }
+ } else {
+ Uri data = intent.getData();
+ String ssp;
+ if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
+ if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
+ forceStopPackageLocked(ssp,
+ intent.getIntExtra(Intent.EXTRA_UID, -1), false, true);
}
}
}
@@ -12113,25 +12135,32 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// installed. Maybe in the future we want to have a special install
// broadcast or such for apps, but we'd like to deliberately make
// this decision.
- boolean skip = false;
- if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
- skip = true;
- } else if (intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())) {
- skip = true;
- } else if (intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
- skip = true;
- }
- String skipPackage = (skip && intent.getData() != null)
- ? intent.getData().getSchemeSpecificPart()
- : null;
- if (skipPackage != null && receivers != null) {
- int NT = receivers.size();
- for (int it=0; it<NT; it++) {
- ResolveInfo curt = (ResolveInfo)receivers.get(it);
- if (curt.activityInfo.packageName.equals(skipPackage)) {
- receivers.remove(it);
- it--;
- NT--;
+ String skipPackages[] = null;
+ if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
+ || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
+ || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
+ Uri data = intent.getData();
+ if (data != null) {
+ String pkgName = data.getSchemeSpecificPart();
+ if (pkgName != null) {
+ skipPackages = new String[] { pkgName };
+ }
+ }
+ } else if (intent.ACTION_MEDIA_RESOURCES_AVAILABLE.equals(intent.getAction())) {
+ skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ }
+ if (skipPackages != null && (skipPackages.length > 0)) {
+ for (String skipPackage : skipPackages) {
+ if (skipPackage != null) {
+ int NT = receivers.size();
+ for (int it=0; it<NT; it++) {
+ ResolveInfo curt = (ResolveInfo)receivers.get(it);
+ if (curt.activityInfo.packageName.equals(skipPackage)) {
+ receivers.remove(it);
+ it--;
+ NT--;
+ }
+ }
}
}
}
@@ -12915,7 +12944,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
final long origId = Binder.clearCallingIdentity();
- forceStopPackageLocked(ii.targetPackage, -1, true);
+ forceStopPackageLocked(ii.targetPackage, -1, true, false);
ProcessRecord app = addAppLocked(ai);
app.instrumentationClass = className;
app.instrumentationInfo = ai;
@@ -12970,7 +12999,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
app.instrumentationProfileFile = null;
app.instrumentationArguments = null;
- forceStopPackageLocked(app.processName, -1, false);
+ forceStopPackageLocked(app.processName, -1, false, false);
}
public void finishInstrumentation(IApplicationThread target,
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 2d0f2544a725..7b722a5838e0 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -1807,16 +1807,30 @@ public class StatusBarService extends IStatusBar.Stub
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addDataScheme("package");
mContext.registerReceiver(this, filter);
+ IntentFilter sdFilter = new IntentFilter(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+ mContext.registerReceiver(this, sdFilter);
}
@Override
public void onReceive(Context context, Intent intent) {
- ArrayList<StatusBarNotification> list = null;
- synchronized (StatusBarService.this) {
+ String pkgList[] = null;
+ if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(intent.getAction())) {
+ pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ } else {
Uri data = intent.getData();
if (data != null) {
String pkg = data.getSchemeSpecificPart();
- list = mNotificationData.notificationsForPackage(pkg);
+ if (pkg != null) {
+ pkgList = new String[]{pkg};
+ }
+ }
+ }
+ ArrayList<StatusBarNotification> list = null;
+ if (pkgList != null) {
+ synchronized (StatusBarService.this) {
+ for (String pkg : pkgList) {
+ list = mNotificationData.notificationsForPackage(pkg);
+ }
}
}
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
new file mode 100644
index 000000000000..b07a10b57df9
--- /dev/null
+++ b/services/tests/servicestests/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+
+LOCAL_JAVA_LIBRARIES := android.test.runner services
+LOCAL_PACKAGE_NAME := FrameworksServicesTests
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
new file mode 100644
index 000000000000..5ce109f46e8b
--- /dev/null
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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.
+ 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.servicestests">
+
+ <uses-permission android:name="android.permission.READ_LOGS" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.frameworks.servicestests"
+ android:label="Frameworks Services Tests" />
+</manifest>
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DropBoxTest.java b/services/tests/servicestests/src/com/android/server/DropBoxTest.java
index d20abd92606e..3842d45004fe 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/DropBoxTest.java
+++ b/services/tests/servicestests/src/com/android/server/DropBoxTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package com.android.server;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
index 7586ba29c435..74218547a300 100644
--- a/telephony/java/com/android/internal/telephony/BaseCommands.java
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -65,6 +65,7 @@ public abstract class BaseCommands implements CommandsInterface {
protected RegistrantList mT53ClirInfoRegistrants = new RegistrantList();
protected RegistrantList mT53AudCntrlInfoRegistrants = new RegistrantList();
protected RegistrantList mRingbackToneRegistrants = new RegistrantList();
+ protected RegistrantList mResendIncallMuteRegistrants = new RegistrantList();
protected Registrant mSMSRegistrant;
protected Registrant mNITZTimeRegistrant;
@@ -579,6 +580,15 @@ public abstract class BaseCommands implements CommandsInterface {
mRingbackToneRegistrants.remove(h);
}
+ public void registerForResendIncallMute(Handler h, int what, Object obj) {
+ Registrant r = new Registrant (h, what, obj);
+ mResendIncallMuteRegistrants.add(r);
+ }
+
+ public void unregisterForResendIncallMute(Handler h) {
+ mResendIncallMuteRegistrants.remove(h);
+ }
+
//***** Protected Methods
/**
* Store new RadioState and send notification based on the changes
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index 1d9f10a96e03..d90c3056bf76 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -537,6 +537,18 @@ public interface CommandsInterface {
void registerForRingbackTone(Handler h, int what, Object obj);
void unregisterForRingbackTone(Handler h);
+ /**
+ * Registers the handler when mute/unmute need to be resent to get
+ * uplink audio during a call.<p>
+ *
+ * @param h Handler for notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ *
+ */
+ void registerForResendIncallMute(Handler h, int what, Object obj);
+ void unregisterForResendIncallMute(Handler h);
+
/**
* Supply the ICC PIN to the ICC card
*
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index a8ad80e9d673..7179bef9f165 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -407,6 +407,16 @@ public interface Phone {
void unregisterForRingbackTone(Handler h);
+ /**
+ * Registers the handler to reset the uplink mute state to get
+ * uplink audio.
+ */
+ void registerForResendIncallMute(Handler h, int what, Object obj);
+
+ /**
+ * Unregisters for resend incall mute notifications.
+ */
+ void unregisterForResendIncallMute(Handler h);
/**
* Notifies when a voice connection has disconnected, either due to local
@@ -1389,11 +1399,6 @@ public interface Phone {
/* CDMA support methods */
- /*
- * TODO(Moto) TODO(Teleca): can getCdmaMin, getEsn, getMeid use more generic calls
- * already defined getXxxx above?
- */
-
/**
* Retrieves the MIN for CDMA phones.
*/
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index bad9ab3e1611..358af9572f72 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -495,6 +495,16 @@ public abstract class PhoneBase extends Handler implements Phone {
mCM.unregisterForRingbackTone(h);
}
+ // Inherited documentation suffices.
+ public void registerForResendIncallMute(Handler h, int what, Object obj) {
+ mCM.registerForResendIncallMute(h,what,obj);
+ }
+
+ // Inherited documentation suffices.
+ public void unregisterForResendIncallMute(Handler h) {
+ mCM.unregisterForResendIncallMute(h);
+ }
+
/**
* Subclasses of Phone probably want to replace this with a
* version scoped to their packages
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index d56d99fd395c..6d3798ed1459 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -351,6 +351,14 @@ public class PhoneProxy extends Handler implements Phone {
mActivePhone.unregisterForRingbackTone(h);
}
+ public void registerForResendIncallMute(Handler h, int what, Object obj) {
+ mActivePhone.registerForResendIncallMute(h,what,obj);
+ }
+
+ public void unregisterForResendIncallMute(Handler h) {
+ mActivePhone.unregisterForResendIncallMute(h);
+ }
+
public boolean getIccRecordsLoaded() {
return mActivePhone.getIccRecordsLoaded();
}
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 1ffcf9b0e5dc..d8e313a79908 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -2333,6 +2333,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break;
case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break;
case RIL_UNSOL_RINGBACK_TONE: ret = responseInts(p); break;
+ case RIL_UNSOL_RESEND_INCALL_MUTE: ret = responseVoid(p); break;
default:
throw new RuntimeException("Unrecognized unsol response: " + response);
@@ -2625,6 +2626,15 @@ public final class RIL extends BaseCommands implements CommandsInterface {
mRingbackToneRegistrants.notifyRegistrants(
new AsyncResult (null, playtone, null));
}
+ break;
+
+ case RIL_UNSOL_RESEND_INCALL_MUTE:
+ if (RILJ_LOGD) unsljLogRet(response, ret);
+
+ if (mResendIncallMuteRegistrants != null) {
+ mResendIncallMuteRegistrants.notifyRegistrants(
+ new AsyncResult (null, ret, null));
+ }
}
}
@@ -2972,10 +2982,9 @@ public final class RIL extends BaseCommands implements CommandsInterface {
numServiceCategories = p.readInt();
if (numServiceCategories == 0) {
- // TODO(Teleca) TODO(Moto): The logic of providing default
- // values should not be done by this transport layer. And
- // needs to be done by the vendor ril or application logic.
- // TODO(Google): Remove ASAP
+ // TODO: The logic of providing default values should
+ // not be done by this transport layer. And needs to
+ // be done by the vendor ril or application logic.
int numInts;
numInts = CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES * CDMA_BSI_NO_OF_INTS_STRUCT + 1;
response = new int[numInts];
@@ -3268,6 +3277,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
case RIL_UNSOL_CDMA_INFO_REC: return "UNSOL_CDMA_INFO_REC";
case RIL_UNSOL_OEM_HOOK_RAW: return "UNSOL_OEM_HOOK_RAW";
case RIL_UNSOL_RINGBACK_TONE: return "UNSOL_RINGBACK_TONG";
+ case RIL_UNSOL_RESEND_INCALL_MUTE: return "UNSOL_RESEND_INCALL_MUTE";
default: return "<unknown reponse>";
}
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index c29adcf7e103..4d8c7ec86e87 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -259,4 +259,5 @@ cat include/telephony/ril.h | \
int RIL_UNSOL_CDMA_INFO_REC = 1027;
int RIL_UNSOL_OEM_HOOK_RAW = 1028;
int RIL_UNSOL_RINGBACK_TONE = 1029;
+ int RIL_UNSOL_RESEND_INCALL_MUTE = 1030;
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index d4b1652e6a7c..1f5accf38f21 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -681,7 +681,7 @@ public class CDMAPhone extends PhoneBase {
public String getVoiceMailNumber() {
String number = null;
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
- // TODO(Moto): The default value of voicemail number should be read from a system property
+ // TODO: The default value of voicemail number should be read from a system property
number = sp.getString(VM_NUMBER_CDMA, "*86");
return number;
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaInformationRecords.java b/telephony/java/com/android/internal/telephony/cdma/CdmaInformationRecords.java
index 7402769cee40..ce6530af8ce6 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaInformationRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaInformationRecords.java
@@ -74,7 +74,7 @@ public final class CdmaInformationRecords {
break;
case RIL_CDMA_T53_RELEASE_INFO_REC:
- // TODO(Moto): WHAT to do, for now fall through and throw exception
+ // TODO: WHAT to do, for now fall through and throw exception
default:
throw new RuntimeException("RIL_UNSOL_CDMA_INFO_REC: unsupported record. Got "
+ CdmaInformationRecords.idToString(id) + " ");
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 42feaa904b10..7f2ba47c44ff 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -1622,9 +1622,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
* Returns IMSI as MCC + MNC + MIN
*/
String getImsi() {
- // TODO(Moto): When RUIM is enabled, IMSI will come from RUIM
- // not build-time props. Moto will provide implementation
- // for RUIM-ready case later.
+ // TODO: When RUIM is enabled, IMSI will come from RUIM not build-time props.
String operatorNumeric = SystemProperties.get(
TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
index b9ece8b965ee..87b0c6060cd2 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -166,10 +166,8 @@ public final class RuimRecords extends IccRecords {
return null;
}
- // TODO(Moto): mncLength is not set anywhere.
if (mncLength != UNINITIALIZED && mncLength != UNKNOWN) {
// Length = length of MCC + length of MNC
- // TODO: change spec name
// length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
return mImsi.substring(0, 3 + mncLength);
}
diff --git a/telephony/tests/telephonytests/AndroidManifest.xml b/telephony/tests/telephonytests/AndroidManifest.xml
index 70aeebc59d15..6a9742343b75 100644
--- a/telephony/tests/telephonytests/AndroidManifest.xml
+++ b/telephony/tests/telephonytests/AndroidManifest.xml
@@ -33,4 +33,5 @@
android:label="Frameworks Telephony Tests">
</instrumentation>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
+
</manifest>
diff --git a/tests/AndroidTests/src/com/android/unit_tests/GsmSmsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
index 8987d6bf5d96..3103fc17e20d 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/GsmSmsTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/GsmSmsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package com.android.internal.telephony;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.SmsHeader;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/MccTableTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
index b2f1dede317d..1ea1285080cc 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/MccTableTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package com.android.internal.telephony;
import com.android.internal.telephony.MccTable;
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java
new file mode 100644
index 000000000000..b63dc71b45fc
--- /dev/null
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/NeighboringCellInfoTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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 com.android.internal.telephony;
+
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.telephony.NeighboringCellInfo;
+import android.test. suitebuilder.annotation.SmallTest;
+
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_EDGE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_GPRS;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
+
+public class NeighboringCellInfoTest extends AndroidTestCase {
+ @SmallTest
+ public void testConstructor() {
+ int rssi = 31;
+ NeighboringCellInfo nc;
+
+ nc = new NeighboringCellInfo(rssi, "FFFFFFF", NETWORK_TYPE_EDGE);
+ assertEquals(NETWORK_TYPE_EDGE, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(0xfff, nc.getLac());
+ assertEquals(0xffff, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
+
+ nc = new NeighboringCellInfo(rssi, "1FF", NETWORK_TYPE_UMTS);
+ assertEquals(NETWORK_TYPE_UMTS, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getLac());
+ assertEquals(0x1ff, nc.getPsc());
+
+ nc = new NeighboringCellInfo(rssi, "1FF", NETWORK_TYPE_UNKNOWN);
+ assertEquals(NETWORK_TYPE_UNKNOWN, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getLac());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
+ }
+
+ @SmallTest
+ public void testParcel() {
+ int rssi = 20;
+
+ NeighboringCellInfo nc = new NeighboringCellInfo(rssi, "12345678", NETWORK_TYPE_GPRS);
+ assertEquals(NETWORK_TYPE_GPRS, nc.getNetworkType());
+ assertEquals(rssi, nc.getRssi());
+ assertEquals(0x1234, nc.getLac());
+ assertEquals(0x5678, nc.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nc.getPsc());
+
+ Parcel p = Parcel.obtain();
+ p.setDataPosition(0);
+ nc.writeToParcel(p, 0);
+
+ p.setDataPosition(0);
+ NeighboringCellInfo nw = new NeighboringCellInfo(p);
+ assertEquals(NETWORK_TYPE_GPRS, nw.getNetworkType());
+ assertEquals(rssi, nw.getRssi());
+ assertEquals(0x1234, nw.getLac());
+ assertEquals(0x5678, nw.getCid());
+ assertEquals(NeighboringCellInfo.UNKNOWN_CID, nw.getPsc());
+ }
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
index db47693db934..58e73e0dabbc 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package com.android.internal.telephony.cdma.sms;
import android.telephony.TelephonyManager;
diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java
index 2f313af62c6c..cbe0253f59ef 100644
--- a/test-runner/android/test/mock/MockPackageManager.java
+++ b/test-runner/android/test/mock/MockPackageManager.java
@@ -438,4 +438,12 @@ public class MockPackageManager extends PackageManager {
public boolean isSafeMode() {
throw new UnsupportedOperationException();
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/tests/AndroidTests/Android.mk b/tests/AndroidTests/Android.mk
index a81b77908077..bff8fba2c6ac 100644
--- a/tests/AndroidTests/Android.mk
+++ b/tests/AndroidTests/Android.mk
@@ -11,8 +11,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := gsf-client
LOCAL_AAPT_FLAGS = -c xx_YY -c cs -c 160dpi -c 32dpi -c 240dpi
LOCAL_SRC_FILES := \
- $(call all-subdir-java-files) \
- src/com/android/unit_tests/os/IAidlTest.aidl
+ $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := AndroidTests
LOCAL_CERTIFICATE := platform
diff --git a/tests/AndroidTests/AndroidManifest.xml b/tests/AndroidTests/AndroidManifest.xml
index e0d8f79bce0e..c2548b927c82 100644
--- a/tests/AndroidTests/AndroidManifest.xml
+++ b/tests/AndroidTests/AndroidManifest.xml
@@ -17,21 +17,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.unit_tests"
android:sharedUserId="com.android.uid.test">
- <permission android:name="com.android.unit_tests.permission.TEST_GRANTED"
- android:protectionLevel="normal"
- android:label="@string/permlab_testGranted"
- android:description="@string/permdesc_testGranted">
- <meta-data android:name="com.android.unit_tests.string" android:value="foo" />
- <meta-data android:name="com.android.unit_tests.boolean" android:value="true" />
- <meta-data android:name="com.android.unit_tests.integer" android:value="100" />
- <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" />
- <meta-data android:name="com.android.unit_tests.float" android:value="100.1" />
- <meta-data android:name="com.android.unit_tests.reference" android:resource="@xml/metadata" />
- </permission>
- <permission android:name="com.android.unit_tests.permission.TEST_DENIED"
- android:protectionLevel="normal"
- android:label="@string/permlab_testDenied"
- android:description="@string/permdesc_testDenied" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
@@ -39,19 +24,12 @@
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
<uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.READ_LOGS"/>
- <uses-permission android:name="android.permission.READ_PHONE_STATE" />
- <uses-permission android:name="android.permission.READ_SMS"/>
- <uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
- <uses-permission android:name="android.permission.WRITE_CONTACTS" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
- <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
- <uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="com.android.unit_tests.permission.TEST_GRANTED" />
+ <uses-permission android:name="com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD" />
+ <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
+ <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.ALL_SERVICES" />
<!-- InstrumentationTestRunner for AndroidTests -->
<instrumentation android:name="android.test.InstrumentationTestRunner"
@@ -60,17 +38,6 @@
<application>
<uses-library android:name="android.test.runner" />
-
- <!-- Activity-level metadata -->
- <meta-data android:name="com.android.unit_tests.isApp" android:value="true" />
- <meta-data android:name="com.android.unit_tests.string" android:value="foo" />
- <meta-data android:name="com.android.unit_tests.boolean" android:value="true" />
- <meta-data android:name="com.android.unit_tests.integer" android:value="100" />
- <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" />
- <meta-data android:name="com.android.unit_tests.float" android:value="100.1" />
- <meta-data android:name="com.android.unit_tests.reference"
- android:resource="@xml/metadata_app" />
-
<activity android:name="AndroidPerformanceTests" android:label="Android Performance Tests">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -78,167 +45,5 @@
</intent-filter>
</activity>
- <!-- Application components used for activity tests -->
-
- <activity android:name=".activity.TestedActivity"
- android:process=":remoteActivity">
- </activity>
- <activity android:name=".activity.LocalActivity" android:multiprocess="true">
- <meta-data android:name="com.android.unit_tests.string" android:value="foo" />
- <meta-data android:name="com.android.unit_tests.boolean" android:value="true" />
- <meta-data android:name="com.android.unit_tests.integer" android:value="100" />
- <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" />
- <meta-data android:name="com.android.unit_tests.float" android:value="100.1" />
- <meta-data android:name="com.android.unit_tests.reference" android:resource="@xml/metadata" />
- </activity>
- <activity android:name=".activity.TestedScreen"
- android:process=":remoteScreen">
- </activity>
- <activity android:name=".activity.LocalScreen" android:multiprocess="true">
- </activity>
- <activity android:name=".activity.ClearTop" android:multiprocess="true"
- android:launchMode="singleTop">
- </activity>
- <activity android:name=".activity.LocalDialog" android:multiprocess="true"
- android:theme="@android:style/Theme.Dialog">
- </activity>
- <activity android:name=".activity.SubActivityScreen">
- </activity>
- <activity android:name=".activity.RemoteSubActivityScreen"
- android:process=":remoteActivity">
- </activity>
- <activity android:name=".activity.LaunchpadActivity" android:multiprocess="true">
- </activity>
- <activity android:name=".activity.LaunchpadTabActivity" android:multiprocess="true">
- </activity>
-
- <receiver android:name=".activity.AbortReceiver">
- <intent-filter android:priority="1">
- <action android:name="com.android.unit_tests.activity.BROADCAST_ABORT" />
- </intent-filter>
- </receiver>
- <receiver android:name=".activity.LocalReceiver">
- <intent-filter android:priority="-1">
- <action android:name="com.android.unit_tests.activity.BROADCAST_ABORT" />
- <action android:name="com.android.unit_tests.activity.BROADCAST_ALL" />
- <action android:name="com.android.unit_tests.activity.BROADCAST_REPEAT" />
- <action android:name="com.android.unit_tests.activity.BROADCAST_LOCAL" />
- <action android:name="com.android.unit_tests.activity.BROADCAST_FAIL_REGISTER" />
- <action android:name="com.android.unit_tests.activity.BROADCAST_FAIL_BIND" />
- </intent-filter>
- <meta-data android:name="com.android.unit_tests.string" android:value="foo" />
- <meta-data android:name="com.android.unit_tests.boolean" android:value="true" />
- <meta-data android:name="com.android.unit_tests.integer" android:value="100" />
- <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" />
- <meta-data android:name="com.android.unit_tests.float" android:value="100.1" />
- <meta-data android:name="com.android.unit_tests.reference" android:resource="@xml/metadata" />
- </receiver>
- <receiver android:name=".activity.ResultReceiver">
- <intent-filter>
- <action android:name="com.android.unit_tests.activity.BROADCAST_RESULT" />
- </intent-filter>
- </receiver>
- <receiver android:name=".activity.LocalGrantedReceiver"
- android:permission="com.android.unit_tests.permission.TEST_GRANTED">
- <intent-filter android:priority="-1">
- <action android:name="com.android.unit_tests.activity.BROADCAST_LOCAL_GRANTED" />
- </intent-filter>
- </receiver>
- <receiver android:name=".activity.LocalDeniedReceiver"
- android:permission="com.android.unit_tests.permission.TEST_DENIED">
- <intent-filter android:priority="-1">
- <action android:name="com.android.unit_tests.activity.BROADCAST_LOCAL_DENIED" />
- </intent-filter>
- </receiver>
- <receiver android:name=".activity.RemoteReceiver"
- android:process=":remoteReceiver">
- <intent-filter android:priority="2">
- <action android:name="com.android.unit_tests.activity.BROADCAST_ABORT" />
- <action android:name="com.android.unit_tests.activity.BROADCAST_ALL" />
- <action android:name="com.android.unit_tests.activity.BROADCAST_REPEAT" />
- <action android:name="com.android.unit_tests.activity.BROADCAST_REMOTE" />
- </intent-filter>
- </receiver>
- <receiver android:name=".activity.RemoteGrantedReceiver"
- android:permission="com.android.unit_tests.permission.TEST_GRANTED">
- <intent-filter android:priority="2">
- <action android:name="com.android.unit_tests.activity.BROADCAST_REMOTE_GRANTED" />
- </intent-filter>
- </receiver>
- <receiver android:name=".activity.RemoteDeniedReceiver"
- android:permission="com.android.unit_tests.permission.TEST_DENIED">
- <intent-filter android:priority="2">
- <action android:name="com.android.unit_tests.activity.BROADCAST_REMOTE_DENIED" />
- </intent-filter>
- </receiver>
- <service android:name=".activity.LocalService">
- <intent-filter>
- <action android:name="com.android.unit_tests.activity.SERVICE_LOCAL" />
- </intent-filter>
- <meta-data android:name="com.android.unit_tests.string" android:value="foo" />
- <meta-data android:name="com.android.unit_tests.boolean" android:value="true" />
- <meta-data android:name="com.android.unit_tests.integer" android:value="100" />
- <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" />
- <meta-data android:name="com.android.unit_tests.float" android:value="100.1" />
- <meta-data android:name="com.android.unit_tests.reference" android:resource="@xml/metadata" />
- </service>
- <service android:name=".activity.LocalDeniedService"
- android:permission="com.android.unit_tests.permission.TEST_DENIED">
- <intent-filter>
- <action android:name="com.android.unit_tests.activity.SERVICE_LOCAL_DENIED" />
- </intent-filter>
- </service>
- <service android:name=".activity.LocalGrantedService"
- android:permission="com.android.unit_tests.permission.TEST_GRANTED">
- <intent-filter>
- <action android:name="com.android.unit_tests.activity.SERVICE_LOCAL_GRANTED" />
- </intent-filter>
- </service>
-
- <provider android:name=".activity.LocalProvider"
- android:authorities="com.android.unit_tests.LocalProvider">
- <meta-data android:name="com.android.unit_tests.string" android:value="foo" />
- <meta-data android:name="com.android.unit_tests.boolean" android:value="true" />
- <meta-data android:name="com.android.unit_tests.integer" android:value="100" />
- <meta-data android:name="com.android.unit_tests.color" android:value="#ff000000" />
- <meta-data android:name="com.android.unit_tests.float" android:value="100.1" />
- <meta-data android:name="com.android.unit_tests.reference" android:resource="@xml/metadata" />
- </provider>
-
- <!-- Application components used for content tests -->
- <provider android:name=".content.MemoryFileProvider"
- android:authorities="com.android.unit_tests.content.MemoryFileProvider"
- android:process=":MemoryFileProvider">
- </provider>
-
- <!-- Application components used for os tests -->
-
- <service android:name=".os.MessengerService"
- android:process=":messengerService">
- </service>
-
- <!-- Application components used for search manager tests -->
-
- <activity android:name=".SearchableActivity"
- android:label="Searchable Activity">
- <intent-filter>
- <action android:name="android.intent.action.SEARCH" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- <meta-data android:name="android.app.searchable"
- android:resource="@xml/searchable" />
- </activity>
-
- <provider android:name=".SuggestionProvider"
- android:authorities="com.android.unit_tests.SuggestionProvider">
- </provider>
-
- <!-- Used to test IPC. -->
- <service android:name=".binder.BinderTestService"
- android:process="binder.BinderTestService" />
- <service android:name=".binder.BinderPerformanceService"
- android:process="binder.BinderPerformanceService" />
- <service android:name=".binder.BinderVsMessagingService"
- android:process="binder.BinderVsMessagingService" />
</application>
</manifest>
diff --git a/tests/AndroidTests/res/layout/layout_three.xml b/tests/AndroidTests/res/layout/layout_three.xml
deleted file mode 100644
index 7b1ccc54149a..000000000000
--- a/tests/AndroidTests/res/layout/layout_three.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 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.
-*/
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
- <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view1" android:layout_width="match_parent" android:layout_height="match_parent"/>
- <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view2" android:layout_width="match_parent" android:layout_height="match_parent"/>
- <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view3" android:layout_width="match_parent" android:layout_height="match_parent"/>
- <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view4" android:layout_width="match_parent" android:layout_height="match_parent"/>
- <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view5" android:layout_width="match_parent" android:layout_height="match_parent"/>
- <view class="com.android.unit_tests.InflateTest$ViewOne" android:id="@+id/view6" android:layout_width="match_parent" android:layout_height="match_parent"/>
-</LinearLayout>
diff --git a/tests/AndroidTests/res/values/strings.xml b/tests/AndroidTests/res/values/strings.xml
index 49d8ae72d964..e8b150a7aacc 100644
--- a/tests/AndroidTests/res/values/strings.xml
+++ b/tests/AndroidTests/res/values/strings.xml
@@ -8,25 +8,13 @@
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,
+ distributed under the License is distributed on an "AS IS" BASI
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.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="permlab_testGranted">Test Granted</string>
- <string name="permdesc_testGranted">Used for running unit tests, for
- testing operations where we have the permission.</string>
- <string name="permlab_testDenied">Test Denied</string>
- <string name="permdesc_testDenied">Used for running unit tests, for
- testing operations where we do not have the permission.</string>
-
- <string name="layout_five_text_text">S</string>
-
- <string name="layout_four_text_text">S</string>
-
- <string name="layout_six_text_text">S</string>
<string name="coerceIntegerToString">100</string>
<string name="coerceBooleanToString">true</string>
@@ -41,17 +29,10 @@
<string name="reference">here</string>
- <string name="metadata_text">text</string>
-
- <string name="menu_test">test</string>
-
<plurals name="plurals_test">
<item quantity="one">A dog</item>
<item quantity="other">Some dogs</item>
</plurals>
- <string name="searchable_label">SearchManager Test</string>
- <string name="searchable_hint">A search hint</string>
-
<!-- <string name="layout_six_text_text">F</string> -->
</resources>
diff --git a/tests/AndroidTests/src/com/android/unit_tests/AndroidPerformanceTests.java b/tests/AndroidTests/src/com/android/unit_tests/AndroidPerformanceTests.java
index b6a859457e21..795fe2bf60a6 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/AndroidPerformanceTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/AndroidPerformanceTests.java
@@ -27,12 +27,8 @@ public class AndroidPerformanceTests extends TestListActivity {
public static class Suite {
public static String[] children() {
return new String[] {
- DatabasePerformanceTests.class.getName(),
- GraphicsPerformanceTests.class.getName(),
JavaPerformanceTests.class.getName(),
- LogTest.PerformanceTest.class.getName(),
PerformanceTests.class.getName(),
- TextViewPerformanceTest.class.getName(),
};
}
}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
index f33b01dd278f..50451e75ae41 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
@@ -16,6 +16,7 @@
package com.android.dumprendertree;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.webkit.MockGeolocation;
@@ -24,7 +25,7 @@ import android.webkit.WebStorage;
import java.util.HashMap;
public class CallbackProxy extends Handler implements EventSender, LayoutTestController {
-
+
private EventSender mEventSender;
private LayoutTestController mLayoutTestController;
@@ -37,6 +38,15 @@ public class CallbackProxy extends Handler implements EventSender, LayoutTestCon
private static final int EVENT_MOUSE_DOWN = 7;
private static final int EVENT_MOUSE_MOVE = 8;
private static final int EVENT_MOUSE_UP = 9;
+ private static final int EVENT_TOUCH_START = 10;
+ private static final int EVENT_TOUCH_MOVE = 11;
+ private static final int EVENT_TOUCH_END = 12;
+ private static final int EVENT_TOUCH_CANCEL = 13;
+ private static final int EVENT_ADD_TOUCH_POINT = 14;
+ private static final int EVENT_UPDATE_TOUCH_POINT = 15;
+ private static final int EVENT_RELEASE_TOUCH_POINT = 16;
+ private static final int EVENT_CLEAR_TOUCH_POINTS = 17;
+ private static final int EVENT_CANCEL_TOUCH_POINT = 18;
private static final int LAYOUT_CLEAR_LIST = 20;
private static final int LAYOUT_DISPLAY = 21;
@@ -107,6 +117,46 @@ public class CallbackProxy extends Handler implements EventSender, LayoutTestCon
mEventSender.mouseUp();
break;
+ case EVENT_TOUCH_START:
+ mEventSender.touchStart();
+ break;
+
+ case EVENT_TOUCH_MOVE:
+ mEventSender.touchMove();
+ break;
+
+ case EVENT_TOUCH_END:
+ mEventSender.touchEnd();
+ break;
+
+ case EVENT_TOUCH_CANCEL:
+ mEventSender.touchCancel();
+ break;
+
+ case EVENT_ADD_TOUCH_POINT:
+ mEventSender.addTouchPoint(msg.arg1, msg.arg2);
+ break;
+
+ case EVENT_UPDATE_TOUCH_POINT:
+ Bundle args = (Bundle) msg.obj;
+ int x = args.getInt("x");
+ int y = args.getInt("y");
+ int id = args.getInt("id");
+ mEventSender.updateTouchPoint(id, x, y);
+ break;
+
+ case EVENT_RELEASE_TOUCH_POINT:
+ mEventSender.releaseTouchPoint(msg.arg1);
+ break;
+
+ case EVENT_CLEAR_TOUCH_POINTS:
+ mEventSender.clearTouchPoints();
+ break;
+
+ case EVENT_CANCEL_TOUCH_POINT:
+ mEventSender.cancelTouchPoint(msg.arg1);
+ break;
+
case LAYOUT_CLEAR_LIST:
mLayoutTestController.clearBackForwardList();
break;
@@ -252,6 +302,51 @@ public class CallbackProxy extends Handler implements EventSender, LayoutTestCon
public void mouseUp() {
obtainMessage(EVENT_MOUSE_UP).sendToTarget();
}
+
+ public void touchStart() {
+ obtainMessage(EVENT_TOUCH_START).sendToTarget();
+ }
+
+ public void addTouchPoint(int x, int y) {
+ obtainMessage(EVENT_ADD_TOUCH_POINT, x, y).sendToTarget();
+ }
+
+ public void updateTouchPoint(int id, int x, int y) {
+ Bundle map = new Bundle();
+ map.putInt("x", x);
+ map.putInt("y", y);
+ map.putInt("id", id);
+ obtainMessage(EVENT_UPDATE_TOUCH_POINT, map).sendToTarget();
+ }
+
+ public void setTouchModifier(String modifier, boolean enabled) {
+ // TODO(benm): Android doesn't support key modifiers on touch events yet.
+ }
+
+ public void touchMove() {
+ obtainMessage(EVENT_TOUCH_MOVE).sendToTarget();
+ }
+
+ public void releaseTouchPoint(int id) {
+ obtainMessage(EVENT_RELEASE_TOUCH_POINT, id, 0).sendToTarget();
+ }
+
+ public void touchEnd() {
+ obtainMessage(EVENT_TOUCH_END).sendToTarget();
+ }
+
+ public void touchCancel() {
+ obtainMessage(EVENT_TOUCH_CANCEL).sendToTarget();
+ }
+
+
+ public void clearTouchPoints() {
+ obtainMessage(EVENT_CLEAR_TOUCH_POINTS).sendToTarget();
+ }
+
+ public void cancelTouchPoint(int id) {
+ obtainMessage(EVENT_CANCEL_TOUCH_POINT, id, 0).sendToTarget();
+ }
// LayoutTestController Methods
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/EventSender.java b/tests/DumpRenderTree/src/com/android/dumprendertree/EventSender.java
index 82fd8d8d61de..23cc8f531bb0 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/EventSender.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/EventSender.java
@@ -26,4 +26,14 @@ public interface EventSender {
public void keyDown (String character);
public void enableDOMUIEventLogging(int DOMNode);
public void fireKeyboardEventsToElement(int DOMNode);
+ public void touchStart();
+ public void touchMove();
+ public void touchEnd();
+ public void touchCancel();
+ public void addTouchPoint(int x, int y);
+ public void updateTouchPoint(int id, int x, int y);
+ public void setTouchModifier(String modifier, boolean enabled);
+ public void releaseTouchPoint(int id);
+ public void clearTouchPoints();
+ public void cancelTouchPoint(int id);
}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 32219fad6397..452368eb309a 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -96,6 +96,8 @@ public class FileFilter {
// tests expect "LayoutTests" in their output.
"storage/domstorage/localstorage/iframe-events.html",
"storage/domstorage/sessionstorage/iframe-events.html",
+ // We do not support multi touch events.
+ "fast/events/touch/basic-multi-touch-events.html",
// below tests (failed or crashes) are filtered out temporarily due to prioritizing
"editing/selection/move-left-right.html",
};
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 5763b85e04b3..e8a66c19b608 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -705,6 +705,7 @@ public class TestShellActivity extends Activity implements LayoutTestController
mDumpDatabaseCallbacks = false;
mCanOpenWindows = false;
mEventSender.resetMouse();
+ mEventSender.clearTouchPoints();
mPageFinished = false;
mOneHundredPercentComplete = false;
mDumpWebKitData = false;
@@ -769,6 +770,12 @@ public class TestShellActivity extends Activity implements LayoutTestController
webview.setWebChromeClient(mChromeClient);
webview.setWebViewClient(mViewClient);
+ // Setting a touch interval of -1 effectively disables the optimisation in WebView
+ // that stops repeated touch events flooding WebCore. The Event Sender only sends a
+ // single event rather than a stream of events (like what would generally happen in
+ // a real use of touch events in a WebView) and so if the WebView drops the event,
+ // the test will fail as the test expects one callback for every touch it synthesizes.
+ webview.setTouchInterval(-1);
}
private WebView mWebView;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java b/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
index eea634636978..996eaba0b73e 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
@@ -16,17 +16,25 @@
package com.android.dumprendertree;
-import android.webkit.WebView;
-import android.view.KeyEvent;
+import android.os.Handler;
+import android.os.SystemClock;
import android.util.*;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.webkit.WebView;
+import java.lang.InterruptedException;
import java.util.Arrays;
+import java.util.Vector;
public class WebViewEventSender implements EventSender {
+
+ private static final String LOGTAG = "WebViewEventSender";
- WebViewEventSender(WebView webView) {
- mWebView = webView;
- }
+ WebViewEventSender(WebView webView) {
+ mWebView = webView;
+ mTouchPoints = new Vector();
+ }
public void resetMouse() {
mouseX = mouseY = 0;
@@ -186,9 +194,162 @@ public class WebViewEventSender implements EventSender {
}
return KeyEvent.KEYCODE_UNKNOWN;
}
-
+
+ public void touchStart() {
+ // We only support single touch so examine the first touch point only.
+ // If multi touch is enabled in the future, we need to re-examine this to send
+ // all the touch points with the event.
+ TouchPoint tp = mTouchPoints.get(0);
+
+ if (tp == null) {
+ return;
+ }
+
+ tp.setDownTime(SystemClock.uptimeMillis());
+ MotionEvent event = MotionEvent.obtain(tp.downTime(), tp.downTime(),
+ MotionEvent.ACTION_DOWN, tp.getX(), tp.getY(), 0);
+ mWebView.onTouchEvent(event);
+ }
+
+ public void touchMove() {
+ TouchPoint tp = mTouchPoints.get(0);
+
+ if (tp == null) {
+ return;
+ }
+
+ if (!tp.hasMoved()) {
+ return;
+ }
+
+ MotionEvent event = MotionEvent.obtain(tp.downTime(), SystemClock.uptimeMillis(),
+ MotionEvent.ACTION_MOVE, tp.getX(), tp.getY(), 0);
+ mWebView.onTouchEvent(event);
+
+ tp.setMoved(false);
+ }
+
+ public void touchEnd() {
+ TouchPoint tp = mTouchPoints.get(0);
+
+ if (tp == null) {
+ return;
+ }
+
+ MotionEvent event = MotionEvent.obtain(tp.downTime(), SystemClock.uptimeMillis(),
+ MotionEvent.ACTION_UP, tp.getX(), tp.getY(), 0);
+ mWebView.onTouchEvent(event);
+
+ if (tp.isReleased()) {
+ mTouchPoints.remove(0);
+ }
+ }
+
+ public void touchCancel() {
+ TouchPoint tp = mTouchPoints.get(0);
+ if (tp == null) {
+ return;
+ }
+
+ if (tp.cancelled()) {
+ MotionEvent event = MotionEvent.obtain(tp.downTime(), SystemClock.uptimeMillis(),
+ MotionEvent.ACTION_CANCEL, tp.getX(), tp.getY(), 0);
+ mWebView.onTouchEvent(event);
+ }
+ }
+
+ public void cancelTouchPoint(int id) {
+ TouchPoint tp = mTouchPoints.get(0);
+ if (tp == null) {
+ return;
+ }
+
+ tp.cancel();
+ }
+
+ public void addTouchPoint(int x, int y) {
+ mTouchPoints.add(new TouchPoint(contentsToWindowX(x), contentsToWindowY(y)));
+ if (mTouchPoints.size() > 1) {
+ Log.w(LOGTAG, "Adding more than one touch point, but multi touch is not supported!");
+ }
+ }
+
+ public void updateTouchPoint(int id, int x, int y) {
+ TouchPoint tp = mTouchPoints.get(0);
+ if (tp == null) {
+ return;
+ }
+
+ tp.update(contentsToWindowX(x), contentsToWindowY(y));
+ tp.setMoved(true);
+ }
+
+ public void setTouchModifier(String modifier, boolean enabled) {
+ // TODO(benm): This needs implementing when Android supports sending key modifiers
+ // in touch events.
+ }
+
+ public void releaseTouchPoint(int id) {
+ TouchPoint tp = mTouchPoints.get(0);
+ if (tp == null) {
+ return;
+ }
+
+ tp.release();
+ }
+
+ public void clearTouchPoints() {
+ mTouchPoints.clear();
+ }
+
+ private int contentsToWindowX(int x) {
+ return (int) (x * mWebView.getScale()) - mWebView.getScrollX();
+ }
+
+ private int contentsToWindowY(int y) {
+ return (int) (y * mWebView.getScale()) - mWebView.getScrollY();
+ }
+
private WebView mWebView = null;
private int mouseX;
private int mouseY;
+ private class TouchPoint {
+ private int mX;
+ private int mY;
+ private long mDownTime;
+ private boolean mReleased;
+ private boolean mMoved;
+ private boolean mCancelled;
+
+ public TouchPoint(int x, int y) {
+ mX = x;
+ mY = y;
+ mReleased = false;
+ mMoved = false;
+ mCancelled = false;
+ }
+
+ public void setDownTime(long downTime) { mDownTime = downTime; }
+ public long downTime() { return mDownTime; }
+ public void cancel() { mCancelled = true; }
+
+ public boolean cancelled() { return mCancelled; }
+
+ public void release() { mReleased = true; }
+ public boolean isReleased() { return mReleased; }
+
+ public void setMoved(boolean moved) { mMoved = moved; }
+ public boolean hasMoved() { return mMoved; }
+
+ public int getX() { return mX; }
+ public int getY() { return mY; }
+
+ public void update(int x, int y) {
+ mX = x;
+ mY = y;
+ }
+ };
+
+ private Vector<TouchPoint> mTouchPoints;
}
diff --git a/tests/FrameworkTest/AndroidManifest.xml b/tests/FrameworkTest/AndroidManifest.xml
index 3030c06be7b2..4db895206660 100644
--- a/tests/FrameworkTest/AndroidManifest.xml
+++ b/tests/FrameworkTest/AndroidManifest.xml
@@ -41,934 +41,12 @@
</intent-filter>
</activity>
- <activity android:name=".focus.DescendantFocusability" android:label="DescendantFocusability">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.FocusAfterRemoval" android:label="FocusAfterRemoval">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.RequestFocus" android:label="RequestFocus">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />V
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.ListOfButtons" android:label="ListOfButtons">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.LinearLayoutGrid" android:label="LinearLayoutGrid">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.ListOfEditTexts" android:label="ListOfEditTexts">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.ListOfInternalSelectionViews" android:label="ListOfInternalSelectionViews">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.ListWithFooterViewAndNewLabels" android:label="FocusListWithFooter">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.ListWithMailMessages" android:label="ListWithMailMessages">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.HorizontalFocusSearch" android:label="HorizontalFocusSearch">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.VerticalFocusSearch" android:label="VerticalFocusSearch">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.AdjacentVerticalRectLists" android:label="AdjacentVerticalRectLists">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".focus.GoneParentFocusedChild" android:label="GoneParentFocusedChild">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.frame.FrameLayoutGravity" android:label="FrameLayoutGravity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.frame.FrameLayoutMargin" android:label="FrameLayoutMargin">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.BaselineAlignmentCenterGravity" android:label="BaselineAlignmentCenterGravity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.BaselineButtons" android:label="BaselineButtons">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.FillInWrap" android:label="FillInWrap">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.BaselineAlignmentZeroWidthAndWeight" android:label="Baseline0WidthAndWeight">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.HorizontalOrientationVerticalAlignment" android:label="HorizontalOrientationVerticalAlignment">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.LLEditTextThenButton" android:label="LLEditTextThenButton">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.LLOfButtons1" android:label="LLOfButtons1">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.LinearLayoutEditTexts" android:label="LinearLayoutEditTexts">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.LLOfButtons2" android:label="LLOfButtons2">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.LLOfTwoFocusableInTouchMode" android:label="LLOfTwoFocusableInTouchMode">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.Weight" android:label="Weight">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.linear.WeightSum" android:label="WeightSum">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.AdjacentListsWithAdjacentISVsInside" android:label="AdjacentListsWithAdjacentISVsInside">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListDividers" android:label="ListDividers">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListViewHeight" android:label="ListViewHeight">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.table.FixedWidth" android:label="CellFixedWidth">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.table.Weight" android:label="CellWeight">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.table.HorizontalGravity" android:label="CellHorizontalGravity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.table.VerticalGravity" android:label="CellVerticalGravity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.table.AddColumn" android:label="AddColumnInTable">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".layout.table.CellSpan" android:label="CellSpan">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".scroll.ButtonAboveTallInternalSelectionView" android:label="ButtonAboveTallInternalSelectionView">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".scroll.ButtonsWithTallTextViewInBetween" android:label="scrollButtonsWithTallTextViewInBetween">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".scroll.RequestRectangleVisible" android:label="ScrollToChildRect">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".scroll.RequestRectangleVisibleWithInternalScroll" android:label="ScrollToChildRectWithInternalScroll">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".scroll.ScrollViewButtonsAndLabels" android:label="ScrollViewButtonsAndLabels">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".scroll.ShortButtons" android:label="scrollShortButtons">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".scroll.TallTextAboveButton" android:label="scrollTallTextAboveButton">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.Include" android:label="IncludeTag">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.Merge" android:label="MergeTag">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.StubbedView" android:label="ViewStub">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.RunQueue" android:label="RunQueue">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.Visibility" android:label="Visibility">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.VisibilityCallback" android:label="VisibilityCallback">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.BigCache" android:label="BigCache">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.ZeroSized" android:label="ZeroSized">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.Disabled" android:label="Disabled">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.PopupWindowVisibility" android:label="PopupWindowVisibility">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.PreDrawListener" android:label="PreDrawListener">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.GlobalFocusChange" android:label="GlobalFocusChange">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListSetSelection" android:label="ListSetSelection">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListSimple" android:label="ListSimple">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListFilter" android:label="ListFilter">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListScrollListener" android:label="ListScrollListener">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListThrasher" android:label="ListThrasher">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListTakeFocusFromSide" android:label="ListTakeFocusFromSide">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListBottomGravity" android:label="ListBottomGravity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListBottomGravityMany" android:label="ListBottomGravityMany">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
-
- <activity android:name=".listview.ListButtonsDiagonalAcrossItems" android:label="ListButtonsDiagonalAcrossItems">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListTopGravity" android:label="ListTopGravity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListTopGravityMany" android:label="ListTopGravityMany">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListEndingWithMultipleSeparators" android:label="ListEndingWithMultipleSeparators">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListGetSelectedView" android:label="ListGetSelectedView">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListInHorizontal" android:label="ListInHorizontal">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListInVertical" android:label="ListInVertical">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListInterleaveFocusables" android:label="ListInterleaveFocusables">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListOfItemsShorterThanScreen" android:label="ListOfItemsShorterThanScreen">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListOfItemsTallerThanScreen" android:label="ListOfItemsTallerThanScreen">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListOfThinItems" android:label="ListOfThinItems">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListOfShortTallShort" android:label="ListOfShortTallShort">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListOfShortShortTallShortShort" android:label="ListOfShortShortTallShortShort">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListWithOffScreenNextSelectable" android:label="ListWithOffScreenNextSelectable">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListWithFirstScreenUnSelectable" android:label="ListWithFirstScreenUnSelectable">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
-
- <activity android:name=".listview.ListWithSeparators" android:label="ListWithSeparators">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListWithHeaders" android:label="ListWithHeaders">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListWithEditTextHeader" android:label="ListWithEditTextHeader">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
-
- <activity android:name=".listview.ListWithNoFadingEdge" android:label="ListWithNoFadingEdge">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListWithScreenOfNoSelectables" android:label="ListWithScreenOfNoSelectables">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListItemFocusablesFarApart" android:label="ListItemFocusablesFarApart">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListItemFocusableAboveUnfocusable" android:label="ListItemFocusableAboveUnfocusable">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListItemFocusablesClose" android:label="ListItemFocusablesClose">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListLastItemPartiallyVisible" android:label="ListLastItemPartiallyVisible">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListItemsExpandOnSelection" android:label="ListItemsExpandOnSelection">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListWithOnItemSelectedAction" android:label="ListWithOnItemSelectedAction">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListItemISVAndButton" android:label="ListItemISVAndButton">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListOfTouchables" android:label="ListOfTouchables">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListRecyclerProfiling" android:label="ListRecyclerProfiling">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListHeterogeneous" android:label="ListHeterogeneous">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListHorizontalFocusWithinItemWins" android:label="ListHorizontalFocusWithinItemWins">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListManagedCursor" android:label="ListManagedCursor">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListWithEmptyView" android:label="ListWithEmptyView">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridInHorizontal" android:label="GridInHorizontal">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridPadding" android:label="GridPadding">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridInVertical" android:label="GridInVertical">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridScrollListener" android:label="GridScrollListener">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridThrasher" android:label="GridThrasher">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridSimple" android:label="GridSimple">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridDelete" android:label="GridDelete">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridSetSelection" android:label="GridSetSelection">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridSetSelectionMany" android:label="GridSetSelectionMany">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridSetSelectionStackFromBottom" android:label="GridSetSelectionStackFromBottom">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridSetSelectionStackFromBottomMany" android:label="GridSetSelectionStackFromBottomMany">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridStackFromBottom" android:label="GridStackFromBottom">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridStackFromBottomMany" android:label="GridStackFromBottomMany">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridVerticalSpacing" android:label="GridVerticalSpacing">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridVerticalSpacingStackFromBottom" android:label="GridVerticalSpacingStackFromBottom">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".gridview.GridSingleColumn" android:label="GridSingleColumn">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".menus.ListContextMenu" android:label="ListContextMenu">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.ViewGroupChildren" android:label="ViewGroup Children">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.RemoteViewsActivity" android:label="RemoteViewsActicity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".drawable.BitmapDrawable" android:label="BitmapDrawable">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".drawable.DrawableBgMinSize" android:label="DrawableBgMinSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".drawable.MutateDrawable" android:label="MutateDrawable">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".activity.TranslucentFancyActivity" android:label="TranslucentFancyActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".view.Longpress" android:label="Longpress">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".expandablelistview.ExpandableListWithHeaders" android:label="ExpandableListWithHeaders">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".listview.ListWithDisappearingItemBug" android:label="ListWithDisappearingItemBug">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".menus.MenuWith1Item" android:label="MenuWith1Item">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".menus.MenuLayoutPortrait" android:label="MenuLayoutPortrait"
- android:screenOrientation="portrait">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".menus.MenuLayoutLandscape" android:label="MenuLayoutLandscape"
- android:screenOrientation="landscape">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".expandablelistview.InflatedExpandableListView" android:label="ExpandableListView Inflated">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name=".expandablelistview.ExpandableListSimple" android:label="ExpandableListSimple">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
<activity android:name=".settings.RingtonePickerActivityLauncher" android:label="RingtonePickerActivityLauncher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
</intent-filter>
</activity>
-
- <activity android:name=".settings.BrightnessLimit" android:label="BrightnessLimit">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <activity android:name="android.widget.AutoCompleteTextViewSimple"
- android:label="AutoCompleteTextViewSimple">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
- <service android:name=".accessibility.AccessibilityTestService">
- <intent-filter>
- <action android:name="android.accessibilityservice.AccessibilityService" />
- </intent-filter>
- </service>
-
- <activity android:name=".radiogroup.RadioGroupActivity" android:label="RadioGroupActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
</application>
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index c53f7f10b898..cbb520388d37 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -38,7 +38,7 @@ public:
mUpdate(false), mExtending(false),
mRequireLocalization(false), mPseudolocalize(false),
mUTF8(false), mEncodingSpecified(false), mValues(false),
- mCompressionMethod(0), mOutputAPKFile(NULL),
+ mCompressionMethod(0), mOutputAPKFile(NULL), mManifestPackageNameOverride(NULL),
mAssetSourceDir(NULL), mProguardFile(NULL),
mAndroidManifestFile(NULL), mPublicOutputFile(NULL),
mRClassDir(NULL), mResourceIntermediatesDir(NULL),
@@ -88,6 +88,8 @@ public:
void setJunkPath(bool val) { mJunkPath = val; }
const char* getOutputAPKFile() const { return mOutputAPKFile; }
void setOutputAPKFile(const char* val) { mOutputAPKFile = val; }
+ const char* getManifestPackageNameOverride() const { return mManifestPackageNameOverride; }
+ void setManifestPackageNameOverride(const char * val) { mManifestPackageNameOverride = val; }
/*
* Input options.
@@ -178,6 +180,7 @@ private:
int mCompressionMethod;
bool mJunkPath;
const char* mOutputAPKFile;
+ const char* mManifestPackageNameOverride;
const char* mAssetSourceDir;
const char* mProguardFile;
const char* mAndroidManifestFile;
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 1e6b52ef1c90..6675ac270a10 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -436,6 +436,15 @@ int main(int argc, char* const argv[])
} else if (strcmp(cp, "-utf16") == 0) {
bundle.setEncodingSpecified(true);
bundle.setUTF8(false);
+ } else if (strcmp(cp, "-rename-manifest-package") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--rename-manifest-package' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setManifestPackageNameOverride(argv[0]);
} else {
fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp);
wantUsage = true;
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index d53c472baac5..0d2ea60ad9af 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -489,11 +489,11 @@ static bool applyFileOverlay(Bundle *bundle,
DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > baseFiles =
baseGroup->getFiles();
for (size_t i=0; i < baseFiles.size(); i++) {
- printf("baseFile %d has flavor %s\n", i,
+ printf("baseFile %ld has flavor %s\n", i,
baseFiles.keyAt(i).toString().string());
}
for (size_t i=0; i < overlayFiles.size(); i++) {
- printf("overlayFile %d has flavor %s\n", i,
+ printf("overlayFile %ld has flavor %s\n", i,
overlayFiles.keyAt(i).toString().string());
}
}
@@ -507,7 +507,7 @@ static bool applyFileOverlay(Bundle *bundle,
keyAt(overlayGroupIndex));
if(baseFileIndex < UNKNOWN_ERROR) {
if (bundle->getVerbose()) {
- printf("found a match (%d) for overlay file %s, for flavor %s\n",
+ printf("found a match (%ld) for overlay file %s, for flavor %s\n",
baseFileIndex,
overlayGroup->getLeaf().string(),
overlayFiles.keyAt(overlayGroupIndex).toString().string());
@@ -562,6 +562,33 @@ void addTagAttribute(const sp<XMLNode>& node, const char* ns8,
node->addAttribute(ns, attr, String16(value));
}
+static void fullyQualifyClassName(String8& package, sp<XMLNode> node) {
+ XMLNode::attribute_entry* attr = node->editAttribute(
+ String16("http://schemas.android.com/apk/res/android"), String16("name"));
+ if (attr != NULL) {
+ String8 name(attr->string);
+
+ // asdf --> package.asdf
+ // .asdf .a.b --> package.asdf package.a.b
+ // asdf.adsf --> asdf.asdf
+ String8 className;
+ const char* p = name.string();
+ const char* q = strchr(p, '.');
+ if (p == q) {
+ className += package;
+ className += name;
+ } else if (q == NULL) {
+ className += package;
+ className += ".";
+ className += name;
+ } else {
+ className += name;
+ }
+ NOISY(printf("Qualifying class '%s' to '%s'", name.string(), className.string()));
+ attr->string.setTo(String16(className));
+ }
+}
+
status_t massageManifest(Bundle* bundle, sp<XMLNode> root)
{
root = root->searchElement(String16(), String16("manifest"));
@@ -591,7 +618,36 @@ status_t massageManifest(Bundle* bundle, sp<XMLNode> root)
addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "maxSdkVersion",
bundle->getMaxSdkVersion());
}
-
+
+ // Deal with manifest package name overrides
+ const char* manifestPackageNameOverride = bundle->getManifestPackageNameOverride();
+ if (manifestPackageNameOverride != NULL) {
+ // Update the actual package name
+ XMLNode::attribute_entry* attr = root->editAttribute(String16(), String16("package"));
+ if (attr == NULL) {
+ fprintf(stderr, "package name is required with --rename-manifest-package.\n");
+ return UNKNOWN_ERROR;
+ }
+ String8 origPackage(attr->string);
+ attr->string.setTo(String16(manifestPackageNameOverride));
+ NOISY(printf("Overriding package '%s' to be '%s'\n", origPackage.string(), manifestPackageNameOverride));
+
+ // Make class names fully qualified
+ sp<XMLNode> application = root->getChildElement(String16(), String16("application"));
+ if (application != NULL) {
+ fullyQualifyClassName(origPackage, application);
+
+ Vector<sp<XMLNode> >& children = const_cast<Vector<sp<XMLNode> >&>(application->getChildren());
+ for (size_t i = 0; i < children.size(); i++) {
+ sp<XMLNode> child = children.editItemAt(i);
+ String8 tag(child->getElementName());
+ if (tag == "activity" || tag == "service" || tag == "receiver" || tag == "provider") {
+ fullyQualifyClassName(origPackage, child);
+ }
+ }
+ }
+ }
+
return NO_ERROR;
}
@@ -1173,14 +1229,14 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
table.writePublicDefinitions(String16(assets->getPackage()), fp);
fclose(fp);
}
-
+#if 0
NOISY(
ResTable rt;
rt.add(resFile->getData(), resFile->getSize(), NULL);
printf("Generated resources:\n");
rt.print();
)
-
+#endif
// These resources are now considered to be a part of the included
// resources, for others to reference.
err = assets->addIncludedResources(resFile);
diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp
index ec585913e441..51afc0a946cc 100644
--- a/tools/aapt/StringPool.cpp
+++ b/tools/aapt/StringPool.cpp
@@ -25,7 +25,7 @@ void printStringPool(const ResStringPool* pool)
const size_t NS = pool->size();
for (size_t s=0; s<NS; s++) {
size_t len;
- printf("String #%d: %s\n", s,
+ printf("String #%ld: %s\n", s,
String8(pool->stringAt(s, &len)).string());
}
}
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 036dde44f0e3..4c5928880d9e 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -555,6 +555,19 @@ const XMLNode::attribute_entry* XMLNode::getAttribute(const String16& ns,
return NULL;
}
+XMLNode::attribute_entry* XMLNode::editAttribute(const String16& ns,
+ const String16& name)
+{
+ for (size_t i=0; i<mAttributes.size(); i++) {
+ attribute_entry * ae = &mAttributes.editItemAt(i);
+ if (ae->ns == ns && ae->name == name) {
+ return ae;
+ }
+ }
+
+ return NULL;
+}
+
const String16& XMLNode::getCData() const
{
return mChars;
diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h
index dc92fa7c620b..e9a263bf41d8 100644
--- a/tools/aapt/XMLNode.h
+++ b/tools/aapt/XMLNode.h
@@ -95,6 +95,8 @@ public:
const attribute_entry* getAttribute(const String16& ns, const String16& name) const;
+ attribute_entry* editAttribute(const String16& ns, const String16& name);
+
const String16& getCData() const;
const String16& getComment() const;
diff --git a/vpn/tests/vpntests/Android.mk b/vpn/tests/vpntests/Android.mk
new file mode 100644
index 000000000000..a19fb56265d0
--- /dev/null
+++ b/vpn/tests/vpntests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PACKAGE_NAME := FrameworksVpnTests
+
+include $(BUILD_PACKAGE)
+
diff --git a/vpn/tests/vpntests/AndroidManifest.xml b/vpn/tests/vpntests/AndroidManifest.xml
new file mode 100644
index 000000000000..d8405f6b8b45
--- /dev/null
+++ b/vpn/tests/vpntests/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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.
+ 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.vpntests">
+ <uses-permission android:name="android.permission.RECEIVE_SMS"/>
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
+ <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
+ <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.frameworks.vpntests"
+ android:label="Frameworks VPN Tests" />
+</manifest>
diff --git a/tests/AndroidTests/src/com/android/unit_tests/VpnTest.java b/vpn/tests/vpntests/src/android/net/vpn/VpnTest.java
index cb64293bd76b..46a57d33ed91 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/VpnTest.java
+++ b/vpn/tests/vpntests/src/android/net/vpn/VpnTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.unit_tests;
+package android.net.vpn;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 1e322bd1448d..0928d2bb4a3b 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -119,6 +119,26 @@ public class WifiMonitor {
private final WifiStateTracker mWifiStateTracker;
+ /**
+ * This indicates the supplicant connection for the monitor is closed
+ */
+ private static final String monitorSocketClosed = "connection closed";
+
+ /**
+ * This indicates a read error on the monitor socket conenction
+ */
+ private static final String wpaRecvError = "recv error";
+
+ /**
+ * Tracks consecutive receive errors
+ */
+ private int mRecvErrors = 0;
+
+ /**
+ * Max errors before we close supplicant connection
+ */
+ private static final int MAX_RECV_ERRORS = 10;
+
public WifiMonitor(WifiStateTracker tracker) {
mWifiStateTracker = tracker;
}
@@ -151,16 +171,13 @@ public class WifiMonitor {
for (;;) {
String eventStr = WifiNative.waitForEvent();
- if (eventStr == null) {
- continue;
- }
-
// Skip logging the common but mostly uninteresting scan-results event
if (Config.LOGD && eventStr.indexOf(scanResultsEvent) == -1) {
Log.v(TAG, "Event [" + eventStr + "]");
}
if (!eventStr.startsWith(eventPrefix)) {
- if (eventStr.startsWith(wpaEventPrefix) && 0 < eventStr.indexOf(passwordKeyMayBeIncorrectEvent)) {
+ if (eventStr.startsWith(wpaEventPrefix) &&
+ 0 < eventStr.indexOf(passwordKeyMayBeIncorrectEvent)) {
handlePasswordKeyMayBeIncorrect();
}
continue;
@@ -216,12 +233,38 @@ public class WifiMonitor {
} else if (event == DRIVER_STATE) {
handleDriverEvent(eventData);
} else if (event == TERMINATING) {
+ /**
+ * If monitor socket is closed, we have already
+ * stopped the supplicant, simply exit the monitor thread
+ */
+ if (eventData.startsWith(monitorSocketClosed)) {
+ if (Config.LOGD) {
+ Log.d(TAG, "Monitor socket is closed, exiting thread");
+ }
+ break;
+ }
+
+ /**
+ * Close the supplicant connection if we see
+ * too many recv errors
+ */
+ if (eventData.startsWith(wpaRecvError)) {
+ if (++mRecvErrors > MAX_RECV_ERRORS) {
+ if (Config.LOGD) {
+ Log.d(TAG, "too many recv errors, closing connection");
+ }
+ } else {
+ continue;
+ }
+ }
+
+ // notify and exit
mWifiStateTracker.notifySupplicantLost();
- // If supplicant is gone, exit the thread
break;
} else {
handleEvent(event, eventData);
}
+ mRecvErrors = 0;
}
}
@@ -293,6 +336,7 @@ public class WifiMonitor {
private void handleSupplicantStateChange(String dataString) {
String[] dataTokens = dataString.split(" ");
+ String BSSID = null;
int networkId = -1;
int newState = -1;
for (String token : dataTokens) {
@@ -301,6 +345,11 @@ public class WifiMonitor {
continue;
}
+ if (nameValue[0].equals("BSSID")) {
+ BSSID = nameValue[1];
+ continue;
+ }
+
int value;
try {
value = Integer.parseInt(nameValue[1]);
@@ -328,7 +377,7 @@ public class WifiMonitor {
if (newSupplicantState == SupplicantState.INVALID) {
Log.w(TAG, "Invalid supplicant state: " + newState);
}
- mWifiStateTracker.notifyStateChange(networkId, newSupplicantState);
+ mWifiStateTracker.notifyStateChange(networkId, BSSID, newSupplicantState);
}
}
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 2668fe0514e4..cb615d262b17 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -304,11 +304,13 @@ public class WifiStateTracker extends NetworkStateTracker {
* thread.
*/
private static class SupplicantStateChangeResult {
- SupplicantStateChangeResult(int networkId, SupplicantState state) {
+ SupplicantStateChangeResult(int networkId, String BSSID, SupplicantState state) {
this.state = state;
+ this.BSSID = BSSID;
this.networkId = networkId;
}
int networkId;
+ String BSSID;
SupplicantState state;
}
@@ -512,10 +514,10 @@ public class WifiStateTracker extends NetworkStateTracker {
* @param networkId the configured network on which the state change occurred
* @param newState the new {@code SupplicantState}
*/
- void notifyStateChange(int networkId, SupplicantState newState) {
+ void notifyStateChange(int networkId, String BSSID, SupplicantState newState) {
Message msg = Message.obtain(
this, EVENT_SUPPLICANT_STATE_CHANGED,
- new SupplicantStateChangeResult(networkId, newState));
+ new SupplicantStateChangeResult(networkId, BSSID, newState));
msg.sendToTarget();
}
@@ -884,6 +886,13 @@ public class WifiStateTracker extends NetworkStateTracker {
int networkId = supplicantStateResult.networkId;
+ /**
+ * The SupplicantState BSSID value is valid in ASSOCIATING state only.
+ * The NetworkState BSSID value comes upon a successful connection.
+ */
+ if (supplicantStateResult.state == SupplicantState.ASSOCIATING) {
+ mLastBssid = supplicantStateResult.BSSID;
+ }
/*
* If we get disconnect or inactive we need to start our
* watchdog timer to start a scan
@@ -928,6 +937,7 @@ public class WifiStateTracker extends NetworkStateTracker {
setSupplicantState(newState);
if (newState == SupplicantState.DORMANT) {
DetailedState newDetailedState;
+ Message reconnectMsg = obtainMessage(EVENT_DEFERRED_RECONNECT, mLastBssid);
if (mIsScanOnly || mRunState == RUN_STATE_STOPPING) {
newDetailedState = DetailedState.IDLE;
} else {
@@ -942,7 +952,7 @@ public class WifiStateTracker extends NetworkStateTracker {
* milliseconds.
*/
if (mRunState == RUN_STATE_RUNNING && !mIsScanOnly && networkId != -1) {
- sendEmptyMessageDelayed(EVENT_DEFERRED_RECONNECT, RECONNECT_DELAY_MSECS);
+ sendMessageDelayed(reconnectMsg, RECONNECT_DELAY_MSECS);
} else if (mRunState == RUN_STATE_STOPPING) {
synchronized (this) {
WifiNative.stopDriverCommand();
@@ -1104,15 +1114,19 @@ public class WifiStateTracker extends NetworkStateTracker {
break;
case EVENT_DEFERRED_RECONNECT:
- /*
+ String BSSID = msg.obj.toString();
+ /**
* If we've exceeded the maximum number of retries for reconnecting
- * to a given network, disable the network so that the supplicant
- * will try some other network, if any is available.
- * TODO: network ID may have changed since we stored it.
+ * to a given network, blacklist the BSSID to allow a connection attempt on
+ * an alternate BSSID if available
*/
if (mWifiInfo.getSupplicantState() != SupplicantState.UNINITIALIZED) {
if (++mReconnectCount > getMaxDhcpRetries()) {
- mWM.disableNetwork(mLastNetworkId);
+ if (LOCAL_LOGD) {
+ Log.d(TAG, "Failed reconnect count: " +
+ mReconnectCount + " Blacklisting " + BSSID);
+ }
+ addToBlacklist(BSSID);
}
synchronized(this) {
WifiNative.reconnectCommand();
@@ -1684,6 +1698,10 @@ public class WifiStateTracker extends NetworkStateTracker {
mNumScansSinceNetworkStateChange = 0;
}
+ public synchronized boolean reassociate() {
+ return WifiNative.reassociateCommand();
+ }
+
public synchronized boolean addToBlacklist(String bssid) {
return WifiNative.addToBlacklistCommand(bssid);
}