From a8675f67e33bc7337d148358783b0fd138b501ff Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Queru Date: Wed, 29 Jul 2009 14:25:07 -0700 Subject: [PATCH] donut snapshot --- Android.mk | 7 +- api/current.xml | 2668 ++++++++++++++++- awt/Android.mk | 2 +- camera/libcameraservice/CameraService.cpp | 11 +- camera/libcameraservice/CameraService.h | 4 +- cmds/keystore/keystore_get.h | 2 +- core/java/android/app/Activity.java | 84 +- .../android/app/ActivityManagerNative.java | 89 +- core/java/android/app/ActivityThread.java | 147 +- core/java/android/app/ApplicationContext.java | 31 +- .../android/app/ApplicationThreadNative.java | 7 +- core/java/android/app/Dialog.java | 64 +- .../java/android/app/IActivityController.aidl | 55 + core/java/android/app/IActivityManager.java | 17 +- core/java/android/app/IActivityWatcher.aidl | 39 +- core/java/android/app/IApplicationThread.java | 2 +- core/java/android/app/ISearchManager.aidl | 6 +- core/java/android/app/SearchDialog.java | 187 +- core/java/android/app/SearchManager.java | 130 +- core/java/android/app/SuggestionsAdapter.java | 289 +- .../android/appwidget/AppWidgetProvider.java | 8 +- .../appwidget/AppWidgetProviderInfo.java | 3 + core/java/android/backup/BackupManager.java | 12 + .../android/content/AbstractTableMerger.java | 49 +- .../java/android/content/ContentProvider.java | 136 +- .../java/android/content/DialogInterface.java | 15 + core/java/android/content/Intent.java | 124 +- .../android/content/SyncStorageEngine.java | 1 + .../android/content/pm/ApplicationInfo.java | 17 +- .../android/content/pm/IPackageManager.aidl | 2 + .../android/content/pm/PackageParser.java | 202 +- .../android/content/pm/PathPermission.java | 68 + .../java/android/content/pm/ProviderInfo.java | 12 + .../content/res/CompatibilityInfo.java | 334 +-- .../android/content/res/Configuration.java | 51 +- core/java/android/content/res/Resources.java | 68 +- .../database/sqlite/SQLiteDatabase.java | 3 +- core/java/android/gesture/Gesture.java | 24 +- core/java/android/gesture/package.html | 2 +- core/java/android/net/Uri.java | 50 +- core/java/android/os/BatteryStats.java | 22 +- core/java/android/os/Process.java | 12 + core/java/android/os/RemoteCallbackList.java | 24 +- core/java/android/provider/Settings.java | 25 +- core/java/android/provider/Telephony.java | 15 +- .../server/search/SearchDialogWrapper.java | 387 +++ .../server/search/SearchManagerService.java | 404 +-- .../android/server/search/SearchableInfo.java | 23 + .../android/server/search/Searchables.java | 32 +- core/java/android/speech/tts/ITts.aidl | 28 +- .../java/android/speech/tts/ITtsCallback.aidl | 2 +- .../java/android/speech/tts/TextToSpeech.java | 500 ++- core/java/android/text/Html.java | 109 +- core/java/android/util/DisplayMetrics.java | 143 +- core/java/android/util/TypedValue.java | 12 +- core/java/android/view/Display.java | 27 + core/java/android/view/Surface.java | 23 +- core/java/android/view/SurfaceView.java | 37 +- core/java/android/view/ViewRoot.java | 49 +- core/java/android/view/Window.java | 8 +- core/java/android/view/WindowManager.java | 18 +- .../webkit/GearsPermissionsManager.java | 240 ++ core/java/android/webkit/LoadListener.java | 32 +- core/java/android/webkit/MimeTypeMap.java | 1 + core/java/android/webkit/URLUtil.java | 2 +- core/java/android/webkit/WebSettings.java | 23 +- core/java/android/widget/AbsListView.java | 2 +- .../widget/AppSecurityPermissions.java | 12 +- .../android/widget/AutoCompleteTextView.java | 24 +- core/java/android/widget/DatePicker.java | 15 + core/java/android/widget/FastScroller.java | 11 +- core/java/android/widget/Filter.java | 36 +- .../android/widget/HorizontalScrollView.java | 81 +- core/java/android/widget/PopupWindow.java | 28 +- core/java/android/widget/RelativeLayout.java | 7 +- core/java/android/widget/ScrollView.java | 100 +- core/java/android/widget/Spinner.java | 15 +- core/java/android/widget/TextView.java | 15 +- core/java/android/widget/Toast.java | 77 +- .../android/internal/os/BatteryStatsImpl.java | 67 +- .../com/android/internal/os/PowerProfile.java | 5 + .../internal/widget/LockPatternView.java | 21 +- .../android/internal/widget/NumberPicker.java | 8 +- core/jni/android/graphics/Bitmap.cpp | 6 +- core/jni/android/graphics/BitmapFactory.cpp | 10 +- core/jni/android/graphics/Graphics.cpp | 56 +- core/jni/android/graphics/GraphicsJNI.h | 6 +- core/jni/android_backup_BackupDataOutput.cpp | 2 +- core/jni/android_hardware_Camera.cpp | 28 +- core/jni/android_media_AudioRecord.cpp | 6 +- core/jni/android_media_AudioTrack.cpp | 8 + core/jni/android_net_wifi_Wifi.cpp | 28 +- core/jni/android_util_AssetManager.cpp | 2 +- core/res/AndroidManifest.xml | 55 + core/res/res/color/search_url_text.xml | 21 + .../res/drawable/expander_ic_maximized.9.png | Bin 1795 -> 1149 bytes .../res/drawable/expander_ic_minimized.9.png | Bin 1757 -> 1172 bytes .../res/drawable/ic_bullet_key_permission.png | Bin 584 -> 597 bytes core/res/res/drawable/ic_text_dot.png | Bin 332 -> 476 bytes core/res/res/drawable/light_header.9.png | Bin 0 -> 183 bytes core/res/res/layout/app_perms_summary.xml | 4 +- .../layout/search_dropdown_app_selector.xml | 44 - .../res/layout/search_dropdown_item_2line.xml | 59 - .../search_dropdown_item_icons_1line.xml | 54 - core/res/res/values-cs/strings.xml | 70 +- core/res/res/values-da/strings.xml | 765 +++++ core/res/res/values-de/strings.xml | 90 +- core/res/res/values-el/strings.xml | 765 +++++ core/res/res/values-es-rUS/strings.xml | 137 +- core/res/res/values-es/strings.xml | 86 +- core/res/res/values-fr/strings.xml | 135 +- .../res/values-he-rIL/donottranslate-cldr.xml | 24 +- .../res/values-hr-rHR/donottranslate-cldr.xml | 147 + core/res/res/values-it/strings.xml | 78 +- core/res/res/values-ja/strings.xml | 135 +- core/res/res/values-ko/strings.xml | 493 +-- core/res/res/values-mcc204-da/strings.xml | 19 + core/res/res/values-mcc204-el/strings.xml | 19 + core/res/res/values-mcc204-pt-rPT/strings.xml | 19 + core/res/res/values-mcc204-sv/strings.xml | 19 + core/res/res/values-mcc204-tr/strings.xml | 19 + core/res/res/values-mcc230-da/strings.xml | 19 + core/res/res/values-mcc230-el/strings.xml | 19 + core/res/res/values-mcc230-pt-rPT/strings.xml | 19 + core/res/res/values-mcc230-sv/strings.xml | 19 + core/res/res/values-mcc230-tr/strings.xml | 19 + core/res/res/values-mcc232-da/strings.xml | 19 + core/res/res/values-mcc232-el/strings.xml | 19 + core/res/res/values-mcc232-pt-rPT/strings.xml | 19 + core/res/res/values-mcc232-sv/strings.xml | 19 + core/res/res/values-mcc232-tr/strings.xml | 19 + core/res/res/values-mcc234-da/strings.xml | 19 + core/res/res/values-mcc234-el/strings.xml | 19 + core/res/res/values-mcc234-pt-rPT/strings.xml | 19 + core/res/res/values-mcc234-sv/strings.xml | 19 + core/res/res/values-mcc234-tr/strings.xml | 19 + core/res/res/values-mcc260-da/strings.xml | 19 + core/res/res/values-mcc260-el/strings.xml | 19 + core/res/res/values-mcc260-pt-rPT/strings.xml | 19 + core/res/res/values-mcc260-sv/strings.xml | 19 + core/res/res/values-mcc260-tr/strings.xml | 19 + core/res/res/values-mcc262-da/strings.xml | 19 + core/res/res/values-mcc262-el/strings.xml | 19 + core/res/res/values-mcc262-pt-rPT/strings.xml | 19 + core/res/res/values-mcc262-sv/strings.xml | 19 + core/res/res/values-mcc262-tr/strings.xml | 19 + .../arrays.xml | 0 .../res/values-nb-rNO/donottranslate-cldr.xml | 147 + core/res/res/values-nb/strings.xml | 156 +- core/res/res/values-nl/strings.xml | 70 +- core/res/res/values-pl/strings.xml | 118 +- .../res/values-pt-rBR/donottranslate-cldr.xml | 2 +- .../res/values-pt-rPT/donottranslate-cldr.xml | 2 +- core/res/res/values-pt-rPT/strings.xml | 765 +++++ .../res/res/values-pt/donottranslate-cldr.xml | 2 +- core/res/res/values-pt/strings.xml | 778 +++-- core/res/res/values-ru/strings.xml | 815 ++--- core/res/res/values-sv/strings.xml | 765 +++++ core/res/res/values-tr/strings.xml | 765 +++++ .../res/values-vi-rVN/donottranslate-cldr.xml | 4 +- core/res/res/values-zh-rCN/strings.xml | 613 ++-- core/res/res/values-zh-rTW/strings.xml | 74 +- core/res/res/values/attrs.xml | 8 + core/res/res/values/attrs_manifest.xml | 30 +- core/res/res/values/colors.xml | 10 +- core/res/res/values/public.xml | 2 + core/res/res/values/styles.xml | 3 +- core/res/res/values/themes.xml | 26 + data/etc/platform.xml | 2 - data/sounds/AudioPackage2.mk | 2 +- data/sounds/OriginalAudio.mk | 2 +- .../guide/topics/resources/resources-i18n.jd | 139 +- graphics/java/android/graphics/Bitmap.java | 73 +- .../java/android/graphics/BitmapFactory.java | 31 +- graphics/java/android/graphics/Canvas.java | 4 - graphics/java/android/graphics/Rect.java | 8 +- .../graphics/drawable/ShapeDrawable.java | 13 +- include/ui/Camera.h | 3 + include/ui/CameraHardwareInterface.h | 2 +- include/ui/ICameraClient.h | 3 +- include/utils/ResourceTypes.h | 87 +- include/utils/String8.h | 116 +- keystore/java/android/security/CertTool.java | 68 +- keystore/java/android/security/Keystore.java | 106 - keystore/jni/cert.c | 114 +- keystore/jni/cert.h | 15 +- keystore/jni/certtool.c | 97 +- libs/audioflinger/AudioFlinger.cpp | 13 +- libs/audioflinger/AudioFlinger.h | 2 +- libs/surfaceflinger/Android.mk | 1 - libs/surfaceflinger/LayerOrientationAnim.cpp | 127 +- libs/surfaceflinger/LayerOrientationAnim.h | 32 - .../LayerOrientationAnimRotate.cpp | 274 -- .../LayerOrientationAnimRotate.h | 77 - libs/surfaceflinger/OrientationAnimation.cpp | 12 +- libs/surfaceflinger/SurfaceFlinger.cpp | 7 + libs/ui/Camera.cpp | 13 + libs/ui/ICameraClient.cpp | 23 +- libs/utils/ResourceTypes.cpp | 17 +- libs/utils/String8.cpp | 298 +- libs/utils/ZipUtils.cpp | 3 +- location/java/android/location/Address.java | 47 + media/java/android/media/AudioManager.java | 15 + media/java/android/media/AudioService.java | 62 +- media/java/android/media/ExifInterface.java | 398 +++ media/java/android/media/IAudioService.aidl | 1 + media/java/android/media/MediaScanner.java | 242 +- media/libmedia/ToneGenerator.cpp | 2 + media/sdutils/sdutil.cpp | 4 +- opengl/libagl/egl.cpp | 2 +- opengl/libs/EGL/egl.cpp | 2 +- packages/SettingsProvider/etc/bookmarks.xml | 4 +- .../res/values-cs/defaults.xml | 22 + .../res/values-cs/strings.xml | 19 + .../res/values-de/defaults.xml | 22 + .../res/values-de/strings.xml | 19 + .../res/values-es/defaults.xml | 22 + .../res/values-es/strings.xml | 19 + .../res/values-fr/defaults.xml | 22 + .../res/values-fr/strings.xml | 19 + .../res/values-it/defaults.xml | 22 + .../res/values-it/strings.xml | 19 + .../res/values-nl/defaults.xml | 22 + .../res/values-nl/strings.xml | 19 + .../res/values-pl/defaults.xml | 22 + .../res/values-pl/strings.xml | 19 + .../res/values-zh-rTW/defaults.xml | 22 + .../res/values-zh-rTW/strings.xml | 19 + .../settings/SettingsBackupAgent.java | 99 +- .../providers/settings/SettingsHelper.java | 11 + .../providers/settings/SettingsProvider.java | 7 +- .../res/values-cs/strings.xml | 19 + .../res/values-de/strings.xml | 19 + .../res/values-es/strings.xml | 19 + .../res/values-fr/strings.xml | 19 + .../res/values-it/strings.xml | 19 + .../res/values-nl/strings.xml | 19 + .../res/values-pl/strings.xml | 19 + .../res/values-zh-rTW/strings.xml | 19 + .../TtsService/jni/android_tts_SynthProxy.cpp | 151 +- .../src/android/tts/SynthProxy.java | 23 +- .../src/android/tts/TtsService.java | 526 +++- .../VpnServices/res/values-cs/strings.xml | 25 + .../VpnServices/res/values-de/strings.xml | 25 + .../VpnServices/res/values-es/strings.xml | 25 + .../VpnServices/res/values-fr/strings.xml | 25 + .../VpnServices/res/values-it/strings.xml | 25 + .../VpnServices/res/values-nl/strings.xml | 25 + .../VpnServices/res/values-pl/strings.xml | 25 + .../VpnServices/res/values-zh-rTW/strings.xml | 25 + .../server/vpn/AndroidServiceProxy.java | 62 +- .../server/vpn/L2tpIpsecPskService.java | 3 +- .../android/server/vpn/L2tpIpsecService.java | 4 +- .../com/android/server/vpn/MtpdHelper.java | 1 - .../server/vpn/VpnConnectingError.java | 35 + .../com/android/server/vpn/VpnService.java | 144 +- .../android/server/vpn/VpnServiceBinder.java | 23 +- .../com/android/server/AppWidgetService.java | 8 +- .../android/server/BackupManagerService.java | 26 +- .../com/android/server/MountListener.java | 1 + .../server/NotificationManagerService.java | 20 +- .../android/server/PackageManagerService.java | 80 +- .../java/com/android/server/SystemServer.java | 17 +- .../java/com/android/server/WifiService.java | 7 +- .../android/server/WindowManagerService.java | 596 ++-- .../server/am/ActivityManagerService.java | 150 +- .../server/am/BatteryStatsService.java | 2 +- .../android/server/am/UsageStatsService.java | 54 +- .../server/status/StatusBarPolicy.java | 8 +- .../android/telephony/TelephonyManager.java | 14 +- .../telephony/cdma/CdmaCellLocation.java | 48 +- .../internal/telephony/CommandsInterface.java | 2 +- .../com/android/internal/telephony/Phone.java | 4 +- .../android/internal/telephony/PhoneBase.java | 2 +- .../internal/telephony/PhoneProxy.java | 4 +- .../com/android/internal/telephony/RIL.java | 5 +- .../internal/telephony/RILConstants.java | 6 + .../internal/telephony/TelephonyIntents.java | 33 + .../telephony/TelephonyProperties.java | 15 +- .../internal/telephony/WspTypeDecoder.java | 28 +- .../internal/telephony/cdma/CDMAPhone.java | 105 +- .../telephony/cdma/CdmaDataConnection.java | 4 +- .../cdma/CdmaServiceStateTracker.java | 56 +- .../internal/telephony/cdma/RuimRecords.java | 13 - .../internal/telephony/gsm/PdpConnection.java | 4 +- .../telephony/test/SimulatedCommands.java | 2 +- tests/AndroidTests/AndroidManifest.xml | 1 + tests/AndroidTests/run_test.sh | 2 +- .../src/com/android/unit_tests/HtmlTest.java | 62 +- .../android/unit_tests/SearchManagerTest.java | 20 - .../android/unit_tests/SearchablesTest.java | 4 +- .../src/com/android/unit_tests/UriTest.java | 37 + .../src/com/android/unit_tests/VpnTest.java | 46 + .../unit_tests/activity/ServiceTest.java | 16 +- .../unit_tests/content/ConfigTest.java | 2 +- tests/DpiTest/AndroidManifest.xml | 9 +- .../logo240dpi.png | Bin .../logo120dpi.png | Bin .../res/drawable-nodpi/logonodpi120.png | Bin 0 -> 5178 bytes .../res/drawable-nodpi/logonodpi160.png | Bin 0 -> 8114 bytes .../res/drawable-nodpi/logonodpi240.png | Bin 0 -> 13388 bytes .../strings.xml | 2 +- .../strings.xml | 2 +- .../strings.xml | 2 +- tests/DpiTest/res/values-long/strings.xml | 19 + .../res/values-normal-long/strings.xml | 19 + .../res/values-normal-notlong/strings.xml | 19 + tests/DpiTest/res/values-normal/strings.xml | 19 + tests/DpiTest/res/values-notlong/strings.xml | 19 + .../DpiTest/res/values-small-long/strings.xml | 19 + .../res/values-small-notlong/strings.xml | 19 + tests/DpiTest/res/values-small/strings.xml | 19 + .../android/test/dpi/DpiTestActivity.java | 49 +- .../test/dpi/DpiTestNoCompatActivity.java | 23 + .../dumprendertree/LoadTestsAutoTest.java | 5 + .../dumprendertree/TestShellActivity.java | 4 + .../tests/ActivityManagerPermissionTests.java | 4 +- tools/aapt/AaptAssets.cpp | 181 +- tools/aapt/AaptAssets.h | 9 +- .../com/android/layoutlib/bridge/Bridge.java | 10 +- vpn/java/android/net/vpn/VpnManager.java | 21 +- vpn/java/android/net/vpn/VpnState.java | 7 +- wifi/java/android/net/wifi/IWifiManager.aidl | 2 +- wifi/java/android/net/wifi/WifiManager.java | 22 +- wifi/java/android/net/wifi/WifiNative.java | 2 +- .../android/net/wifi/WifiStateTracker.java | 24 +- 326 files changed, 18109 insertions(+), 5040 deletions(-) create mode 100644 core/java/android/app/IActivityController.aidl create mode 100644 core/java/android/content/pm/PathPermission.java create mode 100644 core/java/android/server/search/SearchDialogWrapper.java mode change 100644 => 100755 core/java/android/speech/tts/TextToSpeech.java create mode 100644 core/java/android/webkit/GearsPermissionsManager.java create mode 100644 core/res/res/color/search_url_text.xml mode change 100755 => 100644 core/res/res/drawable/ic_bullet_key_permission.png mode change 100755 => 100644 core/res/res/drawable/ic_text_dot.png create mode 100644 core/res/res/drawable/light_header.9.png delete mode 100644 core/res/res/layout/search_dropdown_app_selector.xml delete mode 100644 core/res/res/layout/search_dropdown_item_2line.xml delete mode 100644 core/res/res/layout/search_dropdown_item_icons_1line.xml create mode 100644 core/res/res/values-da/strings.xml create mode 100644 core/res/res/values-el/strings.xml create mode 100644 core/res/res/values-hr-rHR/donottranslate-cldr.xml create mode 100644 core/res/res/values-mcc204-da/strings.xml create mode 100644 core/res/res/values-mcc204-el/strings.xml create mode 100644 core/res/res/values-mcc204-pt-rPT/strings.xml create mode 100644 core/res/res/values-mcc204-sv/strings.xml create mode 100644 core/res/res/values-mcc204-tr/strings.xml create mode 100644 core/res/res/values-mcc230-da/strings.xml create mode 100644 core/res/res/values-mcc230-el/strings.xml create mode 100644 core/res/res/values-mcc230-pt-rPT/strings.xml create mode 100644 core/res/res/values-mcc230-sv/strings.xml create mode 100644 core/res/res/values-mcc230-tr/strings.xml create mode 100644 core/res/res/values-mcc232-da/strings.xml create mode 100644 core/res/res/values-mcc232-el/strings.xml create mode 100644 core/res/res/values-mcc232-pt-rPT/strings.xml create mode 100644 core/res/res/values-mcc232-sv/strings.xml create mode 100644 core/res/res/values-mcc232-tr/strings.xml create mode 100644 core/res/res/values-mcc234-da/strings.xml create mode 100644 core/res/res/values-mcc234-el/strings.xml create mode 100644 core/res/res/values-mcc234-pt-rPT/strings.xml create mode 100644 core/res/res/values-mcc234-sv/strings.xml create mode 100644 core/res/res/values-mcc234-tr/strings.xml create mode 100644 core/res/res/values-mcc260-da/strings.xml create mode 100644 core/res/res/values-mcc260-el/strings.xml create mode 100644 core/res/res/values-mcc260-pt-rPT/strings.xml create mode 100644 core/res/res/values-mcc260-sv/strings.xml create mode 100644 core/res/res/values-mcc260-tr/strings.xml create mode 100644 core/res/res/values-mcc262-da/strings.xml create mode 100644 core/res/res/values-mcc262-el/strings.xml create mode 100644 core/res/res/values-mcc262-pt-rPT/strings.xml create mode 100644 core/res/res/values-mcc262-sv/strings.xml create mode 100644 core/res/res/values-mcc262-tr/strings.xml rename core/res/res/{values-no-rNO => values-nb-rNO}/arrays.xml (100%) create mode 100644 core/res/res/values-nb-rNO/donottranslate-cldr.xml create mode 100644 core/res/res/values-pt-rPT/strings.xml create mode 100644 core/res/res/values-sv/strings.xml create mode 100644 core/res/res/values-tr/strings.xml delete mode 100644 libs/surfaceflinger/LayerOrientationAnimRotate.cpp delete mode 100644 libs/surfaceflinger/LayerOrientationAnimRotate.h create mode 100644 media/java/android/media/ExifInterface.java create mode 100644 packages/SettingsProvider/res/values-cs/defaults.xml create mode 100644 packages/SettingsProvider/res/values-cs/strings.xml create mode 100644 packages/SettingsProvider/res/values-de/defaults.xml create mode 100644 packages/SettingsProvider/res/values-de/strings.xml create mode 100644 packages/SettingsProvider/res/values-es/defaults.xml create mode 100644 packages/SettingsProvider/res/values-es/strings.xml create mode 100644 packages/SettingsProvider/res/values-fr/defaults.xml create mode 100644 packages/SettingsProvider/res/values-fr/strings.xml create mode 100644 packages/SettingsProvider/res/values-it/defaults.xml create mode 100644 packages/SettingsProvider/res/values-it/strings.xml create mode 100644 packages/SettingsProvider/res/values-nl/defaults.xml create mode 100644 packages/SettingsProvider/res/values-nl/strings.xml create mode 100644 packages/SettingsProvider/res/values-pl/defaults.xml create mode 100644 packages/SettingsProvider/res/values-pl/strings.xml create mode 100644 packages/SettingsProvider/res/values-zh-rTW/defaults.xml create mode 100644 packages/SettingsProvider/res/values-zh-rTW/strings.xml create mode 100644 packages/SubscribedFeedsProvider/res/values-cs/strings.xml create mode 100644 packages/SubscribedFeedsProvider/res/values-de/strings.xml create mode 100644 packages/SubscribedFeedsProvider/res/values-es/strings.xml create mode 100644 packages/SubscribedFeedsProvider/res/values-fr/strings.xml create mode 100644 packages/SubscribedFeedsProvider/res/values-it/strings.xml create mode 100644 packages/SubscribedFeedsProvider/res/values-nl/strings.xml create mode 100644 packages/SubscribedFeedsProvider/res/values-pl/strings.xml create mode 100644 packages/SubscribedFeedsProvider/res/values-zh-rTW/strings.xml create mode 100644 packages/VpnServices/res/values-cs/strings.xml create mode 100644 packages/VpnServices/res/values-de/strings.xml create mode 100644 packages/VpnServices/res/values-es/strings.xml create mode 100644 packages/VpnServices/res/values-fr/strings.xml create mode 100644 packages/VpnServices/res/values-it/strings.xml create mode 100644 packages/VpnServices/res/values-nl/strings.xml create mode 100644 packages/VpnServices/res/values-pl/strings.xml create mode 100644 packages/VpnServices/res/values-zh-rTW/strings.xml create mode 100644 packages/VpnServices/src/com/android/server/vpn/VpnConnectingError.java create mode 100755 tests/AndroidTests/src/com/android/unit_tests/VpnTest.java rename tests/DpiTest/res/{drawable-240dpi => drawable-hdpi}/logo240dpi.png (100%) rename tests/DpiTest/res/{drawable-120dpi => drawable-ldpi}/logo120dpi.png (100%) create mode 100644 tests/DpiTest/res/drawable-nodpi/logonodpi120.png create mode 100644 tests/DpiTest/res/drawable-nodpi/logonodpi160.png create mode 100644 tests/DpiTest/res/drawable-nodpi/logonodpi240.png rename tests/DpiTest/res/{values-largeScreen => values-large-long}/strings.xml (92%) rename tests/DpiTest/res/{values-normalScreen => values-large-notlong}/strings.xml (91%) rename tests/DpiTest/res/{values-smallScreen => values-large}/strings.xml (92%) create mode 100644 tests/DpiTest/res/values-long/strings.xml create mode 100644 tests/DpiTest/res/values-normal-long/strings.xml create mode 100644 tests/DpiTest/res/values-normal-notlong/strings.xml create mode 100644 tests/DpiTest/res/values-normal/strings.xml create mode 100644 tests/DpiTest/res/values-notlong/strings.xml create mode 100644 tests/DpiTest/res/values-small-long/strings.xml create mode 100644 tests/DpiTest/res/values-small-notlong/strings.xml create mode 100644 tests/DpiTest/res/values-small/strings.xml create mode 100644 tests/DpiTest/src/com/google/android/test/dpi/DpiTestNoCompatActivity.java diff --git a/Android.mk b/Android.mk index f32129e40fa55..038af0d6b67a0 100644 --- a/Android.mk +++ b/Android.mk @@ -67,10 +67,11 @@ LOCAL_SRC_FILES += \ core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \ core/java/android/accessibilityservice/IEventListener.aidl \ core/java/android/accounts/IAccountsService.aidl \ + core/java/android/app/IActivityController.aidl \ core/java/android/app/IActivityPendingResult.aidl \ core/java/android/app/IActivityWatcher.aidl \ core/java/android/app/IAlarmManager.aidl \ - core/java/android/app/IBackupAgent.aidl \ + core/java/android/app/IBackupAgent.aidl \ core/java/android/app/IInstrumentationWatcher.aidl \ core/java/android/app/INotificationManager.aidl \ core/java/android/app/ISearchManager.aidl \ @@ -88,12 +89,12 @@ LOCAL_SRC_FILES += \ core/java/android/bluetooth/IBluetoothDevice.aidl \ core/java/android/bluetooth/IBluetoothDeviceCallback.aidl \ core/java/android/bluetooth/IBluetoothHeadset.aidl \ - core/java/android/content/IContentService.aidl \ + core/java/android/content/IContentService.aidl \ core/java/android/content/IIntentReceiver.aidl \ core/java/android/content/IIntentSender.aidl \ core/java/android/content/ISyncAdapter.aidl \ core/java/android/content/ISyncContext.aidl \ - core/java/android/content/ISyncStatusObserver.aidl \ + core/java/android/content/ISyncStatusObserver.aidl \ core/java/android/content/pm/IPackageDataObserver.aidl \ core/java/android/content/pm/IPackageDeleteObserver.aidl \ core/java/android/content/pm/IPackageInstallObserver.aidl \ diff --git a/api/current.xml b/api/current.xml index 78562f09ac8fa..0e04f50a89a2f 100644 --- a/api/current.xml +++ b/api/current.xml @@ -496,6 +496,17 @@ visibility="public" > + + + + - - - - + + @@ -23624,7 +23635,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > @@ -23721,6 +23732,50 @@ visibility="public" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -47533,6 +49723,16 @@ visibility="public" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -130809,6 +133321,50 @@ visibility="public" > + + + + + + + + + + + + + + + + + + + + startRecording(recordingCallback, - mCameraService.get()); + ret = mHardware->startRecording(recordingCallback, mCameraService.get()); if (ret != NO_ERROR) { LOGE("mHardware->startRecording() failed with status %d", ret); } @@ -798,7 +797,7 @@ void CameraService::Client::previewCallback(const sp& mem, void* user) } // recording callback -void CameraService::Client::recordingCallback(const sp& mem, void* user) +void CameraService::Client::recordingCallback(nsecs_t timestamp, const sp& mem, void* user) { LOGV("recordingCallback"); sp client = getClientFromCookie(user); @@ -806,7 +805,7 @@ void CameraService::Client::recordingCallback(const sp& mem, void* user return; } // The strong pointer guarantees the client will exist, but no lock is held. - client->postRecordingFrame(mem); + client->postRecordingFrame(timestamp, mem); } // take a picture - image is returned in callback @@ -1072,14 +1071,14 @@ void CameraService::Client::copyFrameAndPostCopiedFrame(sp heap, si mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame); } -void CameraService::Client::postRecordingFrame(const sp& frame) +void CameraService::Client::postRecordingFrame(nsecs_t timestamp, const sp& frame) { LOGV("postRecordingFrame"); if (frame == 0) { LOGW("frame is a null pointer"); return; } - mCameraClient->dataCallback(CAMERA_MSG_VIDEO_FRAME, frame); + mCameraClient->dataCallbackTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, frame); } void CameraService::Client::postPreviewFrame(const sp& mem) diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h index 0f07673940215..ea93789d14a01 100644 --- a/camera/libcameraservice/CameraService.h +++ b/camera/libcameraservice/CameraService.h @@ -132,7 +132,7 @@ private: status_t checkPid(); - static void recordingCallback(const sp& mem, void* user); + static void recordingCallback(nsecs_t timestamp, const sp& mem, void* user); static void previewCallback(const sp& mem, void* user); static void shutterCallback(void *user); static void yuvPictureCallback(const sp& mem, void* user); @@ -144,7 +144,7 @@ private: void postRaw(const sp& mem); void postJpeg(const sp& mem); void postPreviewFrame(const sp& mem); - void postRecordingFrame(const sp& frame); + void postRecordingFrame(nsecs_t timestamp, const sp& frame); void copyFrameAndPostCopiedFrame(sp heap, size_t offset, size_t size); void postError(status_t error); void postAutoFocus(bool focused); diff --git a/cmds/keystore/keystore_get.h b/cmds/keystore/keystore_get.h index a7fd9a556af8d..7665e81a314d6 100644 --- a/cmds/keystore/keystore_get.h +++ b/cmds/keystore/keystore_get.h @@ -29,7 +29,7 @@ * is returned. Otherwise it returns the value in dynamically allocated memory * and sets the size if the pointer is not NULL. One can release the memory by * calling free(). */ -static char *keystore_get(char *key, int *size) +static char *keystore_get(const char *key, int *size) { char buffer[MAX_KEY_VALUE_LENGTH]; char *value; diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index ca9632a490b1a..4ac3b9e9ae20c 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -606,13 +606,13 @@ public class Activity extends ContextThemeWrapper private static final String SAVED_DIALOG_IDS_KEY = "android:savedDialogIds"; private static final String SAVED_DIALOGS_TAG = "android:savedDialogs"; private static final String SAVED_DIALOG_KEY_PREFIX = "android:dialog_"; - private static final String SAVED_SEARCH_DIALOG_KEY = "android:search_dialog"; private SparseArray mManagedDialogs; // set by the thread after the constructor and before onCreate(Bundle savedInstanceState) is called. private Instrumentation mInstrumentation; private IBinder mToken; + private int mIdent; /*package*/ String mEmbeddedID; private Application mApplication; /*package*/ Intent mIntent; @@ -630,7 +630,6 @@ public class Activity extends ContextThemeWrapper /*package*/ int mConfigChangeFlags; /*package*/ Configuration mCurrentConfig; private SearchManager mSearchManager; - private Bundle mSearchDialogState = null; private Window mWindow; @@ -791,9 +790,6 @@ public class Activity extends ContextThemeWrapper protected void onCreate(Bundle savedInstanceState) { mVisibleFromClient = mWindow.getWindowStyle().getBoolean( com.android.internal.R.styleable.Window_windowNoDisplay, true); - // uses super.getSystemService() since this.getSystemService() looks at the - // mSearchManager field. - mSearchManager = (SearchManager) super.getSystemService(Context.SEARCH_SERVICE); mCalled = true; } @@ -808,13 +804,6 @@ public class Activity extends ContextThemeWrapper final void performRestoreInstanceState(Bundle savedInstanceState) { onRestoreInstanceState(savedInstanceState); restoreManagedDialogs(savedInstanceState); - - // Also restore the state of a search dialog (if any) - // TODO more generic than just this manager - Bundle searchState = savedInstanceState.getBundle(SAVED_SEARCH_DIALOG_KEY); - if (searchState != null) { - mSearchManager.restoreSearchDialog(searchState); - } } /** @@ -866,7 +855,7 @@ public class Activity extends ContextThemeWrapper if (dialogState != null) { // Calling onRestoreInstanceState() below will invoke dispatchOnCreate // so tell createDialog() not to do it, otherwise we get an exception - final Dialog dialog = createDialog(dialogId, false); + final Dialog dialog = createDialog(dialogId, dialogState); mManagedDialogs.put(dialogId, dialog); onPrepareDialog(dialogId, dialog); dialog.onRestoreInstanceState(dialogState); @@ -874,13 +863,13 @@ public class Activity extends ContextThemeWrapper } } - private Dialog createDialog(Integer dialogId, boolean dispatchOnCreate) { + private Dialog createDialog(Integer dialogId, Bundle state) { final Dialog dialog = onCreateDialog(dialogId); if (dialog == null) { throw new IllegalArgumentException("Activity#onCreateDialog did " + "not create a dialog for id " + dialogId); } - if (dispatchOnCreate) dialog.dispatchOnCreate(null); + dialog.dispatchOnCreate(state); return dialog; } @@ -1030,14 +1019,6 @@ public class Activity extends ContextThemeWrapper final void performSaveInstanceState(Bundle outState) { onSaveInstanceState(outState); saveManagedDialogs(outState); - - // Also save the state of a search dialog (if any) - // TODO more generic than just this manager - // onPause() should always be called before this method, so mSearchManagerState - // should be up to date. - if (mSearchDialogState != null) { - outState.putBundle(SAVED_SEARCH_DIALOG_KEY, mSearchDialogState); - } } /** @@ -1317,10 +1298,6 @@ public class Activity extends ContextThemeWrapper c.mCursor.close(); } } - - // Clear any search state saved in performPause(). If the state may be needed in the - // future, it will have been saved by performSaveInstanceState() - mSearchDialogState = null; } /** @@ -1341,11 +1318,7 @@ public class Activity extends ContextThemeWrapper */ public void onConfigurationChanged(Configuration newConfig) { mCalled = true; - - // also update search dialog if showing - // TODO more generic than just this manager - mSearchManager.onConfigurationChanged(newConfig); - + if (mWindow != null) { // Pass the configuration changed event to the window mWindow.onConfigurationChanged(newConfig); @@ -2432,7 +2405,7 @@ public class Activity extends ContextThemeWrapper } Dialog dialog = mManagedDialogs.get(id); if (dialog == null) { - dialog = createDialog(id, true); + dialog = createDialog(id, null); mManagedDialogs.put(id, dialog); } @@ -2556,6 +2529,7 @@ public class Activity extends ContextThemeWrapper */ public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData, boolean globalSearch) { + ensureSearchManager(); mSearchManager.startSearch(initialQuery, selectInitialQuery, getComponentName(), appSearchData, globalSearch); } @@ -3266,6 +3240,24 @@ public class Activity extends ContextThemeWrapper return getSharedPreferences(getLocalClassName(), mode); } + private void ensureSearchManager() { + if (mSearchManager != null) { + return; + } + + // uses super.getSystemService() since this.getSystemService() looks at the + // mSearchManager field. + mSearchManager = (SearchManager) super.getSystemService(Context.SEARCH_SERVICE); + int ident = mIdent; + if (ident == 0) { + if (mParent != null) ident = mParent.mIdent; + if (ident == 0) { + throw new IllegalArgumentException("no ident"); + } + } + mSearchManager.setIdent(ident); + } + @Override public Object getSystemService(String name) { if (getBaseContext() == null) { @@ -3276,6 +3268,7 @@ public class Activity extends ContextThemeWrapper if (WINDOW_SERVICE.equals(name)) { return mWindowManager; } else if (SEARCH_SERVICE.equals(name)) { + ensureSearchManager(); return mSearchManager; } return super.getSystemService(name); @@ -3475,14 +3468,17 @@ public class Activity extends ContextThemeWrapper Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, Object lastNonConfigurationInstance, Configuration config) { - attach(context, aThread, instr, token, application, intent, info, title, parent, id, + attach(context, aThread, instr, token, 0, application, intent, info, title, parent, id, lastNonConfigurationInstance, null, config); } - final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, - Application application, Intent intent, ActivityInfo info, CharSequence title, - Activity parent, String id, Object lastNonConfigurationInstance, - HashMap lastNonConfigurationChildInstances, Configuration config) { + final void attach(Context context, ActivityThread aThread, + Instrumentation instr, IBinder token, int ident, + Application application, Intent intent, ActivityInfo info, + CharSequence title, Activity parent, String id, + Object lastNonConfigurationInstance, + HashMap lastNonConfigurationChildInstances, + Configuration config) { attachBaseContext(context); mWindow = PolicyManager.makeNewWindow(this); @@ -3495,6 +3491,7 @@ public class Activity extends ContextThemeWrapper mMainThread = aThread; mInstrumentation = instr; mToken = token; + mIdent = ident; mApplication = application; mIntent = intent; mComponent = intent.getComponent(); @@ -3575,21 +3572,10 @@ public class Activity extends ContextThemeWrapper "Activity " + mComponent.toShortString() + " did not call through to super.onPostResume()"); } - - // restore search dialog, if any - if (mSearchDialogState != null) { - mSearchManager.restoreSearchDialog(mSearchDialogState); - } - mSearchDialogState = null; } final void performPause() { onPause(); - - // save search dialog state if the search dialog is open, - // and then dismiss the search dialog - mSearchDialogState = mSearchManager.saveSearchDialog(); - mSearchManager.stopSearch(); } final void performUserLeaving() { diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index dfa8139eecf46..ba6cc32808d41 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -881,11 +881,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } - case SET_ACTIVITY_WATCHER_TRANSACTION: { + case SET_ACTIVITY_CONTROLLER_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - IActivityWatcher watcher = IActivityWatcher.Stub.asInterface( + IActivityController watcher = IActivityController.Stub.asInterface( data.readStrongBinder()); - setActivityWatcher(watcher); + setActivityController(watcher); return true; } @@ -1052,6 +1052,39 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); return true; } + + case REGISTER_ACTIVITY_WATCHER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IActivityWatcher watcher = IActivityWatcher.Stub.asInterface( + data.readStrongBinder()); + registerActivityWatcher(watcher); + return true; + } + + case UNREGISTER_ACTIVITY_WATCHER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IActivityWatcher watcher = IActivityWatcher.Stub.asInterface( + data.readStrongBinder()); + unregisterActivityWatcher(watcher); + return true; + } + + case START_ACTIVITY_IN_PACKAGE_TRANSACTION: + { + data.enforceInterface(IActivityManager.descriptor); + int uid = data.readInt(); + Intent intent = Intent.CREATOR.createFromParcel(data); + String resolvedType = data.readString(); + IBinder resultTo = data.readStrongBinder(); + String resultWho = data.readString(); + int requestCode = data.readInt(); + boolean onlyIfNeeded = data.readInt() != 0; + int result = startActivityInPackage(uid, intent, resolvedType, + resultTo, resultWho, requestCode, onlyIfNeeded); + reply.writeNoException(); + reply.writeInt(result); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -2105,13 +2138,13 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } - public void setActivityWatcher(IActivityWatcher watcher) throws RemoteException + public void setActivityController(IActivityController watcher) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(watcher != null ? watcher.asBinder() : null); - mRemote.transact(SET_ACTIVITY_WATCHER_TRANSACTION, data, reply, 0); + mRemote.transact(SET_ACTIVITY_CONTROLLER_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); @@ -2290,5 +2323,51 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); } + public void registerActivityWatcher(IActivityWatcher watcher) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(watcher != null ? watcher.asBinder() : null); + mRemote.transact(REGISTER_ACTIVITY_WATCHER_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + public void unregisterActivityWatcher(IActivityWatcher watcher) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(watcher != null ? watcher.asBinder() : null); + mRemote.transact(UNREGISTER_ACTIVITY_WATCHER_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + public int startActivityInPackage(int uid, + Intent intent, String resolvedType, IBinder resultTo, + String resultWho, int requestCode, boolean onlyIfNeeded) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(uid); + intent.writeToParcel(data, 0); + data.writeString(resolvedType); + data.writeStrongBinder(resultTo); + data.writeString(resultWho); + data.writeInt(requestCode); + data.writeInt(onlyIfNeeded ? 1 : 0); + mRemote.transact(START_ACTIVITY_IN_PACKAGE_TRANSACTION, data, reply, 0); + reply.readException(); + int result = reply.readInt(); + reply.recycle(); + data.recycle(); + return result; + } + private IBinder mRemote; } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 5ee29ac4f4738..76b47f1140c38 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -32,8 +32,8 @@ import android.content.pm.InstrumentationInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.pm.ServiceInfo; -import android.content.pm.PackageParser.Component; import android.content.res.AssetManager; +import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.database.sqlite.SQLiteDatabase; @@ -166,43 +166,52 @@ public final class ActivityThread { return metrics; } - Resources getTopLevelResources(String appDir, PackageInfo pkgInfo) { + /** + * Creates the top level Resources for applications with the given compatibility info. + * + * @param resDir the resource directory. + * @param compInfo the compability info. It will use the default compatibility info when it's + * null. + */ + Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) { synchronized (mPackages) { - //Log.w(TAG, "getTopLevelResources: " + appDir); - WeakReference wr = mActiveResources.get(appDir); + // Resources is app scale dependent. + ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale); + //Log.w(TAG, "getTopLevelResources: " + resDir); + WeakReference wr = mActiveResources.get(key); Resources r = wr != null ? wr.get() : null; if (r != null && r.getAssets().isUpToDate()) { - //Log.w(TAG, "Returning cached resources " + r + " " + appDir); + //Log.w(TAG, "Returning cached resources " + r + " " + resDir); return r; } //if (r != null) { // Log.w(TAG, "Throwing away out-of-date resources!!!! " - // + r + " " + appDir); + // + r + " " + resDir); //} AssetManager assets = new AssetManager(); - if (assets.addAssetPath(appDir) == 0) { + if (assets.addAssetPath(resDir) == 0) { return null; } - ApplicationInfo appInfo; - try { - appInfo = getPackageManager().getApplicationInfo( - pkgInfo.getPackageName(), - PackageManager.GET_SUPPORTS_DENSITIES); - } catch (RemoteException e) { - throw new AssertionError(e); - } - //Log.i(TAG, "Resource:" + appDir + ", display metrics=" + metrics); + + //Log.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics); DisplayMetrics metrics = getDisplayMetricsLocked(false); - r = new Resources(assets, metrics, getConfiguration(), appInfo); + r = new Resources(assets, metrics, getConfiguration(), compInfo); //Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration()); // XXX need to remove entries when weak references go away - mActiveResources.put(appDir, new WeakReference(r)); + mActiveResources.put(key, new WeakReference(r)); return r; } } + /** + * Creates the top level resources for the given package. + */ + Resources getTopLevelResources(String resDir, PackageInfo pkgInfo) { + return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo); + } + final Handler getHandler() { return mH; } @@ -223,6 +232,7 @@ public final class ActivityThread { private Resources mResources; private ClassLoader mClassLoader; private Application mApplication; + private CompatibilityInfo mCompatibilityInfo; private final HashMap> mReceivers = new HashMap>(); @@ -250,6 +260,7 @@ public final class ActivityThread { mBaseClassLoader = baseLoader; mSecurityViolation = securityViolation; mIncludeCode = includeCode; + mCompatibilityInfo = new CompatibilityInfo(aInfo); if (mAppDir == null) { if (mSystemContext == null) { @@ -283,6 +294,7 @@ public final class ActivityThread { mIncludeCode = true; mClassLoader = systemContext.getClassLoader(); mResources = systemContext.getResources(); + mCompatibilityInfo = new CompatibilityInfo(mApplicationInfo); } public String getPackageName() { @@ -1077,6 +1089,7 @@ public final class ActivityThread { private static final class ActivityRecord { IBinder token; + int ident; Intent intent; Bundle state; Activity activity; @@ -1286,12 +1299,13 @@ public final class ActivityThread { // we use token to identify this activity without having to send the // activity itself back to the activity manager. (matters more with ipc) - public final void scheduleLaunchActivity(Intent intent, IBinder token, + public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Bundle state, List pendingResults, List pendingNewIntents, boolean notResumed, boolean isForward) { ActivityRecord r = new ActivityRecord(); r.token = token; + r.ident = ident; r.intent = intent; r.activityInfo = info; r.state = state; @@ -1894,6 +1908,32 @@ public final class ActivityThread { } } + private final static class ResourcesKey { + final private String mResDir; + final private float mScale; + final private int mHash; + + ResourcesKey(String resDir, float scale) { + mResDir = resDir; + mScale = scale; + mHash = mResDir.hashCode() << 2 + (int) (mScale * 2); + } + + @Override + public int hashCode() { + return mHash; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ResourcesKey)) { + return false; + } + ResourcesKey peer = (ResourcesKey) obj; + return mResDir.equals(peer.mResDir) && mScale == peer.mScale; + } + } + static IPackageManager sPackageManager; final ApplicationThread mAppThread = new ApplicationThread(); @@ -1939,8 +1979,8 @@ public final class ActivityThread { = new HashMap>(); Display mDisplay = null; DisplayMetrics mDisplayMetrics = null; - HashMap > mActiveResources - = new HashMap >(); + HashMap > mActiveResources + = new HashMap >(); // The lock of mProviderMap protects the following variables. final HashMap mProviderMap @@ -2157,22 +2197,12 @@ public final class ActivityThread { return aInfo; } - public final Activity startActivityNow(Activity parent, String id, - Intent intent, IBinder token, Bundle state) { - ActivityInfo aInfo = resolveActivityInfo(intent); - return startActivityNow(parent, id, intent, aInfo, token, state); - } - - public final Activity startActivityNow(Activity parent, String id, - Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state) { - return startActivityNow(parent, id, intent, activityInfo, token, state, null); - } - public final Activity startActivityNow(Activity parent, String id, Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state, Object lastNonConfigurationInstance) { ActivityRecord r = new ActivityRecord(); r.token = token; + r.ident = 0; r.intent = intent; r.state = state; r.parent = parent; @@ -2296,10 +2326,10 @@ public final class ActivityThread { appContext.setOuterContext(activity); CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mConfiguration); - activity.attach(appContext, this, getInstrumentation(), r.token, app, - r.intent, r.activityInfo, title, r.parent, r.embeddedID, - r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances, - config); + activity.attach(appContext, this, getInstrumentation(), r.token, + r.ident, app, r.intent, r.activityInfo, title, r.parent, + r.embeddedID, r.lastNonConfigurationInstance, + r.lastNonConfigurationChildInstances, config); if (customIntent != null) { activity.mIntent = customIntent; @@ -2545,32 +2575,39 @@ public final class ActivityThread { classname = "android.app.FullBackupAgent"; } try { - java.lang.ClassLoader cl = packageInfo.getClassLoader(); - agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance(); - } catch (Exception e) { - throw new RuntimeException("Unable to instantiate backup agent " - + data.appInfo.backupAgentName + ": " + e.toString(), e); - } - - // set up the agent's context - try { - if (DEBUG_BACKUP) Log.v(TAG, "Initializing BackupAgent " - + data.appInfo.backupAgentName); - - ApplicationContext context = new ApplicationContext(); - context.init(packageInfo, null, this); - context.setOuterContext(agent); - agent.attach(context); - agent.onCreate(); + IBinder binder = null; + try { + java.lang.ClassLoader cl = packageInfo.getClassLoader(); + agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance(); + + // set up the agent's context + if (DEBUG_BACKUP) Log.v(TAG, "Initializing BackupAgent " + + data.appInfo.backupAgentName); + + ApplicationContext context = new ApplicationContext(); + context.init(packageInfo, null, this); + context.setOuterContext(agent); + agent.attach(context); + + agent.onCreate(); + binder = agent.onBind(); + mBackupAgents.put(packageName, agent); + } catch (Exception e) { + // If this is during restore, fail silently; otherwise go + // ahead and let the user see the crash. + Log.e(TAG, "Agent threw during creation: " + e); + if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE) { + throw e; + } + // falling through with 'binder' still null + } // tell the OS that we're live now - IBinder binder = agent.onBind(); try { ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder); } catch (RemoteException e) { // nothing to do. } - mBackupAgents.put(packageName, agent); } catch (Exception e) { throw new RuntimeException("Unable to create BackupAgent " + data.appInfo.backupAgentName + ": " + e.toString(), e); diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java index 38ea686f7077a..afb2fe99c2e06 100644 --- a/core/java/android/app/ApplicationContext.java +++ b/core/java/android/app/ApplicationContext.java @@ -1341,21 +1341,8 @@ class ApplicationContext extends Context { if (pi != null) { ApplicationContext c = new ApplicationContext(); c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED; - c.init(pi, null, mMainThread); + c.init(pi, null, mMainThread, mResources); if (c.mResources != null) { - Resources newRes = c.mResources; - if (mResources.getCompatibilityInfo().applicationScale != - newRes.getCompatibilityInfo().applicationScale) { - DisplayMetrics dm = mMainThread.getDisplayMetricsLocked(false); - c.mResources = new Resources(newRes.getAssets(), dm, - newRes.getConfiguration(), - mResources.getCompatibilityInfo().copy()); - if (DEBUG) { - Log.d(TAG, "loaded context has different scaling. Using container's" + - " compatiblity info:" + mResources.getDisplayMetrics()); - } - - } return c; } } @@ -1417,8 +1404,24 @@ class ApplicationContext extends Context { final void init(ActivityThread.PackageInfo packageInfo, IBinder activityToken, ActivityThread mainThread) { + init(packageInfo, activityToken, mainThread, null); + } + + final void init(ActivityThread.PackageInfo packageInfo, + IBinder activityToken, ActivityThread mainThread, + Resources container) { mPackageInfo = packageInfo; mResources = mPackageInfo.getResources(mainThread); + + if (container != null && container.getCompatibilityInfo().applicationScale != + mResources.getCompatibilityInfo().applicationScale) { + if (DEBUG) { + Log.d(TAG, "loaded context has different scaling. Using container's" + + " compatiblity info:" + container.getDisplayMetrics()); + } + mResources = mainThread.getTopLevelResources( + mPackageInfo.getResDir(), container.getCompatibilityInfo().copy()); + } mMainThread = mainThread; mContentResolver = new ApplicationContentResolver(this, mainThread); diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index b052c99e75fc2..a3c63253d73d8 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -119,13 +119,15 @@ public abstract class ApplicationThreadNative extends Binder data.enforceInterface(IApplicationThread.descriptor); Intent intent = Intent.CREATOR.createFromParcel(data); IBinder b = data.readStrongBinder(); + int ident = data.readInt(); ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data); Bundle state = data.readBundle(); List ri = data.createTypedArrayList(ResultInfo.CREATOR); List pi = data.createTypedArrayList(Intent.CREATOR); boolean notResumed = data.readInt() != 0; boolean isForward = data.readInt() != 0; - scheduleLaunchActivity(intent, b, info, state, ri, pi, notResumed, isForward); + scheduleLaunchActivity(intent, b, ident, info, state, ri, pi, + notResumed, isForward); return true; } @@ -442,7 +444,7 @@ class ApplicationThreadProxy implements IApplicationThread { data.recycle(); } - public final void scheduleLaunchActivity(Intent intent, IBinder token, + public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Bundle state, List pendingResults, List pendingNewIntents, boolean notResumed, boolean isForward) throws RemoteException { @@ -450,6 +452,7 @@ class ApplicationThreadProxy implements IApplicationThread { data.writeInterfaceToken(IApplicationThread.descriptor); intent.writeToParcel(data, 0); data.writeStrongBinder(token); + data.writeInt(ident); info.writeToParcel(data, 0); data.writeBundle(state); data.writeTypedList(pendingResults); diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index 222fe75fb3a27..943275514caff 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -20,6 +20,7 @@ import com.android.internal.policy.PolicyManager; import android.content.Context; import android.content.DialogInterface; +import android.content.ComponentName; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; @@ -86,6 +87,7 @@ public class Dialog implements DialogInterface, Window.Callback, private Message mCancelMessage; private Message mDismissMessage; + private Message mShowMessage; /** * Whether to cancel the dialog when a touch is received outside of the @@ -140,7 +142,7 @@ public class Dialog implements DialogInterface, Window.Callback, w.setWindowManager(mWindowManager, null, null); w.setGravity(Gravity.CENTER); mUiThread = Thread.currentThread(); - mDismissCancelHandler = new DismissCancelHandler(this); + mListenersHandler = new ListenersHandler(this); } /** @@ -235,6 +237,8 @@ public class Dialog implements DialogInterface, Window.Callback, } mWindowManager.addView(mDecor, l); mShowing = true; + + sendShowMessage(); } /** @@ -289,11 +293,20 @@ public class Dialog implements DialogInterface, Window.Callback, } } + private void sendShowMessage() { + if (mShowMessage != null) { + // Obtain a new message so this dialog can be re-used + Message.obtain(mShowMessage).sendToTarget(); + } + } + // internal method to make sure mcreated is set properly without requiring // users to call through to super in onCreate void dispatchOnCreate(Bundle savedInstanceState) { - onCreate(savedInstanceState); - mCreated = true; + if (!mCreated) { + onCreate(savedInstanceState); + mCreated = true; + } } /** @@ -772,8 +785,22 @@ public class Dialog implements DialogInterface, Window.Callback, * This hook is called when the user signals the desire to start a search. */ public boolean onSearchRequested() { - // not during dialogs, no. - return false; + final SearchManager searchManager = (SearchManager) mContext + .getSystemService(Context.SEARCH_SERVICE); + + // can't start search without an associated activity (e.g a system dialog) + if (!searchManager.hasIdent()) { + return false; + } + + // associate search with owner activity if possible (otherwise it will default to + // global search). + final ComponentName appName = mOwnerActivity == null ? null + : mOwnerActivity.getComponentName(); + final boolean globalSearch = (appName == null); + searchManager.startSearch(null, false, appName, null, globalSearch); + dismiss(); + return true; } @@ -888,7 +915,7 @@ public class Dialog implements DialogInterface, Window.Callback, */ public void setOnCancelListener(final OnCancelListener listener) { if (listener != null) { - mCancelMessage = mDismissCancelHandler.obtainMessage(CANCEL, listener); + mCancelMessage = mListenersHandler.obtainMessage(CANCEL, listener); } else { mCancelMessage = null; } @@ -909,12 +936,25 @@ public class Dialog implements DialogInterface, Window.Callback, */ public void setOnDismissListener(final OnDismissListener listener) { if (listener != null) { - mDismissMessage = mDismissCancelHandler.obtainMessage(DISMISS, listener); + mDismissMessage = mListenersHandler.obtainMessage(DISMISS, listener); } else { mDismissMessage = null; } } + /** + * Sets a listener to be invoked when the dialog is shown. + * + * @hide Pending API council approval + */ + public void setOnShowListener(OnShowListener listener) { + if (listener != null) { + mShowMessage = mListenersHandler.obtainMessage(SHOW, listener); + } else { + mShowMessage = null; + } + } + /** * Set a message to be sent when the dialog is dismissed. * @param msg The msg to send when the dialog is dismissed. @@ -949,13 +989,14 @@ public class Dialog implements DialogInterface, Window.Callback, private static final int DISMISS = 0x43; private static final int CANCEL = 0x44; + private static final int SHOW = 0x45; - private Handler mDismissCancelHandler; + private Handler mListenersHandler; - private static final class DismissCancelHandler extends Handler { + private static final class ListenersHandler extends Handler { private WeakReference mDialog; - public DismissCancelHandler(Dialog dialog) { + public ListenersHandler(Dialog dialog) { mDialog = new WeakReference(dialog); } @@ -968,6 +1009,9 @@ public class Dialog implements DialogInterface, Window.Callback, case CANCEL: ((OnCancelListener) msg.obj).onCancel(mDialog.get()); break; + case SHOW: + ((OnShowListener) msg.obj).onShow(mDialog.get()); + break; } } } diff --git a/core/java/android/app/IActivityController.aidl b/core/java/android/app/IActivityController.aidl new file mode 100644 index 0000000000000..8f6b252d555cf --- /dev/null +++ b/core/java/android/app/IActivityController.aidl @@ -0,0 +1,55 @@ +/* +** +** Copyright 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.app; + +import android.content.Intent; + +/** + * Testing interface to monitor what is happening in the activity manager + * while tests are running. Not for normal application development. + * {@hide} + */ +interface IActivityController +{ + /** + * The system is trying to start an activity. Return true to allow + * it to be started as normal, or false to cancel/reject this activity. + */ + boolean activityStarting(in Intent intent, String pkg); + + /** + * The system is trying to return to an activity. Return true to allow + * it to be resumed as normal, or false to cancel/reject this activity. + */ + boolean activityResuming(String pkg); + + /** + * An application process has crashed (in Java). Return true for the + * normal error recovery (app crash dialog) to occur, false to kill + * it immediately. + */ + boolean appCrashed(String processName, int pid, String shortMsg, + String longMsg, in byte[] crashData); + + /** + * An application process is not responding. Return 0 to show the "app + * not responding" dialog, 1 to continue waiting, or -1 to kill it + * immediately. + */ + int appNotResponding(String processName, int pid, String processStats); +} diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 3ec7938b5a10a..95b376cce673d 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -216,7 +216,7 @@ public interface IActivityManager extends IInterface { String packageName, boolean waitForDebugger, boolean persistent) throws RemoteException; public void setAlwaysFinish(boolean enabled) throws RemoteException; - public void setActivityWatcher(IActivityWatcher watcher) + public void setActivityController(IActivityController watcher) throws RemoteException; public void enterSafeMode() throws RemoteException; @@ -257,6 +257,16 @@ public interface IActivityManager extends IInterface { public void stopAppSwitches() throws RemoteException; public void resumeAppSwitches() throws RemoteException; + public void registerActivityWatcher(IActivityWatcher watcher) + throws RemoteException; + public void unregisterActivityWatcher(IActivityWatcher watcher) + throws RemoteException; + + public int startActivityInPackage(int uid, + Intent intent, String resolvedType, IBinder resultTo, + String resultWho, int requestCode, boolean onlyIfNeeded) + throws RemoteException; + /* * Private non-Binder interfaces */ @@ -372,7 +382,7 @@ public interface IActivityManager extends IInterface { int CHECK_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+53; int GRANT_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+54; int REVOKE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+55; - int SET_ACTIVITY_WATCHER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+56; + int SET_ACTIVITY_CONTROLLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+56; int SHOW_WAITING_FOR_DEBUGGER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+57; int SIGNAL_PERSISTENT_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+58; int GET_RECENT_TASKS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+59; @@ -408,4 +418,7 @@ public interface IActivityManager extends IInterface { int START_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+89; int BACKUP_AGENT_CREATED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+90; int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91; + int REGISTER_ACTIVITY_WATCHER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92; + int UNREGISTER_ACTIVITY_WATCHER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93; + int START_ACTIVITY_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94; } diff --git a/core/java/android/app/IActivityWatcher.aidl b/core/java/android/app/IActivityWatcher.aidl index f13a385cc2cad..5d36e3fdb5993 100644 --- a/core/java/android/app/IActivityWatcher.aidl +++ b/core/java/android/app/IActivityWatcher.aidl @@ -1,6 +1,6 @@ -/* //device/java/android/android/app/IInstrumentationWatcher.aidl +/* ** -** Copyright 2007, The Android Open Source Project +** Copyright 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. @@ -17,39 +17,10 @@ package android.app; -import android.content.Intent; - /** - * Testing interface to monitor what is happening in the activity manager - * while tests are running. Not for normal application development. + * Callback interface to watch the user's traversal through activities. * {@hide} */ -interface IActivityWatcher -{ - /** - * The system is trying to start an activity. Return true to allow - * it to be started as normal, or false to cancel/reject this activity. - */ - boolean activityStarting(in Intent intent, String pkg); - - /** - * The system is trying to return to an activity. Return true to allow - * it to be resumed as normal, or false to cancel/reject this activity. - */ - boolean activityResuming(String pkg); - - /** - * An application process has crashed (in Java). Return true for the - * normal error recovery (app crash dialog) to occur, false to kill - * it immediately. - */ - boolean appCrashed(String processName, int pid, String shortMsg, - String longMsg, in byte[] crashData); - - /** - * An application process is not responding. Return 0 to show the "app - * not responding" dialog, 1 to continue waiting, or -1 to kill it - * immediately. - */ - int appNotResponding(String processName, int pid, String processStats); +oneway interface IActivityWatcher { + void activityResuming(int activityId); } diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index c0bc2a03ac91d..c9157702ea575 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -49,7 +49,7 @@ public interface IApplicationThread extends IInterface { void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException; void scheduleResumeActivity(IBinder token, boolean isForward) throws RemoteException; void scheduleSendResult(IBinder token, List results) throws RemoteException; - void scheduleLaunchActivity(Intent intent, IBinder token, + void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Bundle state, List pendingResults, List pendingNewIntents, boolean notResumed, boolean isForward) throws RemoteException; diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl index e8bd60a4d86fa..bd725443e13a9 100644 --- a/core/java/android/app/ISearchManager.aidl +++ b/core/java/android/app/ISearchManager.aidl @@ -34,10 +34,8 @@ interface ISearchManager { in ComponentName launchActivity, in Bundle appSearchData, boolean globalSearch, - ISearchManagerCallback searchManagerCallback); + ISearchManagerCallback searchManagerCallback, + int ident); void stopSearch(); boolean isVisible(); - Bundle onSaveInstanceState(); - void onRestoreInstanceState(in Bundle savedInstanceState); - void onConfigurationChanged(in Configuration newConfig); } diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index fdb619ae2da6e..27c637652d5ef 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -19,22 +19,19 @@ package android.app; import static android.app.SuggestionsAdapter.getColumnString; import android.content.ActivityNotFoundException; -import android.content.BroadcastReceiver; import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.content.ContentResolver; import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Configuration; import android.content.res.Resources; import android.database.Cursor; -import android.graphics.drawable.Drawable; import android.graphics.drawable.Animatable; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; @@ -92,14 +89,13 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS private static final String INSTANCE_KEY_STORED_APPDATA = "sData"; private static final String INSTANCE_KEY_PREVIOUS_COMPONENTS = "sPrev"; private static final String INSTANCE_KEY_USER_QUERY = "uQry"; + + // The extra key used in an intent to the speech recognizer for in-app voice search. + private static final String EXTRA_CALLING_PACKAGE = "calling_package"; private static final int SEARCH_PLATE_LEFT_PADDING_GLOBAL = 12; private static final int SEARCH_PLATE_LEFT_PADDING_NON_GLOBAL = 7; - - // interaction with runtime - private IntentFilter mCloseDialogsFilter; - private IntentFilter mPackageFilter; - + // views & widgets private TextView mBadgeLabel; private ImageView mAppIcon; @@ -143,8 +139,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // A weak map of drawables we've gotten from other packages, so we don't load them // more than once. - private final WeakHashMap mOutsideDrawablesCache = - new WeakHashMap(); + private final WeakHashMap mOutsideDrawablesCache = + new WeakHashMap(); // Last known IME options value for the search edit text. private int mSearchAutoCompleteImeOptions; @@ -210,15 +206,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // Touching outside of the search dialog will dismiss it setCanceledOnTouchOutside(true); - - // Set up broadcast filters - mCloseDialogsFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); - mPackageFilter = new IntentFilter(); - mPackageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); - mPackageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); - mPackageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); - mPackageFilter.addDataScheme("package"); - + // Save voice intent for later queries/launching mVoiceWebSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); mVoiceWebSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -333,16 +321,14 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if (!globalSearch && mSearchable == null) { globalSearch = true; mSearchable = searchManager.getSearchableInfo(componentName, globalSearch); - - // If we still get back null (i.e., there's not even a searchable info available - // for global search), then really give up. - if (mSearchable == null) { - // Unfortunately, we can't log here. it would be logspam every time the user - // clicks the "search" key on a non-search app. - return false; - } } - + + // If there's not even a searchable info available for global search, then really give up. + if (mSearchable == null) { + Log.w(LOG_TAG, "No global search provider."); + return false; + } + mLaunchComponent = componentName; mAppSearchData = appSearchData; // Using globalSearch here is just an optimization, just calling @@ -351,16 +337,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mActivityContext = mSearchable.getActivityContext(getContext()); // show the dialog. this will call onStart(). - if (!isShowing()) { - // First make sure the keyboard is showing (if needed), so that we get the right height - // for the dropdown to respect the IME. - if (getContext().getResources().getConfiguration().hardKeyboardHidden == - Configuration.HARDKEYBOARDHIDDEN_YES) { - InputMethodManager inputManager = (InputMethodManager) - getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - inputManager.showSoftInputUnchecked(0, null); - } - + if (!isShowing()) { // The Dialog uses a ContextThemeWrapper for the context; use this to change the // theme out from underneath us, between the global search theme and the in-app // search theme. They are identical except that the global search theme does not @@ -377,20 +354,10 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } show(); } - updateUI(); return true; } - - @Override - protected void onStart() { - super.onStart(); - - // receive broadcasts - getContext().registerReceiver(mBroadcastReceiver, mCloseDialogsFilter); - getContext().registerReceiver(mBroadcastReceiver, mPackageFilter); - } /** * The search dialog is being dismissed, so handle all of the local shutdown operations. @@ -401,14 +368,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS @Override public void onStop() { super.onStop(); - - // stop receiving broadcasts (throws exception if none registered) - try { - getContext().unregisterReceiver(mBroadcastReceiver); - } catch (RuntimeException e) { - // This is OK - it just means we didn't have any registered - } - + closeSuggestionsAdapter(); // dump extra memory we're hanging on to @@ -455,12 +415,15 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS /** * Save the minimal set of data necessary to recreate the search * - * @return A bundle with the state of the dialog. + * @return A bundle with the state of the dialog, or {@code null} if the search + * dialog is not showing. */ @Override public Bundle onSaveInstanceState() { + if (!isShowing()) return null; + Bundle bundle = new Bundle(); - + // setup info so I can recreate this particular search bundle.putParcelable(INSTANCE_KEY_COMPONENT, mLaunchComponent); bundle.putBundle(INSTANCE_KEY_APPDATA, mAppSearchData); @@ -483,6 +446,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS */ @Override public void onRestoreInstanceState(Bundle savedInstanceState) { + if (savedInstanceState == null) return; + ComponentName launchComponent = savedInstanceState.getParcelable(INSTANCE_KEY_COMPONENT); Bundle appSearchData = savedInstanceState.getBundle(INSTANCE_KEY_APPDATA); boolean globalSearch = savedInstanceState.getBoolean(INSTANCE_KEY_GLOBALSEARCH); @@ -509,7 +474,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS /** * Called after resources have changed, e.g. after screen rotation or locale change. */ - public void onConfigurationChanged(Configuration newConfig) { + public void onConfigurationChanged() { if (isShowing()) { // Redraw (resources may have changed) updateSearchButton(); @@ -524,6 +489,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS */ private void updateUI() { if (mSearchable != null) { + mDecor.setVisibility(View.VISIBLE); updateSearchAutoComplete(); updateSearchButton(); updateSearchAppIcon(); @@ -733,7 +699,10 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (DBG) Log.d(LOG_TAG, "onKeyDown(" + keyCode + "," + event + ")"); - + if (mSearchable == null) { + return false; + } + // handle back key to go back to previous searchable, etc. if (handleBackKey(keyCode, event)) { return true; @@ -769,6 +738,9 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if (DBG_LOG_TIMING) { dbgLogTiming("onTextChanged()"); } + if (mSearchable == null) { + return; + } updateWidgetState(); if (!mSearchAutoComplete.isPerformingCompletion()) { // The user changed the query, remember it. @@ -777,7 +749,10 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } public void afterTextChanged(Editable s) { - if (!mSearchAutoComplete.isPerformingCompletion()) { + if (mSearchable == null) { + return; + } + if (mSearchable.autoUrlDetect() && !mSearchAutoComplete.isPerformingCompletion()) { // The user changed the query, check if it is a URL and if so change the search // button in the soft keyboard to the 'Go' button. int options = (mSearchAutoComplete.getImeOptions() & (~EditorInfo.IME_MASK_ACTION)); @@ -878,11 +853,13 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * @return A completely-configured intent ready to send to the voice search activity */ private Intent createVoiceAppSearchIntent(Intent baseIntent) { + ComponentName searchActivity = mSearchable.getSearchActivity(); + // create the necessary intent to set up a search-and-forward operation // in the voice search system. We have to keep the bundle separate, // because it becomes immutable once it enters the PendingIntent Intent queryIntent = new Intent(Intent.ACTION_SEARCH); - queryIntent.setComponent(mSearchable.getSearchActivity()); + queryIntent.setComponent(searchActivity); PendingIntent pending = PendingIntent.getActivity( getContext(), 0, queryIntent, PendingIntent.FLAG_ONE_SHOT); @@ -922,6 +899,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt); voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language); voiceIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, maxResults); + voiceIntent.putExtra(EXTRA_CALLING_PACKAGE, + searchActivity == null ? null : searchActivity.toShortString()); // Add the values that configure forwarding the results voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, pending); @@ -987,10 +966,11 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS && event.getAction() == KeyEvent.ACTION_UP) { v.cancelLongPress(); - // If this is a url entered by the user and we displayed the 'Go' button which + // If this is a url entered by the user & we displayed the 'Go' button which // the user clicked, launch the url instead of using it as a search query. - if ((mSearchAutoCompleteImeOptions & EditorInfo.IME_MASK_ACTION) - == EditorInfo.IME_ACTION_GO) { + if (mSearchable.autoUrlDetect() && + (mSearchAutoCompleteImeOptions & EditorInfo.IME_MASK_ACTION) + == EditorInfo.IME_ACTION_GO) { Uri uri = Uri.parse(fixUrl(mSearchAutoComplete.getText().toString())); Intent intent = new Intent(Intent.ACTION_VIEW, uri); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -1012,35 +992,11 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS return false; } }; - - /** - * When the ACTION_CLOSE_SYSTEM_DIALOGS intent is received, we should close ourselves - * immediately, in order to allow a higher-priority UI to take over - * (e.g. phone call received). - * - * When a package is added, removed or changed, our current context - * may no longer be valid. This would only happen if a package is installed/removed exactly - * when the search bar is open. So for now we're just going to close the search - * bar. - * Anything fancier would require some checks to see if the user's context was still valid. - * Which would be messier. - */ - private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { - cancel(); - } else if (Intent.ACTION_PACKAGE_ADDED.equals(action) - || Intent.ACTION_PACKAGE_REMOVED.equals(action) - || Intent.ACTION_PACKAGE_CHANGED.equals(action)) { - cancel(); - } - } - }; @Override - public void cancel() { + public void hide() { + if (!isShowing()) return; + // We made sure the IME was displayed, so also make sure it is closed // when we go away. InputMethodManager imm = (InputMethodManager)getContext() @@ -1049,10 +1005,10 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS imm.hideSoftInputFromWindow( getWindow().getDecorView().getWindowToken(), 0); } - - super.cancel(); + + super.hide(); } - + /** * React to the user typing while in the suggestions list. First, check for action * keys. If not handled, try refocusing regular characters into the EditText. @@ -1086,6 +1042,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mSearchAutoComplete.setSelection(selPoint); mSearchAutoComplete.setListSelection(0); mSearchAutoComplete.clearListSelection(); + mSearchAutoComplete.ensureImeVisible(); + return true; } @@ -1276,8 +1234,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } /** - * Launches an intent and dismisses the search dialog (unless the intent - * is one of the special intents that modifies the state of the search dialog). + * Launches an intent, including any special intent handling. Doesn't dismiss the dialog + * since that will be handled in {@link SearchDialogWrapper#performActivityResuming} */ private void launchIntent(Intent intent) { if (intent == null) { @@ -1286,8 +1244,15 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if (handleSpecialIntent(intent)){ return; } - dismiss(); + Log.d(LOG_TAG, "launching " + intent); getContext().startActivity(intent); + + // in global search mode, SearchDialogWrapper#performActivityResuming will handle hiding + // the dialog when the next activity starts, but for in-app search, we still need to + // dismiss the dialog. + if (!mGlobalSearchMode) { + dismiss(); + } } /** @@ -1580,7 +1545,22 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS @Override public void performCompletion() { } - + + /** + * We override this method to be sure and show the soft keyboard if appropriate when + * the TextView has focus. + */ + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + + if (hasWindowFocus) { + InputMethodManager inputManager = (InputMethodManager) + getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.showSoftInput(this, 0); + } + } + /** * We override this method so that we can allow a threshold of zero, which ACTV does not. */ @@ -1595,6 +1575,9 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS */ @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { + if (mSearchDialog.mSearchable == null) { + return false; + } if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) { if (mSearchDialog.backToPreviousComponent()) { return true; diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index e5ba6a4a03c7e..0631ad58929ba 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -20,7 +20,6 @@ import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; -import android.content.res.Configuration; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -1189,8 +1188,6 @@ public class SearchManager /** * Intent extra data key: This key will be used for the extra populated by the * {@link #SUGGEST_COLUMN_INTENT_EXTRA_DATA} column. - * - * {@hide} */ public final static String EXTRA_DATA_KEY = "intent_extra_data_key"; @@ -1270,16 +1267,12 @@ public class SearchManager * result indicates the shortcut refers to a no longer valid sugggestion. * * @see #SUGGEST_COLUMN_SHORTCUT_ID - * - * @hide pending API council approval */ public final static String SUGGEST_URI_PATH_SHORTCUT = "search_suggest_shortcut"; /** * MIME type for shortcut validation. You'll use this in your suggestions content provider * in the getType() function. - * - * @hide pending API council approval */ public final static String SHORTCUT_MIME_TYPE = "vnd.android.cursor.item/vnd.android.search.suggest"; @@ -1390,9 +1383,7 @@ public class SearchManager * this element exists at the given row, this is the data that will be used when * forming the suggestion's intent. If not provided, the Intent's extra data field will be null. * This column allows suggestions to provide additional arbitrary data which will be included as - * an extra under the key EXTRA_DATA_KEY. - * - * @hide Pending API council approval. + * an extra under the key {@link #EXTRA_DATA_KEY}. */ public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data"; /** @@ -1426,8 +1417,6 @@ public class SearchManager * {@link #SUGGEST_NEVER_MAKE_SHORTCUT}, the result will not be stored as a shortcut. * Otherwise, the shortcut id will be used to check back for validation via * {@link #SUGGEST_URI_PATH_SHORTCUT}. - * - * @hide Pending API council approval. */ public final static String SUGGEST_COLUMN_SHORTCUT_ID = "suggest_shortcut_id"; @@ -1444,8 +1433,6 @@ public class SearchManager * Column name for suggestions cursor. Optional. This column is used to specify * that a spinner should be shown in lieu of an icon2 while the shortcut of this suggestion * is being refreshed. - * - * @hide Pending API council approval. */ public final static String SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING = "suggest_spinner_while_refreshing"; @@ -1453,8 +1440,6 @@ public class SearchManager /** * Column value for suggestion column {@link #SUGGEST_COLUMN_SHORTCUT_ID} when a suggestion * should not be stored as a shortcut in global search. - * - * @hide Pending API council approval. */ public final static String SUGGEST_NEVER_MAKE_SHORTCUT = "_-1"; @@ -1501,8 +1486,6 @@ public class SearchManager * Intent action for starting a web search provider's settings activity. * Web search providers should handle this intent if they have provider-specific * settings to implement. - * - * @hide Pending API council approval. */ public final static String INTENT_ACTION_WEB_SEARCH_SETTINGS = "android.search.action.WEB_SEARCH_SETTINGS"; @@ -1511,11 +1494,17 @@ public class SearchManager * Intent action broadcasted to inform that the searchables list or default have changed. * Components should handle this intent if they cache any searchable data and wish to stay * up to date on changes. - * - * @hide Pending API council approval. */ public final static String INTENT_ACTION_SEARCHABLES_CHANGED = "android.search.action.SEARCHABLES_CHANGED"; + + /** + * Intent action broadcasted to inform that the search settings have changed in some way. + * Either searchables have been enabled or disabled, or a different web search provider + * has been chosen. + */ + public final static String INTENT_ACTION_SEARCH_SETTINGS_CHANGED + = "android.search.action.SETTINGS_CHANGED"; /** * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION}, @@ -1532,8 +1521,9 @@ public class SearchManager private final Context mContext; + private int mIdent; + // package private since they are used by the inner class SearchManagerCallback - /* package */ boolean mIsShowing = false; /* package */ final Handler mHandler; /* package */ OnDismissListener mDismissListener = null; /* package */ OnCancelListener mCancelListener = null; @@ -1546,6 +1536,17 @@ public class SearchManager mService = ISearchManager.Stub.asInterface( ServiceManager.getService(Context.SEARCH_SERVICE)); } + + /*package*/ boolean hasIdent() { + return mIdent != 0; + } + + /*package*/ void setIdent(int ident) { + if (mIdent != 0) { + throw new IllegalStateException("mIdent already set"); + } + mIdent = ident; + } /** * Launch search UI. @@ -1592,13 +1593,12 @@ public class SearchManager ComponentName launchActivity, Bundle appSearchData, boolean globalSearch) { - if (DBG) debug("startSearch(), mIsShowing=" + mIsShowing); - if (mIsShowing) return; + if (mIdent == 0) throw new IllegalArgumentException( + "Called from outside of an Activity context"); try { - mIsShowing = true; // activate the search manager and start it up! mService.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData, - globalSearch, mSearchManagerCallback); + globalSearch, mSearchManagerCallback, mIdent); } catch (RemoteException ex) { Log.e(TAG, "startSearch() failed: " + ex); } @@ -1616,15 +1616,10 @@ public class SearchManager * @see #startSearch */ public void stopSearch() { - if (DBG) debug("stopSearch(), mIsShowing=" + mIsShowing); - if (!mIsShowing) return; + if (DBG) debug("stopSearch()"); try { mService.stopSearch(); - // onDismiss will also clear this, but we do it here too since onDismiss() is - // called asynchronously. - mIsShowing = false; } catch (RemoteException ex) { - Log.e(TAG, "stopSearch() failed: " + ex); } } @@ -1638,8 +1633,13 @@ public class SearchManager * @hide */ public boolean isVisible() { - if (DBG) debug("isVisible(), mIsShowing=" + mIsShowing); - return mIsShowing; + if (DBG) debug("isVisible()"); + try { + return mService.isVisible(); + } catch (RemoteException e) { + Log.e(TAG, "isVisible() failed: " + e); + return false; + } } /** @@ -1691,7 +1691,6 @@ public class SearchManager private final Runnable mFireOnDismiss = new Runnable() { public void run() { if (DBG) debug("mFireOnDismiss"); - mIsShowing = false; if (mDismissListener != null) { mDismissListener.onDismiss(); } @@ -1701,7 +1700,6 @@ public class SearchManager private final Runnable mFireOnCancel = new Runnable() { public void run() { if (DBG) debug("mFireOnCancel"); - // doesn't need to clear mIsShowing since onDismiss() always gets called too if (mCancelListener != null) { mCancelListener.onCancel(); } @@ -1720,68 +1718,20 @@ public class SearchManager } - // TODO: remove the DialogInterface interfaces from SearchManager. - // This changes the public API, so I'll do it in a separate change. + /** + * @deprecated This method is an obsolete internal implementation detail. Do not use. + */ public void onCancel(DialogInterface dialog) { throw new UnsupportedOperationException(); } + + /** + * @deprecated This method is an obsolete internal implementation detail. Do not use. + */ public void onDismiss(DialogInterface dialog) { throw new UnsupportedOperationException(); } - /** - * Saves the state of the search UI. - * - * @return A Bundle containing the state of the search dialog, or {@code null} - * if the search UI is not visible. - * - * @hide - */ - public Bundle saveSearchDialog() { - if (DBG) debug("saveSearchDialog(), mIsShowing=" + mIsShowing); - if (!mIsShowing) return null; - try { - return mService.onSaveInstanceState(); - } catch (RemoteException ex) { - Log.e(TAG, "onSaveInstanceState() failed: " + ex); - return null; - } - } - - /** - * Restores the state of the search dialog. - * - * @param searchDialogState Bundle to read the state from. - * - * @hide - */ - public void restoreSearchDialog(Bundle searchDialogState) { - if (DBG) debug("restoreSearchDialog(" + searchDialogState + ")"); - if (searchDialogState == null) return; - try { - mService.onRestoreInstanceState(searchDialogState); - } catch (RemoteException ex) { - Log.e(TAG, "onRestoreInstanceState() failed: " + ex); - } - } - - /** - * Update the search dialog after a configuration change. - * - * @param newConfig The new configuration. - * - * @hide - */ - public void onConfigurationChanged(Configuration newConfig) { - if (DBG) debug("onConfigurationChanged(" + newConfig + "), mIsShowing=" + mIsShowing); - if (!mIsShowing) return; - try { - mService.onConfigurationChanged(newConfig); - } catch (RemoteException ex) { - Log.e(TAG, "onConfigurationChanged() failed:" + ex); - } - } - /** * Gets information about a searchable activity. This method is static so that it can * be used from non-Activity contexts. diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java index 49c94d12f8d03..593b7b736cfaa 100644 --- a/core/java/android/app/SuggestionsAdapter.java +++ b/core/java/android/app/SuggestionsAdapter.java @@ -16,28 +16,31 @@ package android.app; +import android.app.SearchManager.DialogCursorProtocol; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; -import android.content.res.Resources.NotFoundException; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; import android.database.Cursor; -import android.graphics.Canvas; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.StateListDrawable; import android.net.Uri; import android.os.Bundle; import android.server.search.SearchableInfo; import android.text.Html; import android.text.TextUtils; -import android.util.DisplayMetrics; import android.util.Log; -import android.util.TypedValue; +import android.util.SparseArray; import android.view.View; import android.view.ViewGroup; -import android.widget.AbsListView; import android.widget.ImageView; import android.widget.ResourceCursorAdapter; import android.widget.TextView; - -import static android.app.SearchManager.DialogCursorProtocol; +import android.widget.Filter; import java.io.FileNotFoundException; import java.io.IOException; @@ -58,7 +61,8 @@ class SuggestionsAdapter extends ResourceCursorAdapter { private SearchDialog mSearchDialog; private SearchableInfo mSearchable; private Context mProviderContext; - private WeakHashMap mOutsideDrawablesCache; + private WeakHashMap mOutsideDrawablesCache; + private SparseArray mBackgroundsCache; private boolean mGlobalSearchMode; // Cached column indexes, updated when the cursor changes. @@ -87,8 +91,16 @@ class SuggestionsAdapter extends ResourceCursorAdapter { private final Runnable mStartSpinnerRunnable; private final Runnable mStopSpinnerRunnable; - public SuggestionsAdapter(Context context, SearchDialog searchDialog, SearchableInfo searchable, - WeakHashMap outsideDrawablesCache, boolean globalSearchMode) { + /** + * The amount of time we delay in the filter when the user presses the delete key. + * @see Filter#setDelayer(android.widget.Filter.Delayer). + */ + private static final long DELETE_KEY_POST_DELAY = 500L; + + public SuggestionsAdapter(Context context, SearchDialog searchDialog, + SearchableInfo searchable, + WeakHashMap outsideDrawablesCache, + boolean globalSearchMode) { super(context, com.android.internal.R.layout.search_dropdown_item_icons_2line, null, // no initial cursor @@ -102,6 +114,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter { mProviderContext = mSearchable.getProviderContext(mContext, activityContext); mOutsideDrawablesCache = outsideDrawablesCache; + mBackgroundsCache = new SparseArray(); mGlobalSearchMode = globalSearchMode; mStartSpinnerRunnable = new Runnable() { @@ -115,6 +128,18 @@ class SuggestionsAdapter extends ResourceCursorAdapter { mSearchDialog.setWorking(false); } }; + + // delay 500ms when deleting + getFilter().setDelayer(new Filter.Delayer() { + + private int mPreviousLength = 0; + + public long getPostingDelay(CharSequence constraint) { + long delay = constraint.length() < mPreviousLength ? DELETE_KEY_POST_DELAY : 0; + mPreviousLength = constraint.length(); + return delay; + } + }); } /** @@ -252,7 +277,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter { */ @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { - View v = new SuggestionItemView(context, cursor); + View v = super.newView(context, cursor, parent); v.setTag(new ChildViewCache(v)); return v; } @@ -297,13 +322,46 @@ class SuggestionsAdapter extends ResourceCursorAdapter { if (mBackgroundColorCol != -1) { backgroundColor = cursor.getInt(mBackgroundColorCol); } - ((SuggestionItemView)view).setColor(backgroundColor); + Drawable background = getItemBackground(backgroundColor); + view.setBackgroundDrawable(background); final boolean isHtml = mFormatCol > 0 && "html".equals(cursor.getString(mFormatCol)); setViewText(cursor, views.mText1, mText1Col, isHtml); setViewText(cursor, views.mText2, mText2Col, isHtml); - setViewIcon(cursor, views.mIcon1, mIconName1Col); - setViewIcon(cursor, views.mIcon2, mIconName2Col); + + if (views.mIcon1 != null) { + setViewDrawable(views.mIcon1, getIcon1(cursor)); + } + if (views.mIcon2 != null) { + setViewDrawable(views.mIcon2, getIcon2(cursor)); + } + } + + /** + * Gets a drawable with no color when selected or pressed, and the given color when + * neither selected nor pressed. + * + * @return A drawable, or {@code null} if the given color is transparent. + */ + private Drawable getItemBackground(int backgroundColor) { + if (backgroundColor == 0) { + return null; + } else { + Drawable.ConstantState cachedBg = mBackgroundsCache.get(backgroundColor); + if (cachedBg != null) { + if (DBG) Log.d(LOG_TAG, "Background cache hit for color " + backgroundColor); + return cachedBg.newDrawable(); + } + if (DBG) Log.d(LOG_TAG, "Creating new background for color " + backgroundColor); + ColorDrawable transparent = new ColorDrawable(0); + ColorDrawable background = new ColorDrawable(backgroundColor); + StateListDrawable newBg = new StateListDrawable(); + newBg.addState(new int[]{android.R.attr.state_selected}, transparent); + newBg.addState(new int[]{android.R.attr.state_pressed}, transparent); + newBg.addState(new int[]{}, background); + mBackgroundsCache.put(backgroundColor, newBg.getConstantState()); + return newBg; + } } private void setViewText(Cursor cursor, TextView v, int textCol, boolean isHtml) { @@ -313,7 +371,11 @@ class SuggestionsAdapter extends ResourceCursorAdapter { CharSequence text = null; if (textCol >= 0) { String str = cursor.getString(textCol); - text = (str != null && isHtml) ? Html.fromHtml(str) : str; + if (isHtml && looksLikeHtml(str)) { + text = Html.fromHtml(str); + } else { + text = str; + } } // Set the text even if it's null, since we need to clear any previous text. v.setText(text); @@ -325,15 +387,40 @@ class SuggestionsAdapter extends ResourceCursorAdapter { } } - private void setViewIcon(Cursor cursor, ImageView v, int iconNameCol) { - if (v == null) { - return; + private static boolean looksLikeHtml(String str) { + if (TextUtils.isEmpty(str)) return false; + for (int i = str.length() - 1; i >= 0; i--) { + char c = str.charAt(i); + if (c == '<' || c == '&') return true; } - if (iconNameCol < 0) { - return; + return false; + } + + private Drawable getIcon1(Cursor cursor) { + if (mIconName1Col < 0) { + return null; } - String value = cursor.getString(iconNameCol); + String value = cursor.getString(mIconName1Col); Drawable drawable = getDrawableFromResourceValue(value); + if (drawable != null) { + return drawable; + } + return getDefaultIcon1(cursor); + } + + private Drawable getIcon2(Cursor cursor) { + if (mIconName2Col < 0) { + return null; + } + String value = cursor.getString(mIconName2Col); + return getDrawableFromResourceValue(value); + } + + /** + * Sets the drawable in an image view, makes sure the view is only visible if there + * is a drawable. + */ + private void setViewDrawable(ImageView v, Drawable drawable) { // Set the icon even if the drawable is null, since we need to clear any // previous icon. v.setImageDrawable(drawable); @@ -437,12 +524,13 @@ class SuggestionsAdapter extends ResourceCursorAdapter { } // First, check the cache. - Drawable drawable = mOutsideDrawablesCache.get(drawableId); - if (drawable != null) { + Drawable.ConstantState cached = mOutsideDrawablesCache.get(drawableId); + if (cached != null) { if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + drawableId); - return drawable; + return cached.newDrawable(); } + Drawable drawable = null; try { // Not cached, try using it as a plain resource ID in the provider's context. int resourceId = Integer.parseInt(drawableId); @@ -474,9 +562,9 @@ class SuggestionsAdapter extends ResourceCursorAdapter { // If we got a drawable for this resource id, then stick it in the // map so we don't do this lookup again. if (drawable != null) { - mOutsideDrawablesCache.put(drawableId, drawable); + mOutsideDrawablesCache.put(drawableId, drawable.getConstantState()); } - } catch (NotFoundException nfe) { + } catch (Resources.NotFoundException nfe) { if (DBG) Log.d(LOG_TAG, "Icon resource not found: " + drawableId); // drawable = null; } @@ -484,6 +572,90 @@ class SuggestionsAdapter extends ResourceCursorAdapter { return drawable; } + /** + * Gets the left-hand side icon that will be used for the current suggestion + * if the suggestion contains an icon column but no icon or a broken icon. + * + * @param cursor A cursor positioned at the current suggestion. + * @return A non-null drawable. + */ + private Drawable getDefaultIcon1(Cursor cursor) { + // First check the component that the suggestion is originally from + String c = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_INTENT_COMPONENT_NAME); + if (c != null) { + ComponentName component = ComponentName.unflattenFromString(c); + if (component != null) { + Drawable drawable = getActivityIconWithCache(component); + if (drawable != null) { + return drawable; + } + } else { + Log.w(LOG_TAG, "Bad component name: " + c); + } + } + + // Then check the component that gave us the suggestion + Drawable drawable = getActivityIconWithCache(mSearchable.getSearchActivity()); + if (drawable != null) { + return drawable; + } + + // Fall back to a default icon + return mContext.getPackageManager().getDefaultActivityIcon(); + } + + /** + * Gets the activity or application icon for an activity. + * Uses the local icon cache for fast repeated lookups. + * + * @param component Name of an activity. + * @return A drawable, or {@code null} if neither the activity nor the application + * has an icon set. + */ + private Drawable getActivityIconWithCache(ComponentName component) { + // First check the icon cache + String componentIconKey = component.flattenToShortString(); + // Using containsKey() since we also store null values. + if (mOutsideDrawablesCache.containsKey(componentIconKey)) { + Drawable.ConstantState cached = mOutsideDrawablesCache.get(componentIconKey); + return cached == null ? null : cached.newDrawable(); + } + // Then try the activity or application icon + Drawable drawable = getActivityIcon(component); + // Stick it in the cache so we don't do this lookup again. + Drawable.ConstantState toCache = drawable == null ? null : drawable.getConstantState(); + mOutsideDrawablesCache.put(componentIconKey, toCache); + return drawable; + } + + /** + * Gets the activity or application icon for an activity. + * + * @param component Name of an activity. + * @return A drawable, or {@code null} if neither the acitivy or the application + * have an icon set. + */ + private Drawable getActivityIcon(ComponentName component) { + PackageManager pm = mContext.getPackageManager(); + final ActivityInfo activityInfo; + try { + activityInfo = pm.getActivityInfo(component, PackageManager.GET_META_DATA); + } catch (NameNotFoundException ex) { + Log.w(LOG_TAG, ex.toString()); + return null; + } + int iconId = activityInfo.getIconResource(); + if (iconId == 0) return null; + String pkg = component.getPackageName(); + Drawable drawable = pm.getDrawable(pkg, iconId, activityInfo.applicationInfo); + if (drawable == null) { + Log.w(LOG_TAG, "Invalid icon resource " + iconId + " for " + + component.flattenToShortString()); + return null; + } + return drawable; + } + /** * Gets the value of a string column by name. * @@ -500,69 +672,4 @@ class SuggestionsAdapter extends ResourceCursorAdapter { return cursor.getString(col); } - /** - * A parent viewgroup class which holds the actual suggestion item as a child. - * - * The sole purpose of this class is to draw the given background color when the item is in - * normal state and not draw the background color when it is pressed, so that when pressed the - * list view's selection highlight will be displayed properly (if we draw our background it - * draws on top of the list view selection highlight). - */ - private class SuggestionItemView extends ViewGroup { - private int mBackgroundColor; // the background color to draw in normal state. - private View mView; // the suggestion item's view. - - protected SuggestionItemView(Context context, Cursor cursor) { - // Initialize ourselves - super(context); - mBackgroundColor = 0; // transparent by default. - - // For our layout use the default list item height from the current theme. - TypedValue lineHeight = new TypedValue(); - context.getTheme().resolveAttribute( - com.android.internal.R.attr.searchResultListItemHeight, lineHeight, true); - DisplayMetrics metrics = new DisplayMetrics(); - metrics.setToDefaults(); - AbsListView.LayoutParams layout = new AbsListView.LayoutParams( - AbsListView.LayoutParams.FILL_PARENT, - (int)lineHeight.getDimension(metrics)); - - setLayoutParams(layout); - - // Initialize the child view - mView = SuggestionsAdapter.super.newView(context, cursor, this); - if (mView != null) { - addView(mView, layout.width, layout.height); - mView.setVisibility(View.VISIBLE); - } - } - - public void setColor(int backgroundColor) { - mBackgroundColor = backgroundColor; - } - - @Override - public void dispatchDraw(Canvas canvas) { - if (mBackgroundColor != 0 && !isPressed() && !isSelected()) { - canvas.drawColor(mBackgroundColor); - } - super.dispatchDraw(canvas); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (mView != null) { - mView.measure(widthMeasureSpec, heightMeasureSpec); - } - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - if (mView != null) { - mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight()); - } - } - } - } diff --git a/core/java/android/appwidget/AppWidgetProvider.java b/core/java/android/appwidget/AppWidgetProvider.java index 26712a10f0ce4..f1bbedef9024e 100755 --- a/core/java/android/appwidget/AppWidgetProvider.java +++ b/core/java/android/appwidget/AppWidgetProvider.java @@ -64,11 +64,9 @@ public class AppWidgetProvider extends BroadcastReceiver { } else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) { Bundle extras = intent.getExtras(); - if (extras != null) { - int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS); - if (appWidgetIds != null && appWidgetIds.length > 0) { - this.onDeleted(context, appWidgetIds); - } + if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)) { + final int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID); + this.onDeleted(context, new int[] { appWidgetId }); } } else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) { diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java index 8530c355b9351..a2e0ba0a4c269 100644 --- a/core/java/android/appwidget/AppWidgetProviderInfo.java +++ b/core/java/android/appwidget/AppWidgetProviderInfo.java @@ -57,6 +57,9 @@ public class AppWidgetProviderInfo implements Parcelable { * *

This field corresponds to the android:updatePeriodMillis attribute in * the AppWidget meta-data file. + * + *

Note: Updates requested with updatePeriodMillis + * will not be delivered more than once every 30 minutes.

*/ public int updatePeriodMillis; diff --git a/core/java/android/backup/BackupManager.java b/core/java/android/backup/BackupManager.java index 34a1a0c8f2f47..c52fcd2d964ab 100644 --- a/core/java/android/backup/BackupManager.java +++ b/core/java/android/backup/BackupManager.java @@ -42,6 +42,9 @@ import android.util.Log; public class BackupManager { private static final String TAG = "BackupManager"; + /** @hide TODO: REMOVE THIS */ + public static final boolean EVEN_THINK_ABOUT_DOING_RESTORE = false; + private Context mContext; private static IBackupManager sService; @@ -70,6 +73,9 @@ public class BackupManager { * {@link android.app.BackupAgent} subclass will be scheduled when you call this method. */ public void dataChanged() { + if (!EVEN_THINK_ABOUT_DOING_RESTORE) { + return; + } checkServiceBinder(); if (sService != null) { try { @@ -89,6 +95,9 @@ public class BackupManager { * permission if the package named in the argument is not the caller's own. */ public static void dataChanged(String packageName) { + if (!EVEN_THINK_ABOUT_DOING_RESTORE) { + return; + } checkServiceBinder(); if (sService != null) { try { @@ -107,6 +116,9 @@ public class BackupManager { * {@hide} */ public IRestoreSession beginRestoreSession(String transport) { + if (!EVEN_THINK_ABOUT_DOING_RESTORE) { + return null; + } IRestoreSession binder = null; checkServiceBinder(); if (sService != null) { diff --git a/core/java/android/content/AbstractTableMerger.java b/core/java/android/content/AbstractTableMerger.java index 9c760d94ad631..9f609a390ba63 100644 --- a/core/java/android/content/AbstractTableMerger.java +++ b/core/java/android/content/AbstractTableMerger.java @@ -369,30 +369,33 @@ public abstract class AbstractTableMerger // An existing server item has changed // If serverSyncVersion is null, there is no edit URL; // server won't let this change be written. - // Just hold onto it, I guess, in case the server permissions - // change later. - if (serverSyncVersion != null) { - boolean recordChanged = (localSyncVersion == null) || - !serverSyncVersion.equals(localSyncVersion); - if (recordChanged) { - if (localSyncDirty) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "remote record " + serverSyncId - + " conflicts with local _sync_id " + localSyncID - + ", local _id " + localRowId); - } - conflict = true; - } else { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, - "remote record " + - serverSyncId + - " updates local _sync_id " + - localSyncID + ", local _id " + - localRowId); - } - update = true; + boolean recordChanged = (localSyncVersion == null) || + (serverSyncVersion == null) || + !serverSyncVersion.equals(localSyncVersion); + if (recordChanged) { + if (localSyncDirty) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "remote record " + serverSyncId + + " conflicts with local _sync_id " + localSyncID + + ", local _id " + localRowId); } + conflict = true; + } else { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, + "remote record " + + serverSyncId + + " updates local _sync_id " + + localSyncID + ", local _id " + + localRowId); + } + update = true; + } + } else { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, + "Skipping update: localSyncVersion: " + localSyncVersion + + ", serverSyncVersion: " + serverSyncVersion); } } } else { diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 5cc5730c098f3..6b504055ce8de 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -17,6 +17,7 @@ package android.content; import android.content.pm.PackageManager; +import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; import android.content.res.AssetFileDescriptor; import android.content.res.Configuration; @@ -29,6 +30,7 @@ import android.database.SQLException; import android.net.Uri; import android.os.Binder; import android.os.ParcelFileDescriptor; +import android.os.Process; import java.io.File; import java.io.FileNotFoundException; @@ -65,8 +67,10 @@ import java.io.FileNotFoundException; */ public abstract class ContentProvider implements ComponentCallbacks { private Context mContext = null; + private int mMyUid; private String mReadPermission; private String mWritePermission; + private PathPermission[] mPathPermissions; private Transport mTransport = new Transport(); @@ -108,24 +112,20 @@ public abstract class ContentProvider implements ComponentCallbacks { public IBulkCursor bulkQuery(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, CursorWindow window) { - checkReadPermission(uri); + enforceReadPermission(uri); Cursor cursor = ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder); if (cursor == null) { return null; } - String wperm = getWritePermission(); return new CursorToBulkCursorAdaptor(cursor, observer, ContentProvider.this.getClass().getName(), - wperm == null || - getContext().checkCallingOrSelfPermission(getWritePermission()) - == PackageManager.PERMISSION_GRANTED, - window); + hasWritePermission(uri), window); } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - checkReadPermission(uri); + enforceReadPermission(uri); return ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder); } @@ -136,55 +136,84 @@ public abstract class ContentProvider implements ComponentCallbacks { public Uri insert(Uri uri, ContentValues initialValues) { - checkWritePermission(uri); + enforceWritePermission(uri); return ContentProvider.this.insert(uri, initialValues); } public int bulkInsert(Uri uri, ContentValues[] initialValues) { - checkWritePermission(uri); + enforceWritePermission(uri); return ContentProvider.this.bulkInsert(uri, initialValues); } public int delete(Uri uri, String selection, String[] selectionArgs) { - checkWritePermission(uri); + enforceWritePermission(uri); return ContentProvider.this.delete(uri, selection, selectionArgs); } public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - checkWritePermission(uri); + enforceWritePermission(uri); return ContentProvider.this.update(uri, values, selection, selectionArgs); } public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { - if (mode != null && mode.startsWith("rw")) checkWritePermission(uri); - else checkReadPermission(uri); + if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri); + else enforceReadPermission(uri); return ContentProvider.this.openFile(uri, mode); } public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { - if (mode != null && mode.startsWith("rw")) checkWritePermission(uri); - else checkReadPermission(uri); + if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri); + else enforceReadPermission(uri); return ContentProvider.this.openAssetFile(uri, mode); } public ISyncAdapter getSyncAdapter() { - checkWritePermission(null); + enforceWritePermission(null); SyncAdapter sa = ContentProvider.this.getSyncAdapter(); return sa != null ? sa.getISyncAdapter() : null; } - private void checkReadPermission(Uri uri) { + private void enforceReadPermission(Uri uri) { + final int uid = Binder.getCallingUid(); + if (uid == mMyUid) { + return; + } + + final Context context = getContext(); final String rperm = getReadPermission(); final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - if (getContext().checkUriPermission(uri, rperm, null, pid, uid, + if (rperm == null + || context.checkPermission(rperm, pid, uid) + == PackageManager.PERMISSION_GRANTED) { + return; + } + + PathPermission[] pps = getPathPermissions(); + if (pps != null) { + final String path = uri.getPath(); + int i = pps.length; + while (i > 0) { + i--; + final PathPermission pp = pps[i]; + final String pprperm = pp.getReadPermission(); + if (pprperm != null && pp.match(path)) { + if (context.checkPermission(pprperm, pid, uid) + == PackageManager.PERMISSION_GRANTED) { + return; + } + } + } + } + + if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION) == PackageManager.PERMISSION_GRANTED) { return; } + String msg = "Permission Denial: reading " + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + Binder.getCallingPid() @@ -193,20 +222,57 @@ public abstract class ContentProvider implements ComponentCallbacks { throw new SecurityException(msg); } - private void checkWritePermission(Uri uri) { + private boolean hasWritePermission(Uri uri) { + final int uid = Binder.getCallingUid(); + if (uid == mMyUid) { + return true; + } + + final Context context = getContext(); final String wperm = getWritePermission(); final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - if (getContext().checkUriPermission(uri, null, wperm, pid, uid, + if (wperm == null + || context.checkPermission(wperm, pid, uid) + == PackageManager.PERMISSION_GRANTED) { + return true; + } + + PathPermission[] pps = getPathPermissions(); + if (pps != null) { + final String path = uri.getPath(); + int i = pps.length; + while (i > 0) { + i--; + final PathPermission pp = pps[i]; + final String ppwperm = pp.getWritePermission(); + if (ppwperm != null && pp.match(path)) { + if (context.checkPermission(ppwperm, pid, uid) + == PackageManager.PERMISSION_GRANTED) { + return true; + } + } + } + } + + if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == PackageManager.PERMISSION_GRANTED) { + return true; + } + + return false; + } + + private void enforceWritePermission(Uri uri) { + if (hasWritePermission(uri)) { return; } + String msg = "Permission Denial: writing " + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() - + " requires " + wperm; + + " requires " + getWritePermission(); throw new SecurityException(msg); } } @@ -265,6 +331,28 @@ public abstract class ContentProvider implements ComponentCallbacks { return mWritePermission; } + /** + * Change the path-based permission required to read and/or write data in + * the content provider. This is normally set for you from its manifest + * information when the provider is first created. + * + * @param permissions Array of path permission descriptions. + */ + protected final void setPathPermissions(PathPermission[] permissions) { + mPathPermissions = permissions; + } + + /** + * Return the path-based permissions required for read and/or write access to + * this content provider. This method can be called from multiple + * threads, as described in + * Application Fundamentals: + * Processes and Threads. + */ + public final PathPermission[] getPathPermissions() { + return mPathPermissions; + } + /** * Called when the provider is being started. * @@ -600,9 +688,11 @@ public abstract class ContentProvider implements ComponentCallbacks { */ if (mContext == null) { mContext = context; + mMyUid = Process.myUid(); if (info != null) { setReadPermission(info.readPermission); setWritePermission(info.writePermission); + setPathPermissions(info.pathPermissions); } ContentProvider.this.onCreate(); } diff --git a/core/java/android/content/DialogInterface.java b/core/java/android/content/DialogInterface.java index 4afa2946176a5..9f1036e6ea8b0 100644 --- a/core/java/android/content/DialogInterface.java +++ b/core/java/android/content/DialogInterface.java @@ -91,6 +91,21 @@ public interface DialogInterface { public void onDismiss(DialogInterface dialog); } + /** + * Interface used to allow the creator of a dialog to run some code when the + * dialog is shown. + * @hide Pending API council approval + */ + interface OnShowListener { + /** + * This method will be invoked when the dialog is shown. + * + * @param dialog The dialog that was shown will be passed into the + * method. + */ + public void onShow(DialogInterface dialog); + } + /** * Interface used to allow the creator of a dialog to run some code when an * item on the dialog is clicked.. diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 263f9279e69ad..a5f298c5b7c9f 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1112,11 +1112,17 @@ public class Intent implements Parcelable { /** * Broadcast Action: Sent after the screen turns off. + * + *

This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF"; /** * Broadcast Action: Sent after the screen turns on. + * + *

This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON"; @@ -1124,6 +1130,9 @@ public class Intent implements Parcelable { /** * Broadcast Action: Sent when the user is present after device wakes up (e.g when the * keyguard is gone). + * + *

This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_USER_PRESENT= "android.intent.action.USER_PRESENT"; @@ -1134,6 +1143,9 @@ public class Intent implements Parcelable { * in manifests, only by exlicitly registering for it with * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter) * Context.registerReceiver()}. + * + *

This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_TIME_TICK = "android.intent.action.TIME_TICK"; @@ -1152,6 +1164,9 @@ public class Intent implements Parcelable { *

    *
  • time-zone - The java.util.TimeZone.getID() value identifying the new time zone.
  • *
+ * + *

This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_TIMEZONE_CHANGED = "android.intent.action.TIMEZONE_CHANGED"; @@ -1177,6 +1192,9 @@ public class Intent implements Parcelable { * such as installing alarms. You must hold the * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission * in order to receive this broadcast. + * + *

This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED"; @@ -1190,6 +1208,9 @@ public class Intent implements Parcelable { * Broadcast Action: Trigger the download and eventual installation * of a package. *

Input: {@link #getData} is the URI of the package file to download. + * + *

This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL"; @@ -1203,6 +1224,9 @@ public class Intent implements Parcelable { *

  • {@link #EXTRA_REPLACING} is set to true if this is following * an {@link #ACTION_PACKAGE_REMOVED} broadcast for the same package. * + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED"; @@ -1214,6 +1238,9 @@ public class Intent implements Parcelable { *

      *
    • {@link #EXTRA_UID} containing the integer uid assigned to the new package. *
    + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED"; @@ -1229,6 +1256,9 @@ public class Intent implements Parcelable { *

  • {@link #EXTRA_REPLACING} is set to true if this will be followed * by an {@link #ACTION_PACKAGE_ADDED} broadcast for the same package. * + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED"; @@ -1238,6 +1268,9 @@ public class Intent implements Parcelable { *

      *
    • {@link #EXTRA_UID} containing the integer uid assigned to the package. *
    + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED"; @@ -1251,6 +1284,9 @@ public class Intent implements Parcelable { *

      *
    • {@link #EXTRA_UID} containing the integer uid assigned to the package. *
    + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED"; @@ -1263,12 +1299,18 @@ public class Intent implements Parcelable { *

      *
    • {@link #EXTRA_UID} containing the integer uid assigned to the package. *
    + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED"; /** * Broadcast Action: A user ID has been removed from the system. The user * ID number is stored in the extra data under {@link #EXTRA_UID}. + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_UID_REMOVED = "android.intent.action.UID_REMOVED"; @@ -1287,6 +1329,9 @@ public class Intent implements Parcelable { * application to make sure it sees the new changes. Some system code that * can not be restarted will need to watch for this action and handle it * appropriately. + * + *

    This is a protected intent that can only be sent + * by the system. * * @see android.content.res.Configuration */ @@ -1298,15 +1343,21 @@ public class Intent implements Parcelable { * *

    * You can not receive this through components declared - * in manifests, only by exlicitly registering for it with + * in manifests, only by explicitly registering for it with * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter) * Context.registerReceiver()}. + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED"; /** * Broadcast Action: Indicates low battery condition on the device. * This broadcast corresponds to the "Low battery warning" system dialog. + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW"; @@ -1314,6 +1365,9 @@ public class Intent implements Parcelable { * Broadcast Action: Indicates the battery is now okay after being low. * This will be sent after {@link #ACTION_BATTERY_LOW} once the battery has * gone back up to an okay state. + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_BATTERY_OKAY = "android.intent.action.BATTERY_OKAY"; @@ -1323,6 +1377,9 @@ public class Intent implements Parcelable { * Unlike ACTION_BATTERY_CHANGED, applications will be woken for this and so do not have to * stay active to receive this notification. This action can be used to implement actions * that wait until power is available to trigger. + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED"; @@ -1332,6 +1389,9 @@ public class Intent implements Parcelable { * Unlike ACTION_BATTERY_CHANGED, applications will be woken for this and so do not have to * stay active to receive this notification. This action can be used to implement actions * that wait until power is available to trigger. + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED"; @@ -1341,16 +1401,25 @@ public class Intent implements Parcelable { * off, not sleeping). Once the broadcast is complete, the final shutdown * will proceed and all unsaved data lost. Apps will not normally need * to handle this, since the forground activity will be paused as well. + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN"; /** * Broadcast Action: Indicates low memory condition on the device + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW"; /** * Broadcast Action: Indicates low memory condition on the device no longer exists + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK"; @@ -1515,6 +1584,9 @@ public class Intent implements Parcelable { * then cell radio and possibly other radios such as bluetooth or WiFi may have also been * turned off

  • * + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE"; @@ -1593,6 +1665,9 @@ public class Intent implements Parcelable { *

    You must hold the * {@link android.Manifest.permission#PROCESS_OUTGOING_CALLS} * permission to receive this Intent.

    + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_NEW_OUTGOING_CALL = @@ -1601,14 +1676,54 @@ public class Intent implements Parcelable { /** * Broadcast Action: Have the device reboot. This is only for use by * system code. + * + *

    This is a protected intent that can only be sent + * by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_REBOOT = "android.intent.action.REBOOT"; + /** + * Broadcast Action: Triggers the platform Text-To-Speech engine to + * start the activity that installs the resource files on the device + * that are required for TTS to be operational. Since the installation + * of the data can be interrupted or declined by the user, the application + * shouldn't expect successful installation upon return from that intent, + * and if need be, should check installation status with + * {@link #ACTION_TTS_CHECK_TTS_DATA}. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_TTS_INSTALL_TTS_DATA = + "android.intent.action.INSTALL_TTS_DATA"; + + /** + * Broadcast Action: Starts the activity from the platform Text-To-Speech + * engine to verify the proper installation and availability of the + * resource files on the system. Upon completion, the activity will + * return one of the following codes: + * {@link android.speech.tts.TextToSpeech.Engine#CHECK_VOICE_DATA_PASS}, + * {@link android.speech.tts.TextToSpeech.Engine#CHECK_VOICE_DATA_FAIL}, + * {@link android.speech.tts.TextToSpeech.Engine#CHECK_VOICE_DATA_BAD_DATA}, + * {@link android.speech.tts.TextToSpeech.Engine#CHECK_VOICE_DATA_MISSING_DATA}, or + * {@link android.speech.tts.TextToSpeech.Engine#CHECK_VOICE_DATA_MISSING_VOLUME}. + *

    Moreover, the data received in the activity result will contain the following + * fields: + *

      + *
    • {@link android.speech.tts.TextToSpeech.Engine#VOICE_DATA_ROOT_DIRECTORY} which + * indicates the path to the location of the resource files
    • , + *
    • {@link android.speech.tts.TextToSpeech.Engine#VOICE_DATA_FILES} which contains + * the list of all the resource files
    • , + *
    • and {@link android.speech.tts.TextToSpeech.Engine#VOICE_DATA_FILES_INFO} which + * contains, for each resource file, the description of the language covered by + * the file in the xxx-YYY format, where xxx is the 3-letter ISO language code, + * and YYY is the 3-letter ISO country code.
    • + *
    + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_TTS_CHECK_TTS_DATA = + "android.intent.action.CHECK_TTS_DATA"; /** - * @hide - * TODO: This will be unhidden in a later CL. * Broadcast Action: The TextToSpeech synthesizer has completed processing * all of the text in the speech queue. */ @@ -4398,6 +4513,9 @@ public class Intent implements Parcelable { * and {@link #FILL_IN_COMPONENT} to override the restriction where the * corresponding field will not be replaced if it is already set. * + *

    Note: The component field will only be copied if {@link #FILL_IN_COMPONENT} is explicitly + * specified. + * *

    For example, consider Intent A with {data="foo", categories="bar"} * and Intent B with {action="gotit", data-type="some/thing", * categories="one","two"}. diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java index f781e0d0e12df..756f35cca6553 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -338,6 +338,7 @@ public class SyncStorageEngine extends Handler { } reports.add(mChangeListeners.getBroadcastItem(i)); } + mChangeListeners.finishBroadcast(); } if (DEBUG) Log.v(TAG, "reportChange " + which + " to: " + reports); diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index bcf95b6f574eb..4a3137fc95a0f 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -160,20 +160,28 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<11; + /** + * Value for {@link #flags}: true when the application knows how to adjust + * its UI for different screen sizes. Corresponds to + * {@link android.R.styleable#AndroidManifestSupportsScreens_resizeable + * android:resizeable}. + */ + public static final int FLAG_RESIZEABLE_FOR_SCREENS = 1<<12; + /** * Value for {@link #flags}: this is false if the application has set * its android:allowBackup to false, true otherwise. * * {@hide} */ - public static final int FLAG_ALLOW_BACKUP = 1<<12; + public static final int FLAG_ALLOW_BACKUP = 1<<13; /** * Indicates that the application supports any densities; * {@hide} */ public static final int ANY_DENSITY = -1; - private static final int[] ANY_DENSITIES_ARRAY = { ANY_DENSITY }; + static final int[] ANY_DENSITIES_ARRAY = { ANY_DENSITY }; /** * Flags associated with the application. Any combination of @@ -183,7 +191,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP}, * {@link #FLAG_TEST_ONLY}, {@link #FLAG_SUPPORTS_SMALL_SCREENS}, * {@link #FLAG_SUPPORTS_NORMAL_SCREENS}, - * {@link #FLAG_SUPPORTS_LARGE_SCREENS}. + * {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_RESIZEABLE_FOR_SCREENS}. */ public int flags = 0; @@ -399,7 +407,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * @hide */ public void disableCompatibilityMode() { - flags |= FLAG_SUPPORTS_LARGE_SCREENS; + flags |= (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS | + FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS); supportsDensities = ANY_DENSITIES_ARRAY; } } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index bf2a8959c7f4c..e587ca7597601 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -71,6 +71,8 @@ interface IPackageManager { void removePermission(String name); + boolean isProtectedBroadcast(String actionName); + int checkSignatures(String pkg1, String pkg2); String[] getPackagesForUid(int uid); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 558b0c3e369a1..93ba9599be061 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -92,6 +92,8 @@ public class PackageParser { private static final Object mSync = new Object(); private static WeakReference mReadBuffer; + private static boolean sCompatibilityModeEnabled = true; + static class ParsePackageItemArgs { final Package owner; final String[] outError; @@ -672,6 +674,7 @@ public class PackageParser { int supportsSmallScreens = 1; int supportsNormalScreens = 1; int supportsLargeScreens = 1; + int resizeable = 1; int outerDepth = parser.getDepth(); while ((type=parser.next()) != parser.END_DOCUMENT @@ -720,7 +723,7 @@ public class PackageParser { sa.recycle(); if (name != null && !pkg.requestedPermissions.contains(name)) { - pkg.requestedPermissions.add(name); + pkg.requestedPermissions.add(name.intern()); } XmlUtils.skipCurrentTag(parser); @@ -851,21 +854,6 @@ public class PackageParser { XmlUtils.skipCurrentTag(parser); - } else if (tagName.equals("instrumentation")) { - if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) { - return null; - } - } else if (tagName.equals("eat-comment")) { - // Just skip this tag - XmlUtils.skipCurrentTag(parser); - continue; - } else if (RIGID_PARSER) { - outError[0] = "Bad element under : " - + parser.getName(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; - - } else if (tagName.equals("supports-density")) { sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestSupportsDensity); @@ -896,10 +884,50 @@ public class PackageParser { supportsLargeScreens = sa.getInteger( com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens, supportsLargeScreens); + resizeable = sa.getInteger( + com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable, + supportsLargeScreens); sa.recycle(); XmlUtils.skipCurrentTag(parser); + + } else if (tagName.equals("protected-broadcast")) { + sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestProtectedBroadcast); + + String name = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name); + + sa.recycle(); + + if (name != null && (flags&PARSE_IS_SYSTEM) != 0) { + if (pkg.protectedBroadcasts == null) { + pkg.protectedBroadcasts = new ArrayList(); + } + if (!pkg.protectedBroadcasts.contains(name)) { + pkg.protectedBroadcasts.add(name.intern()); + } + } + + XmlUtils.skipCurrentTag(parser); + + } else if (tagName.equals("instrumentation")) { + if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) { + return null; + } + + } else if (tagName.equals("eat-comment")) { + // Just skip this tag + XmlUtils.skipCurrentTag(parser); + continue; + + } else if (RIGID_PARSER) { + outError[0] = "Bad element under : " + + parser.getName(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } else { Log.w(TAG, "Bad element under : " + parser.getName()); @@ -945,15 +973,30 @@ public class PackageParser { >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS; } - + if (resizeable < 0 || (resizeable > 0 + && pkg.applicationInfo.targetSdkVersion + >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) { + pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS; + } + int densities[] = null; int size = pkg.supportsDensityList.size(); if (size > 0) { - int densities[] = pkg.supportsDensities = new int[size]; + densities = pkg.supportsDensities = new int[size]; List densityList = pkg.supportsDensityList; for (int i = 0; i < size; i++) { densities[i] = densityList.get(i); } } + /** + * TODO: enable this before code freeze. b/1967935 + * * + if ((densities == null || densities.length == 0) + && (pkg.applicationInfo.targetSdkVersion + >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) { + pkg.supportsDensities = ApplicationInfo.ANY_DENSITIES_ARRAY; + } + */ + return pkg; } @@ -1419,7 +1462,7 @@ public class PackageParser { sa.recycle(); if (lname != null && !owner.usesLibraries.contains(lname)) { - owner.usesLibraries.add(lname); + owner.usesLibraries.add(lname.intern()); } XmlUtils.skipCurrentTag(parser); @@ -1908,6 +1951,7 @@ public class PackageParser { outInfo.metaData, outError)) == null) { return false; } + } else if (parser.getName().equals("grant-uri-permission")) { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestGrantUriPermission); @@ -1931,7 +1975,7 @@ public class PackageParser { if (str != null) { pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB); } - + sa.recycle(); if (pa != null) { @@ -1946,6 +1990,101 @@ public class PackageParser { outInfo.info.uriPermissionPatterns = newp; } outInfo.info.grantUriPermissions = true; + } else { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "No path, pathPrefix, or pathPattern for "); + XmlUtils.skipCurrentTag(parser); + continue; + } + outError[0] = "No path, pathPrefix, or pathPattern for "; + return false; + } + XmlUtils.skipCurrentTag(parser); + + } else if (parser.getName().equals("path-permission")) { + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestPathPermission); + + PathPermission pa = null; + + String permission = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_permission); + String readPermission = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission); + if (readPermission == null) { + readPermission = permission; + } + String writePermission = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission); + if (writePermission == null) { + writePermission = permission; + } + + boolean havePerm = false; + if (readPermission != null) { + readPermission = readPermission.intern(); + havePerm = true; + } + if (writePermission != null) { + writePermission = readPermission.intern(); + havePerm = true; + } + + if (!havePerm) { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "No readPermission or writePermssion for "); + XmlUtils.skipCurrentTag(parser); + continue; + } + outError[0] = "No readPermission or writePermssion for "; + return false; + } + + String path = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_path); + if (path != null) { + pa = new PathPermission(path, + PatternMatcher.PATTERN_LITERAL, readPermission, writePermission); + } + + path = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix); + if (path != null) { + pa = new PathPermission(path, + PatternMatcher.PATTERN_PREFIX, readPermission, writePermission); + } + + path = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern); + if (path != null) { + pa = new PathPermission(path, + PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission); + } + + sa.recycle(); + + if (pa != null) { + if (outInfo.info.pathPermissions == null) { + outInfo.info.pathPermissions = new PathPermission[1]; + outInfo.info.pathPermissions[0] = pa; + } else { + final int N = outInfo.info.pathPermissions.length; + PathPermission[] newp = new PathPermission[N+1]; + System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N); + newp[N] = pa; + outInfo.info.pathPermissions = newp; + } + } else { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "No path, pathPrefix, or pathPattern for "); + XmlUtils.skipCurrentTag(parser); + continue; + } + outError[0] = "No path, pathPrefix, or pathPattern for "; + return false; } XmlUtils.skipCurrentTag(parser); @@ -2104,8 +2243,8 @@ public class PackageParser { return null; } - boolean success = true; - + name = name.intern(); + TypedValue v = sa.peekValue( com.android.internal.R.styleable.AndroidManifestMetaData_resource); if (v != null && v.resourceId != 0) { @@ -2118,7 +2257,7 @@ public class PackageParser { if (v != null) { if (v.type == TypedValue.TYPE_STRING) { CharSequence cs = v.coerceToString(); - data.putString(name, cs != null ? cs.toString() : null); + data.putString(name, cs != null ? cs.toString().intern() : null); } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) { data.putBoolean(name, v.data != 0); } else if (v.type >= TypedValue.TYPE_FIRST_INT @@ -2299,6 +2438,8 @@ public class PackageParser { public final ArrayList requestedPermissions = new ArrayList(); + public ArrayList protectedBroadcasts; + public final ArrayList usesLibraries = new ArrayList(); public String[] usesLibraryFiles = null; @@ -2499,6 +2640,11 @@ public class PackageParser { public static ApplicationInfo generateApplicationInfo(Package p, int flags) { if (p == null) return null; if (!copyNeeded(flags, p, null)) { + // CompatibilityMode is global state. It's safe to modify the instance + // of the package. + if (!sCompatibilityModeEnabled) { + p.applicationInfo.disableCompatibilityMode(); + } return p.applicationInfo; } @@ -2513,6 +2659,9 @@ public class PackageParser { if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0) { ai.supportsDensities = p.supportsDensities; } + if (!sCompatibilityModeEnabled) { + ai.disableCompatibilityMode(); + } return ai; } @@ -2697,4 +2846,11 @@ public class PackageParser { + " " + service.info.name + "}"; } } + + /** + * @hide + */ + public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) { + sCompatibilityModeEnabled = compatibilityModeEnabled; + } } diff --git a/core/java/android/content/pm/PathPermission.java b/core/java/android/content/pm/PathPermission.java new file mode 100644 index 0000000000000..7e49d7df63cea --- /dev/null +++ b/core/java/android/content/pm/PathPermission.java @@ -0,0 +1,68 @@ +/* + * 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.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PatternMatcher; + +/** + * Description of permissions needed to access a particular path + * in a {@link ProviderInfo}. + */ +public class PathPermission extends PatternMatcher { + private final String mReadPermission; + private final String mWritePermission; + + public PathPermission(String pattern, int type, String readPermission, + String writePermission) { + super(pattern, type); + mReadPermission = readPermission; + mWritePermission = writePermission; + } + + public String getReadPermission() { + return mReadPermission; + } + + public String getWritePermission() { + return mWritePermission; + } + + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeString(mReadPermission); + dest.writeString(mWritePermission); + } + + public PathPermission(Parcel src) { + super(src); + mReadPermission = src.readString(); + mWritePermission = src.readString(); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public PathPermission createFromParcel(Parcel source) { + return new PathPermission(source); + } + + public PathPermission[] newArray(int size) { + return new PathPermission[size]; + } + }; +} \ No newline at end of file diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java index b67ddf6b2a15f..d01460e4216e9 100644 --- a/core/java/android/content/pm/ProviderInfo.java +++ b/core/java/android/content/pm/ProviderInfo.java @@ -28,6 +28,7 @@ import android.os.PatternMatcher; */ public final class ProviderInfo extends ComponentInfo implements Parcelable { + /** The name provider is published under content:// */ public String authority = null; @@ -56,6 +57,14 @@ public final class ProviderInfo extends ComponentInfo */ public PatternMatcher[] uriPermissionPatterns = null; + /** + * If non-null, these are path-specific permissions that are allowed for + * accessing the provider. Any permissions listed here will allow a + * holding client to access the provider, and the provider will check + * the URI it provides when making calls against the patterns here. + */ + public PathPermission[] pathPermissions = null; + /** If true, this content provider allows multiple instances of itself * to run in different process. If false, a single instances is always * run in {@link #processName}. */ @@ -78,6 +87,7 @@ public final class ProviderInfo extends ComponentInfo writePermission = orig.writePermission; grantUriPermissions = orig.grantUriPermissions; uriPermissionPatterns = orig.uriPermissionPatterns; + pathPermissions = orig.pathPermissions; multiprocess = orig.multiprocess; initOrder = orig.initOrder; isSyncable = orig.isSyncable; @@ -94,6 +104,7 @@ public final class ProviderInfo extends ComponentInfo out.writeString(writePermission); out.writeInt(grantUriPermissions ? 1 : 0); out.writeTypedArray(uriPermissionPatterns, parcelableFlags); + out.writeTypedArray(pathPermissions, parcelableFlags); out.writeInt(multiprocess ? 1 : 0); out.writeInt(initOrder); out.writeInt(isSyncable ? 1 : 0); @@ -122,6 +133,7 @@ public final class ProviderInfo extends ComponentInfo writePermission = in.readString(); grantUriPermissions = in.readInt() != 0; uriPermissionPatterns = in.createTypedArray(PatternMatcher.CREATOR); + pathPermissions = in.createTypedArray(PathPermission.CREATOR); multiprocess = in.readInt() != 0; initOrder = in.readInt(); isSyncable = in.readInt() != 0; diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index dfe304d1593d1..517551ec8e149 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -38,7 +38,12 @@ public class CompatibilityInfo { private static final String TAG = "CompatibilityInfo"; /** default compatibility info object for compatible applications */ - public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo(); + public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo() { + @Override + public void setExpandable(boolean expandable) { + throw new UnsupportedOperationException("trying to change default compatibility info"); + } + }; /** * The default width of the screen in portrait mode. @@ -50,18 +55,6 @@ public class CompatibilityInfo { */ public static final int DEFAULT_PORTRAIT_HEIGHT = 480; - /** - * The x-shift mode that controls the position of the content or the window under - * compatibility mode. - * {@see getTranslator} - * {@see Translator#mShiftMode} - */ - private static final int X_SHIFT_NONE = 0; - private static final int X_SHIFT_CONTENT = 1; - private static final int X_SHIFT_AND_CLIP_CONTENT = 2; - private static final int X_SHIFT_WINDOW = 3; - - /** * A compatibility flags */ @@ -76,8 +69,8 @@ public class CompatibilityInfo { /** * A flag mask to indicates that the application can expand over the original size. * The flag is set to true if - * 1) Application declares its expandable in manifest file using or - * 2) The screen size is same as (320 x 480) * density. + * 1) Application declares its expandable in manifest file using or + * 2) Configuration.SCREENLAYOUT_COMPAT_NEEDED is not set * {@see compatibilityFlag} */ private static final int EXPANDABLE = 2; @@ -85,12 +78,34 @@ public class CompatibilityInfo { /** * A flag mask to tell if the application is configured to be expandable. This differs * from EXPANDABLE in that the application that is not expandable will be - * marked as expandable if it runs in (320x 480) * density screen size. + * marked as expandable if Configuration.SCREENLAYOUT_COMPAT_NEEDED is not set. */ private static final int CONFIGURED_EXPANDABLE = 4; - private static final int SCALING_EXPANDABLE_MASK = SCALING_REQUIRED | EXPANDABLE; + /** + * A flag mask to indicates that the application supports large screens. + * The flag is set to true if + * 1) Application declares it supports large screens in manifest file using or + * 2) The screen size is not large + * {@see compatibilityFlag} + */ + private static final int LARGE_SCREENS = 8; + + /** + * A flag mask to tell if the application supports large screens. This differs + * from LARGE_SCREENS in that the application that does not support large + * screens will be marked as supporting them if the current screen is not + * large. + */ + private static final int CONFIGURED_LARGE_SCREENS = 16; + private static final int SCALING_EXPANDABLE_MASK = SCALING_REQUIRED | EXPANDABLE | LARGE_SCREENS; + + /** + * The effective screen density we have selected for this application. + */ + public final int applicationDensity; + /** * Application's scale. */ @@ -106,62 +121,60 @@ public class CompatibilityInfo { */ public final int appFlags; - /** - * Window size in Compatibility Mode, in real pixels. This is updated by - * {@link DisplayMetrics#updateMetrics}. - */ - private int mWidth; - private int mHeight; - - /** - * The x offset to center the window content. In X_SHIFT_WINDOW mode, the offset is added - * to the window's layout. In X_SHIFT_CONTENT/X_SHIFT_AND_CLIP_CONTENT mode, the offset - * is used to translate the Canvas. - */ - private int mXOffset; - public CompatibilityInfo(ApplicationInfo appInfo) { appFlags = appInfo.flags; if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { - mCompatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE; + mCompatibilityFlags |= LARGE_SCREENS | CONFIGURED_LARGE_SCREENS; + } + if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { + mCompatibilityFlags |= EXPANDABLE | CONFIGURED_EXPANDABLE; } float packageDensityScale = -1.0f; + int packageDensity = 0; if (appInfo.supportsDensities != null) { int minDiff = Integer.MAX_VALUE; for (int density : appInfo.supportsDensities) { - if (density == ApplicationInfo.ANY_DENSITY) { + if (density == ApplicationInfo.ANY_DENSITY) { + packageDensity = DisplayMetrics.DENSITY_DEVICE; packageDensityScale = 1.0f; break; } - int tmpDiff = Math.abs(DisplayMetrics.DEVICE_DENSITY - density); + int tmpDiff = Math.abs(DisplayMetrics.DENSITY_DEVICE - density); if (tmpDiff == 0) { + packageDensity = DisplayMetrics.DENSITY_DEVICE; packageDensityScale = 1.0f; break; } // prefer higher density (appScale>1.0), unless that's only option. if (tmpDiff < minDiff && packageDensityScale < 1.0f) { - packageDensityScale = DisplayMetrics.DEVICE_DENSITY / (float) density; + packageDensity = density; + packageDensityScale = DisplayMetrics.DENSITY_DEVICE / (float) density; minDiff = tmpDiff; } } } if (packageDensityScale > 0.0f) { + applicationDensity = packageDensity; applicationScale = packageDensityScale; } else { + applicationDensity = DisplayMetrics.DENSITY_DEFAULT; applicationScale = - DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY; + DisplayMetrics.DENSITY_DEVICE / (float) DisplayMetrics.DENSITY_DEFAULT; } + applicationInvertedScale = 1.0f / applicationScale; if (applicationScale != 1.0f) { mCompatibilityFlags |= SCALING_REQUIRED; } } - private CompatibilityInfo(int appFlags, int compFlags, float scale, float invertedScale) { + private CompatibilityInfo(int appFlags, int compFlags, + int dens, float scale, float invertedScale) { this.appFlags = appFlags; mCompatibilityFlags = compFlags; + applicationDensity = dens; applicationScale = scale; applicationInvertedScale = invertedScale; } @@ -169,8 +182,10 @@ public class CompatibilityInfo { private CompatibilityInfo() { this(ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS - | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS, + | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS + | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS, EXPANDABLE | CONFIGURED_EXPANDABLE, + DisplayMetrics.DENSITY_DEVICE, 1.0f, 1.0f); } @@ -180,23 +195,10 @@ public class CompatibilityInfo { */ public CompatibilityInfo copy() { CompatibilityInfo info = new CompatibilityInfo(appFlags, mCompatibilityFlags, - applicationScale, applicationInvertedScale); - info.setVisibleRect(mXOffset, mWidth, mHeight); + applicationDensity, applicationScale, applicationInvertedScale); return info; } - /** - * Sets the application's visible rect in compatibility mode. - * @param xOffset the application's x offset that is added to center the content. - * @param widthPixels the application's width in real pixels on the screen. - * @param heightPixels the application's height in real pixels on the screen. - */ - public void setVisibleRect(int xOffset, int widthPixels, int heightPixels) { - this.mXOffset = xOffset; - mWidth = widthPixels; - mHeight = heightPixels; - } - /** * Sets expandable bit in the compatibility flag. */ @@ -208,6 +210,17 @@ public class CompatibilityInfo { } } + /** + * Sets large screen bit in the compatibility flag. + */ + public void setLargeScreens(boolean expandable) { + if (expandable) { + mCompatibilityFlags |= CompatibilityInfo.LARGE_SCREENS; + } else { + mCompatibilityFlags &= ~CompatibilityInfo.LARGE_SCREENS; + } + } + /** * @return true if the application is configured to be expandable. */ @@ -215,6 +228,13 @@ public class CompatibilityInfo { return (mCompatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0; } + /** + * @return true if the application is configured to be expandable. + */ + public boolean isConfiguredLargeScreens() { + return (mCompatibilityFlags & CompatibilityInfo.CONFIGURED_LARGE_SCREENS) != 0; + } + /** * @return true if the scaling is required */ @@ -222,67 +242,32 @@ public class CompatibilityInfo { return (mCompatibilityFlags & SCALING_REQUIRED) != 0; } + public boolean supportsScreen() { + return (mCompatibilityFlags & (EXPANDABLE|LARGE_SCREENS)) + == (EXPANDABLE|LARGE_SCREENS); + } + @Override public String toString() { return "CompatibilityInfo{scale=" + applicationScale + - ", compatibility flag=" + mCompatibilityFlags + "}"; + ", supports screen=" + supportsScreen() + "}"; } /** * Returns the translator which can translate the coordinates of the window. * There are five different types of Translator. - * - * 1) {@link CompatibilityInfo#X_SHIFT_AND_CLIP_CONTENT} - * Shift and clip the content of the window at drawing time. Used for activities' - * main window (with no gravity). - * 2) {@link CompatibilityInfo#X_SHIFT_CONTENT} - * Shift the content of the window at drawing time. Used for windows that is created by - * an application and expected to be aligned with the application window. - * 3) {@link CompatibilityInfo#X_SHIFT_WINDOW} - * Create the window with adjusted x- coordinates. This is typically used - * in popup window, where it has to be placed relative to main window. - * 4) {@link CompatibilityInfo#X_SHIFT_NONE} - * No adjustment required, such as dialog. - * 5) Same as X_SHIFT_WINDOW, but no scaling. This is used by {@link SurfaceView}, which - * does not require scaling, but its window's location has to be adjusted. - * * @param params the window's parameter */ public Translator getTranslator(WindowManager.LayoutParams params) { - if ( (mCompatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK) - == CompatibilityInfo.EXPANDABLE) { + if ( (mCompatibilityFlags & SCALING_EXPANDABLE_MASK) + == (EXPANDABLE|LARGE_SCREENS)) { if (DBG) Log.d(TAG, "no translation required"); return null; } - - if ((mCompatibilityFlags & CompatibilityInfo.EXPANDABLE) == 0) { - if ((params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) { - if (DBG) Log.d(TAG, "translation for surface view selected"); - return new Translator(X_SHIFT_WINDOW, false, 1.0f, 1.0f); - } else { - int shiftMode; - if (params.gravity == Gravity.NO_GRAVITY) { - // For Regular Application window - shiftMode = X_SHIFT_AND_CLIP_CONTENT; - if (DBG) Log.d(TAG, "shift and clip translator"); - } else if (params.width == WindowManager.LayoutParams.FILL_PARENT) { - // For Regular Application window - shiftMode = X_SHIFT_CONTENT; - if (DBG) Log.d(TAG, "shift content translator"); - } else if ((params.gravity & Gravity.LEFT) != 0 && params.x > 0) { - shiftMode = X_SHIFT_WINDOW; - if (DBG) Log.d(TAG, "shift window translator"); - } else { - shiftMode = X_SHIFT_NONE; - if (DBG) Log.d(TAG, "no content/window translator"); - } - return new Translator(shiftMode); - } - } else if (isScalingRequired()) { - return new Translator(); - } else { + if (!isScalingRequired()) { return null; } + return new Translator(); } /** @@ -290,97 +275,48 @@ public class CompatibilityInfo { * @hide */ public class Translator { - final private int mShiftMode; - final public boolean scalingRequired; final public float applicationScale; final public float applicationInvertedScale; private Rect mContentInsetsBuffer = null; - private Rect mVisibleInsets = null; + private Rect mVisibleInsetsBuffer = null; - Translator(int shiftMode, boolean scalingRequired, float applicationScale, - float applicationInvertedScale) { - mShiftMode = shiftMode; - this.scalingRequired = scalingRequired; + Translator(float applicationScale, float applicationInvertedScale) { this.applicationScale = applicationScale; this.applicationInvertedScale = applicationInvertedScale; } - Translator(int shiftMode) { - this(shiftMode, - isScalingRequired(), - CompatibilityInfo.this.applicationScale, - CompatibilityInfo.this.applicationInvertedScale); - } - Translator() { - this(X_SHIFT_NONE); + this(CompatibilityInfo.this.applicationScale, + CompatibilityInfo.this.applicationInvertedScale); } /** * Translate the screen rect to the application frame. */ public void translateRectInScreenToAppWinFrame(Rect rect) { - if (rect.isEmpty()) return; // skip if the window size is empty. - switch (mShiftMode) { - case X_SHIFT_AND_CLIP_CONTENT: - rect.intersect(0, 0, mWidth, mHeight); - break; - case X_SHIFT_CONTENT: - rect.intersect(0, 0, mWidth + mXOffset, mHeight); - break; - case X_SHIFT_WINDOW: - case X_SHIFT_NONE: - break; - } - if (scalingRequired) { - rect.scale(applicationInvertedScale); - } + rect.scale(applicationInvertedScale); } /** * Translate the region in window to screen. */ public void translateRegionInWindowToScreen(Region transparentRegion) { - switch (mShiftMode) { - case X_SHIFT_AND_CLIP_CONTENT: - case X_SHIFT_CONTENT: - transparentRegion.scale(applicationScale); - transparentRegion.translate(mXOffset, 0); - break; - case X_SHIFT_WINDOW: - case X_SHIFT_NONE: - transparentRegion.scale(applicationScale); - } + transparentRegion.scale(applicationScale); } /** * Apply translation to the canvas that is necessary to draw the content. */ public void translateCanvas(Canvas canvas) { - if (mShiftMode == X_SHIFT_CONTENT || - mShiftMode == X_SHIFT_AND_CLIP_CONTENT) { - // TODO: clear outside when rotation is changed. - - // Translate x-offset only when the content is shifted. - canvas.translate(mXOffset, 0); - } - if (scalingRequired) { - canvas.scale(applicationScale, applicationScale); - } + canvas.scale(applicationScale, applicationScale); } /** * Translate the motion event captured on screen to the application's window. */ public void translateEventInScreenToAppWindow(MotionEvent event) { - if (mShiftMode == X_SHIFT_CONTENT || - mShiftMode == X_SHIFT_AND_CLIP_CONTENT) { - event.translate(-mXOffset, 0); - } - if (scalingRequired) { - event.scale(applicationInvertedScale); - } + event.scale(applicationInvertedScale); } /** @@ -388,62 +324,21 @@ public class CompatibilityInfo { * Screen's view. */ public void translateWindowLayout(WindowManager.LayoutParams params) { - switch (mShiftMode) { - case X_SHIFT_NONE: - case X_SHIFT_AND_CLIP_CONTENT: - case X_SHIFT_CONTENT: - params.scale(applicationScale); - break; - case X_SHIFT_WINDOW: - params.scale(applicationScale); - params.x += mXOffset; - break; - } + params.scale(applicationScale); } /** * Translate a Rect in application's window to screen. */ public void translateRectInAppWindowToScreen(Rect rect) { - // TODO Auto-generated method stub - if (scalingRequired) { - rect.scale(applicationScale); - } - switch(mShiftMode) { - case X_SHIFT_NONE: - case X_SHIFT_WINDOW: - break; - case X_SHIFT_CONTENT: - case X_SHIFT_AND_CLIP_CONTENT: - rect.offset(mXOffset, 0); - break; - } + rect.scale(applicationScale); } /** * Translate a Rect in screen coordinates into the app window's coordinates. */ public void translateRectInScreenToAppWindow(Rect rect) { - switch (mShiftMode) { - case X_SHIFT_NONE: - case X_SHIFT_WINDOW: - break; - case X_SHIFT_CONTENT: { - rect.intersects(mXOffset, 0, rect.right, rect.bottom); - int dx = Math.min(mXOffset, rect.left); - rect.offset(-dx, 0); - break; - } - case X_SHIFT_AND_CLIP_CONTENT: { - rect.intersects(mXOffset, 0, mWidth + mXOffset, mHeight); - int dx = Math.min(mXOffset, rect.left); - rect.offset(-dx, 0); - break; - } - } - if (scalingRequired) { - rect.scale(applicationInvertedScale); - } + rect.scale(applicationInvertedScale); } /** @@ -451,19 +346,7 @@ public class CompatibilityInfo { * @param params */ public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) { - if (scalingRequired) { - params.scale(applicationScale); - } - switch (mShiftMode) { - // the window location on these mode does not require adjustmenet. - case X_SHIFT_NONE: - case X_SHIFT_WINDOW: - break; - case X_SHIFT_CONTENT: - case X_SHIFT_AND_CLIP_CONTENT: - params.x += mXOffset; - break; - } + params.scale(applicationScale); } /** @@ -482,10 +365,31 @@ public class CompatibilityInfo { * the internal buffer for content insets to avoid extra object allocation. */ public Rect getTranslatedVisbileInsets(Rect visibleInsets) { - if (mVisibleInsets == null) mVisibleInsets = new Rect(); - mVisibleInsets.set(visibleInsets); - translateRectInAppWindowToScreen(mVisibleInsets); - return mVisibleInsets; + if (mVisibleInsetsBuffer == null) mVisibleInsetsBuffer = new Rect(); + mVisibleInsetsBuffer.set(visibleInsets); + translateRectInAppWindowToScreen(mVisibleInsetsBuffer); + return mVisibleInsetsBuffer; + } + } + + /** + * Returns the frame Rect for applications runs under compatibility mode. + * + * @param dm the display metrics used to compute the frame size. + * @param orientation the orientation of the screen. + * @param outRect the output parameter which will contain the result. + */ + public static void updateCompatibleScreenFrame(DisplayMetrics dm, int orientation, + Rect outRect) { + int width = dm.widthPixels; + int portraitHeight = (int) (DEFAULT_PORTRAIT_HEIGHT * dm.density + 0.5f); + int portraitWidth = (int) (DEFAULT_PORTRAIT_WIDTH * dm.density + 0.5f); + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + int xOffset = (width - portraitHeight) / 2 ; + outRect.set(xOffset, 0, xOffset + portraitHeight, portraitWidth); + } else { + int xOffset = (width - portraitWidth) / 2 ; + outRect.set(xOffset, 0, xOffset + portraitWidth, portraitHeight); } } } diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 577aa600a19e1..5f44cc9580673 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -41,6 +41,39 @@ public final class Configuration implements Parcelable, ComparableThe {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size + * of the screen. They may be one of + * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL}, + * or {@link #SCREENLAYOUT_SIZE_LARGE}. + * + *

    The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen + * is wider/taller than normal. They may be one of + * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}. + */ + public int screenLayout; + public static final int TOUCHSCREEN_UNDEFINED = 0; public static final int TOUCHSCREEN_NOTOUCH = 1; public static final int TOUCHSCREEN_STYLUS = 2; @@ -116,18 +149,6 @@ public final class Configuration implements Parcelable, Comparable EMPTY_ARRAY = new LongSparseArray() { @Override @@ -129,53 +131,30 @@ public class Resources { */ public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) { - this(assets, metrics, config, (ApplicationInfo) null); + this(assets, metrics, config, (CompatibilityInfo) null); } /** - * Creates a new Resources object with ApplicationInfo. + * Creates a new Resources object with CompatibilityInfo. * * @param assets Previously created AssetManager. * @param metrics Current display metrics to consider when * selecting/computing resource values. * @param config Desired device configuration to consider when * selecting/computing resource values (optional). - * @param appInfo this resource's application info. + * @param compInfo this resource's compatibility info. It will use the default compatibility + * info when it's null. * @hide */ public Resources(AssetManager assets, DisplayMetrics metrics, - Configuration config, ApplicationInfo appInfo) { + Configuration config, CompatibilityInfo compInfo) { mAssets = assets; - mConfiguration.setToDefaults(); mMetrics.setToDefaults(); - if (appInfo != null) { - mCompatibilityInfo = new CompatibilityInfo(appInfo); - if (DEBUG_CONFIG) { - Log.d(TAG, "compatibility for " + appInfo.packageName + " : " + mCompatibilityInfo); - } - } else { + if (compInfo == null) { mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO; - } - updateConfiguration(config, metrics); - assets.ensureStringBlocks(); - if (mCompatibilityInfo.isScalingRequired()) { - mPreloadedDrawables = emptySparseArray(); } else { - mPreloadedDrawables = sPreloadedDrawables; + mCompatibilityInfo = compInfo; } - } - - /** - * Creates a new resources that uses the given compatibility info. Used to create - * a context for widgets using the container's compatibility info. - * {@see ApplicationContext#createPackageCotnext}. - * @hide - */ - public Resources(AssetManager assets, DisplayMetrics metrics, - Configuration config, CompatibilityInfo info) { - mAssets = assets; - mMetrics.setToDefaults(); - mCompatibilityInfo = info; updateConfiguration(config, metrics); assets.ensureStringBlocks(); if (mCompatibilityInfo.isScalingRequired()) { @@ -1406,6 +1385,15 @@ public class Resources { return mCompatibilityInfo; } + /** + * This is just for testing. + * @hide + */ + public void setCompatibilityInfo(CompatibilityInfo ci) { + mCompatibilityInfo = ci; + updateConfiguration(mConfiguration, mMetrics); + } + /** * Return a resource identifier for the given resource name. A fully * qualified resource name is of the form "package:type/entry". The first @@ -1938,6 +1926,24 @@ public class Resources { + Integer.toHexString(id)); } + /** + * Returns the display adjusted for the Resources' metrics. + * @hide + */ + public Display getDefaultDisplay(Display defaultDisplay) { + if (mDefaultDisplay == null) { + if (!mCompatibilityInfo.isScalingRequired() && mCompatibilityInfo.supportsScreen()) { + // the app supports the display. just use the default one. + mDefaultDisplay = defaultDisplay; + } else { + // display needs adjustment. + mDefaultDisplay = Display.createMetricsBasedDisplay( + defaultDisplay.getDisplayId(), mMetrics); + } + } + return mDefaultDisplay; + } + private TypedArray getCachedStyledAttributes(int len) { synchronized (mTmpValue) { TypedArray attrs = mCachedStyledAttributes; diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index 7d331dc51df55..184d6dced8c70 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -1412,8 +1412,9 @@ public class SQLiteDatabase extends SQLiteClosable { StringBuilder sql = new StringBuilder(120); sql.append("UPDATE "); if (algorithm != null) { - sql.append(" OR "); + sql.append("OR "); sql.append(algorithm.value()); + sql.append(" "); } sql.append(table); diff --git a/core/java/android/gesture/Gesture.java b/core/java/android/gesture/Gesture.java index 2262477a93c4f..62330e1fe3ebf 100755 --- a/core/java/android/gesture/Gesture.java +++ b/core/java/android/gesture/Gesture.java @@ -31,6 +31,7 @@ import java.io.DataInputStream; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicInteger; /** * A gesture can have a single or multiple strokes @@ -44,7 +45,7 @@ public class Gesture implements Parcelable { private static final boolean BITMAP_RENDERING_ANTIALIAS = true; private static final boolean BITMAP_RENDERING_DITHER = true; - private static int sGestureCount = 0; + private static final AtomicInteger sGestureCount = new AtomicInteger(0); private final RectF mBoundingBox = new RectF(); @@ -54,12 +55,7 @@ public class Gesture implements Parcelable { private final ArrayList mStrokes = new ArrayList(); public Gesture() { - mGestureID = GESTURE_ID_BASE + sGestureCount++; - } - - void recycle() { - mStrokes.clear(); - mBoundingBox.setEmpty(); + mGestureID = GESTURE_ID_BASE + sGestureCount.incrementAndGet(); } /** @@ -161,20 +157,6 @@ public class Gesture implements Parcelable { return mGestureID; } - /** - * draw the gesture - * - * @param canvas - */ - void draw(Canvas canvas, Paint paint) { - final ArrayList strokes = mStrokes; - final int count = strokes.size(); - - for (int i = 0; i < count; i++) { - strokes.get(i).draw(canvas, paint); - } - } - /** * Create a bitmap of the gesture with a transparent background * diff --git a/core/java/android/gesture/package.html b/core/java/android/gesture/package.html index a54a01713c91f..32c44d2b7f4de 100644 --- a/core/java/android/gesture/package.html +++ b/core/java/android/gesture/package.html @@ -1,5 +1,5 @@ -@hide +Provides classes to create, recognize, load and save gestures. diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java index c23df217a856d..421d0130b8a0f 100644 --- a/core/java/android/net/Uri.java +++ b/core/java/android/net/Uri.java @@ -104,6 +104,18 @@ public abstract class Uri implements Parcelable, Comparable { /** Log tag. */ private static final String LOG = Uri.class.getSimpleName(); + /** + * NOTE: EMPTY accesses this field during its own initialization, so this + * field *must* be initialized first, or else EMPTY will see a null value! + * + * Placeholder for strings which haven't been cached. This enables us + * to cache null. We intentionally create a new String instance so we can + * compare its identity and there is no chance we will confuse it with + * user data. + */ + @SuppressWarnings("RedundantStringConstructorCall") + private static final String NOT_CACHED = new String("NOT CACHED"); + /** * The empty URI, equivalent to "". */ @@ -349,15 +361,6 @@ public abstract class Uri implements Parcelable, Comparable { /** Placeholder value for an index which hasn't been calculated yet. */ private final static int NOT_CALCULATED = -2; - /** - * Placeholder for strings which haven't been cached. This enables us - * to cache null. We intentionally create a new String instance so we can - * compare its identity and there is no chance we will confuse it with - * user data. - */ - @SuppressWarnings("RedundantStringConstructorCall") - private static final String NOT_CACHED = new String("NOT CACHED"); - /** * Error message presented when a user tries to treat an opaque URI as * hierarchical. @@ -1080,7 +1083,7 @@ public abstract class Uri implements Parcelable, Comparable { /** Used in parcelling. */ static final int TYPE_ID = 3; - private final String scheme; + private final String scheme; // can be null private final Part authority; private final PathPart path; private final Part query; @@ -1089,10 +1092,10 @@ public abstract class Uri implements Parcelable, Comparable { private HierarchicalUri(String scheme, Part authority, PathPart path, Part query, Part fragment) { this.scheme = scheme; - this.authority = authority; - this.path = path; - this.query = query; - this.fragment = fragment; + this.authority = Part.nonNull(authority); + this.path = path == null ? PathPart.NULL : path; + this.query = Part.nonNull(query); + this.fragment = Part.nonNull(fragment); } static Uri readFrom(Parcel parcel) { @@ -1155,21 +1158,18 @@ public abstract class Uri implements Parcelable, Comparable { } private void appendSspTo(StringBuilder builder) { - if (authority != null) { - String encodedAuthority = authority.getEncoded(); - if (encodedAuthority != null) { - // Even if the authority is "", we still want to append "//". - builder.append("//").append(encodedAuthority); - } + String encodedAuthority = authority.getEncoded(); + if (encodedAuthority != null) { + // Even if the authority is "", we still want to append "//". + builder.append("//").append(encodedAuthority); } - // path is never null. String encodedPath = path.getEncoded(); if (encodedPath != null) { builder.append(encodedPath); } - if (query != null && !query.isEmpty()) { + if (!query.isEmpty()) { builder.append('?').append(query.getEncoded()); } } @@ -1229,7 +1229,7 @@ public abstract class Uri implements Parcelable, Comparable { appendSspTo(builder); - if (fragment != null && !fragment.isEmpty()) { + if (!fragment.isEmpty()) { builder.append('#').append(fragment.getEncoded()); } @@ -1503,7 +1503,7 @@ public abstract class Uri implements Parcelable, Comparable { throw new UnsupportedOperationException(NOT_HIERARCHICAL); } - String query = getQuery(); + String query = getEncodedQuery(); if (query == null) { return Collections.emptyList(); } @@ -1566,7 +1566,7 @@ public abstract class Uri implements Parcelable, Comparable { throw new UnsupportedOperationException(NOT_HIERARCHICAL); } - String query = getQuery(); + String query = getEncodedQuery(); if (query == null) { return null; diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 528def5c40118..e203fd5902582 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -507,6 +507,19 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long getBatteryUptime(long curTime); + /** + * @deprecated use getRadioDataUptime + */ + public long getRadioDataUptimeMs() { + return getRadioDataUptime() / 1000; + } + + /** + * Returns the time that the radio was on for data transfers. + * @return the uptime in microseconds while unplugged + */ + public abstract long getRadioDataUptime(); + /** * Returns the current battery realtime in microseconds. * @@ -1128,7 +1141,14 @@ public abstract class BatteryStats implements Parcelable { } if (!didOne) sb.append("No activity"); pw.println(sb.toString()); - + + sb.setLength(0); + sb.append(prefix); + sb.append(" Radio data uptime when unplugged: "); + sb.append(getRadioDataUptime() / 1000); + sb.append(" ms"); + pw.println(sb.toString()); + sb.setLength(0); sb.append(prefix); sb.append(" Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000); diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 1214abcad634a..480519386e488 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -67,6 +67,18 @@ public class Process { */ public static final int PHONE_UID = 1001; + /** + * Defines the UID/GID for the user shell. + * @hide + */ + public static final int SHELL_UID = 2000; + + /** + * Defines the UID/GID for the WIFI supplicant process. + * @hide + */ + public static final int WIFI_UID = 1010; + /** * Defines the start of a range of UIDs (and GIDs), going from this * number to {@link #LAST_APPLICATION_UID} that are reserved for assigning diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java index 23c0a7bf473c4..584224fccc8b0 100644 --- a/core/java/android/os/RemoteCallbackList.java +++ b/core/java/android/os/RemoteCallbackList.java @@ -50,6 +50,7 @@ public class RemoteCallbackList { /*package*/ HashMap mCallbacks = new HashMap(); private Object[] mActiveBroadcast; + private int mBroadcastCount = -1; private boolean mKilled = false; private final class Callback implements IBinder.DeathRecipient { @@ -195,15 +196,16 @@ public class RemoteCallbackList { * This creates a copy of the callback list, which you can retrieve items * from using {@link #getBroadcastItem}. Note that only one broadcast can * be active at a time, so you must be sure to always call this from the - * same thread (usually by scheduling with {@link Handler} or + * same thread (usually by scheduling with {@link Handler}) or * do your own synchronization. You must call {@link #finishBroadcast} * when done. * *

    A typical loop delivering a broadcast looks like this: * *

    -     * final int N = callbacks.beginBroadcast();
    -     * for (int i=0; i 0) {
    +     *     i--;
          *     try {
          *         callbacks.getBroadcastItem(i).somethingHappened();
          *     } catch (RemoteException e) {
    @@ -222,7 +224,12 @@ public class RemoteCallbackList {
          */
         public int beginBroadcast() {
             synchronized (mCallbacks) {
    -            final int N = mCallbacks.size();
    +            if (mBroadcastCount > 0) {
    +                throw new IllegalStateException(
    +                        "beginBroadcast() called while already in a broadcast");
    +            }
    +            
    +            final int N = mBroadcastCount = mCallbacks.size();
                 if (N <= 0) {
                     return 0;
                 }
    @@ -281,12 +288,19 @@ public class RemoteCallbackList {
          * @see #beginBroadcast
          */
         public void finishBroadcast() {
    +        if (mBroadcastCount < 0) {
    +            throw new IllegalStateException(
    +                    "finishBroadcast() called outside of a broadcast");
    +        }
    +        
             Object[] active = mActiveBroadcast;
             if (active != null) {
    -            final int N = active.length;
    +            final int N = mBroadcastCount;
                 for (int i=0; i
    diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
    index 4078fa6d5a734..c292c537e6961 100644
    --- a/core/java/android/provider/Telephony.java
    +++ b/core/java/android/provider/Telephony.java
    @@ -44,7 +44,7 @@ import java.util.regex.Pattern;
      */
     public final class Telephony {
         private static final String TAG = "Telephony";
    -    private static final boolean DEBUG = false;
    +    private static final boolean DEBUG = true;
         private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
     
         // Constructor
    @@ -241,7 +241,7 @@ public final class Telephony {
                 if (uri == null) {
                     return false;
                 }
    -            
    +
                 boolean markAsUnread = false;
                 boolean markAsRead = false;
                 switch(folder) {
    @@ -268,7 +268,7 @@ public final class Telephony {
                 } else if (markAsRead) {
                     values.put(READ, Integer.valueOf(1));
                 }
    -            
    +
                 return 1 == SqliteWrapper.update(context, context.getContentResolver(),
                                 uri, values, null, null);
             }
    @@ -1136,8 +1136,14 @@ public final class Telephony {
                 }
     
                 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()) {
    @@ -1620,6 +1626,9 @@ public final class Telephony {
              *
              * It is recommended to display plmn before / above spn if
              * both are displayed.
    +         *
    +         * 

    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"; diff --git a/core/java/android/server/search/SearchDialogWrapper.java b/core/java/android/server/search/SearchDialogWrapper.java new file mode 100644 index 0000000000000..d3ef5de8634fb --- /dev/null +++ b/core/java/android/server/search/SearchDialogWrapper.java @@ -0,0 +1,387 @@ +/* + * 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.server.search; + +import android.app.ISearchManagerCallback; +import android.app.SearchDialog; +import android.app.SearchManager; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import android.os.DeadObjectException; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.os.SystemProperties; +import android.text.TextUtils; +import android.util.Log; + +/** + * Runs an instance of {@link SearchDialog} on its own thread. + */ +class SearchDialogWrapper +implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { + + private static final String TAG = "SearchManagerService"; + private static final boolean DBG = false; + + private static final String SEARCH_UI_THREAD_NAME = "SearchDialog"; + private static final int SEARCH_UI_THREAD_PRIORITY = + android.os.Process.THREAD_PRIORITY_DEFAULT; + + // Takes no arguments + private static final int MSG_INIT = 0; + // Takes these arguments: + // arg1: selectInitialQuery, 0 = false, 1 = true + // arg2: globalSearch, 0 = false, 1 = true + // obj: searchManagerCallback + // data[KEY_INITIAL_QUERY]: initial query + // data[KEY_LAUNCH_ACTIVITY]: launch activity + // data[KEY_APP_SEARCH_DATA]: app search data + private static final int MSG_START_SEARCH = 1; + // Takes no arguments + private static final int MSG_STOP_SEARCH = 2; + // arg1 is activity id + private static final int MSG_ACTIVITY_RESUMING = 3; + + private static final String KEY_INITIAL_QUERY = "q"; + private static final String KEY_LAUNCH_ACTIVITY = "a"; + private static final String KEY_APP_SEARCH_DATA = "d"; + private static final String KEY_IDENT= "i"; + + // Context used for getting search UI resources + private final Context mContext; + + // Handles messages on the search UI thread. + private final SearchDialogHandler mSearchUiThread; + + // The search UI + SearchDialog mSearchDialog; + + // If the search UI is visible, this is the callback for the client that showed it. + ISearchManagerCallback mCallback = null; + + // Identity of last activity that started search. + private int mStartedIdent = 0; + + // Identity of currently resumed activity. + private int mResumedIdent = 0; + + // True if we have registered our receivers. + private boolean mReceiverRegistered; + + private volatile boolean mVisible = false; + + /** + * Creates a new search dialog wrapper and a search UI thread. The search dialog itself will + * be created some asynchronously on the search UI thread. + * + * @param context Context used for getting search UI resources. + */ + public SearchDialogWrapper(Context context) { + mContext = context; + + // Create the search UI thread + HandlerThread t = new HandlerThread(SEARCH_UI_THREAD_NAME, SEARCH_UI_THREAD_PRIORITY); + t.start(); + mSearchUiThread = new SearchDialogHandler(t.getLooper()); + + // Create search UI on the search UI thread + mSearchUiThread.sendEmptyMessage(MSG_INIT); + } + + public boolean isVisible() { + return mVisible; + } + + /** + * Initializes the search UI. + * Must be called from the search UI thread. + */ + private void init() { + mSearchDialog = new SearchDialog(mContext); + mSearchDialog.setOnCancelListener(this); + mSearchDialog.setOnDismissListener(this); + } + + private void registerBroadcastReceiver() { + if (!mReceiverRegistered) { + IntentFilter filter = new IntentFilter( + Intent.ACTION_CLOSE_SYSTEM_DIALOGS); + filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); + mContext.registerReceiver(mBroadcastReceiver, filter, null, + mSearchUiThread); + mReceiverRegistered = true; + } + } + + private void unregisterBroadcastReceiver() { + if (mReceiverRegistered) { + mContext.unregisterReceiver(mBroadcastReceiver); + mReceiverRegistered = false; + } + } + + /** + * Closes the search dialog when requested by the system (e.g. when a phone call comes in). + */ + private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { + if (!"search".equals(intent.getStringExtra("reason"))) { + if (DBG) debug(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); + performStopSearch(); + } + } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { + if (DBG) debug(Intent.ACTION_CONFIGURATION_CHANGED); + performOnConfigurationChanged(); + } + } + }; + + // + // External API + // + + /** + * Launches the search UI. + * Can be called from any thread. + * + * @see SearchManager#startSearch(String, boolean, ComponentName, Bundle, boolean) + */ + public void startSearch(final String initialQuery, + final boolean selectInitialQuery, + final ComponentName launchActivity, + final Bundle appSearchData, + final boolean globalSearch, + final ISearchManagerCallback searchManagerCallback, + int ident) { + if (DBG) debug("startSearch()"); + Message msg = Message.obtain(); + msg.what = MSG_START_SEARCH; + msg.arg1 = selectInitialQuery ? 1 : 0; + msg.arg2 = globalSearch ? 1 : 0; + msg.obj = searchManagerCallback; + Bundle msgData = msg.getData(); + msgData.putString(KEY_INITIAL_QUERY, initialQuery); + msgData.putParcelable(KEY_LAUNCH_ACTIVITY, launchActivity); + msgData.putBundle(KEY_APP_SEARCH_DATA, appSearchData); + msgData.putInt(KEY_IDENT, ident); + mSearchUiThread.sendMessage(msg); + } + + /** + * Cancels the search dialog. + * Can be called from any thread. + */ + public void stopSearch() { + if (DBG) debug("stopSearch()"); + mSearchUiThread.sendEmptyMessage(MSG_STOP_SEARCH); + } + + /** + * Updates the currently resumed activity. + * Can be called from any thread. + */ + public void activityResuming(int ident) { + if (DBG) debug("activityResuming(ident=" + ident + ")"); + Message msg = Message.obtain(); + msg.what = MSG_ACTIVITY_RESUMING; + msg.arg1 = ident; + mSearchUiThread.sendMessage(msg); + } + + // + // Implementation methods that run on the search UI thread + // + + private class SearchDialogHandler extends Handler { + + public SearchDialogHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_INIT: + init(); + break; + case MSG_START_SEARCH: + handleStartSearchMessage(msg); + break; + case MSG_STOP_SEARCH: + performStopSearch(); + break; + case MSG_ACTIVITY_RESUMING: + performActivityResuming(msg.arg1); + break; + } + } + + private void handleStartSearchMessage(Message msg) { + Bundle msgData = msg.getData(); + String initialQuery = msgData.getString(KEY_INITIAL_QUERY); + boolean selectInitialQuery = msg.arg1 != 0; + ComponentName launchActivity = + (ComponentName) msgData.getParcelable(KEY_LAUNCH_ACTIVITY); + Bundle appSearchData = msgData.getBundle(KEY_APP_SEARCH_DATA); + boolean globalSearch = msg.arg2 != 0; + ISearchManagerCallback searchManagerCallback = (ISearchManagerCallback) msg.obj; + int ident = msgData.getInt(KEY_IDENT); + performStartSearch(initialQuery, selectInitialQuery, launchActivity, + appSearchData, globalSearch, searchManagerCallback, ident); + } + + } + + /** + * Actually launches the search UI. + * This must be called on the search UI thread. + */ + void performStartSearch(String initialQuery, + boolean selectInitialQuery, + ComponentName launchActivity, + Bundle appSearchData, + boolean globalSearch, + ISearchManagerCallback searchManagerCallback, + int ident) { + if (DBG) debug("performStartSearch()"); + + registerBroadcastReceiver(); + mCallback = searchManagerCallback; + + // clean up any hidden dialog that we were waiting to resume + if (mStartedIdent != 0) { + mSearchDialog.dismiss(); + } + + mStartedIdent = ident; + if (DBG) Log.v(TAG, "******************* DIALOG: start"); + + mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData, + globalSearch); + mVisible = true; + } + + /** + * Actually cancels the search UI. + * This must be called on the search UI thread. + */ + void performStopSearch() { + if (DBG) debug("performStopSearch()"); + if (DBG) Log.v(TAG, "******************* DIALOG: cancel"); + mSearchDialog.cancel(); + mVisible = false; + mStartedIdent = 0; + } + + /** + * Updates the resumed activity + * This must be called on the search UI thread. + */ + void performActivityResuming(int ident) { + if (DBG) debug("performResumingActivity(): mStartedIdent=" + + mStartedIdent + ", resuming: " + ident); + this.mResumedIdent = ident; + if (mStartedIdent != 0) { + if (mStartedIdent == mResumedIdent) { + // we are resuming into the activity where we previously hid the dialog, bring it + // back + if (DBG) Log.v(TAG, "******************* DIALOG: show"); + mSearchDialog.show(); + mVisible = true; + } else { + // resuming into some other activity; hide ourselves in case we ever come back + // so we can show ourselves quickly again + if (DBG) Log.v(TAG, "******************* DIALOG: hide"); + mSearchDialog.hide(); + mVisible = false; + } + } + } + + /** + * Must be called from the search UI thread. + */ + void performOnConfigurationChanged() { + if (DBG) debug("performOnConfigurationChanged()"); + mSearchDialog.onConfigurationChanged(); + } + + /** + * Called by {@link SearchDialog} when it goes away. + */ + public void onDismiss(DialogInterface dialog) { + if (DBG) debug("onDismiss()"); + mStartedIdent = 0; + mVisible = false; + callOnDismiss(); + + // we don't need the callback anymore, release it + mCallback = null; + unregisterBroadcastReceiver(); + } + + + /** + * Called by {@link SearchDialog} when the user or activity cancels search. + * Whenever this method is called, {@link #onDismiss} is always called afterwards. + */ + public void onCancel(DialogInterface dialog) { + if (DBG) debug("onCancel()"); + callOnCancel(); + } + + private void callOnDismiss() { + if (mCallback == null) return; + try { + // should be safe to do on the search UI thread, since it's a oneway interface + mCallback.onDismiss(); + } catch (DeadObjectException ex) { + // The process that hosted the callback has died, do nothing + } catch (RemoteException ex) { + Log.e(TAG, "onDismiss() failed: " + ex); + } + } + + private void callOnCancel() { + if (mCallback != null) { + try { + // should be safe to do on the search UI thread, since it's a oneway interface + mCallback.onCancel(); + } catch (DeadObjectException ex) { + // The process that hosted the callback has died, do nothing + } catch (RemoteException ex) { + Log.e(TAG, "onCancel() failed: " + ex); + } + } + } + + private static void debug(String msg) { + Thread thread = Thread.currentThread(); + Log.d(TAG, msg + " (" + thread.getName() + "-" + thread.getId() + ")"); + } +} diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java index 373e61ff97f08..fdeb8f9e3fc23 100644 --- a/core/java/android/server/search/SearchManagerService.java +++ b/core/java/android/server/search/SearchManagerService.java @@ -16,54 +16,43 @@ package android.server.search; +import android.app.ActivityManagerNative; +import android.app.IActivityWatcher; import android.app.ISearchManager; import android.app.ISearchManagerCallback; -import android.app.SearchDialog; import android.app.SearchManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; -import android.content.res.Configuration; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; -import android.os.SystemProperties; -import android.text.TextUtils; import android.util.Log; import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; /** - * This is a simplified version of the Search Manager service. It no longer handles - * presentation (UI). Its function is to maintain the map & list of "searchable" - * items, which provides a mapping from individual activities (where a user might have - * invoked search) to specific searchable activities (where the search will be dispatched). + * The search manager service handles the search UI, and maintains a registry of searchable + * activities. */ -public class SearchManagerService extends ISearchManager.Stub - implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener -{ - // general debugging support +public class SearchManagerService extends ISearchManager.Stub { + + // general debugging support private static final String TAG = "SearchManagerService"; private static final boolean DBG = false; - // class maintenance and general shared data + // Context that the service is running in. private final Context mContext; - private final Handler mHandler; - private boolean mSearchablesDirty; - private final Searchables mSearchables; - final SearchDialog mSearchDialog; - ISearchManagerCallback mCallback = null; + // This field is initialized in ensureSearchablesCreated(), and then never modified. + // Only accessed by ensureSearchablesCreated() and getSearchables() + private Searchables mSearchables; - private final boolean mDisabledOnBoot; - - private static final String DISABLE_SEARCH_PROPERTY = "dev.disablesearchdialog"; + // This field is initialized in ensureSearchDialogCreated(), and then never modified. + // Only accessed by ensureSearchDialogCreated() and getSearchDialog() + private SearchDialogWrapper mSearchDialog; /** * Initializes the Search Manager service in the provided system context. @@ -73,82 +62,98 @@ public class SearchManagerService extends ISearchManager.Stub */ public SearchManagerService(Context context) { mContext = context; - mHandler = new Handler(); - mSearchablesDirty = true; - mSearchables = new Searchables(context); - mSearchDialog = new SearchDialog(context); - mSearchDialog.setOnCancelListener(this); - mSearchDialog.setOnDismissListener(this); - - // Setup the infrastructure for updating and maintaining the list - // of searchable activities. - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_PACKAGE_ADDED); - filter.addAction(Intent.ACTION_PACKAGE_REMOVED); - filter.addAction(Intent.ACTION_PACKAGE_CHANGED); - filter.addDataScheme("package"); - mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); - - // After startup settles down, preload the searchables list, - // which will reduce the delay when the search UI is invoked. - mHandler.post(mRunUpdateSearchable); - - // allows disabling of search dialog for stress testing runs - mDisabledOnBoot = !TextUtils.isEmpty(SystemProperties.get(DISABLE_SEARCH_PROPERTY)); + // call initialize() after all pending actions on the main system thread have finished + new Handler().post(new Runnable() { + public void run() { + initialize(); + } + }); } /** - * Listens for intent broadcasts. - * - * The primary purpose here is to refresh the "searchables" list - * if packages are added/removed. + * Initializes the list of searchable activities and the search UI. */ - private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { + void initialize() { + try { + ActivityManagerNative.getDefault().registerActivityWatcher( + mActivityWatcher); + } catch (RemoteException e) { + } + } + + private synchronized void ensureSearchablesCreated() { + if (mSearchables != null) return; // already created + + mSearchables = new Searchables(mContext); + mSearchables.buildSearchableList(); + + IntentFilter packageFilter = new IntentFilter(); + packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); + packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); + packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); + packageFilter.addDataScheme("package"); + mContext.registerReceiver(mPackageChangedReceiver, packageFilter); + } + + private synchronized void ensureSearchDialogCreated() { + if (mSearchDialog != null) return; + + mSearchDialog = new SearchDialogWrapper(mContext); + } + + private synchronized Searchables getSearchables() { + ensureSearchablesCreated(); + return mSearchables; + } + + private synchronized SearchDialogWrapper getSearchDialog() { + ensureSearchDialogCreated(); + return mSearchDialog; + } + + /** + * Refreshes the "searchables" list when packages are added/removed. + */ + private BroadcastReceiver mPackageChangedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - // First, test for intents that matter at any time - if (action.equals(Intent.ACTION_PACKAGE_ADDED) || - action.equals(Intent.ACTION_PACKAGE_REMOVED) || - action.equals(Intent.ACTION_PACKAGE_CHANGED)) { - mSearchablesDirty = true; - mHandler.post(mRunUpdateSearchable); - return; + if (Intent.ACTION_PACKAGE_ADDED.equals(action) || + Intent.ACTION_PACKAGE_REMOVED.equals(action) || + Intent.ACTION_PACKAGE_CHANGED.equals(action)) { + if (DBG) Log.d(TAG, "Got " + action); + // Dismiss search dialog, since the search context may no longer be valid + getSearchDialog().stopSearch(); + // Update list of searchable activities + getSearchables().buildSearchableList(); + broadcastSearchablesChanged(); } } }; - /** - * This runnable (for the main handler / UI thread) will update the searchables list. - */ - private Runnable mRunUpdateSearchable = new Runnable() { - public void run() { - updateSearchablesIfDirty(); + private IActivityWatcher.Stub mActivityWatcher = new IActivityWatcher.Stub() { + public void activityResuming(int activityId) throws RemoteException { + if (DBG) Log.i("foo", "********************** resuming: " + activityId); + if (mSearchDialog == null) return; + mSearchDialog.activityResuming(activityId); } }; - + /** - * Updates the list of searchables, either at startup or in response to - * a package add/remove broadcast message. + * Informs all listeners that the list of searchables has been updated. */ - private void updateSearchables() { - if (DBG) debug("updateSearchables()"); - mSearchables.buildSearchableList(); - mSearchablesDirty = false; + void broadcastSearchablesChanged() { + mContext.sendBroadcast( + new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED)); } - /** - * Updates the list of searchables if needed. - */ - private void updateSearchablesIfDirty() { - if (mSearchablesDirty) { - updateSearchables(); - } - } + // + // Searchable activities API + // /** - * Returns the SearchableInfo for a given activity + * Returns the SearchableInfo for a given activity. * * @param launchActivity The activity from which we're launching this search. * @param globalSearch If false, this will only launch the search that has been specifically @@ -158,226 +163,83 @@ public class SearchManagerService extends ISearchManager.Stub * @return Returns a SearchableInfo record describing the parameters of the search, * or null if no searchable metadata was available. */ - public SearchableInfo getSearchableInfo(ComponentName launchActivity, boolean globalSearch) { - updateSearchablesIfDirty(); - SearchableInfo si = null; + public SearchableInfo getSearchableInfo(final ComponentName launchActivity, + final boolean globalSearch) { if (globalSearch) { - si = mSearchables.getDefaultSearchable(); + return getSearchables().getDefaultSearchable(); } else { if (launchActivity == null) { Log.e(TAG, "getSearchableInfo(), activity == null"); return null; } - si = mSearchables.getSearchableInfo(launchActivity); + return getSearchables().getSearchableInfo(launchActivity); } - - return si; } /** * Returns a list of the searchable activities that can be included in global search. */ public List getSearchablesInGlobalSearch() { - updateSearchablesIfDirty(); - return mSearchables.getSearchablesInGlobalSearchList(); - } - /** - * Launches the search UI on the main thread of the service. - * - * @see SearchManager#startSearch(String, boolean, ComponentName, Bundle, boolean) - */ - public void startSearch(final String initialQuery, - final boolean selectInitialQuery, - final ComponentName launchActivity, - final Bundle appSearchData, - final boolean globalSearch, - final ISearchManagerCallback searchManagerCallback) { - if (DBG) debug("startSearch()"); - Runnable task = new Runnable() { - public void run() { - performStartSearch(initialQuery, - selectInitialQuery, - launchActivity, - appSearchData, - globalSearch, - searchManagerCallback); - } - }; - mHandler.post(task); + return getSearchables().getSearchablesInGlobalSearchList(); } /** - * Actually launches the search. This must be called on the service UI thread. + * Returns a list of the searchable activities that handle web searches. + * Can be called from any thread. */ - /*package*/ void performStartSearch(String initialQuery, + public List getSearchablesForWebSearch() { + return getSearchables().getSearchablesForWebSearchList(); + } + + /** + * Returns the default searchable activity for web searches. + * Can be called from any thread. + */ + public SearchableInfo getDefaultSearchableForWebSearch() { + return getSearchables().getDefaultSearchableForWebSearch(); + } + + /** + * Sets the default searchable activity for web searches. + * Can be called from any thread. + */ + public void setDefaultWebSearch(final ComponentName component) { + getSearchables().setDefaultWebSearch(component); + broadcastSearchablesChanged(); + } + + // Search UI API + + /** + * Launches the search UI. Can be called from any thread. + * + * @see SearchManager#startSearch(String, boolean, ComponentName, Bundle, boolean) + */ + public void startSearch(String initialQuery, boolean selectInitialQuery, ComponentName launchActivity, Bundle appSearchData, boolean globalSearch, - ISearchManagerCallback searchManagerCallback) { - if (DBG) debug("performStartSearch()"); - - if (mDisabledOnBoot) { - Log.d(TAG, "ignoring start search request because " + DISABLE_SEARCH_PROPERTY - + " system property is set."); - return; - } - - mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData, - globalSearch); - if (searchManagerCallback != null) { - mCallback = searchManagerCallback; - } + ISearchManagerCallback searchManagerCallback, + int ident) { + getSearchDialog().startSearch(initialQuery, + selectInitialQuery, + launchActivity, + appSearchData, + globalSearch, + searchManagerCallback, + ident); } /** * Cancels the search dialog. Can be called from any thread. */ public void stopSearch() { - if (DBG) debug("stopSearch()"); - mHandler.post(new Runnable() { - public void run() { - performStopSearch(); - } - }); + getSearchDialog().stopSearch(); } - /** - * Cancels the search dialog. Must be called from the service UI thread. - */ - /*package*/ void performStopSearch() { - if (DBG) debug("performStopSearch()"); - mSearchDialog.cancel(); - } - - /** - * Determines if the Search UI is currently displayed. - * - * @see SearchManager#isVisible() - */ public boolean isVisible() { - return postAndWait(mIsShowing, false, "isShowing()"); - } - - private final Callable mIsShowing = new Callable() { - public Boolean call() { - return mSearchDialog.isShowing(); - } - }; - - public Bundle onSaveInstanceState() { - return postAndWait(mOnSaveInstanceState, null, "onSaveInstanceState()"); - } - - private final Callable mOnSaveInstanceState = new Callable() { - public Bundle call() { - if (mSearchDialog.isShowing()) { - return mSearchDialog.onSaveInstanceState(); - } else { - return null; - } - } - }; - - public void onRestoreInstanceState(final Bundle searchDialogState) { - if (searchDialogState != null) { - mHandler.post(new Runnable() { - public void run() { - mSearchDialog.onRestoreInstanceState(searchDialogState); - } - }); - } - } - - public void onConfigurationChanged(final Configuration newConfig) { - mHandler.post(new Runnable() { - public void run() { - if (mSearchDialog.isShowing()) { - mSearchDialog.onConfigurationChanged(newConfig); - } - } - }); - } - - /** - * Called by {@link SearchDialog} when it goes away. - */ - public void onDismiss(DialogInterface dialog) { - if (DBG) debug("onDismiss()"); - if (mCallback != null) { - try { - mCallback.onDismiss(); - } catch (RemoteException ex) { - Log.e(TAG, "onDismiss() failed: " + ex); - } - } - } - - /** - * Called by {@link SearchDialog} when the user or activity cancels search. - * When this is called, {@link #onDismiss} is called too. - */ - public void onCancel(DialogInterface dialog) { - if (DBG) debug("onCancel()"); - if (mCallback != null) { - try { - mCallback.onCancel(); - } catch (RemoteException ex) { - Log.e(TAG, "onCancel() failed: " + ex); - } - } - } - - /** - * Returns a list of the searchable activities that handle web searches. - */ - public List getSearchablesForWebSearch() { - updateSearchablesIfDirty(); - return mSearchables.getSearchablesForWebSearchList(); - } - - /** - * Returns the default searchable activity for web searches. - */ - public SearchableInfo getDefaultSearchableForWebSearch() { - updateSearchablesIfDirty(); - return mSearchables.getDefaultSearchableForWebSearch(); - } - - /** - * Sets the default searchable activity for web searches. - */ - public void setDefaultWebSearch(ComponentName component) { - mSearchables.setDefaultWebSearch(component); - } - - /** - * Runs an operation on the handler for the service, blocks until it returns, - * and returns the value returned by the operation. - * - * @param Return value type. - * @param callable Operation to run. - * @param errorResult Value to return if the operations throws an exception. - * @param name Operation name to include in error log messages. - * @return The value returned by the operation. - */ - private V postAndWait(Callable callable, V errorResult, String name) { - FutureTask task = new FutureTask(callable); - mHandler.post(task); - try { - return task.get(); - } catch (InterruptedException ex) { - Log.e(TAG, "Error calling " + name + ": " + ex); - return errorResult; - } catch (ExecutionException ex) { - Log.e(TAG, "Error calling " + name + ": " + ex); - return errorResult; - } - } - - private static void debug(String msg) { - Thread thread = Thread.currentThread(); - Log.d(TAG, msg + " (" + thread.getName() + "-" + thread.getId() + ")"); + return mSearchDialog != null && mSearchDialog.isVisible(); } } diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java index 8ef1f154d72d9..045b0c2f0874f 100644 --- a/core/java/android/server/search/SearchableInfo.java +++ b/core/java/android/server/search/SearchableInfo.java @@ -67,6 +67,7 @@ public final class SearchableInfo implements Parcelable { private final int mSearchImeOptions; private final boolean mIncludeInGlobalSearch; private final boolean mQueryAfterZeroResults; + private final boolean mAutoUrlDetect; private final String mSettingsDescription; private final String mSuggestAuthority; private final String mSuggestPath; @@ -288,6 +289,8 @@ public final class SearchableInfo implements Parcelable { com.android.internal.R.styleable.Searchable_includeInGlobalSearch, false); mQueryAfterZeroResults = a.getBoolean( com.android.internal.R.styleable.Searchable_queryAfterZeroResults, false); + mAutoUrlDetect = a.getBoolean( + com.android.internal.R.styleable.Searchable_autoUrlDetect, false); mSettingsDescription = a.getString( com.android.internal.R.styleable.Searchable_searchSettingsDescription); @@ -439,6 +442,14 @@ public final class SearchableInfo implements Parcelable { mActionKeys.put(keyInfo.getKeyCode(), keyInfo); } + /** + * Gets search information for the given activity. + * + * @param context Context to use for reading activity resources. + * @param activityInfo Activity to get search information from. + * @return Search information about the given activity, or {@code null} if + * the activity has no or invalid searchability meta-data. + */ public static SearchableInfo getActivityMetaData(Context context, ActivityInfo activityInfo) { // for each component, try to find metadata XmlResourceParser xml = @@ -666,6 +677,16 @@ public final class SearchableInfo implements Parcelable { return mQueryAfterZeroResults; } + /** + * Checks whether this searchable activity has auto URL detect turned on. + * + * @return The value of the autoUrlDetect attribute, + * or false if the attribute is not set. + */ + public boolean autoUrlDetect() { + return mAutoUrlDetect; + } + /** * Support for parcelable and aidl operations. */ @@ -698,6 +719,7 @@ public final class SearchableInfo implements Parcelable { mSearchImeOptions = in.readInt(); mIncludeInGlobalSearch = in.readInt() != 0; mQueryAfterZeroResults = in.readInt() != 0; + mAutoUrlDetect = in.readInt() != 0; mSettingsDescription = in.readString(); mSuggestAuthority = in.readString(); @@ -735,6 +757,7 @@ public final class SearchableInfo implements Parcelable { dest.writeInt(mSearchImeOptions); dest.writeInt(mIncludeInGlobalSearch ? 1 : 0); dest.writeInt(mQueryAfterZeroResults ? 1 : 0); + dest.writeInt(mAutoUrlDetect ? 1 : 0); dest.writeString(mSettingsDescription); dest.writeString(mSuggestAuthority); diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java index c7cc8edf108d8..c615957367231 100644 --- a/core/java/android/server/search/Searchables.java +++ b/core/java/android/server/search/Searchables.java @@ -17,7 +17,6 @@ package android.server.search; import com.android.internal.app.ResolverActivity; -import com.android.internal.R; import android.app.SearchManager; import android.content.ComponentName; @@ -27,7 +26,6 @@ import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.content.res.Resources; import android.os.Bundle; import android.util.Log; @@ -249,7 +247,12 @@ public class Searchables { for (int i = 0; i < webSearchInfoList.size(); ++i) { ActivityInfo ai = webSearchInfoList.get(i).activityInfo; ComponentName component = new ComponentName(ai.packageName, ai.name); - newSearchablesForWebSearchList.add(newSearchablesMap.get(component)); + SearchableInfo searchable = newSearchablesMap.get(component); + if (searchable == null) { + Log.w(LOG_TAG, "did not find component in searchables: " + component); + } else { + newSearchablesForWebSearchList.add(searchable); + } } } @@ -264,7 +267,7 @@ public class Searchables { } // Find the default web search provider. - ComponentName webSearchActivity = getPreferredWebSearchActivity(); + ComponentName webSearchActivity = getPreferredWebSearchActivity(mContext); SearchableInfo newDefaultSearchableForWebSearch = null; if (webSearchActivity != null) { newDefaultSearchableForWebSearch = newSearchablesMap.get(webSearchActivity); @@ -283,9 +286,6 @@ public class Searchables { mDefaultSearchable = newDefaultSearchable; mDefaultSearchableForWebSearch = newDefaultSearchableForWebSearch; } - - // Inform all listeners that the list of searchables has been updated. - mContext.sendBroadcast(new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED)); } /** @@ -295,9 +295,10 @@ public class Searchables { * @param action Intent action for which this activity is to be set as preferred. * @return true if component was detected and set as preferred activity, false if not. */ - private boolean setPreferredActivity(ComponentName component, String action) { + private static boolean setPreferredActivity(Context context, + ComponentName component, String action) { Log.d(LOG_TAG, "Checking component " + component); - PackageManager pm = mContext.getPackageManager(); + PackageManager pm = context.getPackageManager(); ActivityInfo ai; try { ai = pm.getActivityInfo(component, 0); @@ -326,10 +327,10 @@ public class Searchables { return true; } - public ComponentName getPreferredWebSearchActivity() { + private static ComponentName getPreferredWebSearchActivity(Context context) { // Check if we have a preferred web search activity. Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); - PackageManager pm = mContext.getPackageManager(); + PackageManager pm = context.getPackageManager(); ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); if (ri == null || ri.activityInfo.name.equals(ResolverActivity.class.getName())) { @@ -338,11 +339,11 @@ public class Searchables { // The components in the providers array are checked in the order of declaration so the // first one has the highest priority. If the component exists in the system it is set // as the preferred activity to handle intent action web search. - String[] preferredActivities = mContext.getResources().getStringArray( + String[] preferredActivities = context.getResources().getStringArray( com.android.internal.R.array.default_web_search_providers); for (String componentName : preferredActivities) { ComponentName component = ComponentName.unflattenFromString(componentName); - if (setPreferredActivity(component, Intent.ACTION_WEB_SEARCH)) { + if (setPreferredActivity(context, component, Intent.ACTION_WEB_SEARCH)) { return component; } } @@ -354,7 +355,8 @@ public class Searchables { if (cn.flattenToShortString().equals(GOOGLE_SEARCH_COMPONENT_NAME)) { ComponentName enhancedGoogleSearch = ComponentName.unflattenFromString( ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME); - if (setPreferredActivity(enhancedGoogleSearch, Intent.ACTION_WEB_SEARCH)) { + if (setPreferredActivity(context, enhancedGoogleSearch, + Intent.ACTION_WEB_SEARCH)) { return enhancedGoogleSearch; } } @@ -397,7 +399,7 @@ public class Searchables { * Sets the default searchable activity for web searches. */ public synchronized void setDefaultWebSearch(ComponentName component) { - setPreferredActivity(component, Intent.ACTION_WEB_SEARCH); + setPreferredActivity(mContext, component, Intent.ACTION_WEB_SEARCH); buildSearchableList(); } } diff --git a/core/java/android/speech/tts/ITts.aidl b/core/java/android/speech/tts/ITts.aidl index c9a6180d4e694..1812188ff0873 100755 --- a/core/java/android/speech/tts/ITts.aidl +++ b/core/java/android/speech/tts/ITts.aidl @@ -27,37 +27,37 @@ import android.content.Intent; * {@hide} */ interface ITts { - int setSpeechRate(in int speechRate); + int setSpeechRate(in String callingApp, in int speechRate); - int setPitch(in int pitch); + int setPitch(in String callingApp, in int pitch); - int speak(in String text, in int queueMode, in String[] params); + int speak(in String callingApp, in String text, in int queueMode, in String[] params); boolean isSpeaking(); - int stop(); + int stop(in String callingApp); - void addSpeech(in String text, in String packageName, in int resId); + void addSpeech(in String callingApp, in String text, in String packageName, in int resId); - void addSpeechFile(in String text, in String filename); + void addSpeechFile(in String callingApp, in String text, in String filename); String[] getLanguage(); int isLanguageAvailable(in String language, in String country, in String variant); - int setLanguage(in String language, in String country, in String variant); + int setLanguage(in String callingApp, in String language, in String country, in String variant); - boolean synthesizeToFile(in String text, in String[] params, in String outputDirectory); + boolean synthesizeToFile(in String callingApp, in String text, in String[] params, in String outputDirectory); - int playEarcon(in String earcon, in int queueMode, in String[] params); + int playEarcon(in String callingApp, in String earcon, in int queueMode, in String[] params); - void addEarcon(in String earcon, in String packageName, in int resId); + void addEarcon(in String callingApp, in String earcon, in String packageName, in int resId); - void addEarconFile(in String earcon, in String filename); + void addEarconFile(in String callingApp, in String earcon, in String filename); - void registerCallback(ITtsCallback cb); + int registerCallback(in String callingApp, ITtsCallback cb); - void unregisterCallback(ITtsCallback cb); + int unregisterCallback(in String callingApp, ITtsCallback cb); - int playSilence(in long duration, in int queueMode, in String[] params); + int playSilence(in String callingApp, in long duration, in int queueMode, in String[] params); } diff --git a/core/java/android/speech/tts/ITtsCallback.aidl b/core/java/android/speech/tts/ITtsCallback.aidl index 48ed73e021658..c9898eb761306 100755 --- a/core/java/android/speech/tts/ITtsCallback.aidl +++ b/core/java/android/speech/tts/ITtsCallback.aidl @@ -23,5 +23,5 @@ package android.speech.tts; * {@hide} */ oneway interface ITtsCallback { - void markReached(String mark); + void utteranceCompleted(String utteranceId); } diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java old mode 100644 new mode 100755 index 616b3f113ffb7..bb6b4b0385d84 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -22,6 +22,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.media.AudioManager; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; @@ -97,41 +98,147 @@ public class TextToSpeech { public void onInit(int status); } + /** + * Called when the TTS has completed saying something that has an utterance ID set. + * + * The OnUtteranceCompletedListener must implement the onUtteranceCompleted function. + * onUtteranceCompleted is passed a String that is the utteranceId given in + * the original speak call. + */ + public interface OnUtteranceCompletedListener { + public void onUtteranceCompleted(String utteranceId); + } + + /** * Internal constants for the TTS functionality * - * {@hide} */ public class Engine { // default values for a TTS engine when settings are not found in the provider + /** + * {@hide} + */ public static final int FALLBACK_TTS_DEFAULT_RATE = 100; // 1x + /** + * {@hide} + */ public static final int FALLBACK_TTS_DEFAULT_PITCH = 100;// 1x + /** + * {@hide} + */ public static final int FALLBACK_TTS_USE_DEFAULTS = 0; // false - public static final String FALLBACK_TTS_DEFAULT_LANG = "eng"; - public static final String FALLBACK_TTS_DEFAULT_COUNTRY = ""; - public static final String FALLBACK_TTS_DEFAULT_VARIANT = ""; + /** + * {@hide} + */ + public static final String FALLBACK_TTS_DEFAULT_SYNTH = "com.svox.pico"; + + // default values for rendering + public static final int TTS_DEFAULT_STREAM = AudioManager.STREAM_MUSIC; // return codes for a TTS engine's check data activity + /** + * Indicates success when checking the installation status of the resources used by the + * text-to-speech engine with the android.intent.action.CHECK_TTS_DATA intent. + */ public static final int CHECK_VOICE_DATA_PASS = 1; + /** + * Indicates failure when checking the installation status of the resources used by the + * text-to-speech engine with the android.intent.action.CHECK_TTS_DATA intent. + */ public static final int CHECK_VOICE_DATA_FAIL = 0; + /** + * Indicates erroneous data when checking the installation status of the resources used by + * the text-to-speech engine with the android.intent.action.CHECK_TTS_DATA intent. + */ public static final int CHECK_VOICE_DATA_BAD_DATA = -1; + /** + * Indicates missing resources when checking the installation status of the resources used + * by the text-to-speech engine with the android.intent.action.CHECK_TTS_DATA intent. + */ public static final int CHECK_VOICE_DATA_MISSING_DATA = -2; - public static final int CHECK_VOICE_DATA_MISSING_DATA_NO_SDCARD = -3; + /** + * Indicates missing storage volume when checking the installation status of the resources + * used by the text-to-speech engine with the android.intent.action.CHECK_TTS_DATA intent. + */ + public static final int CHECK_VOICE_DATA_MISSING_VOLUME = -3; // return codes for a TTS engine's check data activity + /** + * Extra information received with the android.intent.action.CHECK_TTS_DATA intent where + * the text-to-speech engine specifies the path to its resources. + */ public static final String VOICE_DATA_ROOT_DIRECTORY = "dataRoot"; + /** + * Extra information received with the android.intent.action.CHECK_TTS_DATA intent where + * the text-to-speech engine specifies the file names of its resources under the + * resource path. + */ public static final String VOICE_DATA_FILES = "dataFiles"; + /** + * Extra information received with the android.intent.action.CHECK_TTS_DATA intent where + * the text-to-speech engine specifies the locale associated with each resource file. + */ public static final String VOICE_DATA_FILES_INFO = "dataFilesInfo"; - // keys for the parameters passed with speak commands + // keys for the parameters passed with speak commands. Hidden keys are used internally + // to maintain engine state for each TextToSpeech instance. + /** + * {@hide} + */ public static final String TTS_KEY_PARAM_RATE = "rate"; + /** + * {@hide} + */ public static final String TTS_KEY_PARAM_LANGUAGE = "language"; + /** + * {@hide} + */ public static final String TTS_KEY_PARAM_COUNTRY = "country"; + /** + * {@hide} + */ public static final String TTS_KEY_PARAM_VARIANT = "variant"; - public static final int TTS_PARAM_POSITION_RATE = 0; - public static final int TTS_PARAM_POSITION_LANGUAGE = 2; - public static final int TTS_PARAM_POSITION_COUNTRY = 4; - public static final int TTS_PARAM_POSITION_VARIANT = 6; + /** + * Parameter key to specify the audio stream type to be used when speaking text + * or playing back a file. + */ + public static final String TTS_KEY_PARAM_STREAM = "streamType"; + /** + * Parameter key to identify an utterance in the completion listener after text has been + * spoken, a file has been played back or a silence duration has elapsed. + */ + public static final String TTS_KEY_PARAM_UTTERANCE_ID = "utteranceId"; + + // key positions in the array of cached parameters + /** + * {@hide} + */ + protected static final int TTS_PARAM_POSITION_RATE = 0; + /** + * {@hide} + */ + protected static final int TTS_PARAM_POSITION_LANGUAGE = 2; + /** + * {@hide} + */ + protected static final int TTS_PARAM_POSITION_COUNTRY = 4; + /** + * {@hide} + */ + protected static final int TTS_PARAM_POSITION_VARIANT = 6; + /** + * {@hide} + */ + protected static final int TTS_PARAM_POSITION_STREAM = 8; + /** + * {@hide} + */ + protected static final int TTS_PARAM_POSITION_UTTERANCE_ID = 10; + /** + * {@hide} + */ + protected static final int TTS_NB_CACHED_PARAMS = 6; } /** @@ -140,7 +247,9 @@ public class TextToSpeech { private ServiceConnection mServiceConnection; private ITts mITts = null; + private ITtsCallback mITtscallback = null; private Context mContext = null; + private String mPackageName = ""; private OnInitListener mInitListener = null; private boolean mStarted = false; private final Object mStartLock = new Object(); @@ -161,13 +270,16 @@ public class TextToSpeech { */ public TextToSpeech(Context context, OnInitListener listener) { mContext = context; + mPackageName = mContext.getPackageName(); mInitListener = listener; - mCachedParams = new String[2*4]; // 4 parameters, store key and value + mCachedParams = new String[2*Engine.TTS_NB_CACHED_PARAMS]; // store key and value mCachedParams[Engine.TTS_PARAM_POSITION_RATE] = Engine.TTS_KEY_PARAM_RATE; mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE] = Engine.TTS_KEY_PARAM_LANGUAGE; mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY] = Engine.TTS_KEY_PARAM_COUNTRY; mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT] = Engine.TTS_KEY_PARAM_VARIANT; + mCachedParams[Engine.TTS_PARAM_POSITION_STREAM] = Engine.TTS_KEY_PARAM_STREAM; + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = Engine.TTS_KEY_PARAM_UTTERANCE_ID; mCachedParams[Engine.TTS_PARAM_POSITION_RATE + 1] = String.valueOf(Engine.FALLBACK_TTS_DEFAULT_RATE); @@ -177,6 +289,10 @@ public class TextToSpeech { mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = defaultLoc.getISO3Country(); mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = defaultLoc.getVariant(); + mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = + String.valueOf(Engine.TTS_DEFAULT_STREAM); + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = ""; + initTts(); } @@ -263,18 +379,24 @@ public class TextToSpeech { return TTS_ERROR; } try { - mITts.addSpeech(text, packagename, resourceId); + mITts.addSpeech(mPackageName, text, packagename, resourceId); return TTS_SUCCESS; } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - addSpeech", "RemoteException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (NullPointerException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - addSpeech", "NullPointerException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (IllegalStateException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - addSpeech", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } @@ -301,18 +423,127 @@ public class TextToSpeech { return TTS_ERROR; } try { - mITts.addSpeechFile(text, filename); + mITts.addSpeechFile(mPackageName, text, filename); return TTS_SUCCESS; } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - addSpeech", "RemoteException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (NullPointerException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - addSpeech", "NullPointerException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (IllegalStateException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - addSpeech", "IllegalStateException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } + return TTS_ERROR; + } + } + + + /** + * Adds a mapping between a string of text and a sound resource in a + * package. + * + * @see #TTS.playEarcon(String earcon, int queueMode, String[] params) + * + * @param earcon The name of the earcon + * Example: "[tick]"
    + * + * @param packagename + * Pass the packagename of the application that contains the + * resource. If the resource is in your own application (this is + * the most common case), then put the packagename of your + * application here.
    + * Example: "com.google.marvin.compass"
    + * The packagename can be found in the AndroidManifest.xml of + * your application. + *

    + * <manifest xmlns:android="..." + * package="com.google.marvin.compass"> + *

    + * + * @param resourceId + * Example: R.raw.tick_snd + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int addEarcon(String earcon, String packagename, int resourceId) { + synchronized(mStartLock) { + if (!mStarted) { + return TTS_ERROR; + } + try { + mITts.addEarcon(mPackageName, earcon, packagename, resourceId); + return TTS_SUCCESS; + } catch (RemoteException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - addEarcon", "RemoteException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - addEarcon", "NullPointerException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - addEarcon", "IllegalStateException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } + return TTS_ERROR; + } + } + + + /** + * Adds a mapping between a string of text and a sound file. Using this, it + * is possible to add custom earcons. + * + * @param earcon + * The name of the earcon + * @param filename + * The full path to the sound file (for example: + * "/sdcard/mysounds/tick.wav") + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int addEarcon(String earcon, String filename) { + synchronized (mStartLock) { + if (!mStarted) { + return TTS_ERROR; + } + try { + mITts.addEarconFile(mPackageName, earcon, filename); + return TTS_SUCCESS; + } catch (RemoteException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - addEarcon", "RemoteException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - addEarcon", "NullPointerException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - addEarcon", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } @@ -347,22 +578,38 @@ public class TextToSpeech { return result; } try { - // TODO support extra parameters, passing cache of current parameters for the moment - result = mITts.speak(text, queueMode, mCachedParams); + if ((params != null) && (!params.isEmpty())) { + String extra = params.get(Engine.TTS_KEY_PARAM_STREAM); + if (extra != null) { + mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = extra; + } + extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID); + if (extra != null) { + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra; + } + } + result = mITts.speak(mPackageName, text, queueMode, mCachedParams); } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - speak", "RemoteException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (NullPointerException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - speak", "NullPointerException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (IllegalStateException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - speak", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } finally { - return result; + resetCachedParams(); + return result; } } } @@ -388,22 +635,38 @@ public class TextToSpeech { return result; } try { - // TODO support extra parameters, passing null for the moment - result = mITts.playEarcon(earcon, queueMode, null); + if ((params != null) && (!params.isEmpty())) { + String extra = params.get(Engine.TTS_KEY_PARAM_STREAM); + if (extra != null) { + mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = extra; + } + extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID); + if (extra != null) { + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra; + } + } + result = mITts.playEarcon(mPackageName, earcon, queueMode, null); } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - playEarcon", "RemoteException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (NullPointerException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - playEarcon", "NullPointerException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (IllegalStateException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - playEarcon", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } finally { - return result; + resetCachedParams(); + return result; } } } @@ -419,25 +682,36 @@ public class TextToSpeech { * * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. */ - public int playSilence(long durationInMs, int queueMode) { + public int playSilence(long durationInMs, int queueMode, HashMap params) { synchronized (mStartLock) { int result = TTS_ERROR; if (!mStarted) { return result; } try { - // TODO support extra parameters, passing cache of current parameters for the moment - result = mITts.playSilence(durationInMs, queueMode, mCachedParams); + if ((params != null) && (!params.isEmpty())) { + String extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID); + if (extra != null) { + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra; + } + } + result = mITts.playSilence(mPackageName, durationInMs, queueMode, mCachedParams); } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - playSilence", "RemoteException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (NullPointerException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - playSilence", "NullPointerException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (IllegalStateException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - playSilence", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } finally { @@ -461,14 +735,20 @@ public class TextToSpeech { return mITts.isSpeaking(); } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - isSpeaking", "RemoteException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (NullPointerException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - isSpeaking", "NullPointerException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (IllegalStateException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - isSpeaking", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } @@ -489,17 +769,23 @@ public class TextToSpeech { return result; } try { - result = mITts.stop(); + result = mITts.stop(mPackageName); } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - stop", "RemoteException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (NullPointerException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - stop", "NullPointerException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (IllegalStateException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - stop", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } finally { @@ -534,10 +820,24 @@ public class TextToSpeech { if (speechRate > 0) { int rate = (int)(speechRate*100); mCachedParams[Engine.TTS_PARAM_POSITION_RATE + 1] = String.valueOf(rate); - result = mITts.setSpeechRate(rate); + // the rate is not set here, instead it is cached so it will be associated + // with all upcoming utterances. + if (speechRate > 0.0f) { + result = TTS_SUCCESS; + } else { + result = TTS_ERROR; + } } - } catch (RemoteException e) { + } catch (NullPointerException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - setSpeechRate", "NullPointerException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - setSpeechRate", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } finally { @@ -570,10 +870,24 @@ public class TextToSpeech { } try { if (pitch > 0) { - result = mITts.setPitch((int)(pitch*100)); + result = mITts.setPitch(mPackageName, (int)(pitch*100)); } } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - setPitch", "RemoteException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - setPitch", "NullPointerException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - setPitch", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } finally { @@ -593,7 +907,9 @@ public class TextToSpeech { * @param loc * The locale describing the language to be used. * - * @return Code indicating the support status for the locale. See the TTS_LANG_ codes. + * @return code indicating the support status for the locale. See {@link #TTS_LANG_AVAILABLE}, + * {@link #TTS_LANG_COUNTRY_AVAILABLE}, {@link #TTS_LANG_COUNTRY_VAR_AVAILABLE}, + * {@link #TTS_LANG_MISSING_DATA} and {@link #TTS_LANG_NOT_SUPPORTED}. */ public int setLanguage(Locale loc) { synchronized (mStartLock) { @@ -605,10 +921,27 @@ public class TextToSpeech { mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1] = loc.getISO3Language(); mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = loc.getISO3Country(); mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = loc.getVariant(); - result = mITts.setLanguage(mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1], + + result = mITts.setLanguage(mPackageName, + mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1], mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1], mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] ); + } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - setLanguage", "RemoteException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - setLanguage", "NullPointerException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - setLanguage", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } finally { @@ -637,6 +970,20 @@ public class TextToSpeech { } } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - getLanguage", "RemoteException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - getLanguage", "NullPointerException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - getLanguage", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } @@ -650,8 +997,9 @@ public class TextToSpeech { * @param loc * The Locale describing the language to be used. * - * @return one of TTS_LANG_NOT_SUPPORTED, TTS_LANG_MISSING_DATA, TTS_LANG_AVAILABLE, - * TTS_LANG_COUNTRY_AVAILABLE, TTS_LANG_COUNTRY_VAR_AVAILABLE. + * @return code indicating the support status for the locale. See {@link #TTS_LANG_AVAILABLE}, + * {@link #TTS_LANG_COUNTRY_AVAILABLE}, {@link #TTS_LANG_COUNTRY_VAR_AVAILABLE}, + * {@link #TTS_LANG_MISSING_DATA} and {@link #TTS_LANG_NOT_SUPPORTED}. */ public int isLanguageAvailable(Locale loc) { synchronized (mStartLock) { @@ -664,6 +1012,20 @@ public class TextToSpeech { loc.getISO3Country(), loc.getVariant()); } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - isLanguageAvailable", "RemoteException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - isLanguageAvailable", "NullPointerException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - isLanguageAvailable", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } finally { @@ -694,26 +1056,98 @@ public class TextToSpeech { return result; } try { - // TODO support extra parameters, passing null for the moment - if (mITts.synthesizeToFile(text, null, filename)){ + if ((params != null) && (!params.isEmpty())) { + // no need to read the stream type here + String extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID); + if (extra != null) { + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra; + } + } + if (mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename)){ result = TTS_SUCCESS; } } catch (RemoteException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - synthesizeToFile", "RemoteException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (NullPointerException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - synthesizeToFile", "NullPointerException"); + e.printStackTrace(); mStarted = false; initTts(); } catch (IllegalStateException e) { // TTS died; restart it. + Log.e("TextToSpeech.java - synthesizeToFile", "IllegalStateException"); + e.printStackTrace(); mStarted = false; initTts(); } finally { - return result; + resetCachedParams(); + return result; } } } + + /** + * Convenience method to reset the cached parameters to the current default values + * if they are not persistent between calls to the service. + */ + private void resetCachedParams() { + mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = + String.valueOf(Engine.TTS_DEFAULT_STREAM); + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID+ 1] = ""; + } + + /** + * Sets the OnUtteranceCompletedListener that will fire when an utterance completes. + * + * @param listener + * The OnUtteranceCompletedListener + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int setOnUtteranceCompletedListener( + final OnUtteranceCompletedListener listener) { + synchronized (mStartLock) { + int result = TTS_ERROR; + if (!mStarted) { + return result; + } + mITtscallback = new ITtsCallback.Stub() { + public void utteranceCompleted(String utteranceId) throws RemoteException { + if (listener != null) { + listener.onUtteranceCompleted(utteranceId); + } + } + }; + try { + result = mITts.registerCallback(mPackageName, mITtscallback); + } catch (RemoteException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - registerCallback", "RemoteException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - registerCallback", "NullPointerException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - registerCallback", "IllegalStateException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } finally { + return result; + } + } + } + } diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java index 70e12970e6c2b..380e5fd8d197a 100644 --- a/core/java/android/text/Html.java +++ b/core/java/android/text/Html.java @@ -25,6 +25,7 @@ import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; +import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Typeface; import android.graphics.drawable.Drawable; @@ -40,6 +41,7 @@ import android.text.style.StrikethroughSpan; import android.text.style.StyleSpan; import android.text.style.SubscriptSpan; import android.text.style.SuperscriptSpan; +import android.text.style.TextAppearanceSpan; import android.text.style.TypefaceSpan; import android.text.style.URLSpan; import android.text.style.UnderlineSpan; @@ -49,6 +51,7 @@ import com.android.internal.util.XmlUtils; import java.io.IOException; import java.io.StringReader; import java.nio.CharBuffer; +import java.util.HashMap; /** * This class processes HTML strings into displayable styled text. @@ -633,53 +636,24 @@ class HtmlToSpannedConverter implements ContentHandler { if (where != len) { Font f = (Font) obj; - if (f.mColor != null) { - int c = -1; - - if (f.mColor.equalsIgnoreCase("aqua")) { - c = 0x00FFFF; - } else if (f.mColor.equalsIgnoreCase("black")) { - c = 0x000000; - } else if (f.mColor.equalsIgnoreCase("blue")) { - c = 0x0000FF; - } else if (f.mColor.equalsIgnoreCase("fuchsia")) { - c = 0xFF00FF; - } else if (f.mColor.equalsIgnoreCase("green")) { - c = 0x008000; - } else if (f.mColor.equalsIgnoreCase("grey")) { - c = 0x808080; - } else if (f.mColor.equalsIgnoreCase("lime")) { - c = 0x00FF00; - } else if (f.mColor.equalsIgnoreCase("maroon")) { - c = 0x800000; - } else if (f.mColor.equalsIgnoreCase("navy")) { - c = 0x000080; - } else if (f.mColor.equalsIgnoreCase("olive")) { - c = 0x808000; - } else if (f.mColor.equalsIgnoreCase("purple")) { - c = 0x800080; - } else if (f.mColor.equalsIgnoreCase("red")) { - c = 0xFF0000; - } else if (f.mColor.equalsIgnoreCase("silver")) { - c = 0xC0C0C0; - } else if (f.mColor.equalsIgnoreCase("teal")) { - c = 0x008080; - } else if (f.mColor.equalsIgnoreCase("white")) { - c = 0xFFFFFF; - } else if (f.mColor.equalsIgnoreCase("yellow")) { - c = 0xFFFF00; - } else { - try { - c = XmlUtils.convertValueToInt(f.mColor, -1); - } catch (NumberFormatException nfe) { - // Can't understand the color, so just drop it. + if (!TextUtils.isEmpty(f.mColor)) { + if (f.mColor.startsWith("@")) { + Resources res = Resources.getSystem(); + String name = f.mColor.substring(1); + int colorRes = res.getIdentifier(name, "color", "android"); + if (colorRes != 0) { + ColorStateList colors = res.getColorStateList(colorRes); + text.setSpan(new TextAppearanceSpan(null, 0, 0, colors, null), + where, len, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } else { + int c = getHtmlColor(f.mColor); + if (c != -1) { + text.setSpan(new ForegroundColorSpan(c | 0xFF000000), + where, len, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } - } - - if (c != -1) { - text.setSpan(new ForegroundColorSpan(c | 0xFF000000), - where, len, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } @@ -843,4 +817,47 @@ class HtmlToSpannedConverter implements ContentHandler { mLevel = level; } } + + private static HashMap COLORS = buildColorMap(); + + private static HashMap buildColorMap() { + HashMap map = new HashMap(); + map.put("aqua", 0x00FFFF); + map.put("black", 0x000000); + map.put("blue", 0x0000FF); + map.put("fuchsia", 0xFF00FF); + map.put("green", 0x008000); + map.put("grey", 0x808080); + map.put("lime", 0x00FF00); + map.put("maroon", 0x800000); + map.put("navy", 0x000080); + map.put("olive", 0x808000); + map.put("purple", 0x800080); + map.put("red", 0xFF0000); + map.put("silver", 0xC0C0C0); + map.put("teal", 0x008080); + map.put("white", 0xFFFFFF); + map.put("yellow", 0xFFFF00); + return map; + } + + /** + * Converts an HTML color (named or numeric) to an integer RGB value. + * + * @param color Non-null color string. + * @return A color value, or {@code -1} if the color string could not be interpreted. + */ + private static int getHtmlColor(String color) { + Integer i = COLORS.get(color.toLowerCase()); + if (i != null) { + return i; + } else { + try { + return XmlUtils.convertValueToInt(color, -1); + } catch (NumberFormatException nfe) { + return -1; + } + } + } + } diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index 4179edbe7f9cf..061f98a5a53ed 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -27,17 +27,31 @@ import android.os.*; */ public class DisplayMetrics { /** - * The reference density used throughout the system. - * - * @hide Pending API council approval + * Standard quantized DPI for low-density screens. */ - public static final int DEFAULT_DENSITY = 160; + public static final int DENSITY_LOW = 120; + + /** + * Standard quantized DPI for medium-density screens. + */ + public static final int DENSITY_MEDIUM = 160; + + /** + * Standard quantized DPI for high-density screens. + */ + public static final int DENSITY_HIGH = 240; + + /** + * The reference density used throughout the system. + */ + public static final int DENSITY_DEFAULT = DENSITY_MEDIUM; /** * The device's density. - * @hide + * @hide becase eventually this should be able to change while + * running, so shouldn't be a constant. */ - public static final int DEVICE_DENSITY = getDeviceDensity(); + public static final int DENSITY_DEVICE = getDeviceDensity(); /** * The absolute width of the display in pixels. @@ -62,7 +76,7 @@ public class DisplayMetrics { * 320x480 but the screen size remained 1.5"x2" then the density would be * increased (probably to 1.5). * - * @see #DEFAULT_DENSITY + * @see #DENSITY_DEFAULT */ public float density; /** @@ -95,10 +109,10 @@ public class DisplayMetrics { public void setToDefaults() { widthPixels = 0; heightPixels = 0; - density = DEVICE_DENSITY / (float) DEFAULT_DENSITY; + density = DENSITY_DEVICE / (float) DENSITY_DEFAULT; scaledDensity = density; - xdpi = DEVICE_DENSITY; - ydpi = DEVICE_DENSITY; + xdpi = DENSITY_DEVICE; + ydpi = DENSITY_DEVICE; } /** @@ -109,60 +123,77 @@ public class DisplayMetrics { */ public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation, int screenLayout) { - int xOffset = 0; - if (!compatibilityInfo.isConfiguredExpandable()) { - // Note: this assume that configuration is updated before calling - // updateMetrics method. - if (screenLayout == Configuration.SCREENLAYOUT_LARGE) { - // This is a large screen device and the app is not - // compatible with large screens, to diddle it. - - compatibilityInfo.setExpandable(false); - // Figure out the compatibility width and height of the screen. - int defaultWidth; - int defaultHeight; - switch (orientation) { - case Configuration.ORIENTATION_LANDSCAPE: { - defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density); - defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density); - break; - } - case Configuration.ORIENTATION_PORTRAIT: - case Configuration.ORIENTATION_SQUARE: - default: { - defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density); - defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density); - break; - } - case Configuration.ORIENTATION_UNDEFINED: { - // don't change - return; - } - } - - if (defaultWidth < widthPixels) { - // content/window's x offset in original pixels - xOffset = ((widthPixels - defaultWidth) / 2); - widthPixels = defaultWidth; - } - if (defaultHeight < heightPixels) { - heightPixels = defaultHeight; - } - - } else { - // the screen size is same as expected size. make it expandable + boolean expandable = compatibilityInfo.isConfiguredExpandable(); + boolean largeScreens = compatibilityInfo.isConfiguredLargeScreens(); + + // Note: this assume that configuration is updated before calling + // updateMetrics method. + if (!expandable) { + if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) == 0) { + expandable = true; + // the current screen size is compatible with non-resizing apps. compatibilityInfo.setExpandable(true); + } else { + compatibilityInfo.setExpandable(false); + } + } + if (!largeScreens) { + if ((screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) + != Configuration.SCREENLAYOUT_SIZE_LARGE) { + largeScreens = true; + // the current screen size is not large. + compatibilityInfo.setLargeScreens(true); + } else { + compatibilityInfo.setLargeScreens(false); + } + } + + if (!expandable || !largeScreens) { + // This is a larger screen device and the app is not + // compatible with large screens, so diddle it. + + // Figure out the compatibility width and height of the screen. + int defaultWidth; + int defaultHeight; + switch (orientation) { + case Configuration.ORIENTATION_LANDSCAPE: { + defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density + + 0.5f); + defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density + + 0.5f); + break; + } + case Configuration.ORIENTATION_PORTRAIT: + case Configuration.ORIENTATION_SQUARE: + default: { + defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density + + 0.5f); + defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density + + 0.5f); + break; + } + case Configuration.ORIENTATION_UNDEFINED: { + // don't change + return; + } + } + + if (defaultWidth < widthPixels) { + // content/window's x offset in original pixels + widthPixels = defaultWidth; + } + if (defaultHeight < heightPixels) { + heightPixels = defaultHeight; } } - compatibilityInfo.setVisibleRect(xOffset, widthPixels, heightPixels); if (compatibilityInfo.isScalingRequired()) { float invertedRatio = compatibilityInfo.applicationInvertedScale; density *= invertedRatio; scaledDensity *= invertedRatio; xdpi *= invertedRatio; ydpi *= invertedRatio; - widthPixels *= invertedRatio; - heightPixels *= invertedRatio; + widthPixels = (int) (widthPixels * invertedRatio + 0.5f); + heightPixels = (int) (heightPixels * invertedRatio + 0.5f); } } @@ -179,6 +210,6 @@ public class DisplayMetrics { // The reason for this is that ro.sf.lcd_density is write-once and is // set by the init process when it parses build.prop before anything else. return SystemProperties.getInt("qemu.sf.lcd_density", - SystemProperties.getInt("ro.sf.lcd_density", DEFAULT_DENSITY)); + SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT)); } } diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java index d4ba9e21ac13f..ed4529851d8f0 100644 --- a/core/java/android/util/TypedValue.java +++ b/core/java/android/util/TypedValue.java @@ -140,12 +140,16 @@ public class TypedValue { /** * If {@link #density} is equal to this value, then the density should be - * treated as the system's default density value: {@link DisplayMetrics#DEFAULT_DENSITY}. - * - * @hide Pending API council approval + * treated as the system's default density value: {@link DisplayMetrics#DENSITY_DEFAULT}. */ public static final int DENSITY_DEFAULT = 0; + /** + * If {@link #density} is equal to this value, then there is no density + * associated with the resource and it should not be scaled. + */ + public static final int DENSITY_NONE = 0xffff; + /* ------------------------------------------------------------ */ /** The type held by this value, as defined by the constants here. @@ -171,8 +175,6 @@ public class TypedValue { /** * If the Value came from a resource, this holds the corresponding pixel density. - * - * @hide Pending API council approval * */ public int density; diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 09ebeed543e18..5551f64bcde34 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -117,5 +117,32 @@ public class Display private static final Object mStaticInit = new Object(); private static boolean mInitialized = false; + + /** + * Returns a display object which uses the metric's width/height instead. + * @hide + */ + public static Display createMetricsBasedDisplay(int displayId, DisplayMetrics metrics) { + return new CompatibleDisplay(displayId, metrics); + } + + private static class CompatibleDisplay extends Display { + private final DisplayMetrics mMetrics; + + private CompatibleDisplay(int displayId, DisplayMetrics metrics) { + super(displayId); + mMetrics = metrics; + } + + @Override + public int getWidth() { + return mMetrics.widthPixels; + } + + @Override + public int getHeight() { + return mMetrics.heightPixels; + } + } } diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 0178d635fb3bd..83c30e1855f96 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -19,6 +19,7 @@ package android.view; import android.graphics.*; import android.os.Parcelable; import android.os.Parcel; +import android.util.DisplayMetrics; import android.util.Log; /** @@ -131,6 +132,10 @@ public class Surface implements Parcelable { @SuppressWarnings("unused") private Canvas mCanvas; + // The display metrics used to provide the pseudo canvas size for applications + // running in compatibility mode. This is set to null for regular mode. + private DisplayMetrics mDisplayMetrics; + /** * Exception thrown when a surface couldn't be created or resized */ @@ -167,7 +172,23 @@ public class Surface implements Parcelable { * {@hide} */ public Surface() { - mCanvas = new Canvas(); + mCanvas = new Canvas() { + @Override + public int getWidth() { + return mDisplayMetrics == null ? super.getWidth() : mDisplayMetrics.widthPixels; + } + @Override + public int getHeight() { + return mDisplayMetrics == null ? super.getHeight() : mDisplayMetrics.heightPixels; + } + }; + } + + /** + * Sets the display metrics used to provide canva's width/height in comaptibility mode. + */ + void setCompatibleDisplayMetrics(DisplayMetrics metrics) { + mDisplayMetrics = metrics; } /** diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 45b0f0a790829..95bba97c75977 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -17,7 +17,7 @@ package android.view; import android.content.Context; -import android.content.res.CompatibilityInfo; +import android.content.res.Resources; import android.content.res.CompatibilityInfo.Translator; import android.graphics.Canvas; import android.graphics.PixelFormat; @@ -256,9 +256,9 @@ public class SurfaceView extends View { public boolean dispatchTouchEvent(MotionEvent event) { // SurfaceView uses pre-scaled size unless fixed size is requested. This hook // scales the event back to the pre-scaled coordinates for such surface. - if (mRequestedWidth < 0 && mTranslator != null) { + if (mScaled) { MotionEvent scaledBack = MotionEvent.obtain(event); - scaledBack.scale(mTranslator.applicationScale); + mTranslator.translateEventInScreenToAppWindow(event); try { return super.dispatchTouchEvent(scaledBack); } finally { @@ -290,15 +290,23 @@ public class SurfaceView extends View { public void setWindowType(int type) { mWindowType = type; } + + boolean mScaled = false; private void updateWindow(boolean force) { if (!mHaveFrame) { return; } - mTranslator = ((ViewRoot)getRootView().getParent()).mTranslator; + ViewRoot viewRoot = (ViewRoot) getRootView().getParent(); + mTranslator = viewRoot.mTranslator; float appScale = mTranslator == null ? 1.0f : mTranslator.applicationScale; + Resources res = getContext().getResources(); + if (mTranslator != null || !res.getCompatibilityInfo().supportsScreen()) { + mSurface.setCompatibleDisplayMetrics(res.getDisplayMetrics()); + } + int myWidth = mRequestedWidth; if (myWidth <= 0) myWidth = getWidth(); int myHeight = mRequestedHeight; @@ -306,9 +314,12 @@ public class SurfaceView extends View { // Use original size if the app specified the size of the view, // and let the flinger to scale up. - if (mRequestedWidth <= 0 && mTranslator != null && mTranslator.scalingRequired) { - myWidth *= appScale; - myHeight *= appScale; + if (mRequestedWidth <= 0 && mTranslator != null) { + myWidth = (int) (myWidth * appScale + 0.5f); + myHeight = (int) (myHeight * appScale + 0.5f); + mScaled = true; + } else { + mScaled = false; } getLocationInWindow(mLocation); @@ -352,8 +363,10 @@ public class SurfaceView extends View { | WindowManager.LayoutParams.FLAG_SCALED | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE - | WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING ; + if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) { + mLayout.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW; + } mLayout.memoryType = mRequestedType; @@ -533,6 +546,7 @@ public class SurfaceView extends View { private SurfaceHolder mSurfaceHolder = new SurfaceHolder() { private static final String LOG_TAG = "SurfaceHolder"; + private int mSaveCount; public boolean isCreating() { return mIsCreating; @@ -627,6 +641,10 @@ public class SurfaceView extends View { if (localLOGV) Log.i(TAG, "Returned canvas: " + c); if (c != null) { mLastLockTime = SystemClock.uptimeMillis(); + if (mScaled) { + mSaveCount = c.save(); + mTranslator.translateCanvas(c); + } return c; } @@ -649,6 +667,9 @@ public class SurfaceView extends View { } public void unlockCanvasAndPost(Canvas canvas) { + if (mScaled) { + canvas.restoreToCount(mSaveCount); + } mSurface.unlockCanvasAndPost(canvas); mSurfaceLock.unlock(); } diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 6f6e22477d257..2f92b32e53f1c 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -42,6 +42,7 @@ import android.view.inputmethod.InputMethodManager; import android.widget.Scroller; import android.content.pm.PackageManager; import android.content.res.CompatibilityInfo; +import android.content.res.Resources; import android.content.Context; import android.app.ActivityManagerNative; import android.Manifest; @@ -385,10 +386,15 @@ public final class ViewRoot extends Handler implements ViewParent, if (mView == null) { mView = view; mWindowAttributes.copyFrom(attrs); - - CompatibilityInfo compatibilityInfo = - mView.getContext().getResources().getCompatibilityInfo(); + attrs = mWindowAttributes; + Resources resources = mView.getContext().getResources(); + CompatibilityInfo compatibilityInfo = resources.getCompatibilityInfo(); mTranslator = compatibilityInfo.getTranslator(attrs); + + if (mTranslator != null || !compatibilityInfo.supportsScreen()) { + mSurface.setCompatibleDisplayMetrics(resources.getDisplayMetrics()); + } + boolean restore = false; if (attrs != null && mTranslator != null) { restore = true; @@ -397,11 +403,14 @@ public final class ViewRoot extends Handler implements ViewParent, } if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs); + if (!compatibilityInfo.supportsScreen()) { + attrs.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW; + } + mSoftInputMode = attrs.softInputMode; mWindowAttributesChanged = true; mAttachInfo.mRootView = view; - mAttachInfo.mScalingRequired = - mTranslator == null ? false : mTranslator.scalingRequired; + mAttachInfo.mScalingRequired = mTranslator == null ? false : true; mAttachInfo.mApplicationScale = mTranslator == null ? 1.0f : mTranslator.applicationScale; if (panelParentView != null) { @@ -493,8 +502,12 @@ public final class ViewRoot extends Handler implements ViewParent, void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) { synchronized (this) { int oldSoftInputMode = mWindowAttributes.softInputMode; + // preserve compatible window flag if exists. + int compatibleWindowFlag = + mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW; mWindowAttributes.copyFrom(attrs); - + mWindowAttributes.flags |= compatibleWindowFlag; + if (newView) { mSoftInputMode = attrs.softInputMode; requestLayout(); @@ -899,7 +912,8 @@ public final class ViewRoot extends Handler implements ViewParent, mHeight = frame.height(); if (initialized) { - mGlCanvas.setViewport((int) (mWidth * appScale), (int) (mHeight * appScale)); + mGlCanvas.setViewport((int) (mWidth * appScale + 0.5f), + (int) (mHeight * appScale + 0.5f)); } boolean focusChangedDueToTouchMode = ensureTouchModeLocally( @@ -1229,7 +1243,7 @@ public final class ViewRoot extends Handler implements ViewParent, if (fullRedrawNeeded) { mAttachInfo.mIgnoreDirtyState = true; - dirty.union(0, 0, (int) (mWidth * appScale), (int) (mHeight * appScale)); + dirty.union(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f)); } if (DEBUG_ORIENTATION || DEBUG_DRAW) { @@ -1297,7 +1311,8 @@ public final class ViewRoot extends Handler implements ViewParent, if (DEBUG_DRAW) { Context cxt = mView.getContext(); Log.i(TAG, "Drawing: package:" + cxt.getPackageName() + - ", metrics=" + mView.getContext().getResources().getDisplayMetrics()); + ", metrics=" + cxt.getResources().getDisplayMetrics() + + ", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo()); } int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { @@ -1363,6 +1378,15 @@ public final class ViewRoot extends Handler implements ViewParent, // is non-null and we just want to scroll to whatever that // rectangle is). View focus = mRealFocusedView; + + // When in touch mode, focus points to the previously focused view, + // which may have been removed from the view hierarchy. The following + // line checks whether the view is still in the hierarchy + if (focus == null || focus.getParent() == null) { + mRealFocusedView = null; + return false; + } + if (focus != mLastScrolledFocus) { // If the focus has changed, then ignore any requests to scroll // to a rectangle; first we want to make sure the entire focus @@ -1731,7 +1755,8 @@ public final class ViewRoot extends Handler implements ViewParent, if (mGlCanvas != null) { float appScale = mAttachInfo.mApplicationScale; mGlCanvas.setViewport( - (int) (mWidth * appScale), (int) (mHeight * appScale)); + (int) (mWidth * appScale + 0.5f), + (int) (mHeight * appScale + 0.5f)); } } } @@ -2376,8 +2401,8 @@ public final class ViewRoot extends Handler implements ViewParent, } int relayoutResult = sWindowSession.relayout( mWindow, params, - (int) (mView.mMeasuredWidth * appScale), - (int) (mView.mMeasuredHeight * appScale), + (int) (mView.mMeasuredWidth * appScale + 0.5f), + (int) (mView.mMeasuredHeight * appScale + 0.5f), viewVisibility, insetsPending, mWinFrame, mPendingContentInsets, mPendingVisibleInsets, mSurface); if (restore) { diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index d7457a030468e..576c8c1a84835 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -358,6 +358,8 @@ public abstract class Window { private class LocalWindowManager implements WindowManager { LocalWindowManager(WindowManager wm) { mWindowManager = wm; + mDefaultDisplay = mContext.getResources().getDefaultDisplay( + mWindowManager.getDefaultDisplay()); } public final void addView(View view, ViewGroup.LayoutParams params) { @@ -420,10 +422,12 @@ public abstract class Window { } public Display getDefaultDisplay() { - return mWindowManager.getDefaultDisplay(); + return mDefaultDisplay; } - WindowManager mWindowManager; + private final WindowManager mWindowManager; + + private final Display mDefaultDisplay; } /** diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index bdb86d703b3b8..c0be9e8a3e2b0 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -483,11 +483,12 @@ public interface WindowManager extends ViewManager { * {@hide} */ public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000; - /** Window flag: special flag to let a window ignore the compatibility scaling. - * This is used by SurfaceView to create a window that does not scale the content. + /** Window flag: special flag to limit the size of the window to be + * original size ([320x480] x density). Used to create window for applications + * running under compatibility mode. * * {@hide} */ - public static final int FLAG_NO_COMPATIBILITY_SCALING = 0x00100000; + public static final int FLAG_COMPATIBLE_WINDOW = 0x00100000; /** Window flag: a special option intended for system dialogs. When * this flag is set, the window will demand focus unconditionally when @@ -978,6 +979,9 @@ public interface WindowManager extends ViewManager { sb.append(" or="); sb.append(screenOrientation); } + if ((flags & FLAG_COMPATIBLE_WINDOW) != 0) { + sb.append(" compatible=true"); + } sb.append('}'); return sb.toString(); } @@ -987,13 +991,13 @@ public interface WindowManager extends ViewManager { * @hide */ public void scale(float scale) { - x *= scale; - y *= scale; + x = (int) (x * scale + 0.5f); + y = (int) (y * scale + 0.5f); if (width > 0) { - width *= scale; + width = (int) (width * scale + 0.5f); } if (height > 0) { - height *= scale; + height = (int) (height * scale + 0.5f); } } diff --git a/core/java/android/webkit/GearsPermissionsManager.java b/core/java/android/webkit/GearsPermissionsManager.java new file mode 100644 index 0000000000000..e70e449686208 --- /dev/null +++ b/core/java/android/webkit/GearsPermissionsManager.java @@ -0,0 +1,240 @@ +/* + * 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.webkit; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.database.ContentObserver; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; +import android.database.sqlite.SQLiteStatement; +import android.os.Handler; +import android.preference.PreferenceManager; +import android.provider.Settings; +import android.util.Log; + +import java.io.File; +import java.util.HashSet; + +/** + * Donut-specific hack to keep Gears permissions in sync with the + * system location setting. + */ +class GearsPermissionsManager { + // The application context. + Context mContext; + // The path to gears.so. + private String mGearsPath; + + // The Gears permissions database directory. + private final static String GEARS_DATABASE_DIR = "gears"; + // The Gears permissions database file name. + private final static String GEARS_DATABASE_FILE = "permissions.db"; + // The Gears location permissions table. + private final static String GEARS_LOCATION_ACCESS_TABLE_NAME = + "LocationAccess"; + // The Gears storage access permissions table. + private final static String GEARS_STORAGE_ACCESS_TABLE_NAME = "Access"; + // The Gears permissions db schema version table. + private final static String GEARS_SCHEMA_VERSION_TABLE_NAME = + "VersionInfo"; + // The Gears permission value that denotes "allow access to location". + private static final int GEARS_ALLOW_LOCATION_ACCESS = 1; + // The shared pref name. + private static final String LAST_KNOWN_LOCATION_SETTING = + "lastKnownLocationSystemSetting"; + // The Browser package name. + private static final String BROWSER_PACKAGE_NAME = "com.android.browser"; + // The Secure Settings observer that will be notified when the system + // location setting changes. + private SecureSettingsObserver mSettingsObserver; + // The Google URLs whitelisted for Gears location access. + private static HashSet sGearsWhiteList; + + static { + sGearsWhiteList = new HashSet(); + // NOTE: DO NOT ADD A "/" AT THE END! + sGearsWhiteList.add("http://www.google.com"); + sGearsWhiteList.add("http://www.google.co.uk"); + } + + private static final String LOGTAG = "webcore"; + static final boolean DEBUG = false; + static final boolean LOGV_ENABLED = DEBUG; + + GearsPermissionsManager(Context context, String gearsPath) { + mContext = context; + mGearsPath = gearsPath; + } + + public void doCheckAndStartObserver() { + // Are we running in the browser? + if (!BROWSER_PACKAGE_NAME.equals(mContext.getPackageName())) { + return; + } + // Do the check. + checkGearsPermissions(); + // Install the observer. + mSettingsObserver = new SecureSettingsObserver(); + mSettingsObserver.observe(); + } + + private void checkGearsPermissions() { + // Get the current system settings. + int setting = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.USE_LOCATION_FOR_SERVICES, -1); + // Check if we need to set the Gears permissions. + if (setting != -1 && locationSystemSettingChanged(setting)) { + setGearsPermissionForGoogleDomains(setting); + } + } + + private boolean locationSystemSettingChanged(int newSetting) { + SharedPreferences prefs = + PreferenceManager.getDefaultSharedPreferences(mContext); + int oldSetting = 0; + oldSetting = prefs.getInt(LAST_KNOWN_LOCATION_SETTING, oldSetting); + if (oldSetting == newSetting) { + return false; + } + Editor ed = prefs.edit(); + ed.putInt(LAST_KNOWN_LOCATION_SETTING, newSetting); + ed.commit(); + return true; + } + + private void setGearsPermissionForGoogleDomains(int systemPermission) { + // Transform the system permission into a boolean flag. When this + // flag is true, it means the origins in gGearsWhiteList are added + // to the Gears location permission table with permission 1 (allowed). + // When the flag is false, the origins in gGearsWhiteList are removed + // from the Gears location permission table. Next time the user + // navigates to one of these origins, she will see the normal Gears + // permission prompt. + boolean addToGearsLocationTable = (systemPermission == 1 ? true : false); + // Build the path to the Gears library. + + File file = new File(mGearsPath).getParentFile(); + if (file == null) { + return; + } + // Build the Gears database file name. + file = new File(file.getAbsolutePath() + File.separator + + GEARS_DATABASE_DIR + File.separator + GEARS_DATABASE_FILE); + // Remember whether or not we need to create the LocationAccess table. + boolean needToCreateTables = !file.exists(); + // If the database file does not yet exist and the system location + // setting says that the Gears origins need to be removed from the + // location permission table, it means that we don't actually need + // to do anything at all. + if (needToCreateTables && !addToGearsLocationTable) { + return; + } + // Try opening the Gears database. + SQLiteDatabase permissions; + try { + permissions = SQLiteDatabase.openOrCreateDatabase(file, null); + } catch (SQLiteException e) { + if (LOGV_ENABLED) { + Log.v(LOGTAG, "Could not open Gears permission DB: " + + e.getMessage()); + } + // Just bail out. + return; + } + // We now have a database open. Begin a transaction. + permissions.beginTransaction(); + try { + if (needToCreateTables) { + // Create the tables. Note that this creates the + // Gears tables for the permissions DB schema version 2. + // The Gears schema upgrade process will take care of the rest. + // First, the storage access table. + SQLiteStatement statement = permissions.compileStatement( + "CREATE TABLE IF NOT EXISTS " + + GEARS_STORAGE_ACCESS_TABLE_NAME + + " (Name TEXT UNIQUE, Value)"); + statement.execute(); + // Next the location access table. + statement = permissions.compileStatement( + "CREATE TABLE IF NOT EXISTS " + + GEARS_LOCATION_ACCESS_TABLE_NAME + + " (Name TEXT UNIQUE, Value)"); + statement.execute(); + // Finally, the schema version table. + statement = permissions.compileStatement( + "CREATE TABLE IF NOT EXISTS " + + GEARS_SCHEMA_VERSION_TABLE_NAME + + " (Name TEXT UNIQUE, Value)"); + statement.execute(); + // Set the schema version to 2. + ContentValues schema = new ContentValues(); + schema.put("Name", "Version"); + schema.put("Value", 2); + permissions.insert(GEARS_SCHEMA_VERSION_TABLE_NAME, null, + schema); + } + + if (addToGearsLocationTable) { + ContentValues permissionValues = new ContentValues(); + + for (String url : sGearsWhiteList) { + permissionValues.put("Name", url); + permissionValues.put("Value", GEARS_ALLOW_LOCATION_ACCESS); + permissions.replace(GEARS_LOCATION_ACCESS_TABLE_NAME, null, + permissionValues); + permissionValues.clear(); + } + } else { + for (String url : sGearsWhiteList) { + permissions.delete(GEARS_LOCATION_ACCESS_TABLE_NAME, "Name=?", + new String[] { url }); + } + } + // Commit the transaction. + permissions.setTransactionSuccessful(); + } catch (SQLiteException e) { + if (LOGV_ENABLED) { + Log.v(LOGTAG, "Could not set the Gears permissions: " + + e.getMessage()); + } + } finally { + permissions.endTransaction(); + permissions.close(); + } + } + + class SecureSettingsObserver extends ContentObserver { + SecureSettingsObserver() { + super(new Handler()); + } + + void observe() { + ContentResolver resolver = mContext.getContentResolver(); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.USE_LOCATION_FOR_SERVICES), false, this); + } + + @Override + public void onChange(boolean selfChange) { + checkGearsPermissions(); + } + } +} diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java index 39360cd72a23e..474fa82db2d74 100644 --- a/core/java/android/webkit/LoadListener.java +++ b/core/java/android/webkit/LoadListener.java @@ -38,6 +38,7 @@ import com.android.internal.R; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Vector; import java.util.regex.Pattern; @@ -72,7 +73,12 @@ class LoadListener extends Handler implements EventHandler { private static final int HTTP_NOT_FOUND = 404; private static final int HTTP_PROXY_AUTH = 407; - private static final String CERT_MIMETYPE = "application/x-x509-ca-cert"; + private static HashSet sCertificateMimeTypeMap; + static { + sCertificateMimeTypeMap = new HashSet(); + sCertificateMimeTypeMap.add("application/x-x509-ca-cert"); + sCertificateMimeTypeMap.add("application/x-pkcs12"); + } private static int sNativeLoaderCount; @@ -318,7 +324,17 @@ class LoadListener extends Handler implements EventHandler { if (mMimeType.equalsIgnoreCase("text/plain") || mMimeType.equalsIgnoreCase("application/octet-stream")) { - String newMimeType = guessMimeTypeFromExtension(); + // for attachment, use the filename in the Content-Disposition + // to guess the mimetype + String contentDisposition = headers.getContentDisposition(); + String url = null; + if (contentDisposition != null) { + url = URLUtil.parseContentDisposition(contentDisposition); + } + if (url == null) { + url = mUrl; + } + String newMimeType = guessMimeTypeFromExtension(url); if (newMimeType != null) { mMimeType = newMimeType; } @@ -936,7 +952,7 @@ class LoadListener extends Handler implements EventHandler { // This commits the headers without checking the response status code. private void commitHeaders() { - if (mIsMainPageLoader && CERT_MIMETYPE.equals(mMimeType)) { + if (mIsMainPageLoader && sCertificateMimeTypeMap.contains(mMimeType)) { // In the case of downloading certificate, we will save it to the // Keystore in commitLoad. Do not call webcore. return; @@ -982,7 +998,7 @@ class LoadListener extends Handler implements EventHandler { private void commitLoad() { if (mCancelled) return; - if (mIsMainPageLoader && CERT_MIMETYPE.equals(mMimeType)) { + if (mIsMainPageLoader && sCertificateMimeTypeMap.contains(mMimeType)) { // In the case of downloading certificate, we will save it to the // Keystore and stop the current loading so that it will not // generate a new history page @@ -1409,7 +1425,7 @@ class LoadListener extends Handler implements EventHandler { // of frames. If no content-type was specified, it is fine to // default to text/html. mMimeType = "text/html"; - String newMimeType = guessMimeTypeFromExtension(); + String newMimeType = guessMimeTypeFromExtension(mUrl); if (newMimeType != null) { mMimeType = newMimeType; } @@ -1419,15 +1435,15 @@ class LoadListener extends Handler implements EventHandler { /** * guess MIME type based on the file extension. */ - private String guessMimeTypeFromExtension() { + private String guessMimeTypeFromExtension(String url) { // PENDING: need to normalize url if (WebView.LOGV_ENABLED) { - Log.v(LOGTAG, "guessMimeTypeFromExtension: mURL = " + mUrl); + Log.v(LOGTAG, "guessMimeTypeFromExtension: url = " + url); } String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension( - MimeTypeMap.getFileExtensionFromUrl(mUrl)); + MimeTypeMap.getFileExtensionFromUrl(url)); if (mimeType != null) { // XXX: Until the servers send us either correct xhtml or diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java index 85c2275df9916..fdbc692bf271d 100644 --- a/core/java/android/webkit/MimeTypeMap.java +++ b/core/java/android/webkit/MimeTypeMap.java @@ -335,6 +335,7 @@ public /* package */ class MimeTypeMap { sMimeTypeMap.loadEntry("application/x-object", "o", false); sMimeTypeMap.loadEntry("application/x-oz-application", "oza", false); + sMimeTypeMap.loadEntry("application/x-pkcs12", "p12", false); sMimeTypeMap.loadEntry("application/x-pkcs7-certreqresp", "p7r", false); sMimeTypeMap.loadEntry("application/x-pkcs7-crl", "crl", false); diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java index d6ac3e9093bfc..9889fe9e8de00 100644 --- a/core/java/android/webkit/URLUtil.java +++ b/core/java/android/webkit/URLUtil.java @@ -348,7 +348,7 @@ public final class URLUtil { * This header provides a filename for content that is going to be * downloaded to the file system. We only support the attachment type. */ - private static String parseContentDisposition(String contentDisposition) { + static String parseContentDisposition(String contentDisposition) { try { Matcher m = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition); if (m.find()) { diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index ec671d5dac523..c5012f1a5ebfa 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -17,13 +17,13 @@ package android.webkit; import android.content.Context; +import android.content.pm.PackageManager; import android.os.Build; import android.os.Handler; import android.os.Message; import android.provider.Checkin; import java.lang.SecurityException; -import android.content.pm.PackageManager; import java.util.Locale; @@ -176,6 +176,9 @@ public class WebSettings { private boolean mBuiltInZoomControls = false; private boolean mAllowFileAccess = true; + // The Gears permissions manager. Only in Donut. + static GearsPermissionsManager sGearsPermissionsManager; + // Class to handle messages before WebCore is ready. private class EventHandler { // Message id for syncing @@ -1148,6 +1151,7 @@ public class WebSettings { if (WebView.DEBUG) { junit.framework.Assert.assertTrue(frame.mNativeFrame != 0); } + checkGearsPermissions(); nativeSync(frame.mNativeFrame); mSyncPending = false; mEventHandler.createHandler(); @@ -1163,6 +1167,23 @@ public class WebSettings { return size; } + private void checkGearsPermissions() { + // Did we already check the permissions at startup? + if (sGearsPermissionsManager != null) { + return; + } + // Is the pluginsPath sane? + String pluginsPath = getPluginsPath(); + if (pluginsPath == null || pluginsPath.length() == 0) { + // We don't yet have a meaningful plugin path, so + // we can't do anything about the Gears permissions. + return; + } + sGearsPermissionsManager = + new GearsPermissionsManager(mContext, pluginsPath); + sGearsPermissionsManager.doCheckAndStartObserver(); + } + /* Post a SYNC message to handle syncing the native settings. */ private synchronized void postSync() { // Only post if a sync is not pending diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index f9ca8cb7a43b4..777beed7ed138 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -720,7 +720,7 @@ public abstract class AbsListView extends AdapterView implements Te @Override public void getFocusedRect(Rect r) { View view = getSelectedView(); - if (view != null) { + if (view != null && view.getParent() == this) { // the focused rectangle of the selected view offset into the // coordinate space of this view. view.getFocusedRect(r); diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java index c4b5ef8915586..6579660011515 100755 --- a/core/java/android/widget/AppSecurityPermissions.java +++ b/core/java/android/widget/AppSecurityPermissions.java @@ -18,6 +18,7 @@ package android.widget; import com.android.internal.R; import android.content.Context; +import android.content.res.Resources; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageParser; @@ -319,15 +320,14 @@ public class AppSecurityPermissions implements View.OnClickListener { boolean dangerous) { View permView = mInflater.inflate(R.layout.app_permission_item, null); Drawable icon = dangerous ? mDangerousIcon : mNormalIcon; - int grpColor = dangerous ? R.color.perms_dangerous_grp_color : - R.color.perms_normal_grp_color; - int permColor = dangerous ? R.color.perms_dangerous_perm_color : - R.color.perms_normal_perm_color; TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group); TextView permDescView = (TextView) permView.findViewById(R.id.permission_list); - permGrpView.setTextColor(mContext.getResources().getColor(grpColor)); - permDescView.setTextColor(mContext.getResources().getColor(permColor)); + if (dangerous) { + final Resources resources = mContext.getResources(); + permGrpView.setTextColor(resources.getColor(R.color.perms_dangerous_grp_color)); + permDescView.setTextColor(resources.getColor(R.color.perms_dangerous_perm_color)); + } ImageView imgView = (ImageView)permView.findViewById(R.id.perm_icon); imgView.setImageDrawable(icon); diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index 675aba23ae812..4bc00de33e815 100644 --- a/core/java/android/widget/AutoCompleteTextView.java +++ b/core/java/android/widget/AutoCompleteTextView.java @@ -31,6 +31,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.WindowManager; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.EditorInfo; @@ -141,6 +142,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mPopup = new PopupWindow(context, attrs, com.android.internal.R.attr.autoCompleteTextViewStyle); + mPopup.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); TypedArray a = context.obtainStyledAttributes( @@ -208,8 +210,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe if (mDropDownAlwaysVisible && mPopup.isShowing() && mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED) { - mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); - showDropDown(); + ensureImeVisible(); } } @@ -1084,11 +1085,21 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe /** * Issues a runnable to show the dropdown as soon as possible. * - * @hide internal used only by Search Dialog + * @hide internal used only by SearchDialog */ public void showDropDownAfterLayout() { post(mShowDropDownRunnable); } + + /** + * Ensures that the drop down is not obscuring the IME. + * + * @hide internal used only here and SearchDialog + */ + public void ensureImeVisible() { + mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); + showDropDown(); + } /** *

    Displays the drop down on screen.

    @@ -1285,11 +1296,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe } } - // Max height available on the screen for a popup. If this AutoCompleteTextView has - // the dropDownAlwaysVisible attribute, and the input method is not currently required, - // we then we ask for the height ignoring any bottom decorations like the input method. - // Otherwise we respect the input method. - boolean ignoreBottomDecorations = mDropDownAlwaysVisible && + // Max height available on the screen for a popup. + boolean ignoreBottomDecorations = mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; final int maxHeight = mPopup.getMaxAvailableHeight( getDropDownAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations); diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java index 54f27072b4f93..3b9f1de4c66c9 100644 --- a/core/java/android/widget/DatePicker.java +++ b/core/java/android/widget/DatePicker.java @@ -110,6 +110,8 @@ public class DatePicker extends FrameLayout { * subtract by one to ensure our internal state is always 0-11 */ mMonth = newVal - 1; + // Adjust max day of the month + adjustMaxDay(); if (mOnDateChangedListener != null) { mOnDateChangedListener.onDateChanged(DatePicker.this, mYear, mMonth, mDay); } @@ -121,9 +123,12 @@ public class DatePicker extends FrameLayout { mYearPicker.setOnChangeListener(new OnChangedListener() { public void onChanged(NumberPicker picker, int oldVal, int newVal) { mYear = newVal; + // Adjust max day for leap years if needed + adjustMaxDay(); if (mOnDateChangedListener != null) { mOnDateChangedListener.onDateChanged(DatePicker.this, mYear, mMonth, mDay); } + updateDaySpinner(); } }); @@ -318,4 +323,14 @@ public class DatePicker extends FrameLayout { public int getDayOfMonth() { return mDay; } + + private void adjustMaxDay(){ + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.YEAR, mYear); + cal.set(Calendar.MONTH, mMonth); + int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH); + if (mDay > max) { + mDay = max; + } + } } diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java index cd965fc62e626..2da777a47920c 100644 --- a/core/java/android/widget/FastScroller.java +++ b/core/java/android/widget/FastScroller.java @@ -26,6 +26,7 @@ import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.SystemClock; +import android.util.TypedValue; import android.view.MotionEvent; /** @@ -116,17 +117,19 @@ class FastScroller { mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX); } - private void useThumbDrawable(Drawable drawable) { + private void useThumbDrawable(Context context, Drawable drawable) { mThumbDrawable = drawable; - mThumbW = 64; //mCurrentThumb.getIntrinsicWidth(); - mThumbH = 52; //mCurrentThumb.getIntrinsicHeight(); + mThumbW = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + 64, context.getResources().getDisplayMetrics()); + mThumbH = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + 52, context.getResources().getDisplayMetrics()); mChangedBounds = true; } private void init(Context context) { // Get both the scrollbar states drawables final Resources res = context.getResources(); - useThumbDrawable(res.getDrawable( + useThumbDrawable(context, res.getDrawable( com.android.internal.R.drawable.scrollbar_handle_accelerated_anim2)); mOverlayDrawable = res.getDrawable( diff --git a/core/java/android/widget/Filter.java b/core/java/android/widget/Filter.java index 7e55c78a39b30..d901540273275 100644 --- a/core/java/android/widget/Filter.java +++ b/core/java/android/widget/Filter.java @@ -46,6 +46,8 @@ public abstract class Filter { private Handler mThreadHandler; private Handler mResultHandler; + private Delayer mDelayer; + private final Object mLock = new Object(); /** @@ -55,6 +57,20 @@ public abstract class Filter { mResultHandler = new ResultsHandler(); } + /** + * Provide an interface that decides how long to delay the message for a given query. Useful + * for heuristics such as posting a delay for the delete key to avoid doing any work while the + * user holds down the delete key. + * + * @param delayer The delayer. + * @hide + */ + public void setDelayer(Delayer delayer) { + synchronized (mLock) { + mDelayer = delayer; + } + } + /** *

    Starts an asynchronous filtering operation. Calling this method * cancels all previous non-executed filtering requests and posts a new @@ -85,10 +101,13 @@ public abstract class Filter { public final void filter(CharSequence constraint, FilterListener listener) { synchronized (mLock) { if (mThreadHandler == null) { - HandlerThread thread = new HandlerThread(THREAD_NAME); + HandlerThread thread = new HandlerThread( + THREAD_NAME, android.os.Process.THREAD_PRIORITY_BACKGROUND); thread.start(); mThreadHandler = new RequestHandler(thread.getLooper()); } + + final long delay = (mDelayer == null) ? 0 : mDelayer.getPostingDelay(constraint); Message message = mThreadHandler.obtainMessage(FILTER_TOKEN); @@ -101,7 +120,7 @@ public abstract class Filter { mThreadHandler.removeMessages(FILTER_TOKEN); mThreadHandler.removeMessages(FINISH_TOKEN); - mThreadHandler.sendMessage(message); + mThreadHandler.sendMessageDelayed(message, delay); } } @@ -288,4 +307,17 @@ public abstract class Filter { */ FilterResults results; } + + /** + * @hide + */ + public interface Delayer { + + /** + * @param constraint The constraint passed to {@link Filter#filter(CharSequence)} + * @return The delay that should be used for + * {@link Handler#sendMessageDelayed(android.os.Message, long)} + */ + long getPostingDelay(CharSequence constraint); + } } diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index f86b37cf8b3ad..46e514c8b44e9 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -286,18 +286,20 @@ public class HorizontalScrollView extends FrameLayout { return; } - final View child = getChildAt(0); - int width = getMeasuredWidth(); - if (child.getMeasuredWidth() < width) { - final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams(); - - int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, mPaddingTop - + mPaddingBottom, lp.height); - width -= mPaddingLeft; - width -= mPaddingRight; - int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY); - - child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + if (getChildCount() > 0) { + final View child = getChildAt(0); + int width = getMeasuredWidth(); + if (child.getMeasuredWidth() < width) { + final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, mPaddingTop + + mPaddingBottom, lp.height); + width -= mPaddingLeft; + width -= mPaddingRight; + int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY); + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } } } @@ -636,7 +638,7 @@ public class HorizontalScrollView extends FrameLayout { mTempRect.left = getScrollX() + width; int count = getChildCount(); if (count > 0) { - View view = getChildAt(count - 1); + View view = getChildAt(0); if (mTempRect.left + width > view.getRight()) { mTempRect.left = view.getRight() - width; } @@ -674,7 +676,7 @@ public class HorizontalScrollView extends FrameLayout { if (right) { int count = getChildCount(); if (count > 0) { - View view = getChildAt(count - 1); + View view = getChildAt(0); mTempRect.right = view.getRight(); mTempRect.left = mTempRect.right - width; } @@ -751,9 +753,9 @@ public class HorizontalScrollView extends FrameLayout { if (direction == View.FOCUS_LEFT && getScrollX() < scrollDelta) { scrollDelta = getScrollX(); - } else if (direction == View.FOCUS_RIGHT) { - - int daRight = getChildAt(getChildCount() - 1).getRight(); + } else if (direction == View.FOCUS_RIGHT && getChildCount() > 0) { + + int daRight = getChildAt(0).getRight(); int screenRight = getScrollX() + getWidth(); @@ -975,6 +977,7 @@ public class HorizontalScrollView extends FrameLayout { * @return The scroll delta. */ protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) { + if (getChildCount() == 0) return 0; int width = getWidth(); int screenLeft = getScrollX(); @@ -1008,7 +1011,7 @@ public class HorizontalScrollView extends FrameLayout { } // make sure we aren't scrolling beyond the end of our content - int right = getChildAt(getChildCount() - 1).getRight(); + int right = getChildAt(0).getRight(); int distanceToRight = right - screenRight; scrollXDelta = Math.min(scrollXDelta, distanceToRight); @@ -1148,27 +1151,29 @@ public class HorizontalScrollView extends FrameLayout { * which means we want to scroll towards the left. */ public void fling(int velocityX) { - int width = getWidth() - mPaddingRight - mPaddingLeft; - int right = getChildAt(0).getWidth(); - - mScroller.fling(mScrollX, mScrollY, velocityX, 0, 0, right - width, 0, 0); - - final boolean movingRight = velocityX > 0; - - View newFocused = findFocusableViewInMyBounds(movingRight, - mScroller.getFinalX(), findFocus()); - - if (newFocused == null) { - newFocused = this; + if (getChildCount() > 0) { + int width = getWidth() - mPaddingRight - mPaddingLeft; + int right = getChildAt(0).getWidth(); + + mScroller.fling(mScrollX, mScrollY, velocityX, 0, 0, right - width, 0, 0); + + final boolean movingRight = velocityX > 0; + + View newFocused = findFocusableViewInMyBounds(movingRight, + mScroller.getFinalX(), findFocus()); + + if (newFocused == null) { + newFocused = this; + } + + if (newFocused != findFocus() + && newFocused.requestFocus(movingRight ? View.FOCUS_RIGHT : View.FOCUS_LEFT)) { + mScrollViewMovedFocus = true; + mScrollViewMovedFocus = false; + } + + invalidate(); } - - if (newFocused != findFocus() - && newFocused.requestFocus(movingRight ? View.FOCUS_RIGHT : View.FOCUS_LEFT)) { - mScrollViewMovedFocus = true; - mScrollViewMovedFocus = false; - } - - invalidate(); } /** diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 0c2cd55d2ee37..90fbb77d255e8 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -27,7 +27,6 @@ import android.view.WindowManager; import android.view.Gravity; import android.view.ViewGroup; import android.view.ViewTreeObserver; -import android.view.WindowManagerImpl; import android.view.ViewTreeObserver.OnScrollChangedListener; import android.view.View.OnTouchListener; import android.graphics.PixelFormat; @@ -82,6 +81,7 @@ public class PopupWindow { private View mPopupView; private boolean mFocusable; private int mInputMethodMode = INPUT_METHOD_FROM_FOCUSABLE; + private int mSoftInputMode; private boolean mTouchable = true; private boolean mOutsideTouchable = false; private boolean mClippingEnabled = true; @@ -446,6 +446,30 @@ public class PopupWindow { public void setInputMethodMode(int mode) { mInputMethodMode = mode; } + + /** + * Sets the operating mode for the soft input area. + * + * @param mode The desired mode, see + * {@link android.view.WindowManager.LayoutParams#softInputMode} + * for the full list + * + * @see android.view.WindowManager.LayoutParams#softInputMode + * @see #getSoftInputMode() + */ + public void setSoftInputMode(int mode) { + mSoftInputMode = mode; + } + + /** + * Returns the current value in {@link #setSoftInputMode(int)}. + * + * @see #setSoftInputMode(int) + * @see android.view.WindowManager.LayoutParams#softInputMode + */ + public int getSoftInputMode() { + return mSoftInputMode; + } /** *

    Indicates whether the popup window receives touch events.

    @@ -822,7 +846,7 @@ public class PopupWindow { p.flags = computeFlags(p.flags); p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; p.token = token; - p.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; + p.softInputMode = mSoftInputMode; p.setTitle("PopupWindow:" + Integer.toHexString(hashCode())); return p; diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index e62dda58ba423..24c0e2a4a2d9b 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -1295,11 +1295,8 @@ public class RelativeLayout extends ViewGroup { if (rule > 0) { // The node this node depends on final Node dependency = keyNodes.get(rule); - if (dependency == node) { - throw new IllegalStateException("A view cannot have a dependency" + - " on itself"); - } - if (dependency == null) { + // Skip unknowns and self dependencies + if (dependency == null || dependency == node) { continue; } // Add the current node as a dependent diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 90e1242396f3f..703cd8e278b7e 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -20,8 +20,6 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; import android.util.AttributeSet; -import android.util.Config; -import android.util.Log; import android.view.FocusFinder; import android.view.KeyEvent; import android.view.MotionEvent; @@ -54,7 +52,6 @@ import java.util.List; */ public class ScrollView extends FrameLayout { static final String TAG = "ScrollView"; - static final boolean localLOGV = false || Config.LOGV; static final int ANIMATED_SCROLL_GAP = 250; @@ -287,18 +284,21 @@ public class ScrollView extends FrameLayout { return; } - final View child = getChildAt(0); - int height = getMeasuredHeight(); - if (child.getMeasuredHeight() < height) { - final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams(); - - int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, mPaddingLeft - + mPaddingRight, lp.width); - height -= mPaddingTop; - height -= mPaddingBottom; - int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); - - child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + if (getChildCount() > 0) { + final View child = getChildAt(0); + int height = getMeasuredHeight(); + if (child.getMeasuredHeight() < height) { + final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, mPaddingLeft + + mPaddingRight, lp.width); + height -= mPaddingTop; + height -= mPaddingBottom; + int childHeightMeasureSpec = + MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } } } @@ -756,13 +756,14 @@ public class ScrollView extends FrameLayout { if (direction == View.FOCUS_UP && getScrollY() < scrollDelta) { scrollDelta = getScrollY(); } else if (direction == View.FOCUS_DOWN) { - - int daBottom = getChildAt(getChildCount() - 1).getBottom(); - - int screenBottom = getScrollY() + getHeight(); - - if (daBottom - screenBottom < maxJump) { - scrollDelta = daBottom - screenBottom; + if (getChildCount() > 0) { + int daBottom = getChildAt(0).getBottom(); + + int screenBottom = getScrollY() + getHeight(); + + if (daBottom - screenBottom < maxJump) { + scrollDelta = daBottom - screenBottom; + } } } if (scrollDelta == 0) { @@ -830,16 +831,12 @@ public class ScrollView extends FrameLayout { public final void smoothScrollBy(int dx, int dy) { long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll; if (duration > ANIMATED_SCROLL_GAP) { - if (localLOGV) Log.v(TAG, "Smooth scroll: mScrollY=" + mScrollY - + " dy=" + dy); mScroller.startScroll(mScrollX, mScrollY, dx, dy); invalidate(); } else { if (!mScroller.isFinished()) { mScroller.abortAnimation(); } - if (localLOGV) Log.v(TAG, "Immediate scroll: mScrollY=" + mScrollY - + " dy=" + dy); scrollBy(dx, dy); } mLastScroll = AnimationUtils.currentAnimationTimeMillis(); @@ -922,9 +919,6 @@ public class ScrollView extends FrameLayout { View child = getChildAt(0); mScrollX = clamp(x, getWidth() - mPaddingRight - mPaddingLeft, child.getWidth()); mScrollY = clamp(y, getHeight() - mPaddingBottom - mPaddingTop, child.getHeight()); - if (localLOGV) Log.v(TAG, "mScrollY=" + mScrollY + " y=" + y - + " height=" + this.getHeight() - + " child height=" + child.getHeight()); } else { mScrollX = x; mScrollY = y; @@ -986,6 +980,7 @@ public class ScrollView extends FrameLayout { * @return The scroll delta. */ protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) { + if (getChildCount() == 0) return 0; int height = getHeight(); int screenTop = getScrollY(); @@ -1005,9 +1000,6 @@ public class ScrollView extends FrameLayout { int scrollYDelta = 0; - if (localLOGV) Log.v(TAG, "child=" + rect.toShortString() - + " screenTop=" + screenTop + " screenBottom=" + screenBottom - + " height=" + height); if (rect.bottom > screenBottom && rect.top > screenTop) { // need to move down to get it in view: move down just enough so // that the entire rectangle is in view (or at least the first @@ -1022,10 +1014,8 @@ public class ScrollView extends FrameLayout { } // make sure we aren't scrolling beyond the end of our content - int bottom = getChildAt(getChildCount() - 1).getBottom(); + int bottom = getChildAt(0).getBottom(); int distanceToBottom = bottom - screenBottom; - if (localLOGV) Log.v(TAG, "scrollYDelta=" + scrollYDelta - + " distanceToBottom=" + distanceToBottom); scrollYDelta = Math.min(scrollYDelta, distanceToBottom); } else if (rect.top < screenTop && rect.bottom < screenBottom) { @@ -1164,26 +1154,28 @@ public class ScrollView extends FrameLayout { * which means we want to scroll towards the top. */ public void fling(int velocityY) { - int height = getHeight() - mPaddingBottom - mPaddingTop; - int bottom = getChildAt(0).getHeight(); - - mScroller.fling(mScrollX, mScrollY, 0, velocityY, 0, 0, 0, bottom - height); - - final boolean movingDown = velocityY > 0; - - View newFocused = - findFocusableViewInMyBounds(movingDown, mScroller.getFinalY(), findFocus()); - if (newFocused == null) { - newFocused = this; + if (getChildCount() > 0) { + int height = getHeight() - mPaddingBottom - mPaddingTop; + int bottom = getChildAt(0).getHeight(); + + mScroller.fling(mScrollX, mScrollY, 0, velocityY, 0, 0, 0, bottom - height); + + final boolean movingDown = velocityY > 0; + + View newFocused = + findFocusableViewInMyBounds(movingDown, mScroller.getFinalY(), findFocus()); + if (newFocused == null) { + newFocused = this; + } + + if (newFocused != findFocus() + && newFocused.requestFocus(movingDown ? View.FOCUS_DOWN : View.FOCUS_UP)) { + mScrollViewMovedFocus = true; + mScrollViewMovedFocus = false; + } + + invalidate(); } - - if (newFocused != findFocus() - && newFocused.requestFocus(movingDown ? View.FOCUS_DOWN : View.FOCUS_UP)) { - mScrollViewMovedFocus = true; - mScrollViewMovedFocus = false; - } - - invalidate(); } /** diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java index 80d688ef27932..bcddca18009ea 100644 --- a/core/java/android/widget/Spinner.java +++ b/core/java/android/widget/Spinner.java @@ -24,7 +24,6 @@ import android.content.DialogInterface.OnClickListener; import android.content.res.TypedArray; import android.database.DataSetObserver; import android.util.AttributeSet; -import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; @@ -40,6 +39,7 @@ import android.view.ViewGroup; public class Spinner extends AbsSpinner implements OnClickListener { private CharSequence mPrompt; + private AlertDialog mPopup; public Spinner(Context context) { this(context, null); @@ -78,6 +78,16 @@ public class Spinner extends AbsSpinner implements OnClickListener { } } + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + if (mPopup != null && mPopup.isShowing()) { + mPopup.dismiss(); + mPopup = null; + } + } + /** *

    A spinner does not support item click events. Calling this method * will raise an exception.

    @@ -244,7 +254,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { if (mPrompt != null) { builder.setTitle(mPrompt); } - builder.setSingleChoiceItems(adapter, getSelectedItemPosition(), this).show(); + mPopup = builder.setSingleChoiceItems(adapter, getSelectedItemPosition(), this).show(); } return handled; @@ -253,6 +263,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { public void onClick(DialogInterface dialog, int which) { setSelection(which); dialog.dismiss(); + mPopup = null; } /** diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index d8ed4f0e4e86c..3fab6929caa51 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -2443,7 +2443,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (ss.error != null) { - setError(ss.error); + final CharSequence error = ss.error; + // Display the error later, after the first layout pass + post(new Runnable() { + public void run() { + setError(error); + } + }); } } @@ -3263,7 +3269,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final TextView err = (TextView) inflater.inflate(com.android.internal.R.layout.textview_hint, null); - mPopup = new ErrorPopup(err, 200, 50); + final float scale = getResources().getDisplayMetrics().density; + mPopup = new ErrorPopup(err, (int) (200 * scale + 0.5f), + (int) (50 * scale + 0.5f)); mPopup.setFocusable(false); // The user is entering text, so the input method is needed. We // don't want the popup to be displayed on top of it. @@ -3317,11 +3325,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * The "25" is the distance between the point and the right edge * of the background */ + final float scale = getResources().getDisplayMetrics().density; final Drawables dr = mDrawables; return getWidth() - mPopup.getWidth() - getPaddingRight() - - (dr != null ? dr.mDrawableSizeRight : 0) / 2 + 25; + - (dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f); } /** diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index 670692f552dfb..df957ac5d0786 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -65,6 +65,7 @@ public class Toast { */ public static final int LENGTH_LONG = 1; + final Handler mHandler = new Handler(); final Context mContext; final TN mTN; int mDuration; @@ -84,7 +85,7 @@ public class Toast { */ public Toast(Context context) { mContext = context; - mTN = new TN(context); + mTN = new TN(); mY = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.toast_y_offset); } @@ -229,7 +230,8 @@ public class Toast { public static Toast makeText(Context context, CharSequence text, int duration) { Toast result = new Toast(context); - LayoutInflater inflate = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + LayoutInflater inflate = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null); TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message); tv.setText(text); @@ -286,8 +288,7 @@ public class Toast { private static INotificationManager sService; - static private INotificationManager getService() - { + static private INotificationManager getService() { if (sService != null) { return sService; } @@ -295,28 +296,42 @@ public class Toast { return sService; } - private class TN extends ITransientNotification.Stub - { - TN(Context context) - { + private class TN extends ITransientNotification.Stub { + final Runnable mShow = new Runnable() { + public void run() { + handleShow(); + } + }; + + final Runnable mHide = new Runnable() { + public void run() { + handleHide(); + } + }; + + private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(); + + WindowManagerImpl mWM; + + TN() { // XXX This should be changed to use a Dialog, with a Theme.Toast // defined that sets up the layout params appropriately. - mParams.height = WindowManager.LayoutParams.WRAP_CONTENT; - mParams.width = WindowManager.LayoutParams.WRAP_CONTENT; - mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + final WindowManager.LayoutParams params = mParams; + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + params.width = WindowManager.LayoutParams.WRAP_CONTENT; + params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; - mParams.format = PixelFormat.TRANSLUCENT; - mParams.windowAnimations = com.android.internal.R.style.Animation_Toast; - mParams.type = WindowManager.LayoutParams.TYPE_TOAST; - mParams.setTitle("Toast"); + params.format = PixelFormat.TRANSLUCENT; + params.windowAnimations = com.android.internal.R.style.Animation_Toast; + params.type = WindowManager.LayoutParams.TYPE_TOAST; + params.setTitle("Toast"); } /** * schedule handleShow into the right thread */ - public void show() - { + public void show() { if (localLOGV) Log.v(TAG, "SHOW: " + this); mHandler.post(mShow); } @@ -324,14 +339,12 @@ public class Toast { /** * schedule handleHide into the right thread */ - public void hide() - { + public void hide() { if (localLOGV) Log.v(TAG, "HIDE: " + this); mHandler.post(mHide); } - public void handleShow() - { + public void handleShow() { if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView + " mNextView=" + mNextView); if (mView != mNextView) { @@ -361,8 +374,7 @@ public class Toast { } } - public void handleHide() - { + public void handleHide() { if (localLOGV) Log.v(TAG, "HANDLE HIDE: " + this + " mView=" + mView); if (mView != null) { // note: checking parent() just to make sure the view has @@ -377,24 +389,5 @@ public class Toast { mView = null; } } - - Runnable mShow = new Runnable() { - public void run() { - handleShow(); - } - }; - - Runnable mHide = new Runnable() { - public void run() { - handleHide(); - } - }; - - private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(); - - WindowManagerImpl mWM; } - - final Handler mHandler = new Handler(); } - diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index a03802dff0128..a449e5f00919a 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -16,6 +16,7 @@ package com.android.internal.os; +import android.bluetooth.BluetoothHeadset; import android.os.BatteryStats; import android.os.NetStat; import android.os.Parcel; @@ -128,7 +129,10 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mBluetoothOn; StopwatchTimer mBluetoothOnTimer; - + + /** Bluetooth headset object */ + BluetoothHeadset mBtHeadset; + /** * These provide time bases that discount the time the device is plugged * in to power. @@ -160,6 +164,9 @@ public final class BatteryStatsImpl extends BatteryStats { private long mRadioDataUptime; private long mRadioDataStart; + private int mBluetoothPingCount; + private int mBluetoothPingStart = -1; + /* * Holds a SamplingTimer associated with each kernel wakelock name being tracked. */ @@ -920,14 +927,18 @@ public final class BatteryStatsImpl extends BatteryStats { dataTransfer[STATS_UNPLUGGED] = currentBytes; } - private long getCurrentRadioDataUptimeMs() { + /** + * Radio uptime in microseconds when transferring data. This value is very approximate. + * @return + */ + private long getCurrentRadioDataUptime() { try { File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms"); if (!awakeTimeFile.exists()) return 0; BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile)); String line = br.readLine(); br.close(); - return Long.parseLong(line); + return Long.parseLong(line) * 1000; } catch (NumberFormatException nfe) { // Nothing } catch (IOException ioe) { @@ -936,14 +947,44 @@ public final class BatteryStatsImpl extends BatteryStats { return 0; } + /** + * @deprecated use getRadioDataUptime + */ public long getRadioDataUptimeMs() { + return getRadioDataUptime() / 1000; + } + + /** + * Returns the duration that the cell radio was up for data transfers. + */ + public long getRadioDataUptime() { if (mRadioDataStart == -1) { return mRadioDataUptime; } else { - return getCurrentRadioDataUptimeMs() - mRadioDataStart; + return getCurrentRadioDataUptime() - mRadioDataStart; } } + private int getCurrentBluetoothPingCount() { + if (mBtHeadset != null) { + return mBtHeadset.getBatteryUsageHint(); + } + return -1; + } + + public int getBluetoothPingCount() { + if (mBluetoothPingStart == -1) { + return mBluetoothPingCount; + } else if (mBtHeadset != null) { + return getCurrentBluetoothPingCount() - mBluetoothPingStart; + } + return -1; + } + + public void setBtHeadset(BluetoothHeadset headset) { + mBtHeadset = headset; + } + public void doUnplug(long batteryUptime, long batteryRealtime) { for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { Uid u = mUidStats.valueAt(iu); @@ -961,8 +1002,11 @@ public final class BatteryStatsImpl extends BatteryStats { doDataUnplug(mTotalDataRx, NetStat.getTotalRxBytes()); doDataUnplug(mTotalDataTx, NetStat.getTotalTxBytes()); // Track radio awake time - mRadioDataStart = getCurrentRadioDataUptimeMs(); + mRadioDataStart = getCurrentRadioDataUptime(); mRadioDataUptime = 0; + // Track bt headset ping count + mBluetoothPingStart = getCurrentBluetoothPingCount(); + mBluetoothPingCount = 0; } public void doPlug(long batteryUptime, long batteryRealtime) { @@ -985,8 +1029,12 @@ public final class BatteryStatsImpl extends BatteryStats { doDataPlug(mTotalDataRx, NetStat.getTotalRxBytes()); doDataPlug(mTotalDataTx, NetStat.getTotalTxBytes()); // Track radio awake time - mRadioDataUptime = getRadioDataUptimeMs(); + mRadioDataUptime = getRadioDataUptime(); mRadioDataStart = -1; + + // Track bt headset ping count + mBluetoothPingCount = getBluetoothPingCount(); + mBluetoothPingStart = -1; } public void noteStartGps(int uid) { @@ -3335,6 +3383,9 @@ public final class BatteryStatsImpl extends BatteryStats { mRadioDataUptime = in.readLong(); mRadioDataStart = -1; + mBluetoothPingCount = in.readInt(); + mBluetoothPingStart = -1; + mKernelWakelockStats.clear(); int NKW = in.readInt(); for (int ikw = 0; ikw < NKW; ikw++) { @@ -3415,7 +3466,9 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(getTotalTcpBytesSent(STATS_UNPLUGGED)); // Write radio uptime for data - out.writeLong(getRadioDataUptimeMs()); + out.writeLong(getRadioDataUptime()); + + out.writeInt(getBluetoothPingCount()); out.writeInt(mKernelWakelockStats.size()); for (Map.Entry ent : mKernelWakelockStats.entrySet()) { diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java index 4a8d8b182f903..94f703add4692 100644 --- a/core/java/com/android/internal/os/PowerProfile.java +++ b/core/java/com/android/internal/os/PowerProfile.java @@ -86,6 +86,11 @@ public class PowerProfile { */ public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active"; + /** + * Power consumption when Bluetooth driver gets an AT command. + */ + public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at"; + /** * Power consumption when screen is on, not including the backlight power. */ diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java index 7f99ac84eb493..53be8911f3754 100644 --- a/core/java/com/android/internal/widget/LockPatternView.java +++ b/core/java/com/android/internal/widget/LockPatternView.java @@ -20,23 +20,22 @@ package com.android.internal.widget; import com.android.internal.R; import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Rect; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; +import android.os.Debug; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; -import android.os.Debug; import android.os.Vibrator; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; -import android.view.WindowManager; import java.util.ArrayList; import java.util.List; @@ -393,17 +392,9 @@ public class LockPatternView extends View { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final WindowManager wm = (WindowManager) getContext() - .getSystemService(Context.WINDOW_SERVICE); - final int width = wm.getDefaultDisplay().getWidth(); - final int height = wm.getDefaultDisplay().getHeight(); - int squareSide = Math.min(width, height); - - // if in landscape... - if (width > height) { - squareSide -= STATUS_BAR_HEIGHT; - } - + final int width = MeasureSpec.getSize(widthMeasureSpec); + final int height = MeasureSpec.getSize(heightMeasureSpec); + final int squareSide = Math.min(width, height); setMeasuredDimension(squareSide, squareSide); } diff --git a/core/java/com/android/internal/widget/NumberPicker.java b/core/java/com/android/internal/widget/NumberPicker.java index 2f08c8dd424b4..0424ced5c76e5 100644 --- a/core/java/com/android/internal/widget/NumberPicker.java +++ b/core/java/com/android/internal/widget/NumberPicker.java @@ -243,9 +243,11 @@ public class NumberPicker extends LinearLayout implements OnClickListener, private void validateCurrentView(CharSequence str) { int val = getSelectedPos(str.toString()); if ((val >= mStart) && (val <= mEnd)) { - mPrevious = mCurrent; - mCurrent = val; - notifyChange(); + if (mCurrent != val) { + mPrevious = mCurrent; + mCurrent = val; + notifyChange(); + } } updateView(); } diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index af8ecf5cccc34..3fb07a74a6f6f 100644 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -224,7 +224,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, SkBitmap bitmap; bitmap.setConfig(config, width, height); - if (!GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL)) { + if (!GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL, true)) { return NULL; } @@ -240,7 +240,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src, SkBitmap::Config dstConfig, jboolean isMutable) { SkBitmap result; - JavaPixelAllocator allocator(env); + JavaPixelAllocator allocator(env, true); if (!src->copyTo(&result, dstConfig, &allocator)) { return NULL; @@ -356,7 +356,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { } } - if (!GraphicsJNI::setJavaPixelRef(env, bitmap, ctable)) { + if (!GraphicsJNI::setJavaPixelRef(env, bitmap, ctable, true)) { ctable->safeUnref(); delete bitmap; return NULL; diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 137707fa93bf5..0c842650962fb 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -23,6 +23,7 @@ static jfieldID gOptions_configFieldID; static jfieldID gOptions_ditherFieldID; static jfieldID gOptions_purgeableFieldID; static jfieldID gOptions_shareableFieldID; +static jfieldID gOptions_nativeAllocFieldID; static jfieldID gOptions_widthFieldID; static jfieldID gOptions_heightFieldID; static jfieldID gOptions_mimeFieldID; @@ -300,6 +301,11 @@ static bool optionsShareable(JNIEnv* env, jobject options) { env->GetBooleanField(options, gOptions_shareableFieldID); } +static bool optionsReportSizeToVM(JNIEnv* env, jobject options) { + return NULL == options || + !env->GetBooleanField(options, gOptions_nativeAllocFieldID); +} + static jobject nullObjectReturn(const char msg[]) { if (msg) { SkDebugf("--- %s\n", msg); @@ -330,6 +336,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, SkBitmap::Config prefConfig = SkBitmap::kNo_Config; bool doDither = true; bool isPurgeable = allowPurgeable && optionsPurgeable(env, options); + bool reportSizeToVM = optionsReportSizeToVM(env, options); if (NULL != options) { sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID); @@ -355,7 +362,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, decoder->setDitherImage(doDither); NinePatchPeeker peeker; - JavaPixelAllocator javaAllocator(env); + JavaPixelAllocator javaAllocator(env, reportSizeToVM); SkBitmap* bitmap = new SkBitmap; Res_png_9patch dummy9Patch; @@ -699,6 +706,7 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) { gOptions_ditherFieldID = getFieldIDCheck(env, gOptions_class, "inDither", "Z"); gOptions_purgeableFieldID = getFieldIDCheck(env, gOptions_class, "inPurgeable", "Z"); gOptions_shareableFieldID = getFieldIDCheck(env, gOptions_class, "inInputShareable", "Z"); + gOptions_nativeAllocFieldID = getFieldIDCheck(env, gOptions_class, "inNativeAlloc", "Z"); gOptions_widthFieldID = getFieldIDCheck(env, gOptions_class, "outWidth", "I"); gOptions_heightFieldID = getFieldIDCheck(env, gOptions_class, "outHeight", "I"); gOptions_mimeFieldID = getFieldIDCheck(env, gOptions_class, "outMimeType", "Ljava/lang/String;"); diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 6eebbdcfb5636..6e159a8853d59 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -5,6 +5,7 @@ #include "SkRegion.h" #include +//#define REPORT_SIZE_TO_JVM //#define TRACK_LOCK_COUNT void doThrow(JNIEnv* env, const char* exc, const char* msg) { @@ -444,7 +445,7 @@ private: }; bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, - SkColorTable* ctable) { + SkColorTable* ctable, bool reportSizeToVM) { Sk64 size64 = bitmap->getSize64(); if (size64.isNeg() || !size64.is32()) { doThrow(env, "java/lang/IllegalArgumentException", @@ -453,35 +454,41 @@ bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, } size_t size = size64.get32(); - // SkDebugf("-------------- inform VM we've allocated %d bytes\n", size); jlong jsize = size; // the VM wants longs for the size - bool r = env->CallBooleanMethod(gVMRuntime_singleton, - gVMRuntime_trackExternalAllocationMethodID, - jsize); - if (GraphicsJNI::hasException(env)) { - return false; + if (reportSizeToVM) { + // SkDebugf("-------------- inform VM we've allocated %d bytes\n", size); + bool r = env->CallBooleanMethod(gVMRuntime_singleton, + gVMRuntime_trackExternalAllocationMethodID, + jsize); + if (GraphicsJNI::hasException(env)) { + return false; + } + if (!r) { + LOGE("VM won't let us allocate %zd bytes\n", size); + doThrowOOME(env, "bitmap size exceeds VM budget"); + return false; + } } - if (!r) { - LOGE("VM won't let us allocate %zd bytes\n", size); - doThrowOOME(env, "bitmap size exceeds VM budget"); - return false; - } - // call the version of malloc that returns null on failure void* addr = sk_malloc_flags(size, 0); if (NULL == addr) { - // SkDebugf("-------------- inform VM we're releasing %d bytes which we couldn't allocate\n", size); - // we didn't actually allocate it, so inform the VM - env->CallVoidMethod(gVMRuntime_singleton, - gVMRuntime_trackExternalFreeMethodID, - jsize); - if (!GraphicsJNI::hasException(env)) { - doThrowOOME(env, "bitmap size too large for malloc"); + if (reportSizeToVM) { + // SkDebugf("-------------- inform VM we're releasing %d bytes which we couldn't allocate\n", size); + // we didn't actually allocate it, so inform the VM + env->CallVoidMethod(gVMRuntime_singleton, + gVMRuntime_trackExternalFreeMethodID, + jsize); + if (!GraphicsJNI::hasException(env)) { + doThrowOOME(env, "bitmap size too large for malloc"); + } } return false; } - bitmap->setPixelRef(new AndroidPixelRef(env, addr, size, ctable))->unref(); + SkPixelRef* pr = reportSizeToVM ? + new AndroidPixelRef(env, addr, size, ctable) : + new SkMallocPixelRef(addr, size, ctable); + bitmap->setPixelRef(pr)->unref(); // since we're already allocated, we lockPixels right away // HeapAllocator behaves this way too bitmap->lockPixels(); @@ -490,12 +497,11 @@ bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, /////////////////////////////////////////////////////////////////////////////// -JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env) : fEnv(env) -{ -} +JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env, bool reportSizeToVM) + : fEnv(env), fReportSizeToVM(reportSizeToVM) {} bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) { - return GraphicsJNI::setJavaPixelRef(fEnv, bitmap, ctable); + return GraphicsJNI::setJavaPixelRef(fEnv, bitmap, ctable, fReportSizeToVM); } //////////////////////////////////////////////////////////////////////////////// diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h index e2dc9acf1beb3..16925e41ab4f3 100644 --- a/core/jni/android/graphics/GraphicsJNI.h +++ b/core/jni/android/graphics/GraphicsJNI.h @@ -59,7 +59,8 @@ public: Returns true on success. If it returns false, then it failed, and the appropriate exception will have been raised. */ - static bool setJavaPixelRef(JNIEnv*, SkBitmap*, SkColorTable* ctable); + static bool setJavaPixelRef(JNIEnv*, SkBitmap*, SkColorTable* ctable, + bool reportSizeToVM); /** Copy the colors in colors[] to the bitmap, convert to the correct format along the way. @@ -71,12 +72,13 @@ public: class JavaPixelAllocator : public SkBitmap::Allocator { public: - JavaPixelAllocator(JNIEnv* env); + JavaPixelAllocator(JNIEnv* env, bool reportSizeToVM); // overrides virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable); private: JNIEnv* fEnv; + bool fReportSizeToVM; }; class AutoJavaFloatArray { diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp index d02590e62e692..ce30aaa890068 100644 --- a/core/jni/android_backup_BackupDataOutput.cpp +++ b/core/jni/android_backup_BackupDataOutput.cpp @@ -70,7 +70,7 @@ writeEntityData_native(JNIEnv* env, jobject clazz, int w, jbyteArray data, int s int err; BackupDataWriter* writer = (BackupDataWriter*)w; - if (env->GetArrayLength(data) > size) { + if (env->GetArrayLength(data) < size) { // size mismatch return -1; } diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 77a8a7286c633..9053468cebbf2 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -29,15 +29,6 @@ using namespace android; -enum CallbackMessageID { - kShutterCallback = 0, - kRawCallback = 1, - kJpegCallback = 2, - kPreviewCallback = 3, - kAutoFocusCallback = 4, - kErrorCallback = 5 -}; - struct fields_t { jfieldID context; jfieldID surface; @@ -55,6 +46,7 @@ public: ~JNICameraContext() { release(); } virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); virtual void postData(int32_t msgType, const sp& dataPtr); + virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr); sp getCamera() { Mutex::Autolock _l(mLock); return mCamera; } void release(); @@ -136,16 +128,13 @@ void JNICameraContext::copyAndPost(JNIEnv* env, const sp& dataPtr, int uint8_t *heapBase = (uint8_t*)heap->base(); if (heapBase != NULL) { - uint8_t *data = heapBase + offset; + const jbyte* data = reinterpret_cast(heapBase + offset); obj = env->NewByteArray(size); if (obj == NULL) { LOGE("Couldn't allocate byte array for JPEG data"); env->ExceptionClear(); } else { - jbyte *bytes = env->GetByteArrayElements(obj, NULL); - memcpy(bytes, data, size); - env->ReleaseByteArrayElements(obj, bytes, 0); - + env->SetByteArrayRegion(obj, 0, size, data); } } else { LOGE("image heap is NULL"); @@ -182,12 +171,19 @@ void JNICameraContext::postData(int32_t msgType, const sp& dataPtr) mCameraJObjectWeak, msgType, 0, 0, NULL); break; default: - LOGV("dataCallback(%d, %p)", msgType, dataPtr.get()); + // TODO: Change to LOGV + LOGD("dataCallback(%d, %p)", msgType, dataPtr.get()); copyAndPost(env, dataPtr, msgType); break; } } +void JNICameraContext::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr) +{ + // TODO: plumb up to Java. For now, just drop the timestamp + postData(msgType, dataPtr); +} + // connect to camera service static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) { @@ -227,6 +223,8 @@ static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobj // finalizer is invoked later. static void android_hardware_Camera_release(JNIEnv *env, jobject thiz) { + // TODO: Change to LOGV + LOGD("release camera"); JNICameraContext* context = NULL; sp camera; { diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index e71e3481862e4..44a9e8cbcc585 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -212,8 +212,10 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, // failure: native_init_failure: + env->DeleteGlobalRef(lpCallbackData->audioRecord_class); + env->DeleteGlobalRef(lpCallbackData->audioRecord_ref); delete lpCallbackData; - + native_track_failure: delete lpRecorder; @@ -274,6 +276,8 @@ static void android_media_AudioRecord_finalize(JNIEnv *env, jobject thiz) { thiz, javaAudioRecordFields.nativeCallbackCookie); if (lpCookie) { LOGV("deleting lpCookie: %x\n", (int)lpCookie); + env->DeleteGlobalRef(lpCookie->audioRecord_class); + env->DeleteGlobalRef(lpCookie->audioRecord_ref); delete lpCookie; } diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index e7d4694a2aafa..fd92fbed912cb 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -75,6 +75,9 @@ class AudioTrackJniStorage { int mStreamType; AudioTrackJniStorage() { + mCallbackData.audioTrack_class = 0; + mCallbackData.audioTrack_ref = 0; + mStreamType = AudioSystem::DEFAULT; } ~AudioTrackJniStorage() { @@ -318,6 +321,8 @@ native_init_failure: env->SetIntField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, 0); native_track_failure: + env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_class); + env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_ref); delete lpJniStorage; env->SetIntField(thiz, javaAudioTrackFields.jniData, 0); return AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED; @@ -415,6 +420,9 @@ static void android_media_AudioTrack_native_finalize(JNIEnv *env, jobject thiz) AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetIntField( thiz, javaAudioTrackFields.jniData); if (pJniStorage) { + // delete global refs created in native_setup + env->DeleteGlobalRef(pJniStorage->mCallbackData.audioTrack_class); + env->DeleteGlobalRef(pJniStorage->mCallbackData.audioTrack_ref); //LOGV("deleting pJniStorage: %x\n", (int)pJniStorage); delete pJniStorage; } diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp index 9f93e2f042d12..ae744a8dd4d9c 100644 --- a/core/jni/android_net_wifi_Wifi.cpp +++ b/core/jni/android_net_wifi_Wifi.cpp @@ -27,6 +27,8 @@ namespace android { +static jboolean sScanModeActive = false; + /* * The following remembers the jfieldID's of the fields * of the DhcpInfo Java object, so that we don't have @@ -254,27 +256,29 @@ static jboolean android_net_wifi_reassociateCommand(JNIEnv* env, jobject clazz) return doBooleanCommand("REASSOCIATE", "OK"); } -static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz) +static jboolean doSetScanMode(jboolean setActive) +{ + return doBooleanCommand((setActive ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE"), "OK"); +} + +static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz, jboolean forceActive) { jboolean result; + // Ignore any error from setting the scan mode. // The scan will still work. - (void)doBooleanCommand("DRIVER SCAN-ACTIVE", "OK"); + if (forceActive && !sScanModeActive) + doSetScanMode(true); result = doBooleanCommand("SCAN", "OK"); - (void)doBooleanCommand("DRIVER SCAN-PASSIVE", "OK"); + if (forceActive && !sScanModeActive) + doSetScanMode(sScanModeActive); return result; } static jboolean android_net_wifi_setScanModeCommand(JNIEnv* env, jobject clazz, jboolean setActive) { - jboolean result; - // Ignore any error from setting the scan mode. - // The scan will still work. - if (setActive) { - return doBooleanCommand("DRIVER SCAN-ACTIVE", "OK"); - } else { - return doBooleanCommand("DRIVER SCAN-PASSIVE", "OK"); - } + sScanModeActive = setActive; + return doSetScanMode(setActive); } static jboolean android_net_wifi_startDriverCommand(JNIEnv* env, jobject clazz) @@ -509,7 +513,7 @@ static JNINativeMethod gWifiMethods[] = { { "disconnectCommand", "()Z", (void *)android_net_wifi_disconnectCommand }, { "reconnectCommand", "()Z", (void *)android_net_wifi_reconnectCommand }, { "reassociateCommand", "()Z", (void *)android_net_wifi_reassociateCommand }, - { "scanCommand", "()Z", (void*) android_net_wifi_scanCommand }, + { "scanCommand", "(Z)Z", (void*) android_net_wifi_scanCommand }, { "setScanModeCommand", "(Z)Z", (void*) android_net_wifi_setScanModeCommand }, { "startDriverCommand", "()Z", (void*) android_net_wifi_startDriverCommand }, { "stopDriverCommand", "()Z", (void*) android_net_wifi_stopDriverCommand }, diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index 2d90ba49aecc7..59f40670c41bb 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -553,7 +553,7 @@ static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject c config.touchscreen = (uint8_t)touchscreen; config.density = (uint16_t)density; config.keyboard = (uint8_t)keyboard; - config.inputFlags = (uint8_t)keyboardHidden< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -995,6 +1027,29 @@ android:description="@string/permdesc_changeBackgroundDataSetting" android:label="@string/permlab_changeBackgroundDataSetting" /> + + + + + + + + + + + + + diff --git a/core/res/res/drawable/expander_ic_maximized.9.png b/core/res/res/drawable/expander_ic_maximized.9.png index eb461e9d3827c1ad11d4b0c3081db62179a6a6a1..778255ae27c83ae6f2a94b9c4616c2bbc1db8f26 100644 GIT binary patch literal 1149 zcmV-@1cLjCP)B5!PO>j}N$gYSF1mmKWZn_dtyAN3f0?}X=A<#t?lR~5nfy7ZH zqS2V7V`rR)&+*akySaCIxtSS{iD6viz~_HF=l{R?&g(zt+T=|+l+=|&JO7}hrAk2> zij7uMTx@a*%105WN`(C#cJrq&MF4Fs;Ly7^fiU0)d^mCb6BmIWFNXPo7#kaFsYEF# zC^(;!lT*O{NF?$v%8O?x&CSiD@LxppBEgr3GnVF7Q zrqN^J6Z7BQ-QAp-nR!%SU;jJ)eF~r1B-}@ffKx5Z#f621U!6|pc}3Bh4Fm!&Dk>^| zM)hyRJbot;aQGVL+oh$Y-?Fo_ohkyXLN+!w0%c`o*HC?c*eCJ)Y)MF5Fqgbu?=M+d zSMiUQ-Mjj93A}6_3m*eyD^779Z9F0ab z7-aqZ{nFOfCc$7Z)@Oii?4yt2Z;mG?xm86JBM}u_1$1?FiO1uSP$(olJw39%z8>pi zoo(!+4}Gmd$VqNh5qS=W?4-n)LSeG8brIoo(!+4}GnJASbz1 z)3%*!d~k4}!Pt~TLqpQu-Y%=FtAfNOKA%te`uem!zuzx~g@v-Sv!e;2@AC5U|GB_s zGkEN(GZDq;B8CV9D=RA+c}Yo$Y;SM#=xNqmXCHm&YmFx-xm87kG1`D}Gz}6?Ey=OV z#qD;>*47qxy$06V#yCcv>gwvMtRjqpkx55KN35PGTN30Vr_QbRop_z@w(7rhCWHnYAT|#{71AHqy)AxWc(GsW}(L{SB zh@jW7`KE7Dyx+{^1Yy@uQQ6Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXG~ z0U#Dx&$i6~00x6eL_t(o!|j+|XjJJL$A9lRCo>t{e035X2NP{=Ohwp>MMMJG6(n0k z7i8%YC0(pdFSZvAni2?J<+3-eOahXNQWSbs7pjX`@S_yOEO--Inif|QOfyM#Gn1KQ ztj^3i^S)0nJSR?OGO5-=d*KTYGw^=>pXdEQUk6?c;eR)T{{s+j$J_DBL%q&gr7T2@ zQc77OV)^@38R-QuzR2r1gL=g^3a|j@hP&kr$YPo?IRwK6OBdzSXo(N zadDBEnHjEMzu}6Qhs9#?>h0UNf9nI%TUlo-AeIjzbnMu%Us<;O$xlD~tfjlVn{C^+ zy^Kb_qDs9y>iP5MOioTRF)@)f#$3C5_wEqj`e4lK00}_UzyE&Eua#y0V0>)MYHx4f zaQPNw0$_fAp25LEqqYA0{{8zu0SdLis2boLp#JdT!@smF>&I8GUbTZK_;(;G!K|#T zaQ5t3ZH)QN!-o%l?t>{+K9gO86XAmg4}K~lKbx4C*cOY$FvehvK}23jg0+!IgzoNc z>-zQIenwn^CZjL;7@F1E_ zr#}z8sT_<|VGRoicXV`oTr3vf>*?vCR4V;fq^GBcVzKbvo;`a$2EzVbYBL}N-0(c_ zcwb*%sJ^~_%fq$S8)U1s_4W1i^_>p6Zt*x!4>;wXX1yerrBJHQ2XbJ4XD6jn3D5KJ zJa7HL(a}-*`}4){RoM5NjxBE~|*0V1yJ z#@ahNsz3}44KXz}MJ|_PczBrA)z$U6)zwvohlk1Ka!gH4F*Gz(1*W~d1JCnfKtw6! zl;2!gy*v6RR($dnp+Xj+MCP^d`#9}cD zg#yjZ%@hiS4gX`Y7>PuJWHMQ`e`#q6qjk{-v8C4p(K9zYJG&ts7-R4}k7P2*`1m+o zU0vk!d2HLpwr%qHJY8K~jE|3#OeXO>uPXk`&dwr`tCdsAi)iELf~D!{=_-wkF}SYF z+}s>vV`KF8_L9%%$>;O*_VzM1HpblC9Ioqbx_5ed8epj`-^gaUCImDAyF#JRpi=5b zw{G3CBaz4kt;+LAXJ;puE?olP!i5Vwe*Cy9BM1D*=kuI6aYBp871wpgL}UqA^Rx1X z5U>339?@E79mhGkYuB!Z&d$!7;XR#BbMoX#jvP6{qeqXb=F1b{ojZ4!oSgi|7?aRi ze+@hZia{o}H;Jruj^orhjU2)c_fuekxHdDTwV!cetw>jkr7WR zb+1$^{ZT|#fM>onWHXLp1k3|-z%r2WL2OzoIyF8M zXnzArDI+2Qcb1JY3%;cqMP$40^7!O?CL%ds^RI!dQdUO9torU+sMS`yQab@`1Kt4| zfd*hZ5b@^%o@w75^GaFIM9fp4nE&)S@gKDlRSlL>Dl8)P{*whD9Kcpe1y55_O1UDE z_q8whe0ZY~VR3a$5u ziZP;Q#>tGaI%@iTJLiNm*@8u0VSu;!26Izs73Lf^h@1ZvhUY>p2ht{J=JLoc});froow-XTUtMyhY2 zWoKvKOixeGW`8&wev0<^5n5GM)iC^5aC-$}w$A02mxgF#>dA$D=scBOG!y_ zyvj62Ecd(F4i68X&&@*!gWcr6idxC8Uv>gwuOX=!PhIs#&a?CtFZ^7HdQ$K`K`{qsU1(0K#q!`a!{ z4$QrmKDq*;9sppiJSi$FYQwFcz_Af8Z6|7_qobprW@Kb|kB*LnI6gj(LS0>*)YQ~S zFc>`5N0@QsAQw5c^Mo-9zLJuXyCzXAdU|@eBRJerUtce~yStLemmn884Q{PuS-I0hO+l5ULi4Y2fq_wqGkV{k$N2j8qLRwl{;`)=5 z+`1w{8ygz|GeN~8b#G~DDPasb$*n75v9q&tdVhca&?K;CKwg)YmP%@Bsv3d3ygV5k z9F(=SwNrj(Jh{k8Ze0;PXjZ1CrdH!k2g#e8o7KaKp`jr)1soCUgRRp+E^->&di4ZW zbOlV!@bK^_NJcK}+?p|EWo7DmdU{%oi1qX|4=?VDot>Rvb#?XExcwdCe!j>l%KiK? z@c!7?*hi?KuE!G+@A$R~zyjW{tgQS2w|@b?K}=Bl6g8X~`~W0BB11m2+wCeBko+vr zhrWzqEIG&(D?qE-M$i+OZ-HNHYiqxsn3!0@ut!WWrnO$v(ucl`VJtZeu76cydSTvW znFka#H8mCcd_EVpWjac}Yep&e_xk#Jcz%99*xlVdgImmC4}ss$6rfXM#;g&yQJCBU zZW!O4hRZXS`T#4ZM_jK)=^s3|`npKnXaw(}(a5j>00001P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXG~ z0V5#2Sa6pB00v!2L_t(o!|j+~XjIu5z<=l5ab^;`iAly7WyWYl*(fZy4|xa#3Jr)* zv8-KVpj|=x;6v1PEAhpG4|$V{$wSOTEkp}GY(Z^pOP5uP4}w0dY-v_dM_e@~Ow2zM z?aaCNoUaewi8GU#Y}OXq2M-)B-22_{``zz5-*>)q;q?&ycSHC;fOt3FjU^BD7P1P^ zD5Vim1@|SK4sa+Xh%7l7)DmT08;8hGcI@~#7L9I?L?RymYm`#&0f@+~2+yny{*lY& z{(9xgmCu171e5OqQcHmFfXKFO+kPI6M)zv1TX*i<8Qrj918df-p`oDxfQg9-o;`a; zI-TayrAx+%+%`Eg^u-r{`+W#x7lT<0M28U3A9r+|^0fZ=z<~pGZEbB-S69EOMz7tE zQg2kfdi9E%H*YdHI5_33`~1tRUw#Id5XOBUkUT`Zy}kXnp6C6nzrSCnQmG>26~8Wo zdh+B6-3JdkME-E&#*JSB*-9{~0$c=$x3;$aMr*xqXlTgGhv2&)N?|4@CfK`ouXWD- z?)L55zXGx-6_hISDy)gvmMvR;AtDC{2M4R0nwoIV;haN6mNfISRaI5AwYBMs7cc%W zkw`orA0Pi`!2&J{K{;UAvf>nOX46T08$< zGMS{iySpw3f=__z(1xl6l26fCb93`Y#+VP=+uP@rmCjSAPBAw($IF*5Idtd{)6>%x zWrHA~y}cb{%!kd*%^#suEVQL6c_aeFjWOFhJ3FKCc)X(Gv9U1{i3F=xuV#FFoFhk$ zFf%h#Q9d4z)7jY>HO6d5Bp%wT=#gb1NXw>8n+Spc-}mu-e}Uq@zCKp2T!}G;L?S^Z zli|dP6AR=D-`}`#BgU8(rF1;BRn{Xqq^$CNzbTbWR)h$GfbsEhPM)LOf|A(2?1sBq?TImX7u=#MmG&JCxTMk4^K_cbKIe@hmrPO>HmK#A3aR2^&rl+Sd#^8A#)z#J1 z)YK3JK~YW7T4Sw6L{LgaM8vBUntaxH&bi#^=;(ays5ED1XE}E471otrPTbr1t9YJi36;Nj1CVEFY1ln-d-jrC#kKi#TY{}nWVS3mj@3X zRD5T6co<+*L~Lnw)g^7c1p+7X)wy%$?Ck99ypqC7X{}}J)~&>1F?`=Al}a%%Fu>!- zj~B=lhVlIQ^A`B3Tw72G;z9xA8}nzSROZ^XYh^=Yt>x&^qoh(PQmGVY&YU5gPGgKI zGF}*(>({R%BAFnte+gTHpl}yfCF#2ysP{Z?Z6vbnQ?1pGvuDpPOD2;=vCi+pt*xy9 z+_`fH-}j4lU8U4~wmg0Ml>Phn`@o-!F{iDykAX?xWgbQqELJ5VF`!l{-6Z1PkHuoY z)>?1AaN&ZgtE(#uQ*P@ogqWI|qN}S*MC2P|{9fnmU0@8D0do29=#ow=0J0+P1u&A! zD9Mc5z(i}fQ# zHO2Eh-&*%b#I3)4`Eu>5RjYI|nIsmA&3|$Jng{eek8C!})vH(O>FEiabLqg^0pJ@T z155+2LJ+Ccp(&-cC(gxyS|9w21s&DfL7|z70Jw8A4=By-~W?l-83hN)Z;hAXJcX&W(hgsu7XpN~vYx z`trjpcp)OsfiV%80w$GG(;_lk&^*gq9Vf!}?gu~(@LrhaRpGPzIV~2TMIoeS9ZL*#KzC zd2Dk3{`^Z+nss{tO?(Wrv>&HIEKKz@3F>=kstG{K0mlFN;eQ9im#3c?{{MrAm;x}- zHBi;!n^E!t=sx=M^G_o%coqNt`uhPMZ%mB&pu|Tti`fM@3P3(W6F#7~_2mN~eE~^K z0GjwHw-}h9Ko*h`e+73EloTko7?_~ulUyosvG!ABF)%>|ASWo4e8|KIOU>A%1Armr zK$gYO1clS(oPWYx0#J(;aD-GnSr+3+P{=->{~$~KJRUU;&@4!N$puPKKo{S~=i(pl zzBBy&`G5N Z08qKGx)4JKFy#OM002ovPDHLkV1mVo?nD3p delta 522 zcmV+l0`>jX1jq!CNq_1|L_t(|+G70w|3AY(049b30t03-3t74zuS@`v{ZL*ZgKYQ$ zQjK6FHIBdBSm?mR&9NUv?CTFl9*y_|G!1H?rTxT+QPtu<_m>p_DFZB022eTb2lb0{ zGX*3>1?~fx0?^=v`4*<+!;9A+6eWz(KTy@jKuh~!mV&^UOMmw+fH0C00jL`4`S`S=YRVRfC=h69=#i&bO6po`RSXXfMMYUlFDiUUiN+zpP_*}4_|{VRFM~D zz-tBrgCo&F{pZGn1cv{A9DtYs8~*U|GsBbTZwo;f#Kxr#WCqwQVuJd?{#pSAX`%bb zg$0Jg{{B0_qFD^~$)D@J`&pQo9Pkwb51zhLRB&wmfPXirWyE<4zzGUpUCIP3uW$A^ zz}a}B1mpp*nG6gKczyiiV(WVjb`}9@R{B4F{`tV6UoD6?j_*8r{o&7FVEi!rqY4I@ z1u~Ohs($nCOW~1sU*_YBV-mp!a4Ut<7RYETbJXHdiwB*>009O7vacl(Z;n{200000 MNkvXXt^-0~f^x&|0{{R3 diff --git a/core/res/res/drawable/ic_text_dot.png b/core/res/res/drawable/ic_text_dot.png old mode 100755 new mode 100644 index bb02379498f66764463f280f30d4bc94de282b18..47913f66595a8a2f3ce1b059bfe29c0bb64ddd8f GIT binary patch delta 449 zcmV;y0Y3iB0^9>3iBL{Q4GJ0x0000DNk~Le0000U0000U2nGNE06Q?QqLCpde*u0; zL_t(|+U%A;OT$1I#*^S6;vfb!VzG;8z#;*`!LQ)r?9fRN`e8bB=;YMF!O3rsO-Mm0 zf`cdoCD61f;w0(6#OEogXeoNaNtb)!;ga`#cz@ho?ueeIsWyu+v>Am0EAYR?++WPP zt}kHNgw~ic%r4w8rYq?x*iTNN1-f)4ms@3WRUa!#aK`JDSr z1<%~X^wgl##FWaylc_d9MUkE^jv*Dd-dsD#d%%E$`GCc%Lq3O2EQxFQby$7t{TE9# z4l#vpy~0p&ocof_!!uV(6$KmjvK^Y + android:background="?android:attr/listDivider" /> + android:background="?android:attr/listDivider" /> diff --git a/core/res/res/layout/search_dropdown_app_selector.xml b/core/res/res/layout/search_dropdown_app_selector.xml deleted file mode 100644 index f86645fa829de..0000000000000 --- a/core/res/res/layout/search_dropdown_app_selector.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - diff --git a/core/res/res/layout/search_dropdown_item_2line.xml b/core/res/res/layout/search_dropdown_item_2line.xml deleted file mode 100644 index 5546b6636bb99..0000000000000 --- a/core/res/res/layout/search_dropdown_item_2line.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - diff --git a/core/res/res/layout/search_dropdown_item_icons_1line.xml b/core/res/res/layout/search_dropdown_item_icons_1line.xml deleted file mode 100644 index 4f65d746b4eba..0000000000000 --- a/core/res/res/layout/search_dropdown_item_icons_1line.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 7dbeaebe5d72c..7160b41f49301 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -21,6 +21,7 @@ "GB" "TB" "PB" + "%1$s %2$s" "<bez názvu>" "…" "(žádné telefonní číslo)" @@ -48,6 +49,12 @@ "Blokování hovorů" "Změna hesla" "Změna kódu PIN" + "Volané číslo uvedeno" + "Volání čísla omezeno" + "Konference tří účastníků" + "Odmítnutí nevyžádaných obtěžujících hovorů" + "Doručení volaného čísla" + "Nerušit" "Ve výchozím nastavení je identifikace volajícího omezena. Příští hovor: Omezeno" "Ve výchozím nastavení je identifikace volajícího omezena. Příští hovor: Neomezeno" "Ve výchozím nastavení není identifikace volajícího omezena. Příští hovor: Omezeno" @@ -67,11 +74,27 @@ "Synchronizace" "Pakety" "PAD" + "Indikátor roamingu svítí" + "Indikátor roamingu nesvítí" + "Indikátor roamingu bliká" + "Není v blízkosti" + "Mimo budovu" + "Roaming – preferovaný systém" + "Roaming – dostupný systém" + "Roaming – alianční partner" + "Roaming – prémiový partner" + "Roaming – úplná funkčnost služby" + "Roaming – částečná funkčnost služby" + "Banner roamingu je zapnutý" + "Banner roamingu je vypnutý" + "Vyhledávání služby" "{0}: Nepřesměrováno" "{0}: {1}" "{0}: {1} po {2} sek." "{0}: Nepřesměrováno" "{0}: Nepřesměrováno" + "Požadavek zadaný pomocí kódu funkce byl úspěšně dokončen." + "Problém s připojením nebo neplatný kód funkce." "OK" "Webová stránka obsahuje chybu." "Adresu URL nelze najít." @@ -88,6 +111,7 @@ "K souboru nelze získat přístup." "Požadovaný soubor nebyl nalezen." "Je zpracováváno příliš mnoho požadavků. Opakujte akci později." + "Certifikát je uložen v systémovém úložišti klíčů." "Synchronizace" "Synchronizace" "Příliš mnoho smazaných položek služby %s." @@ -133,6 +157,8 @@ "Nízkoúrovňový přístup a kontrola nad systémem." "Nástroje pro vývojáře" "Funkce pouze pro vývojáře aplikací" + "Úložiště" + "Přístup ke kartě SD." "zakázání či změny stavového řádku" "Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony." "rozbalení a sbalení stavového řádku" @@ -165,6 +191,10 @@ "Umožňuje aplikaci vynutit zavření a přesunutí libovolné činnosti v popředí na pozadí. Běžné aplikace by toto nastavení neměly nikdy využívat." "načtení interního stavu systému" "Umožňuje aplikaci načíst interní stav systému. Škodlivé aplikace mohou načíst řádu soukromých a zabezpečených informací, které by nikdy neměly potřebovat." + "Částečné vypnutí" + "Uvede správce činností do vypnutého stavu. Nedojde však k úplnému vypnutí." + "Zabránit přepínání aplikací" + "Zabrání uživateli přepnout na jinou aplikaci." "sledování a řízení spouštění všech aplikací" "Umožňuje aplikaci sledovat a řídit spouštění činností systémem. Škodlivé aplikace mohou zcela ovládnout systém. Toto oprávnění je zapotřebí pouze pro účely vývoje, nikdy pro běžné použití telefonu." "odeslání vysílání o odstranění balíčku" @@ -179,6 +209,8 @@ "Umožňuje aplikaci ovládat, zda jsou činnosti vždy dokončeny po přesunutí do pozadí. Běžné aplikace toto nastavení nikdy nevyužívají." "změna statistických údajů o baterii" "Umožňuje změnu shromážděných statistických údajů o baterii. Není určeno pro běžné aplikace." + "Ovládat zálohování a obnovu systému" + "Umožňuje aplikaci ovládat mechanizmus zálohování a obnovy systému. Není určeno k použití v běžných aplikacích." "zobrazení nepovolených oken" "Umožňuje vytvoření oken, která mají být použita interním systémem uživatelského rozhraní. Běžné aplikace toto nastavení nepoužívají." "zobrazení upozornění systémové úrovně" @@ -245,6 +277,8 @@ "Vytváří simulované zdroje polohy pro účely testování. Škodlivé aplikace mohou pomocí tohoto nastavení změnit polohu či stav vrácený zdroji skutečné polohy, jako je např. jednotka GPS či poskytovatelé sítě." "přístup k dalším příkazům poskytovatele polohy" "Umožňuje získat přístup k dalším příkazům poskytovatele polohy. Škodlivé aplikace mohou pomocí tohoto nastavení narušit funkci GPS či jiných zdrojů polohy." + "Oprávnění k instalaci poskytovatele polohy" + "Vytvořit simulace zdrojů polohy pro účely testování. Škodlivé aplikace mohou toto nastavení využít k přepsání polohy nebo stavu vráceného zdroji skutečné polohy, například systémem GPS nebo poskytovateli sítí. Mohou také monitorovat polohu a ohlásit ji externímu zdroji." "upřesnění polohy (GPS)" "Umožňuje aplikaci přístup ke zdrojům přesné polohy v telefonu, jako je například systém GPS, je-li k dispozici. Škodlivé aplikace mohou pomocí tohoto nastavení zjistit vaši polohu a mohou zvýšit spotřebu baterie." "přibližná poloha (pomocí sítě)" @@ -317,6 +351,8 @@ "Umožňuje aplikaci zobrazit informace o stavu připojení WiFi." "Změnit stav WiFi" "Umožňuje aplikaci připojit se k přístupovým bodům WiFi či se od nich odpojit a provádět změny nakonfigurovaných sítí WiFi." + "Povolit příjem Wi-Fi Multicast" + "Povoluje aplikaci přijímat pakety, které nebyly adresovány přímo vašemu zařízení. Pomocí této možnosti můžete objevit služby nabízené ve vaší blízkosti. Spotřeba energie je vyšší než u režimu bez vícesměrového vysílání (multicast)." "správa rozhraní Bluetooth" "Umožňuje aplikaci konfigurovat místní telefon s rozhraním Bluetooth a vyhledávat a párovat vzdálená zařízení." "vytvoření připojení Bluetooth" @@ -337,6 +373,8 @@ "Umožní aplikaci číst soukromá slova, jména a fráze, která uživatel mohl uložit do svého slovníku." "zapisovat do slovníku definovaného uživatelem" "Umožní aplikaci zapisovat nová slova do uživatelského slovníku." + "Změnit/smazat obsah karty SD" + "Umožní aplikaci zápis na kartu SD." "Domů" "Mobil" @@ -353,6 +391,7 @@ "Ostatní" "Vlastní" + "Mobilní" "Domů" "Práce" @@ -393,6 +432,8 @@ "Správně!" "Zkuste to prosím znovu" "Nabíjení (%d%%)" + + "Připojte dobíjecí zařízení." "Není vložena SIM karta." "V telefonu není žádná karta SIM." @@ -414,7 +455,8 @@ "Neplatné uživatelské jméno nebo heslo." "%-l%P" "%-l%p" - "Vymazat oznámení" + + "Žádná oznámení" "Probíhající" "Oznámení" @@ -423,6 +465,7 @@ "Prosím připojte dobíjecí zařízení" "Baterie je vybitá:" "zbývá méně než %d%%." + "Proč?" "Test továrního nastavení se nezdařil" "Test FACTORY_TEST lze provést pouze u balíčků nainstalovaných ve složce /system/app." "Nebyl nalezen žádný balíček umožňující test FACTORY_TEST." @@ -431,6 +474,10 @@ "JavaScript" "Chcete opustit tuto stránku?"\n\n"%s"\n\n"Vyberte OK, chcete-li pokračovat, nebo Zrušit, chcete-li na stránce zůstat." "Potvrdit" + "Čtení historie a záložek prohlížeče" + "Umožňuje aplikaci číst všechny navštívené adresy URL a záložky prohlížeče." + "Zapisovat historii a záložky prohlížeče" + "Umožní aplikaci změnit historii či záložky prohlížeče uložené v telefonu. Škodlivé aplikace mohou pomocí tohoto nastavení vymazat či pozměnit data prohlížeče." "Chcete, aby si prohlížeč zapamatoval toto heslo?" "Nyní ne" "Zapamatovat" @@ -538,10 +585,6 @@ "Poledne" "půlnoc" "Půlnoc" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "Vybrat vše" @@ -579,6 +622,7 @@ "Služba %1$s (%2$s) nereaguje." "Proces %1$s neodpovídá." "Ukončit aplikaci" + "Nahlásit" "Počkat" "Ladit" "Vyberte činnost s textem" @@ -632,22 +676,26 @@ "Formátovat kartu SD" "Opravdu chcete kartu SD naformátovat? Všechna data na kartě budou ztracena." "Formátovat" + + + + "Výběr metody zadávání dat" " AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ" " 0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ" "kandidáti" "Příprava karty SD" - "Kontrola chyb" + "Kontrola chyb." "Prázdná karta SD" - "Karta SD je prázdná nebo používá nepodporovaný systém souborů." + "Karta SD je prázdná nebo obsahuje nepodporovaný systém souborů." "Poškozená karta SD" - "Karta SD je poškozena. Pravděpodobně ji bude nutné znovu formátovat." + "Karta SD je poškozená. Bude pravděpodobně nutné ji přeformátovat." "Karta SD byla neočekávaně odebrána" "Chcete-li zabránit ztrátě dat, kartu SD před odebráním odpojte." "Kartu SD je možné bezpečně odebrat" - "Kartu SD lze nyní bezpečně vyjmout." + "Kartu SD lze bezpečně odebrat." "Karta SD byla odstraněna" - "Karta SD byla odebrána. Chcete-li zvětšit úložiště svého zařízení, vložte kartu SD." + "Karta SD byla odebrána. Vložte novou kartu." "Nebyly nalezeny žádné odpovídající aktivity." "aktualizovat statistiku použití součástí" "Umožňuje změnu shromážděných statistických údajů o použití součástí. Není určeno pro běžné aplikace." @@ -661,4 +709,6 @@ "Spustit" "Vytočit číslo"\n" %s." "Vytvořit kontakt"\n"pro %s." + "Zaškrtnuto" + "Nezaškrtnuto" diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml new file mode 100644 index 0000000000000..a3e8dc5d06f3d --- /dev/null +++ b/core/res/res/values-da/strings.xml @@ -0,0 +1,765 @@ + + + + "B" + "Kb" + "Mb" + "Gb" + "Tb" + "Pb" + + + "<uden navn>" + "…" + "(Intet telefonnummer)" + "(Ukendt)" + "Voicemail" + "MSISDN1" + "Forbindelsesproblemer eller ugyldigt MMI-nummer." + "Tjenesten blev aktiveret." + "Tjenesten blev aktiveret for:" + "Tjenesten er deaktiveret." + "Registreringen er afsluttet." + "Sletning afsluttet." + "Forkert adgangskode." + "MMI-nummer afsluttet." + "Den gamle PIN-kode, du indtastede, er ikke korrekt." + "Den indtastede PUK-kode er ikke korrekt." + "De indtastede PIN-koder stemmer ikke overens." + "Indtast en PIN-kode på mellem 4 og 8 tal." + "Dit SIM-kort er låst med PUK-koden. Indtast PUK-koden for at låse den op." + "Indtast PUK2-koden for at låse op for SIM-kortet." + "Indgående opkalds-id" + "Udgående opkalds-id" + "Viderestilling af opkald" + "Ventende opkald" + "Opkaldsspærring" + "Ændring af adgangskode" + "ændring af PIN-kode" + + + + + + + + + + + + + "Standarder for opkalds-id til begrænset. Næste opkald: Begrænset" + "Standarder for opkalds-id til begrænset. Næste opkald: Ikke begrænset" + "Standarder for opkalds-id til ikke begrænset. Næste opkald: Begrænset" + "Standarder for opkalds-id til ikke begrænset. Næste opkald: Ikke begrænset" + "Tjenesten leveres ikke!" + "Indstillingen for opkalds-id kan ikke ændres." + "Begrænset adgang ændret" + "Datatjeneste er blokeret." + "Nødtjeneste er blokeret." + "Stemme-/SMS-tjeneste er blokeret." + "Alle stemme-/SMS-tjenester er blokerede." + "Stemme" + "Data" + "FAX" + "SMS" + "Asynkroniser" + "Synkroniser" + "Pakke" + "PAD" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "{0}: Ikke videresendt" + "{0}: {1}" + "{0}: {1} efter {2} sekunder" + "{0}: Ikke videresendt" + "{0}: Ikke videresendt" + + + + + "OK" + "Websiden indeholder en fejl." + "Webadressen kunne ikke findes." + "Planen for webstedsgodkendelse er ikke understøttet." + "Godkendelse mislykkedes." + "Godkendelse via proxyserveren mislykkedes." + "Der kunne ikke oprettes forbindelse til serveren." + "Serveren kunne ikke kommunikere. Prøv igen senere." + "Der opstod timeout for forbindelsen til serveren." + "Siden indeholder for mange serveromdirigeringer." + "Protokollen understøttes ikke." + "Der kunne ikke etableres en sikker forbindelse." + "Siden kunne ikke åbnes, fordi webadressen er ugyldig." + "Der kunne ikke oprettes adgang til filen." + "Den anmodede fil blev ikke fundet." + "Der behandles for mange anmodninger. Prøv igen senere." + + + "Synkroniser" + "Synkroniser" + "For mange %s sletninger" + "Telefonens lagerplads er fuld. Slet nogle filer for at frigøre plads." + "Mig" + "Telefonvalgmuligheder" + "Lydløs" + "Slå trådløs til" + "Slå trådløs fra" + "Skærmlås" + "Sluk" + "Lukker ned ..." + "Din telefon lukkes ned." + "Der er ingen nye programmer." + "Telefonvalgmuligheder" + "Skærmlås" + "Sluk" + "Lydløs" + "Lyden er FRA" + "Lyden er TIL" + "Flytilstand" + "Flytilstand er TIL" + "Flytilstand er FRA" + "Sikker tilstand" + "Android-system" + "Tjenester, der koster dig penge" + "Tillader et program at gøre ting, som kan koste penge." + "Dine beskeder" + "Læs og skriv dine SMS-, e-mail- og andre beskeder." + "Dine personlige oplysninger" + "Få direkte adgang til dine kontaktpersoner og din kalender, der er gemt på telefonen." + "Din placering" + "Overvåg din fysiske placering" + "Netværkskommunikation" + "Tillader programmer at få adgang til forskellige netværksfunktioner." + "Dine Google-konti" + "Få adgang til tilgængelige Google-konti." + "Hardwarekontroller" + "Direkte adgang til hardware på håndsættet." + "Telefonopkald" + "Overvåg, registrer og behandl telefonopkald." + "Systemværktøjer" + "Adgang og kontrol til systemet på lavere niveau." + "Udviklingsværktøjer" + "Funktioner kun til programudviklere." + + + + + "deaktiver eller rediger statuslinje" + "Tillader et program at deaktivere statuslinjen eller tilføje eller fjerne systemikoner." + "udvid/skjul statuslinje" + "Tillader et program at udvide eller skjule statuslinjen." + "opfang udgående opkald" + "Tillader et program at behandle udgående opkald og ændre nummeret, der skal ringes til. Ondsindede programmer kan overvåge, omdirigere eller forhindre udgående opkald." + "modtag SMS" + "Tillader et program at modtage og behandle SMS-beskeder. Ondsindede programmer kan overvåge dine beskeder eller slette dem uden at vise dem til dig." + "modtag MMS" + "Tillader et program at modtage og behandle MMS-beskeder. Ondsindede programmer kan overvåge dine beskeder eller slette dem uden at vise dem til dig." + "send SMS-beskeder" + "Tillader et program at sende SMS-beskeder. Ondsindede programmer kan eventuelt koste dig penge ved at sende beskeder uden din bekræftelse." + "læs SMS eller MMS" + "Tillader et program at læse SMS-beskeder, der er gemt på din telefon eller dit SIM-kort. Ondsindede programmer kan eventuelt læse dine fortrolige beskeder." + "rediger SMS eller MMS" + "Tillader et program at skrive til SMS-beskeder, der er gemt på din telefon eller dit SIM-kort. Ondsindede programmer kan eventuelt slette dine beskeder." + "modtag WAP" + "Tillader et program at modtage og behandle WAP-beskeder. Ondsindede programmer kan overvåge dine beskeder eller slette dem uden at vise dem til dig." + "hent kørende programmer" + "Tillader et program at hente oplysninger om nuværende og for nyligt kørende opgaver. Tillader eventuelt ondsindede programmer at finde private oplysninger om andre programmer." + "omorganiser kørende programmer" + "Tillader et program at flytte opgaver til forgrunden og baggrunden. Ondsindede programmer kan tvinge dem selv til forgrunden uden din kontrol." + "aktiver programfejlretning" + "Tillader et program at slå fejlretning af andet program til. Ondsindede programmer kan bruge dette til at standse andre programmer." + "skift dine UI-indstillinger" + "Tillader et program at ændre den nuværende konfiguration, som f.eks. den lokale eller overordnede skrifttypestørrelse." + "genstart andre programmer" + "Tillader et program at tvangsgenstarte andre programmer." + "tving programmet til at lukke" + "Tillader et program at tvinge alle programmer, der er i forgrunden, til at lukke og gå tilbage. Bør aldrig være nødvendigt til normale programmer." + "hent intern systemtilstand" + "Tillader et program at hente systemets interne tilstand. Ondsindede programmer kan hente en række private og sikre oplysninger, som de normalt aldrig bør have brug for." + + + + + + + + + "overvåg og kontroller start af alle programmer" + "Tillader et program at overvåge og kontrollere, hvordan systemet starter aktiviteter. Ondsindede programmer kan fuldstændig kompromittere systemet. Denne tilladelse er kun nødvendig til udvikling, aldrig til normal telefonbrug." + "send udsendelse om fjernet pakke" + "Tillader et program at udsende en meddelelse om, at en programpakke er fjernet. Ondsindede programmer kan bruge dette til at afslutte et andet kørende program." + "send SMS-modtaget udsendelse" + "Tillader et program at udsende en meddelelse om, at der er modtaget en SMS-besked. Ondsindede programmer kan eventuelt bruge dette til at forfalske indgående SMS-beskeder." + "send WAP-PUSH-modtaget udsendelse" + "Tillader et program at udsende en meddelelse om, at der er modtaget en WAP PUSH-besked. Ondsindede programmer kan eventuelt bruge dette til at forfalske modtagelse af MMS-besked eller i det skjulte erstatte indholdet på alle websider med ondsindede varianter." + "begræns antallet af kørende processer" + "Tillader et program at kontrollere det maksimale antal processer, der kan køre. Er aldrig nødvendigt til normale programmer." + "få alle baggrundsprogrammer til at lukke" + "Tillader et program at kontrollere, om aktiviteter altid afsluttes, så snart de går i baggrunden. Aldrig nødvendigt til normale programmer." + "rediger batteristatistikker" + "Tillader ændring af indsamlede batteristatistikker. Ikke til brug for normale programmer." + + + + + "vis uautoriserede vinduer" + "Tillader oprettelse af vinduer, der er beregnet til at blive brugt af den interne systembrugergrænseflade. Ikke til brug for normale programmer." + "vis underretninger på systemniveau" + "Tillader et program at vise systemunderretningsvinduer. Ondsindede programmer kan overtage hele telefonens skærm." + "rediger global animationshastighed" + "Tillader et program at ændre den globale animationshastighed (hurtigere eller langsommere animationer) når som helst." + "administrer programtokens" + "Tillader programmet at oprette og administrere deres egen tokens og gå uden om deres normale Z-rækkefølge. Bør aldrig være nødvendigt til normale programmer." + "tryk på taster og kontrolknapper" + "Tillader et program at levere sine egne inputbegivenheder (tastetryk osv.) til andre programmer. Ondsindede programmer kan bruge dette til at overtage telefonen." + "registrerer, hvad du indtaster, og hvilke handlinger du foretager dig" + "Tillader et program at holde øje med de taster, du trykker på, selv når du interagerer med andre programmer (som f.eks. indtastning af adgangskode). Bør aldrig være nødvendigt til normale programmer." + "forpligt til en inputmetode" + "Tillader brugeren at forpligte sig på en inputmetodes grænseflade på øverste niveau. Bør aldrig være nødvendig til normale programmer." + "skift skærmretning" + "Tillader et program at ændre rotationen af skærmen når som helst. Bør aldrig være nødvendigt til normale programmer." + "send Linux-signaler til programmer" + "Tillader program at anmode om, at det leverede signal sendes til alle vedholdende processer." + "lad altid programmet køre" + "Tillader et program at gøre dele af sig selv vedholdende, så systemet ikke kan bruge det til andre programmer." + "slet programmer" + "Tillader et program at slette Android-pakker. Ondsindede programmer kan bruge dette til at slette vigtige programmer." + "slet andre programmers data" + "Lader et program rydde brugerdata." + "slet andre programmers cacher" + "Tillader et program at slette cachefiler." + "måler programmets lagerplads" + "Tillader et program at hente dets kode, data og cachestørrelser" + "installer programmer direkte" + "Tillader et program at installere nye eller opdaterede Android-pakker. Ondsindede programmer kan bruge dette til at tilføje nye programmer med vilkårlige, effektive tilladelser." + "slet alle cachedata for programmet" + "Tillader et program at frigøre plads på telefonen ved at slette filer i programmets cachemappe. Adgang er normalt meget begrænset til systemprocesser." + "læs systemlogfiler" + "Tillader et program at læse fra systemets forskellige logfiler. Dermed kan generelle oplysninger om, hvad du laver med telefonen, opdages, men logfilerne skulle ikke indeholde personlige eller private oplysninger." + "læs/skriv til ressourcer ejet af diag" + "Tillader et program at læse og skrive til alle ressourcer, der ejes af diag-gruppen, som f.eks. flier i /dev. Dette kan muligvis påvirke systemets stabilitet og sikkerhed. Dette bør KUN bruges til hardwarespecifikke diagnosticeringer foretaget af producent eller udbyder." + "aktiver eller deaktiver programkomponenter" + "Tillader et program at ændre, om en komponent fra et andet program er aktiveret eller ej. Ondsindede programmer kan bruge dette til at deaktivere vigtige telefonfunktioner. Denne tilladelse skal anvendes med forsigtighed, da det kan forårsage ubrugelige, inkonsekvente eller ustabile programkomponenter." + "indstil foretrukne programmer" + "Tillader et program at ændre dine foretrukne programmer. Dette kan tillade, at ondsindede programmer ændrer kørende programmer i det skjulte og narrer dine eksisterende programmer til at indsamle personlige data fra dig." + "rediger globale systemindstillinger" + "Tillader et program at ændre systemets indstillingsdata. Ondsindede programmer kan skade systemets konfiguration." + "rediger sikre systemindstillinger" + "Tillader et program at ændre systemernes sikre indstillingsdata. Ikke til brug til almindelige programmer." + "rediger kortet over Google-tjenester" + "Tillader et program at ændre kortet over Google-tjenester. Ikke til brug til normale programmer." + "start automatisk ved opstart" + "Tillader et program at starte selv, når systemet er færdig med at starte. Dette kan gøre start af telefonen langsommere og generelt gøre telefonen langsommere ved altid at lade programmet køre." + "send klæbende udsendelse" + "Tillader et program at sende klæbende udsendelser, der bliver tilbage, efter udsendelsen er slut. Ondsindede programmer kan gøre telefonen langsom eller ustabil ved at få den til at bruge for meget hukommelse." + "læs kontaktpersondata" + "Tillader et program at læse alle kontaktpersondata (adresse), der er gemt på din telefon. Ondsindede programmer kan bruge dette til at sende dine data til andre mennesker." + "skriv kontaktpersondata" + "Tillader et program at ændre telefonens kontaktpersondata (adresse), der er gemt på din telefon. Ondsindede programmer kan bruge dette til at slette eller ændre kontaktpersondata." + "skriv ejerdata" + "Tillader et program at ændre telefonens ejerdata, der er gemt på din telefon. Ondsindede programmer kan bruge dette til at slette eller ændre ejerdata." + "læs ejerdata" + "Tillader et program at læse telefonens ejerdata, der er gemt på din telefon. Ondsindede programmer kan bruge dette til at læse ejerdata." + "læs kalenderdata" + "Tillader et program at læse alle kalenderbegivenheder, der er gemt på din telefon. Ondsindede programmer kan bruge dette til at sende dine kalenderbegivenheder til andre mennesker." + "skriv kalenderdata" + "Tillader et program at ændre telefonens kalenderbegivenheder, der er gemt på din telefon. Ondsindede programmer kan bruge dette til at slette eller ændre kalenderdata." + "imiterede placeringskilder til test" + "Opret imiterede placeringskilder til testning. Ondsindede programmer kan bruge dette til at tilsidesætte den returnerede placering og/eller status fra rigtige placeringskilder som f.eks. GPS eller netværksudbydere." + "få adgang til ekstra kommandoer for placeringsudbyder" + "Få adgang til ekstra kommandoer fra placeringsudbyder. Ondsindede programmer kan bruge dette til at gribe ind i driften af GPS\'en eller andre placeringskilder." + + + + + "fin (GPS) placering" + "Få adgang til gode placeringskilder, som f.eks. Global Positioning System på telefonen, når det er tilgængeligt. Ondsindede programmer kan bruge dette til at finde ud af, hvor du er og kan eventuelt bruge yderligere batterikapacitet." + "grov (netværksbaseret) placering" + "Få adgang til grove placeringskilder som f.eks. den mobile netværksdatabase for at finde en omtrentlig placering for telefonen, hvor det er muligt. Ondsindede programmer kan bruge dette til at finde ud af, hvor du omtrent er." + "få adgang til SurfaceFlinger" + "Tillader et program at bruge SurfaceFlinger-funktioner på lavt niveau." + "læs rammebuffer" + "Tillader et program at læse/bruge indholdet fra rammebufferen." + "skift dine lydindstillinger" + "Tillader et program at ændre globale lydindstillinger som f.eks. lydstyrke og kanalisering." + "optag lyd" + "Tillader et program at få adgang til lydregistreringsstien." + "tag billeder" + "Tillader programmet at tage billeder med kameraet. Dette tillader programmet til hver en tid at indsamle de billeder, kameraet ser." + "deaktiver telefonen permanent" + "Tillader programmet at deaktivere hele telefonen permanent. Dette er meget farligt." + "tving telefon til at genstarte" + "Tillader programmet at tvinge telefonen til at genstarte." + "monter eller demonter filsystemer" + "Tillader programmet at montere eller demontere filsystemer til flytbar lagring." + "formater ekstern lagring" + "Tillader et program at formatere flytbar lagring." + "kontroller vibrator" + "Lader programmet kontrollere vibratoren." + "kontroller lommelygte" + "Tillader programmet at kontrollere lommelygten." + "test hardware" + "Tillader et program at kontrollere forskellige perifere enheder med det formål at teste hardwaren." + "ring direkte op til telefonnumre" + "Tillader programmet at ringe til telefonnumre uden din indgriben. Ondsindede programmer kan forårsage uventede opkald på din telefonregning. Vær opmærksom på, at det ikke tillader programmet at ringe til nødnumre." + "ring direkte op til alle telefonnumre" + "Tillader programmet at ringe til alle telefonnumre inklusive nødnumre uden din indgriben. Ondsindede programmer kan eventuelt foretage unødvendige og ulovlige opkald til nødtjenester." + "kontroller meddelelser om placeringsopdatering" + "Tillader aktivering/deaktivering af placeringsdata fra radioen. Ikke til brug til normale programmer." + "egenskaber for adgangskontrol" + "Tillader læse/skrive-adgang til egenskaber, der er uploadet af kontroltjenesten. Ikke til brug til normale programmer." + "vælg widgets" + "Tillader programmet at fortælle systemet, hvilke widgets der kan bruges af hvilke programmer. Med denne tilladelse kan programmer give adgang til personlige data til andre programmer. Ikke til brug til normale programmer." + "rediger telefontilstand" + "Tillader programmet at kontrollere enhedens telefonfunktioner. Et program med denne tilladelse kan skifte netværk, slå telefonens radio til og fra og lignende uden nogensinde at underrette dig." + "læs telefontilstand" + "Tillader programmet at få adgang til enhedens telefonfunktioner. Et program med denne tilladelse kan afgøre denne telefons nummer, om et opkald er aktivt, nummeret som opkaldet er forbundet til osv." + "afhold telefonen fra at gå i dvale" + "Tillader et program at forhindre telefonen i at gå i dvale." + "Tænd eller sluk for telefonen" + "Tillader programmet at slå telefonen til eller fra." + "kør i fabriksindstillet testtilstand" + "Kør som en producenttest på lavt niveau. Giver fuld adgang til telefonens hardware. Kun tilgængeligt når en telefon kører i producenttesttilstand." + "angiv tapet" + "Tillader programmet at opsætte systemets tapet." + "opsæt tip til tapetstørrelse" + "Tillader programmet at opsætte størrelsestip for systemets tapet." + "nulstil system til fabriksstandarder" + "Tillader et program fuldstændig at nulstille systemet til fabriksindstillingerne, slette alle data, konfigurationen og installerede programmer." + "indstil tidszone" + "Tillader et program at ændre telefonens tidszone." + "opdag kendte konti" + "Tillader et program at hente listen over konti, der er kendt af telefonen." + "vis netværkstilstand" + "Tillader et program at vise tilstanden for alle netværk." + "Fuld internetadgang" + "Tillader et program at oprette netværks-sockets." + "skriv indstillinger for adgangspunktnavn" + "Tillader et program at ændre APN-indstillingerne, som f.eks. enhver APNs Proxy og Port." + "skift netværksforbindelse" + "Tillader et program at ændre netværksforbindelsens tilstand." + "skift brugerindstilling for baggrundsdata" + "Tillader et program at ændre brugerindstillingerne for baggrundsdata." + "vis Wi-Fi-tilstand" + "Tillader et program at vise oplysninger om Wi-Fi-tilstanden." + "skift Wi-Fi-tilstand" + "Tillader et program at oprette og afbryde forbindelse fra Wi-Fi-adgangspunkter og foretage ændringer til konfigurerede Wi-Fi-netværk." + + + + + "bluetooth-administration" + "Tillader et program at konfigurere den lokale Bluetooth-telefon samt at opdage og parre med fjerne enheder." + "opret Bluetooth-forbindelser" + "Tillader et program at vise konfigurationen af den lokale Bluetooth-telefon samt at oprette og acceptere forbindelse med parrede enheder." + "deaktiver tastaturlås" + "Tillader et program at deaktivere tastaturlåsen og al associeret adgangskodesikkerhed. Et legitimt eksempel på dette er, at telefonen deaktiverer tastaturlåsen, når der modtages et indgående telefonopkald, og genaktiverer tastaturlåsen, når opkaldet er afsluttet." + "læs synkroniseringsindstillinger" + "Tillader et program at læse synkroniseringsindstillingerne, som f.eks. om synkronisering er aktiveret for kontaktpersoner." + "skriv synkroniseringsindstillinger" + "Tillader et program at ændre synkroniseringsindstillingerne, som f.eks. om synkronisering er aktiveret for kontaktpersoner." + "læs synkroniseringsstatistikker" + "Tillader et program at læse synkroniseringsstatistikkerne, som f.eks. oversigt over forekomne synkroniseringer." + "læs abonnerede feeds" + "Lader et program få detaljer om de aktuelt synkroniserede feeds." + "skriv abonnerede feeds" + "Tillader et program at ændre dine aktuelle synkroniserede feeds. Dette kan muligvis lade et ondsindet program ændre dine synkroniserede feeds." + "læs brugerdefineret ordbog" + "Tillader et program at læse alle private ord, navne og sætninger, som brugeren eventuelt har gemt i brugerordbogen." + "skriv til den brugerdefinerede mappe" + "Tillader et program at skrive nye ord i brugermappen." + + + + + + "Start" + "Mobil" + "Arbejde" + "Arbejdsfax" + "Hjemmefax" + "Personsøger" + "Andet" + "Tilpasset" + + + "Start" + "Arbejde" + "Anden" + "Tilpasset" + + "Mobil" + + "Start" + "Arbejde" + "Anden" + "Tilpasset" + + + "Start" + "Arbejde" + "Anden" + "Tilpasset" + + + "Arbejde" + "Anden" + "Tilpasset" + + + "AIM" + "Windows Live" + "Yahoo" + "Skype" + "QQ" + "Google Talk" + "ICQ" + "Jabber" + + "Indtast PIN-kode" + "Forkert PIN-kode!" + "Tryk på Menu og dernæst på 0 for at låse op." + "Nødnummer" + "(Ingen tjeneste)" + "Skærmen er låst." + "Tryk på Menu for at låse op eller foretage et nødopkald." + "Tryk på Menu for at låse op." + "Tegn mønster til at låse op" + "Nødopkald" + "Rigtigt!" + "Beklager! Prøv igen" + "Oplader (%d%%)" + + + "Tilslut din oplader." + "Der er ikke noget SIM-kort." + "Der er ikke noget SIM-kort i telefonen." + "Indsæt et SIM-kort." + "Netværket er låst" + "SIM-kort er låst med PUK-koden." + "Se brugervejledningen, eller kontakt kundeservice." + "SIM-kortet er låst." + "Låser SIM-kortet op ..." + "Du har tegnet dit mønster til at låse op forkert %d gange. "\n\n"Prøv igen om %d sekunder." + "Du har tegnet dit mønster til at låse op forkert %d gange. Efter %d forsøg mere vil du blive bedt om at låse din telefon op ved hjælp af dit Google-login"\n\n" Prøv igen om %d sekunder." + "Prøv igen om %d sekunder." + "Har du glemt mønster?" + "For mange mønsterforsøg!" + "For at låse op skal du logge ind med din Google-konto" + "Brugernavn (e-mail)" + "Adgangskode" + "Log ind" + "Ugyldigt brugernavn eller ugyldig adgangskode." + "%-l%P" + "%-l%p" + + + "Ingen meddelelser" + "Løbende" + "Meddelelser" + "%d%%" + "Oplader ..." + "Forbind oplader" + "Batteriet er ved at blive tomt:" + "mindre end %d%% tilbage." + + + "Fabrikstest mislykkedes" + "Handlingen FACTORY_TEST understøttes kun af pakker installeret i /system/app." + "Der blev ikke fundet nogen pakke, som leverer handlingen FACTORY_TEST." + "Genstart" + "Siden på \'%s\' siger:" + "Javascript" + "Naviger væk fra denne side?"\n\n"%s"\n\n" Vælg OK for at fortsætte eller Annuller for at blive på den aktuelle side." + "Bekræft" + + + + + + + + + "Ønsker du, at browseren skal huske denne adgangskode?" + "Ikke nu" + "Husk" + "Aldrig" + "Du har ikke tilladelse til at åbne denne side." + "Teksten er kopieret til udklipsholderen." + "Flere" + "Menu+" + "plads" + "indtast" + "slet" + "Søg" + "For 1 måned siden" + "Før for 1 måned siden" + + "For 1 sekund siden" + "For %d sekunder siden" + + + "For 1 minut siden" + "For %d minutter siden" + + + "For 1 time siden" + "For %d timer siden" + + + "i går" + "For %d dage siden" + + + "om 1 sekund" + "om %d sekunder" + + + "om 1 minut" + "om %d minutter" + + + "om 1 time" + "om %d timer" + + + "i morgen" + "om %d dage" + + + "For 1 sek. siden" + "For %d sek. siden" + + + "For 1 min. siden" + "For %d min. siden" + + + "For 1 time siden" + "For %d timer siden" + + + "i går" + "For %d dage siden" + + + "om 1 sek." + "om %d sekunder" + + + "om 1 min." + "om %d min." + + + "om 1 time" + "om %d timer" + + + "i morgen" + "om %d dage" + + "den %s" + "kl. %s" + "i %s" + "dag" + "dage" + "time" + "timer" + "min." + "min." + "sek." + "sek." + "uge" + "uger" + "år" + "år" + "Hver ugedag (man.-fre.)" + "Dagligt" + "Ugentlig hver %s" + "Månedligt" + "Årligt" + "Video kan ikke afspilles" + "Beklager! Denne video er ikke gyldig til streaming på denne enhed." + "Beklager! Denne video kan ikke afspilles." + "OK" + "%1$s, %2$s" + "middag" + "Middag" + "midnat" + "Midnat" + "%1$02d:%2$02d" + "%1$d:%2$02d:%3$02d" + "Vælg alle" + "Vælg tekst" + "Stands med at vælge tekst" + "Klip" + "Klip alle" + "Kopier" + "Kopier alle" + "Indsæt" + "Kopier webadresse" + "Inputmetode" + "Føj \"%s\" til ordbog" + "Rediger tekst" + "Der er ikke så meget plads tilbage" + "Der er næsten ikke mere plads på telefonen." + "OK" + "Annuller" + "OK" + "Annuller" + "Bemærk" + "TIL" + "FRA" + "Afslut handling ved hjælp af" + "Brug som standard til denne handling." + "Ryd standard i Startindstillinger > Programmer > Administrer programmer." + "Vælg en handling" + "Der er ingen programmer, der kan foretage denne handling." + "Beklager!" + "Programmet %1$s (proces %2$s) er standset uventet. Prøv igen." + "Processen %1$s er standset uventet. Prøv igen." + "Beklager!" + "Aktivitet %1$s (i programmet %2$s) svarer ikke." + "Aktivitet %1$s (igangværende %2$s) svarer ikke." + "Programmet %1$s (igangværende %2$s) svarer ikke." + "Processen %1$s svarer ikke." + "Tving til at lukke" + + + "Vent" + "Fejlretning" + "Vælg en handling for teksten" + "Opkaldslydstyrke" + "Medielydstyrke" + "Spiller gennem Bluetooth" + "Opkaldslydstyrke" + "Bluetooth-lydstyrke under opkald" + "Alarmlydstyrke" + "Meddelelseslydstyrke" + "Lydstyrke" + "Standardringetone" + "Standardringetone (%1$s)" + "Lydløs" + "Ringetoner" + "Ukendt ringetone" + + "Wi-Fi-netværk tilgængeligt" + "Tilgængelige Wi-Fi-netværk" + + + "Åbent Wi-Fi-netværk tilgængeligt" + "Der er åbne Wi-Fi-netværk tilgængelige" + + "Indsæt tegn" + "Ukendt program" + "Sender SMS-beskeder" + "Der sendes et stort antal SMS-beskeder. Vælg \"OK\" for at fortsætte eller \"Annuller\" for at stoppe med at sende." + "OK" + "Annuller" + "Indstil" + "Standard" + "Der kræves ingen tilladelser" + "Skjul" + "Vis alle" + "Indlæser ..." + "USB forbundet" + "Du har forbundet din telefon til din computer via USB. Vælg \"Monter\", hvis du ønsker at kopiere filer mellem din computer og din telefons SD-kort." + "Monter" + "Indsæt ikke" + "Der opstod et problem med at bruge dit SD-kort til USB-lagring." + "USB forbundet" + "Vælg for at kopiere filer til/fra din computer." + "Slå USB-lagringen fra" + "Vælg for at slå USB-lagring fra." + "Slå USB-lagring fra" + "Inden du slår USB-lagringen fra, skal du sørge for, at du demonterer USB-værten. Vælg \"Slå fra\" for at slå USB-lagringen fra." + "Slå fra" + "Annuller" + "Der opstod et problem med at slå USB-lagringen fra. Sørg for, at du har demonteret USB-værten, og prøv så igen." + "Formater SD-kort" + "Er du sikker på, du ønsker at formatere SD-kortet? Alle data på kortet mistes." + "Formater" + + + + + "Vælg inputmetode" + " ABCDEFGHIJKLMNOPQRSTUVWXYZ" + " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "kandidater" + "Forbereder SD-kort" + + + "Blankt SD-kort" + + + "Beskadiget SD-kort" + + + "SD-kort blev uventet fjernet" + "Demonter SD-kortet inden fjernelse for at undgå tab af data." + "SD-kortet kan fjernes sikkert" + + + "SD-kortet er fjernet" + + + "Der blev ikke fundet nogen matchende aktiviteter" + "opdater brugerstatistikker for komponenter" + "Tillader ændring af indsamlede brugerstatistikker for komponenter. Ikke til brug til normale programmer." + "Tryk to gange for zoomkontrol" + "Der opstod en fejl under forøgelsen af widgeten" + "Gå" + "Søg" + "Send" + "Næste" + "Færdig" + "Udfør" + "Ring til nummer"\n"ved hjælp af %s" + "Opret kontaktperson"\n"ved hjælp af %s" + + + + + diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index dfb454991aa4d..56d9ef829641a 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -21,6 +21,7 @@ "GB" "TB" "PB" + "%1$s %2$s" "<Unbenannt>" "…" "(Keine Telefonnummer)" @@ -43,11 +44,17 @@ "Geben Sie zum Entsperren der SIM-Karte den PUK2 ein." "Anrufer-ID für eingehenden Anruf" "Anrufer-ID für abgehenden Anruf" - "Anrufweiterleitung" + "Rufweiterleitung" "Anklopfen" "Anrufsperre" "Passwort-Änderung" "PIN-Änderung" + "Rufnummer vorhanden" + "Rufnummer begrenzt" + "Dreierkonferenz" + "Ablehnung unerwünschter Anrufe" + "Rufnummernübermittlung" + "Bitte nicht stören" "Anrufer-ID ist standardmäßig beschränkt. Nächster Anruf: Beschränkt" "Anrufer-ID ist standardmäßig beschränkt. Nächster Anruf: Nicht beschränkt" "Anrufer-ID ist standardmäßig nicht beschränkt. Nächster Anruf: Beschränkt" @@ -67,11 +74,27 @@ "Synchron" "Paket" "PAD" + "Roaming-Anzeige ein" + "Roaming-Anzeige aus" + "Roaming-Anzeige blinkend" + "Außerhalb der Netzwerkumgebung" + "Außerhalb des Gebäudes" + "Roaming - Bevorzugtes System" + "Roaming - Verfügbares System" + "Roaming - Allianzpartner" + "Roaming - Premiumpartner" + "Roaming - Volle Dienstfunktionalität" + "Roaming - Partielle Dienstfunktionalität" + "Roaming-Banner ein" + "Roaming-Banner aus" + "Suche nach Dienst" "{0}: Nicht weitergeleitet" "{0}: {1}" "{0}{1} nach {2} Sekunden." "{0}: Nicht weitergeleitet" "{0}: Nicht weitergeleitet" + "Funktionscode abgeschlossen" + "Verbindungsproblem oder ungültiger Funktionscode" "OK" "Auf der Webseite ist ein Fehler aufgetreten." "Die URL konnte nicht gefunden werden." @@ -88,6 +111,7 @@ "Auf die Datei konnte nicht zugegriffen werden." "Die angeforderte Datei wurde nicht gefunden." "Es werden zurzeit zu viele Anfragen verarbeitet. Versuchen Sie es später erneut." + "Das Zertifikat wird im Schlüsselspeicher des Systems gespeichert." "Synchronisieren" "Synchronisieren" "Zu viele %s gelöscht." @@ -108,9 +132,9 @@ "Lautlos" "Ton ist bereits AUS" "Ton ist momentan AN" - "Flugzeugmodus" - "Flugzeugmodus ist AN" - "Flugzeugmodus ist AUS" + "Flugmodus" + "Flugmodus ist AN" + "Flugmodus ist AUS" "Abgesicherter Modus" "Android System" "Kostenpflichtige Dienste" @@ -133,6 +157,8 @@ "Zugriff und Steuerung des Systems auf niedrigerer Ebene." "Entwickler-Tools" "Funktionen nur für Anwendungsentwickler vorgesehen." + "Speicher" + "Greift auf die SD-Karte zu." "Statusleiste deaktivieren oder ändern" "Ermöglicht der Anwendung, die Statusanzeige zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen." "Statusleiste ein-/ausblenden" @@ -165,6 +191,10 @@ "Ermöglicht einer Anwendung, alle Aktivitäten, die im Vordergrund ablaufen, zu beenden und in den Hintergrund zu schieben. Sollte nicht für normale Anwendungen benötigt werden." "Systeminternen Status abrufen" "Ermöglicht einer Anwendung, den internen Status des Systems abzurufen. Schädliche Anwendungen rufen hierbei möglicherweise eine Vielzahl an privaten und geschützten Daten ab, die Sie in der Regel nicht benötigen würden." + "partielles Herunterfahren" + "Versetzt den Aktivitätsmanager in einen heruntergefahrenen Zustand. Führt kein vollständiges Herunterfahren aus." + "Anwendungswechsel verhindern" + "Hindert den Nutzer daran, zu einer anderen Anwendung zu wechseln" "Start von Anwendungen überwachen und steuern" "Ermöglicht der Anwendung, den Start von Systemaktivitäten zu überwachen und zu steuern. Schädliche Anwendungen können so das gesamte System beeinträchtigen. Diese Berechtigung wird nur zu Entwicklungszwecken und nie für die normale Telefonnutzung benötigt." "Broadcast ohne Paket senden" @@ -179,6 +209,8 @@ "Überlässt einer Anwendung die Entscheidung, ob Aktivitäten beendet werden, sobald Sie in den Hintergrund rücken. Wird nicht für normale Anwendungen benötigt." "Akku-Daten ändern" "Ermöglicht die Änderung von gesammelten Akku-Daten. Nicht für normale Anwendungen vorgesehen." + "Systemsicherung und -wiederherstellung kontrollieren" + "Ermöglicht der Anwendung, den Sicherungs- und Wiederherstellungsmechanismus des Systems zu kontrollieren. Nicht für normale Anwendungen vorgesehen." "nicht autorisierte Fenster anzeigen" "Ermöglicht die Erstellung von Fenstern, die von der Benutzeroberfläche des internen Systems verwendet werden. Nicht für normale Anwendungen geeignet." "Warnungen auf Systemebene anzeigen" @@ -245,6 +277,8 @@ "Erstellt falsche Standortquellen für Testzwecke. Schädliche Anwendungen können so den von den echten Standortquellen wie GPS oder Netzwerkanbieter zurückgegebenen Standort und/oder Status überschreiben." "Auf zusätzliche Dienstanbieterbefehle für Standort zugreifen" "Zugriff auf zusätzliche Dienstanbieterbefehle für Standort. Schädliche Anwendungen könnten so die Funktionsweise von GPS oder anderen Standortquellen beeinträchtigen." + "Berechtigung zur Installation eines Standortanbieters" + "Erstellt falsche Standortquellen für Testzwecke. Schädliche Anwendungen können so den von den echten Standortquellen wie GPS oder Netzwerkanbieter zurückgegebenen Standort und/oder Status überschreiben oder Ihren Standort überwachen und an eine externe Quelle weitergeben." "genauer (GPS-) Standort" "Zugriff auf genaue Standortquellen wie GPS auf dem Telefon (falls verfügbar). Schädliche Anwendungen können damit bestimmen, so Sie sich befinden und so Ihren Akku zusätzlich belasten." "ungefährer (netzwerkbasierter) Standort" @@ -278,13 +312,13 @@ "Alle Telefonnummern direkt anrufen" "Ermöglicht der Anwendung, ohne Ihr Eingreifen eine beliebige Telefonnummer zu wählen, einschließlich Notfallnummern. Schädliche Anwendungen können so unnötige und illegale Anrufe an Notdienste tätigen." "Benachrichtigungen für Standortaktualisierung steuern" - "Ermöglicht die Aktivierung/Deaktivierung der Radio-Benachrichtigungen über Standort-Updates. Nicht für normale Anwendungen vorgesehen." + "Ermöglicht die Aktivierung/Deaktivierung der Mobilfunkbenachrichtigungen über Standort-Updates. Nicht für normale Anwendungen vorgesehen." "Auf Check-In-Eigenschaften zugreifen" "Ermöglicht den Schreib-/Lesezugriff auf vom Check-In-Service hochgeladene Elemente. Nicht für normale Anwendungen vorgesehen." "Widgets auswählen" "Ermöglicht der Anwendung, dem System zu melden, welche Widgets von welcher Anwendung verwendet werden können. Mit dieser Berechtigung können Anwendungen anderen Anwendungen Zugriff auf persönliche Daten gewähren. Nicht für normale Anwendungen vorgesehen." "Telefonstatus ändern" - "Ermöglicht einer Anwendung, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder das Radio des Telefons ein- und ausschalten, ohne Sie darüber zu informieren." + "Ermöglicht einer Anwendung, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder die Mobilfunkverbindung des Telefons ein- und ausschalten, ohne Sie darüber zu informieren." "Telefonstatus lesen" "Ermöglicht der Anwendung, auf die Telefonfunktionen des Gerätes zuzugreifen. Eine Anwendung mit dieser Berechtigung kann unter anderem bestimmen, welche Telefonnummer dieses Telefon verwendet, ob ein Anruf aktiv ist oder mit welcher Nummer der Anrufer verbunden ist." "Standby-Modus deaktivieren" @@ -317,6 +351,8 @@ "Ermöglicht einer Anwendung, die Informationen zum WLAN-Status einzusehen." "WLAN-Status ändern" "Ermöglicht einer Anwendung, eine Verbindung zu den WLAN-Zugangspunkten herzustellen und diese zu trennen oder Änderungen an den konfigurierten WLAN-Netzwerken vorzunehmen." + "WLAN-Multicast-Empfang zulassen" + "Ermöglicht einer Anwendung, Datenpakete zu empfangen, die nicht direkt an Ihr Gerät gerichtet sind. Dies kann bei der Erkennung von in der Nähe angebotenen Diensten hilfreich sein. Diese Einstellung verbraucht mehr Energie als der Nicht-Multicast-Modus." "Bluetooth-Verwaltung" "Ermöglicht einer Anwendung, das lokale Bluetooth-Telefon zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen." "Bluetooth-Verbindungen herstellen" @@ -337,6 +373,8 @@ "Erlaubt einer Anwendung, alle privaten Wörter, Namen und Ausdrücke zu lesen, die ein Nutzer in seinem Wörterbuch gespeichert hat." "in nutzerdefiniertes Wörterbuch schreiben" "Erlaubt einer Anwendung, neue Wörter in das Wörterbuch des Nutzers zu schreiben." + "SD-Karten-Inhalt ändern/löschen" + "Ermöglicht einer Anwendung, auf die SD-Karte zu schreiben" "Privat" "Mobil" @@ -353,6 +391,7 @@ "Andere" "Benutzerdefiniert" + "Mobil" "Privat" "Arbeit" @@ -382,17 +421,19 @@ "PIN-Code eingeben" "Falscher PIN-Code!" - "Drücken Sie zum Entsperren auf \"Menü\" und dann auf \"0\"." + "Drücken Sie zum Entsperren die Menütaste und dann auf \"0\"." "Notrufnummer" "(kein Dienst)" "Display gesperrt." - "Drücken Sie auf \"Menü\", um das Telefon zu entsperren oder einen Notruf zu tätigen." - "Drücken Sie zum Entsperren auf \"Menü\"." + "Drücken Sie die Menütaste, um das Telefon zu entsperren oder einen Notruf zu tätigen." + "Zum Entsperren die Menütaste drücken" "Schema für Entsperrung zeichnen" "Notruf" "Korrekt!" "Tut uns leid. Versuchen Sie es noch einmal." "Wird geladen (%d%%)" + + "Bitte Ladegerät anschließen" "Keine SIM-Karte." "Keine SIM-Karte im Telefon." @@ -400,7 +441,7 @@ "Netzwerk gesperrt" "SIM-Karte ist gesperrt. PUK-Eingabe erforderlich." "Weitere Informationen finden Sie in der Bedienungsanleitung oder wenden Sie sich an den Kundendienst." - "SIM-Karte ist gesperrt." + "Bitte PIN-Code eingeben" "SIM-Karte wird entsperrt..." "Sie haben Ihr Entsperrungsmuster %d-mal falsch gezeichnet. "\n\n"Versuchen Sie es in %d Sekunden erneut." "Sie haben Ihr Entsperrungsmuster %d-mal falsch gezeichnet. Nach %d weiteren erfolglosen Versuchen werden Sie aufgefordert, Ihr Telefon mithilfe Ihrer Google-Anmeldeinformationen zu entsperren. "\n\n"Versuchen Sie es in %d Sekunden erneut." @@ -414,7 +455,8 @@ "Ungültiger Nutzername oder ungültiges Passwort." "%-l%P" "%-l%p" - "Benachrichtigungen löschen" + + "Keine Benachrichtigungen" "Aktuell" "Benachrichtigungen" @@ -423,6 +465,7 @@ "Ladegerät anschließen" "Akku ist fast leer." "Nur noch weniger als %d%% vorhanden." + "Warum?" "Werkstest fehlgeschlagen" "Die Aktion FACTORY_TEST wird nur für unter \"/system/app\" gespeicherte Pakete unterstützt." "Es wurden kein Paket mit der Aktion FACTORY_TEST gefunden." @@ -431,6 +474,10 @@ "JavaScript" "Von dieser Seite navigieren?"\n\n"%s"\n\n"Wählen Sie \"OK\", um fortzufahren, oder wählen Sie \"Abbrechen\", um auf der aktuellen Seite zu bleiben." "Bestätigen" + "Browserverlauf und Lesezeichen lesen" + "Ermöglicht der Anwendung, alle URLs, die mit dem Browser besucht wurden, sowie alle Lesezeichen des Browsers zu lesen." + "Browserverlauf und Lesezeichen schreiben" + "Ermöglicht einer Anwendung, den auf Ihrem Telefon gespeicherten Browserverlauf und die Lesezeichen zu ändern. Schädliche Anwendungen können so Ihre Browserdaten löschen oder ändern." "Möchten Sie, dass der Browser dieses Passwort speichert?" "Nicht jetzt" "Speichern" @@ -538,10 +585,6 @@ "Mittag" "Mitternacht" "Mitternacht" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "Alles auswählen" @@ -565,7 +608,7 @@ "Achtung" "EIN" "AUS" - "Aktion beenden mit" + "Aktion durchführen mit" "Standardmäßig für diese Aktion verwenden." "Löschen Sie die Standardeinstellungen unter \"Starteinstellungen > Anwendungen > Anwendungen verwalten\"." "Aktion auswählen" @@ -579,6 +622,7 @@ "Anwendung %1$s (in Prozess %2$s) reagiert nicht." "Prozess %1$s reagiert nicht." "Schließen erzwingen" + "Bericht" "Warten" "Fehler suchen" "Aktion für Text auswählen" @@ -632,22 +676,26 @@ "SD-Karte formatieren" "Möchten Sie die SD-Karte wirklich formatieren? Alle Daten auf Ihrer Karte gehen dann verloren." "Format" + + + + "Eingabemethode auswählen" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "Kandidaten" "SD-Karte wird vorbereitet" - "Nach Fehlern wird gesucht" + "Nach Fehlern wird gesucht." "SD-Karte leer" - "Die SD-Karte ist leer oder verwendet ein Dateisystem, das nicht unterstützt wird." + "SD-Karte ist leer oder verfügt über ein nicht unterstütztes Dateisystem." "Beschädigte SD-Karte" "Die SD-Karte ist beschädigt. Sie müssen Ihre Karte eventuell neu formatieren." "SD-Karte unerwartet entfernt" "SD-Karte vor dem Entnehmen trennen, um Datenverlust zu vermeiden." "SD-Karte\nkann entfernt werden." - "Die SD-Karte kann jetzt entfernt werden." + "Die SD-Karte kann entfernt werden." "SD-Karte entfernt" - "Die SD-Karte wurde entfernt. Legen Sie eine neue SD-Karte ein, um den Speicherplatz Ihres Geräts zu erweitern." + "SD-Karte entfernt. Legen Sie eine neue ein." "Keine passenden Aktivitäten gefunden" "Nutzungsstatistik der Komponente aktualisieren" "Ermöglicht die Änderung von gesammelten Nutzungsstatistiken der Komponente. Nicht für normale Anwendungen vorgesehen." @@ -661,4 +709,6 @@ "Ausführen" "Nummer"\n"mit %s wählen" "Neuer Kontakt"\n"mit %s erstellen" + "aktiviert" + "nicht aktiviert" diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml new file mode 100644 index 0000000000000..5c6ba5ac79cfc --- /dev/null +++ b/core/res/res/values-el/strings.xml @@ -0,0 +1,765 @@ + + + + "B" + "KB" + "MB" + "GB" + "TB" + "PB" + + + "<χωρίς τίτλο>" + "…" + "(Δεν υπάρχει τηλεφωνικός αριθμός)" + "(Άγνωστο)" + "Αυτόματος τηλεφωνητής" + "MSISDN1" + "Πρόβλημα σύνδεσης ή μη έγκυρος κώδικας MMI." + "Η υπηρεσία ενεργοποιήθηκε." + "Η υπηρεσία ενεργοποιήθηκε για:" + "Η υπηρεσία έχει απενεργοποιηθεί." + "Η εγγραφή ήταν επιτυχής." + "Η διαγραφή ήταν επιτυχής." + "Εσφαλμένος κωδικός πρόσβασης." + "Το MMI ολοκληρώθηκε." + "Ο παλιός αριθμός PIN που πληκτρολογήσατε είναι εσφαλμένος." + "Ο κωδικός PUK που πληκτρολογήσατε είναι εσφαλμένος." + "Οι αριθμοί PIN που πληκτρολογήσατε δεν ταιριάζουν." + "Πληκτρολογήστε έναν αριθμό PIN μεγέθους 4 έως 8 αριθμών." + "Η κάρτα SIM έχει κλειδωθεί με κωδικό PUK. Πληκτρολογήστε τον κωδικό PUK για να την ξεκλειδώσετε." + "Πληκτρολογήστε τον κωδικό PUK2 για την κατάργηση αποκλεισμού της κάρτας SIM." + "Εισερχόμενη αναγνώριση κλήσης" + "Εξερχόμενη αναγνώριση κλήσης" + "Προώθηση κλήσεων" + "Αναμονή κλήσης" + "Φραγή κλήσεων" + "Αλλαγή κωδικού πρόσβασης" + "Αλλαγή αριθμού PIN" + + + + + + + + + + + + + "Η αναγνώριση κλήσης βρίσκεται από προεπιλογή στην \"περιορισμένη\". Επόμενη κλήση: Περιορισμένη." + "Η αναγνώριση κλήσης βρίσκεται από προεπιλογή στην \"περιορισμένη\". Επόμενη κλήση: Μη περιορισμένη" + "Η αναγνώριση κλήσης βρίσκεται από προεπιλογή στην \"μη περιορισμένη\". Επόμενη κλήση: Περιορισμένη." + "Η αναγνώριση κλήσης βρίσκεται από προεπιλογή στην \"μη περιορισμένη\". Επόμενη κλήση: Μη περιορισμένη" + "Η υπηρεσία δεν προβλέπεται." + "Δεν είναι δυνατή η αλλαγή της ρύθμισης αναγνώρισης κλήσης." + "Η περιορισμένη πρόσβαση άλλαξε" + "Η υπηρεσία δεδομένων είναι αποκλεισμένη." + "Η υπηρεσία έκτακτης ανάγκης είναι αποκλεισμένη." + "Η φωνητική υπηρεσία/υπηρεσία SMS είναι αποκλεισμένη." + "Όλες οι φωνητικές υπηρεσίες/υπηρεσίες SMS έχουν αποκλειστεί." + "Φωνή" + "Δεδομένα" + "ΦΑΞ" + "SMS" + "Μη συγχρονισμένα" + "Συγχρονισμός" + "Πακέτο" + "PAD" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "{0}: Δεν προωθήθηκε" + "{0}: {1}" + "{0}: {1} μετά από {2} δευτερόλεπτα" + "{0}: Δεν προωθήθηκε" + "{0}: Δεν προωθήθηκε" + + + + + "OK" + "Η ιστοσελίδα περιέχει ένα σφάλμα." + "Δεν ήταν δυνατή η εύρεση της διεύθυνσης URL." + "Το πλάνο ελέγχου ταυτότητας ιστοτόπου δεν υποστηρίζεται." + "Ο έλεγχος ταυτότητας δεν ήταν επιτυχής." + "Ο έλεγχος ταυτότητας μέσω του διακομιστή μεσολάβησης δεν ήταν επιτυχής." + "Η σύνδεση στον διακομιστή δεν ήταν επιτυχής." + "Η επικοινωνία με τον διακομιστή απέτυχε. Προσπαθήστε ξανά αργότερα." + "Το όριο χρόνου της σύνδεσης στον διακομιστή έληξε." + "Αυτή η σελίδα περιέχει πάρα πολλές ανακατευθύνσεις διακομιστή." + "Το πρωτόκολλο δεν υποστηρίζεται." + "Δεν ήταν δυνατή η επίτευξη ασφαλούς σύνδεσης." + "Δεν ήταν δυνατό το άνοιγμα της σελίδας επειδή η διεύθυνση URL δεν είναι έγκυρη." + "Η πρόσβαση στο αρχείο δεν ήταν δυνατή." + "Το αρχείο που ζητήθηκε δεν βρέθηκε." + "Πραγματοποιείται επεξεργασία πάρα πολλών αιτημάτων. Προσπαθήστε ξανά αργότερα." + + + "Συγχρονισμός" + "Συγχρονισμός" + "Πάρα πολλές %s διαγραφές." + "Ο αποθηκευτικός χώρος του τηλεφώνου είναι πλήρης! Διαγράψτε μερικά αρχεία για να δημιουργήσετε ελεύθερο χώρο." + "Για εμένα" + "Επιλογές τηλεφώνου" + "Λειτουργία σίγασης" + "Ενεργοποίηση ασύρματου" + "Απενεργοποίηση ασύρματου" + "Κλείδωμα οθόνης" + "Απενεργοποίηση" + "Απενεργοποίηση..." + "Το τηλέφωνό σας θα απενεργοποιηθεί." + "Δεν υπάρχουν πρόσφατες εφαρμογές." + "Επιλογές τηλεφώνου" + "Κλείδωμα οθόνης" + "Απενεργοποίηση" + "Λειτουργία σίγασης" + "Ο ήχος είναι απενεργοποιημένος" + "Ο ήχος είναι ενεργοποιημένος" + "Λειτουργία πτήσης" + "Η λειτουργία πτήσης είναι ενεργοποιημένη." + "Η λειτουργία πτήσης είναι απενεργοποιημένη" + "Ασφαλής λειτουργία" + "Σύστημα Android" + "Υπηρεσίες επί πληρωμή." + "Επιτρέπει σε εφαρμογές να πραγματοποιήσουν ενέργειες για τις οποίες ενδέχεται να χρεωθείτε." + "Τα μηνύματά σας" + "Ανάγνωση και εγγραφή των μηνυμάτων SMS, των μηνυμάτων ηλεκτρονικού ταχυδρομείου και άλλων μηνυμάτων." + "Οι προσωπικές σας πληροφορίες" + "Άμεση πρόσβαση στις επαφές και στο ημερολόγιό σας που είναι αποθηκευμένα στο τηλέφωνο." + "Η τοποθεσία σας" + "Παρακολούθηση της φυσικής τοποθεσίας σας" + "Επικοινωνία δικτύου" + "Επιτρέπει σε εφαρμογές να αποκτήσουν πρόσβαση σε διάφορες λειτουργίες δικτύου." + "Οι λογαριασμοί σας Google" + "Πρόσβαση στους διαθέσιμους λογαριασμούς Google." + "Στοιχεία ελέγχου υλικού" + "Άμεση πρόσβαση στο υλικό της συσκευής τηλεφώνου." + "Τηλεφωνικές κλήσεις" + "Παρακολούθηση, καταγραφή και επεξεργασία τηλεφωνικών κλήσεων." + "Εργαλεία συστήματος" + "Χαμηλού επιπέδου πρόσβαση και έλεγχος του συστήματος." + "Εργαλεία ανάπτυξης" + "Δυνατότητες που είναι απαραίτητες μόνο σε προγραμματιστές εφαρμογών." + + + + + "απενεργοποίηση ή τροποποίηση γραμμής κατάστασης" + "Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος." + "ανάπτυξη/σύμπτυξη γραμμής κατάστασης" + "Επιτρέπει σε μια εφαρμογή να αναπτύξει ή να συμπτύξει την γραμμή κατάστασης." + "φραγή εξερχόμενων κλήσεων" + "Επιτρέπει σε μια εφαρμογή την επεξεργασία εξερχόμενων κλήσεων και την αλλαγή του αριθμού που πρόκειται να κληθεί. Κακόβουλες εφαρμογές ενδέχεται να παρακολουθούν, να ανακατευθύνουν ή να παρεμποδίζουν εξερχόμενες κλήσεις." + "λήψη SMS" + "Επιτρέπει σε μια εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων SMS. Κακόβουλες εφαρμογές ενδέχεται να παρακολουθούν τα μηνύματά σας ή να τα διαγράφουν χωρίς να σας ειδοποιούν." + "λήψη MMS" + "Επιτρέπει σε μια εφαρμογή την λήψη και την επεξεργασία μηνυμάτων MMS. Κακόβουλες εφαρμογές ενδέχεται να παρακολουθούν τα μηνύματά σας ή να τα διαγράφουν χωρίς να σας ειδοποιούν." + "αποστολή μηνυμάτων SMS" + "Επιτρέπει σε μια εφαρμογή την αποστολή μηνυμάτων SMS. Κακόβουλες εφαρμογές ενδέχεται να σας χρεώσουν αποστέλλοντας μηνύματα χωρίς την έγκρισή σας." + "ανάγνωση μηνυμάτων SMS ή MMS" + "Επιτρέπει σε μια εφαρμογή την ανάγνωση μηνυμάτων SMS που είναι αποθηκευμένα στο τηλέφωνό σας ή στην κάρτα SIM. Κακόβουλες εφαρμογές ενδέχεται να αναγνώσουν τα εμπιστευτικά σας μηνύματα." + "επεξεργασία SMS ή MMS" + "Επιτρέπει σε μια εφαρμογή την εγγραφή σε μηνύματα SMS που είναι αποθηκευμένα στο τηλέφωνό σας ή στην κάρτα SIM. Κακόβουλες εφαρμογές ενδέχεται να διαγράψουν τα μηνύματά σας." + "λήψη WAP" + "Επιτρέπει σε μια εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων WAP. Κακόβουλες εφαρμογές ενδέχεται να παρακολουθούν τα μηνύματά σας ή να τα διαγράφουν χωρίς να σας ειδοποιούν." + "ανάκτηση εκτελούμενων εφαρμογών" + "Επιτρέπει σε μια εφαρμογή να ανακτήσει πληροφορίες σχετικά με τις τρέχουσες εκτελούμενες εργασίες και στις εργασίες που έχουν πρόσφατα εκτελεστεί. Ενδέχεται να δώσει τη δυνατότητα σε κακόβουλες εφαρμογές να ανακαλύψουν ιδιωτικές πληροφορίες σχετικά με άλλες εφαρμογές." + "αναδιάταξη εκτελούμενων εφαρμογών" + "Επιτρέπει σε μια εφαρμογή τη μετακίνηση εργασιών στο προσκήνιο και στο φόντο. Κακόβουλες εφαρμογές μπορούν να προωθηθούν στο προσκήνιο χωρίς να μπορείτε να τις ελέγξετε." + "ενεργοποίηση εντοπισμού σφαλμάτων εφαρμογής" + "Επιτρέπει σε μια εφαρμογή να ενεργοποιήσει τον εντοπισμό σφαλμάτων για μια άλλη εφαρμογή. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να τερματίσουν άλλες εφαρμογές." + "αλλαγή των ρυθμίσεων του UI" + "Επιτρέπει σε μια εφαρμογή την αλλαγή της τρέχουσας διαμόρφωσης, όπως οι τοπικές ρυθμίσεις ή το μέγεθος γραμματοσειράς γενικά." + "επανεκκίνηση άλλων εφαρμογών" + "Επιτρέπει σε μια εφαρμογή να πραγματοποιήσει αναγκαστική επανεκκίνηση άλλων εφαρμογών." + "αναγκαστικός τερματισμός εφαρμογής" + "Επιτρέπει σε μια εφαρμογή να εξαναγκάσει οποιαδήποτε δραστηριότητα που βρίσκεται στο προσκήνιο να κλείσει και να μεταβεί στο φόντο. Δεν είναι απαραίτητο για κανονικές εφαρμογές." + "ανάκτηση εσωτερικής κατάστασης συστήματος" + "Επιτρέπει σε μια εφαρμογή να ανακτήσει την εσωτερική κατάσταση του συστήματος. Κακόβουλες εφαρμογές ενδέχεται να ανακτήσουν μεγάλο εύρος ιδιωτικών και ασφαλών πληροφοριών, τις οποίες δεν χρειάζονται." + + + + + + + + + "παρακολούθηση και έλεγχος όλων των εκκινήσεων εφαρμογών" + "Επιτρέπει σε μια εφαρμογή να παρακολουθεί και να ελέγχει τον τρόπο με τον οποίο το σύστημα εκκινεί δραστηριότητες. Κακόβουλες εφαρμογές ενδέχεται να θέσουν σε κίνδυνο το σύστημα. Αυτή η άδεια είναι απαραίτητη μόνο για ανάπτυξη και ποτέ για κανονική χρήση τηλεφώνου." + "αποστολή εκπομπής χωρίς πακέτο" + "Επιτρέπει σε μια εφαρμογή την εκπομπή μια ειδοποίησης σχετικά με την κατάργηση ενός πακέτου εφαρμογών. Κακόβουλες εφαρμογές ενδέχεται να το χρησιμοποιήσουν για να τερματίσουν άλλες εκτελούμενες εφαρμογές." + "αποστολή εκπομπής που έχει ληφθεί με μήνυμα SMS" + "Επιτρέπει σε μια εφαρμογή την εκπομπή ειδοποίησης σχετικά με τη λήψη μηνύματος SMS. Κακόβουλες εφαρμογές ενδέχεται να το χρησιμοποιήσουν για την δημιουργία πλαστών εισερχόμενων μηνυμάτων SMS." + "αποστολή εκπομπής που έχει ληφθεί με WAP-PUSH" + "Επιτρέπει σε μια εφαρμογή να εκπέμψει μια ειδοποίηση σχετικά με τη λήψη μηνύματος WAP PUSH. Κακόβουλες εφαρμογές ενδέχεται να το χρησιμοποιήσουν για να δημιουργήσουν ψευδείς λήψεις μηνυμάτων MMS ή για να αντικαταστήσουν χωρίς ειδοποίηση το περιεχόμενο μιας ιστοσελίδας με κακόβουλες παραλλαγές." + "περιορισμός αριθμού εκτελούμενων διαδικασιών" + "Επιτρέπει σε μια εφαρμογή τον έλεγχο του μέγιστου αριθμού διαδικασιών που θα εκτελούνται. Δεν είναι ποτέ απαραίτητο για κανονικές εφαρμογές." + "κλείσιμο όλων των εφαρμογών στο φόντο" + "Επιτρέπει σε μια εφαρμογή να ελέγχει εάν οι δραστηριότητες ολοκληρώνονται πάντοτε μόλις μεταβούν στο φόντο. Δεν είναι ποτέ απαραίτητο για κανονικές εφαρμογές." + "τροποποίηση στατιστικών μπαταρίας" + "Επιτρέπει την τροποποίηση στατιστικών μπαταρίας που έχουν συλλεχθεί. Δεν πρέπει να χρησιμοποιείται από συνήθεις εφαρμογές." + + + + + "προβολή μη εξουσιοδοτημένων παραθύρων" + "Επιτρέπει τη δημιουργία παραθύρων που πρόκειται να χρησιμοποιηθούν από την εσωτερική διεπαφή χρήστη του συστήματος. Δεν πρέπει να χρησιμοποιείται από κανονικές εφαρμογές." + "εμφάνιση ειδοποιήσεων επιπέδου συστήματος" + "Επιτρέπει σε μια εφαρμογή την προβολή παραθύρων ειδοποίησης συστήματος. Κακόβουλες εφαρμογές μπορούν να εμφανιστούν σε ολόκληρη την οθόνη του τηλεφώνου." + "τροποποίηση καθολικής ταχύτητας κίνησης εικόνας" + "Επιτρέπει σε μια εφαρμογή την αλλαγή της καθολικής ταχύτητας κίνησης εικόνας (ταχύτερη ή βραδύτερη κίνηση) οποιαδήποτε στιγμή." + "διαχείριση αναγνωριστικών εφαρμογής" + "Επιτρέπει σε εφαρμογές τη δημιουργία και τη διαχείριση των δικών τους αναγνωριστικών, παρακάμπτοντας την κανονική διάταξη Z. Δεν είναι απαραίτητο για κανονικές εφαρμογές." + "πάτημα πλήκτρων και κουμπιών ελέγχου" + "Επιτρέπει σε μια εφαρμογή την απόδοση των γεγονότων εισόδου της (πατήματα πλήκτρων κ.λπ.) σε άλλες εφαρμογές. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να αναλάβουν τον έλεγχο του τηλεφώνου." + "καταγραφή των ενεργειών σας και των στοιχείων που πληκτρολογείτε" + "Επιτρέπει σε εφαρμογές να παρακολουθούν τα πλήκτρα που πατάτε, ακόμη και σε μια άλλη εφαρμογή (όπως π.χ. η καταχώρηση ενός κωδικού πρόσβασης). Δεν είναι απαραίτητο για συνήθεις εφαρμογές." + "δέσμευση σε μέθοδο εισόδου" + "Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας μεθόδου εισόδου. Δεν είναι απαραίτητο για συνήθεις εφαρμογές." + "αλλαγή προσανατολισμού οθόνης" + "Επιτρέπει σε μια εφαρμογή την αλλαγή της περιστροφής της οθόνης οποιαδήποτε στιγμή. Δεν είναι απαραίτητο για κανονικές εφαρμογές." + "αποστολή σημάτων Linux σε εφαρμογές" + "Επιτρέπει σε μια εφαρμογή την αποστολή αιτήματος για την αποστολή του παρεχόμενου σήματος σε όλες τις υπάρχουσες διαδικασίες." + "η εφαρμογή να εκτελείται συνεχώς" + "Επιτρέπει σε μια εφαρμογή την μετατροπή τμημάτων της σε συνεχή, ώστε το σύστημα να μην μπορεί να τη χρησιμοποιήσει για άλλες εφαρμογές." + "διαγραφή εφαρμογών" + "Επιτρέπει σε μια εφαρμογή τη διαγραφή πακέτων Android. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν σημαντικές εφαρμογές." + "διαγραφή δεδομένων άλλων εφαρμογών" + "Επιτρέπει σε μια εφαρμογή να εκκαθαρίζει τα δεδομένα χρήστη." + "διαγραφή προσωρινών μνημών άλλων εφαρμογών" + "Επιτρέπει σε μια εφαρμογή τη διαγραφή αρχείων προσωρινής μνήμης." + "μέτρηση αποθηκευτικού χώρου εφαρμογής" + "Επιτρέπει σε μια εφαρμογή να ανακτήσει τα μεγέθη κώδικα, δεδομένων και προσωρινής μνήμης" + "απευθείας εγκατάσταση εφαρμογών" + "Επιτρέπει σε μια εφαρμογή την εγκατάσταση νέων ή ενημερωμένων πακέτων Android. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να προσθέσουν νέες εφαρμογές με πολλές αυθαίρετες άδειες." + "διαγραφή όλων των δεδομένων προσωρινής μνήμης εφαρμογής" + "Επιτρέπει σε μια εφαρμογή να αυξήσει τον ελεύθερο χώρο αποθήκευσης του τηλεφώνου διαγράφοντας αρχεία από τον κατάλογο προσωρινής μνήμης της εφαρμογής. Η πρόσβαση είναι συνήθως πολύ περιορισμένη στη διαδικασία συστήματος." + "ανάγνωση αρχείων καταγραφής συστήματος" + "Επιτρέπει σε μια εφαρμογή να αναγνώσει τα αρχεία καταγραφής του συστήματος. Έτσι μπορεί να ανακαλύψει γενικές πληροφορίες σχετικά με τις δραστηριότητές σας στο τηλέφωνο, όμως δεν θα πρέπει να περιέχουν προσωπικές ή ιδιωτικές πληροφορίες." + "ανάγνωση/εγγραφή σε πόρους που ανήκουν στο διαγνωστικό" + "Επιτρέπει σε μια εφαρμογή την ανάγνωση και την εγγραφή σε πόρο που ανήκει στην ομάδα διαγνωστικού (π.χ. αρχεία στον κατάλογο /dev). Αυτό ενδέχεται να επηρεάσει την σταθερότητα και την ασφάλεια του συστήματος. Θα πρέπει να χρησιμοποιείται ΜΟΝΟ για διαγνωστικά υλικού του κατασκευαστή ή του χειριστή." + "ενεργοποίηση ή απενεργοποίηση στοιχείων εφαρμογής" + "Επιτρέπει σε μια εφαρμογή την επιλογή ενεργοποίησης ή μη ενός στοιχείου μιας άλλης εφαρμογής. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να απενεργοποιήσουν σημαντικές δυνατότητες του τηλεφώνου. Η χορήγηση άδειας πρέπει να γίνεται με προσοχή, καθώς είναι πιθανό τα στοιχεία μιας εφαρμογής να καταστούν ασυνεχή, ασταθή ή να είναι αδύνατον να χρησιμοποιηθούν." + "ορισμός προτιμώμενων εφαρμογών" + "Επιτρέπει σε μια εφαρμογή να τροποποιεί τις εφαρμογές που προτιμάτε. Αυτό ενδέχεται να δώσει τη δυνατότητα σε κακόβουλες εφαρμογές να αλλάξουν χωρίς ειδοποίηση τις εφαρμογές που εκτελούνται, \"ξεγελώντας\" τις υπάρχουσες εφαρμογές ώστε να συλλέξουν ιδιωτικά δεδομένα." + "τροποποίηση καθολικών ρυθμίσεων συστήματος" + "Επιτρέπει σε μια εφαρμογή την τροποποίηση των δεδομένων των ρυθμίσεων του συστήματος. Κακόβουλες εφαρμογές μπορούν να καταστρέψουν τη διαμόρφωση του συστήματός σας." + "τροποποίηση ασφαλών ρυθμίσεων συστήματος" + "Επιτρέπει σε μια εφαρμογή να τροποποιεί τα δεδομένα ασφαλών ρυθμίσεων συστήματος. Δεν πρέπει να χρησιμοποιείται από κανονικές εφαρμογές." + "μετατροπή του χάρτη υπηρεσιών Google" + "Επιτρέπει σε μια εφαρμογή την τροποποίηση του χάρτη υπηρεσιών Google. Δεν πρέπει να χρησιμοποιείται από κανονικές εφαρμογές." + "αυτόματη εκκίνηση κατά την εκκίνηση του υπολογιστή" + "Επιτρέπει σε μια εφαρμογή να ξεκινήσει αυτόματα μόλις ολοκληρωθεί η εκκίνηση του συστήματος. Αυτό ενδέχεται να καθυστερήσει την εκκίνηση του τηλεφώνου και να προκαλέσει γενική μείωση της ταχύτητας λειτουργίας του τηλεφώνου, καθώς η εφαρμογή θα εκτελείται συνεχώς." + "αποστολή εκπομπής sticky" + "Επιτρέπει σε μια εφαρμογή την αποστολή εκπομπών sticky, οι οποίες παραμένουν μετά το τέλος της εκπομπής. Κακόβουλες εφαρμογές μπορούν να μειώσουν την ταχύτητα λειτουργίας του τηλεφώνου ή να την καταστήσουν ασταθή χρησιμοποιώντας πολύ μεγάλο ποσό μνήμης." + "ανάγνωση δεδομένων επαφής" + "Επιτρέπει σε μια εφαρμογή την ανάγνωση όλων των δεδομένων επαφής (διεύθυνσης) που είναι αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να αποστείλουν τα δεδομένα σας σε τρίτους." + "εγγραφή δεδομένων επαφής" + "Επιτρέπει σε μια εφαρμογή να τροποποιεί τα δεδομένα επαφής (διεύθυνσης) που είναι αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν τα δεδομένα επαφών σας." + "εγγραφή δεδομένων κατόχου" + "Επιτρέπει σε μια εφαρμογή να τροποποιήσει τα δεδομένα κατόχου τηλεφώνου στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να τροποποιήσουν τα δεδομένα κατόχου." + "ανάγνωση δεδομένων κατόχου" + "Επιτρέπει σε μια εφαρμογή την ανάγνωση των δεδομένων κατόχου τηλεφώνου που είναι αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για την ανάγνωση δεδομένων κατόχου τηλεφώνου." + "ανάγνωση δεδομένων ημερολογίου" + "Επιτρέπει σε μια εφαρμογή να αναγνώσει όλα τα συμβάντα ημερολογίου που είναι αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να αποστείλουν συμβάντα ημερολογίου σε άλλους χρήστες." + "εγγραφή δεδομένων ημερολογίου" + "Επιτρέπει σε μια εφαρμογή την τροποποίηση των συμβάντων ημερολογίου που είναι αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν ή για να τροποποιήσουν τα δεδομένα ημερολογίου σας." + "δημιουργία ψευδών πηγών τοποθεσίας για δοκιμή" + "Δημιουργία εικονικών πηγών τοποθεσίας για δοκιμή. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να παρακάμψουν την τοποθεσία και/ή την κατάσταση που βρίσκουν πραγματικές πηγές τοποθεσίας, όπως πάροχοι GPS ή πάροχοι δικτύου." + "πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας" + "Πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας. Κακόβουλες εφαρμογές ενδέχεται να το χρησιμοποιήσουν ώστε να παρέμβουν στη λειτουργία του GPS ή άλλων πηγών τοποθεσίας." + + + + + "ακριβής τοποθεσία (GPS)" + "Πρόσβαση σε πηγές ακριβούς τοποθεσίας, όπως το Παγκόσμιο Σύστημα Εντοπισμού (GPS) στο τηλέφωνο, όπου αυτό είναι διαθέσιμο. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να προσδιορίσουν τη θέση που βρίσκεστε και ενδέχεται να καταναλώσουν επιπλέον ισχύ μπαταρίας." + "κατά προσέγγιση (βασισμένη στο δίκτυο) τοποθεσία" + "Πρόσβαση σε πηγές κατά προσέγγιση τοποθεσίας, όπως η βάση δεδομένων δικτύου κινητής τηλεφωνίας για τον κατά προσέγγιση προσδιορισμό της τοποθεσίας του τηλεφώνου, όπου αυτό είναι διαθέσιμο. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να προσδιορίσουν κατά προσέγγιση τη θέση σας." + "πρόσβαση στο SurfaceFlinger" + "Επιτρέπει σε μια εφαρμογή να χρησιμοποιεί λειτουργίες SurfaceFlinger χαμηλού επιπέδου." + "ανάγνωση προσωρινής μνήμης πλαισίου" + "Επιτρέπει στην εφαρμογή να χρησιμοποιήσει και να αναγνώσει το περιεχόμενο της προσωρινής μνήμης πλαισίου." + "αλλαγή των ρυθμίσεων ήχου" + "Επιτρέπει σε μια εφαρμογή να τροποποιήσει καθολικές ρυθμίσεις ήχου όπως ένταση ήχου και δρομολόγηση ήχου." + "εγγραφή ήχου" + "Επιτρέπει σε μια εφαρμογή την πρόσβαση στη διαδρομή εγγραφής ήχου." + "λήψη φωτογραφιών" + "Επιτρέπει σε μια εφαρμογή τη λήψη φωτογραφιών με την κάμερα. Αυτό επιτρέπει στην εφαρμογή να συλλέξει εικόνες, στις οποίες εστιάζει η κάμερα οποιαδήποτε στιγμή." + "μόνιμη απενεργοποίηση τηλεφώνου" + "Επιτρέπει στην εφαρμογή τη μόνιμη απενεργοποίηση όλων των λειτουργιών του τηλεφώνου, το οποίο είναι εξαιρετικά επικίνδυνο." + "αναγκαστική επανεκκίνηση τηλεφώνου" + "Επιτρέπει στην εφαρμογή να προκαλέσει αναγκαστική επανεκκίνηση του τηλεφώνου." + "Προσάρτηση και αποπροσάρτηση συστημάτων αρχείων" + "Επιτρέπει στην εφαρμογή την προσάρτηση και αποπροσάρτηση συστημάτων αρχείων για αφαιρούμενο αποθηκευτικό χώρο." + "διαμόρφωση εξωτερικού αποθηκευτικού χώρου" + "Επιτρέπει στην εφαρμογή τη διαμόρφωση αφαιρούμενου αποθηκευτικού χώρου." + "έλεγχος δόνησης" + "Επιτρέπει στην εφαρμογή τον έλεγχο του δονητή." + "έλεγχος φακού" + "Επιτρέπει στην εφαρμογή τον έλεγχο του φακού." + "δοκιμή υλικού" + "Επιτρέπει σε μια εφαρμογή τον έλεγχο διαφόρων περιφερειακών για την εκτέλεση δοκιμών υλικού." + "απευθείας κλήση τηλεφωνικών αριθμών" + "Επιτρέπει σε μια εφαρμογή την κλήση τηλεφωνικών αριθμών χωρίς την παρέμβασή σας. Κακόβουλες εφαρμογές ενδέχεται να ευθύνονται για μη αναμενόμενες κλήσεις στον λογαριασμό τηλεφώνου σας. Λάβετε υπόψη ότι αυτό δεν επιτρέπει την κλήση αριθμών έκτακτης ανάγκης." + "απευθείας κλήση τηλεφωνικών αριθμών" + "Επιτρέπει στην εφαρμογή την κλήση τηλεφωνικού αριθμού, συμπεριλαμβανομένων και αριθμών έκτακτης ανάγκης, χωρίς την παρέμβασή σας. Κακόβουλες εφαρμογές ενδέχεται να πραγματοποιήσουν μη αναγκαίες και παράνομες κλήσεις σε υπηρεσίες έκτακτης ανάγκης." + "έλεγχος ειδοποιήσεων ενημέρωσης τοποθεσίας" + "Επιτρέπει την ενεργοποίηση/απενεργοποίηση ειδοποιήσεων ενημέρωσης τοποθεσίας από τον πομπό. Δεν πρέπει να χρησιμοποιείται από κανονικές εφαρμογές." + "πρόσβαση σε ιδιότητες ελέγχου εισόδου" + "Επιτρέπει την πρόσβαση για ανάγνωση/εγγραφή σε ιδιότητες που έχουν μεταφορτωθεί από την υπηρεσία ελέγχου εισόδου. Δεν πρέπει να χρησιμοποιείται από συνήθεις εφαρμογές." + "επιλογή γραφικών στοιχείων" + "Επιτρέπει στην εφαρμογή να ορίσει στο σύστημα ποια γραφικά στοιχεία μπορεί να χρησιμοποιήσει κάθε εφαρμογή. Με αυτή την άδεια, οι εφαρμογές μπορούν να παρέχουν πρόσβαση σε προσωπικά δεδομένα σε άλλες εφαρμογές. Δεν πρέπει να χρησιμοποιείται από συνήθεις εφαρμογές." + "τροποποίηση κατάστασης τηλεφώνου" + "Επιτρέπει στην εφαρμογή τον έλεγχο των τηλεφωνικών δυνατοτήτων της συσκευής. Μια εφαρμογή με αυτήν την άδεια μπορεί να πραγματοποιήσει εναλλαγή μεταξύ δικτύων, να ενεργοποιήσει και να απενεργοποιήσει τον πομπό του τηλεφώνου κ.λπ. χωρίς να σας ειδοποιήσει." + "ανάγνωση κατάστασης τηλεφώνου" + "Επιτρέπει στην εφαρμογή την πρόσβαση στις λειτουργίες τηλεφώνου της συσκευής. Μια εφαρμογή με αυτή την άδεια μπορεί να προσδιορίσει τον τηλεφωνικό αριθμό του τηλεφώνου, αν μια κλήση είναι ενεργή ή όχι, τον τηλεφωνικό αριθμό της κλήσης κ.λπ.." + "παρεμπόδιση μετάβασης του τηλεφώνου σε κατάσταση αδράνειας" + "Επιτρέπει σε μια εφαρμογή την παρεμπόδιση της μετάβασης του τηλεφώνου σε κατάσταση αδράνειας." + "ενεργοποίηση και απενεργοποίηση τηλεφώνου" + "Επιτρέπει σε μια εφαρμογή να ενεργοποιήσει ή να απενεργοποιήσει το τηλέφωνο." + "εκτέλεση σε λειτουργία εργοστασιακής δοκιμής" + "Εκτέλεση ως χαμηλού επιπέδου δοκιμή κατασκευαστή, ώστε να επιτρέπεται πλήρης πρόσβαση στο υλικό του τηλεφώνου. Διαθέσιμο μόνο όταν το τηλέφωνο βρίσκεται σε λειτουργία δοκιμής κατασκευαστή." + "ορισμός ταπετσαρίας" + "Επιτρέπει στην εφαρμογή τον ορισμό της ταπετσαρίας συστήματος." + "ορισμός συμβουλών μεγέθους ταπετσαρίας" + "Επιτρέπει στην εφαρμογή τον ορισμό συμβουλών μεγέθους ταπετσαρίας συστήματος." + "επαναφορά συστήματος στις εργοστασιακές προεπιλογές" + "Επιτρέπει σε μια εφαρμογή να επαναφέρει πλήρως το σύστημα στις εργοστασιακές ρυθμίσεις, διαγράφοντας όλα τα δεδομένα, τις διαμορφώσεις και τις εγκατεστημένες εφαρμογές." + "ορισμός ζώνης ώρας" + "Επιτρέπει σε μια εφαρμογή την αλλαγή της ζώνης ώρας του τηλεφώνου." + "ανακάλυψη γνωστών λογαριασμών" + "Επιτρέπει σε μια εφαρμογή να λάβει τη λίστα λογαριασμών του τηλεφώνου." + "προβολή κατάστασης δικτύου" + "Επιτρέπει σε μια εφαρμογή την προβολή της κατάστασης όλων των δικτύων." + "πλήρης πρόσβαση στο Διαδίκτυο" + "Επιτρέπει σε μια εφαρμογή τη δημιουργία υποδοχών δικτύου (sockets)." + "εγγραφή ρυθμίσεων Ονόματος σημείου πρόσβασης (APN)" + "Επιτρέπει σε μια εφαρμογή να τροποποιήσει τις ρυθμίσεις APN, όπως Διακομιστής μεσολάβησης και Θύρα για ένα APN." + "αλλαγή συνδεσιμότητας δικτύου" + "Επιτρέπει σε μια εφαρμογή την αλλαγή της κατάστασης συνδεσιμότητας δικτύου." + "αλλαγή ρύθμισης της χρήσης δεδομένων στο παρασκήνιο" + "Επιτρέπει σε μια εφαρμογή την αλλαγή της ρύθμισης χρήσης δεδομένων φόντου." + "προβολή κατάστασης Wi-Fi" + "Επιτρέπει σε μια εφαρμογή την προβολή των πληροφοριών σχετικά με την κατάσταση του Wi-Fi." + "αλλαγή κατάστασης Wi-Fi" + "Επιτρέπει σε μια εφαρμογή τη σύνδεση σε σημεία πρόσβασης Wi-Fi και την αποσύνδεση από αυτά, καθώς και την πραγματοποίηση αλλαγών σε διαμορφωμένα δίκτυα Wi-Fi." + + + + + "διαχείριση bluetooth" + "Επιτρέπει σε μια εφαρμογή τη διαμόρφωση του τοπικού τηλεφώνου Bluetooth και την ανακάλυψη και σύζευξη με απομακρυσμένες συσκευές." + "δημιουργία συνδέσεων Bluetooth" + "Επιτρέπει σε μια εφαρμογή να προβάλει τη διαμόρφωση του τοπικού τηλεφώνου Bluetooth και επίσης να πραγματοποιεί και να αποδέχεται συνδέσεις με συζευγμένες συσκευές." + "απενεργοποίηση κλειδώματος πληκτρολογίου" + "Επιτρέπει σε μια εφαρμογή την απενεργοποίηση του κλειδώματος πληκτρολογίου και άλλης σχετικής ασφάλειας με κωδικό πρόσβασης. Για παράδειγμα, η απενεργοποίηση του κλειδώματος πληκτρολογίου όταν λαμβάνεται εισερχόμενη τηλεφωνική κλήση και η επανενεργοποίηση του κλειδώματος πληκτρολογίου όταν η κλήση τερματιστεί." + "ανάγνωση ρυθμίσεων συγχρονισμού" + "Επιτρέπει σε μια εφαρμογή την ανάγνωση των ρυθμίσεων συγχρονισμού, όπως π.χ. εάν ο συγχρονισμός είναι ενεργοποιημένος για τις Επαφές." + "καταγραφή ρυθμίσεων συγχρονισμού" + "Επιτρέπει σε μια εφαρμογή την τροποποίηση των ρυθμίσεων συγχρονισμού (π.χ. εάν ο συγχρονισμός είναι ενεργοποιημένος για τις Επαφές)." + "ανάγνωση στατιστικών συγχρονισμού" + "Επιτρέπει σε μια εφαρμογή την ανάγνωση των στατιστικών συγχρονισμού (π.χ. το ιστορικό των συγχρονισμών που έχουν πραγματοποιηθεί)." + "ανάγνωση ροών δεδομένων στις οποίες έχετε εγγραφεί" + "Επιτρέπει σε μια εφαρμογή τη λήψη λεπτομερειών σχετικά με τις τρέχουσες συγχρονισμένες ροές δεδομένων." + "εγγραφή ροών δεδομένων στις οποίες έχετε εγγραφεί" + "Επιτρέπει σε μια εφαρμογή να τροποποιήσει τις ροές δεδομένων, με τις οποίες είστε συγχρονισμένοι αυτή τη στιγμή. Αυτό θα μπορούσε να δώσει τη δυνατότητα σε μια κακόβουλη εφαρμογή να αλλάξει τις συγχρονισμένες ροές δεδομένων σας." + "ανάγνωση καθορισμένου από τον χρήστη λεξικού" + "Επιτρέπει σε μια εφαρμογή να αναγνώσει ιδιωτικές λέξεις και φράσεις και ιδιωτικά ονόματα, τα οποία ο χρήστης ενδέχεται να έχει αποθηκεύσει στο λεξικό χρήστη." + "εγγραφή σε καθορισμένο από τον χρήστη λεξικό" + "Επιτρέπει σε μια εφαρμογή την εγγραφή νέων λέξεων στο λεξικό χρήστη." + + + + + + "Οικία" + "Κινητό" + "Εργασία" + "Φαξ εργασίας" + "Φαξ οικίας" + "Pager" + "Άλλο" + "Προσαρμοσμένο" + + + "Οικία" + "Εργασία" + "Άλλο" + "Προσαρμοσμένο" + + "Κινητό" + + "Οικία" + "Εργασία" + "Άλλο" + "Προσαρμοσμένο" + + + "Οικία" + "Εργασία" + "Άλλο" + "Προσαρμοσμένο" + + + "Εργασία" + "Άλλο" + "Προσαρμοσμένο" + + + "AIM" + "Windows Live" + "Yahoo" + "Skype" + "QQ" + "Google Talk" + "ICQ" + "Jabber" + + "Πληκτρολογήστε τον κωδικό αριθμό PIN" + "Εσφαλμένος κωδικός αριθμός PIN!" + "Για ξεκλείδωμα, πατήστε το πλήκτρο Menu και, στη συνέχεια, το πλήκτρο 0." + "Αριθμός έκτακτης ανάγκης" + "(Καμία υπηρεσία)" + "Η οθόνη κλειδώθηκε." + "Πατήστε \"Menu\" για ξεκλείδωμα ή για κλήση έκτακτης ανάγκης." + "Πατήστε \"Μενού\" για ξεκλείδωμα." + "Σχεδιασμός μοτίβου για ξεκλείδωμα" + "Κλήση έκτακτης ανάγκης" + "Σωστό!" + "Προσπαθήστε αργότερα" + "Φόρτιση (%d%%)" + + + "Συνδέστε τον φορτιστή." + "Δεν υπάρχει κάρτα SIM." + "Δεν υπάρχει κάρτα SIM στο τηλέφωνο." + "Τοποθετήστε μια κάρτα SIM." + "Το δίκτυο κλειδώθηκε" + "Η κάρτα SIM είναι κλειδωμένη με κωδικό PUK." + "Ανατρέξτε στον οδηγό χρήσης ή επικοινωνήστε με την εξυπηρέτηση πελατών." + "Η κάρτα SIM είναι κλειδωμένη." + "Ξεκλείδωμα κάρτας SIM..." + "Σχεδιάσατε εσφαλμένα το μοτίβο ξεκλειδώματος%d φορές. "\n\n"Προσπαθήστε ξανά σε %d δευτερόλεπτα." + "Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα %d φορές. Μετά από %d ανεπιτυχείς προσπάθειες ακόμη, θα σας ζητηθεί να ξεκλειδώσετε το τηλέφωνό σας με τη χρήση της σύνδεσής σας Google."\n\n" Προσπαθήστε ξανά σε %d \nδευτερόλεπτα." + "Προσπαθήστε ξανά σε %d δευτερόλεπτα." + "Ξεχάσατε το μοτίβο;" + "Πάρα πολλές προσπάθειες μοτίβου!" + "Για ξεκλείδωμα, συνδεθείτε με τον λογαριασμό σας Google" + "Όνομα χρήστη (διεύθυνση ηλεκτρονικού ταχυδρομείου)" + "Κωδικός πρόσβασης" + "Σύνδεση" + "Μη έγκυρο όνομα χρήστη ή κωδικός πρόσβασης." + "%-l%P" + "%-l%p" + + + "Δεν υπάρχουν ειδοποιήσεις" + "Εν εξελίξει" + "Ειδοποιήσεις" + "%d%%" + "Φόρτιση..." + "Συνδέστε τον φορτιστή" + "Η στάθμη της μπαταρίας είναι χαμηλή:" + "απομένουν λιγότερο από %d%%." + + + "Η εργοστασιακή δοκιμή απέτυχε" + "Η ενέργεια FACTORY_TEST υποστηρίζεται μόνο για πακέτα που είναι εγκατεστημένα στον κατάλογο /system/app." + "Δεν βρέθηκε πακέτο που να παρέχει την ενέργεια FACTORY_TEST." + "Επανεκκίνηση" + "Η σελίδα στο \'%s\' λέει:" + "JavaScript" + "Απομάκρυνση από αυτή τη σελίδα;"\n\n"%s"\n\n"Επιλέξτε OK για συνέχεια, ή Ακύρωση για παραμονή στην τρέχουσα σελίδα." + "Επιβεβαίωση" + + + + + + + + + "Θέλετε το πρόγραμμα περιήγησης να διατηρήσει αυτόν τον κωδικό πρόσβασης;" + "Να μην γίνει τώρα" + "Διατήρηση" + "Ποτέ" + "Δεν έχετε άδεια για να ανοίξετε αυτή τη σελίδα." + "Το κείμενο αντιγράφηκε στο πρόχειρο." + "Περισσότερα" + "Πλήκτρο Menu+" + "διάστημα" + "εισαγωγή" + "διαγραφή" + "Αναζήτηση" + "πριν από 1 μήνα" + "Παλαιότερα από 1 μήνα" + + "πριν από 1 δευτερόλεπτο" + "πριν από %d δευτερόλεπτα" + + + "πριν από 1 λεπτό" + "πριν από %d λεπτά" + + + "πριν από 1 ώρα" + "πριν από %d ώρες" + + + "χθες" + "πριν από %d ημέρες" + + + "σε 1 δευτερόλεπτο" + "σε %d δευτερόλεπτα" + + + "σε 1 λεπτό" + "σε %d λεπτά" + + + "σε 1 ώρα" + "σε %d ώρες" + + + "αύριο" + "σε %d ημέρες" + + + "πριν από 1 δευτερόλεπτο" + "πριν από %d δευτερόλεπτα" + + + "πριν από 1 λεπτό" + "πριν από %d λεπτά" + + + "πριν από 1 ώρα" + "πριν από %d ώρες" + + + "χθες" + "πριν από %d ημέρες" + + + "σε 1 δευτερόλεπτο" + "σε %d δευτερόλεπτα" + + + "σε 1 λεπτό" + "σε %d λεπτά" + + + "σε 1 ώρα" + "σε %d ώρες" + + + "αύριο" + "σε %d ημέρες" + + "σε %s" + "στο %s" + "σε %s" + "ημέρα" + "ημέρες" + "ώρα" + "ώρες" + "λεπτά" + "λεπτά" + "δευτερόλεπτο" + "δευτερόλεπτα" + "εβδομάδα" + "εβδομάδες" + "έτος" + "έτη" + "Καθημερινές (Δευ-Παρ)" + "Καθημερινά" + "Κάθε εβδομάδα στο %s" + "Μηνιαία" + "Ετήσια" + "Δεν είναι δυνατή η αναπαραγωγή βίντεο" + "Αυτό το βίντεο δεν είναι έγκυρο για ροή σε αυτή τη συσκευή." + "Δεν είναι δυνατή η προβολή αυτού του βίντεο." + "OK" + "%1$s, %2$s" + "μεσημέρι" + "Μεσημέρι" + "μεσάνυχτα" + "Μεσάνυχτα" + "%1$02d:%2$02d" + "%1$d:%2$02d:%3$02d" + "Επιλογή όλων" + "Επιλογή κειμένου" + "Διακοπή επιλογής κειμένου" + "Αποκοπή" + "Αποκοπή όλων" + "Αντιγραφή" + "Αντιγραφή όλων" + "Επικόλληση" + "Αντιγραφή διεύθυνσης URL" + "Μέθοδος εισόδου" + "Προσθήκη \"%s\" στο λεξικό" + "Επεξεργασία κειμένου" + "Απομένει λίγος ελεύθερος χώρος" + "Έχει απομείνει λίγος ελεύθερος αποθηκευτικός χώρος στο τηλέφωνο." + "OK" + "Ακύρωση" + "OK" + "Ακύρωση" + "Προσοχή" + "Ενεργοποιημένο" + "Απενεργοποίηση" + "Ολοκλήρωση ενέργειας με τη χρήση" + "Χρήση από προεπιλογή για αυτήν την ενέργεια." + "Εκκαθάριση προεπιλεγμένων σε Ρυθμίσεις αρχικής σελίδας > Εφαρμογές > Διαχείριση εφαρμογών." + "Επιλέξτε μια ενέργεια" + "Δεν υπάρχουν εφαρμογές, οι οποίες μπορούν να εκτελέσουν αυτήν την ενέργεια." + "Λυπούμαστε!" + "Υπήρξε μη αναμενόμενη διακοπή της εφαρμογής %1$s (διαδικασία %2$s). Προσπαθήστε ξανά." + "Υπήρξε μη αναμενόμενη διακοπή της διαδικασίας %1$s. Προσπαθήστε αργότερα." + "Λυπούμαστε!" + "Η δραστηριότητα %1$s (στην εφαρμογή %2$s) δεν αποκρίνεται." + "Η δραστηριότητα %1$s (στη διαδικασία %2$s) δεν αποκρίνεται." + "Η εφαρμογή %1$s (στη διαδικασία %2$s) δεν αποκρίνεται." + "Η διαδικασία %1$s δεν αποκρίνεται." + "Αναγκαστικό κλείσιμο" + + + "Αναμονή" + "Εντοπισμός σφαλμάτων" + "Επιλέξτε μια ενέργεια για το κείμενο" + "Ένταση ειδοποίησης ήχου" + "Ένταση ήχου πολυμέσων" + "Αναπαραγωγή μέσω Bluetooth" + "Ένταση ήχου κλήσης" + "Ένταση ήχου για εισερχόμενη κληση μέσω Bluetooth" + "Ένταση ήχου ξυπνητηριού" + "Ένταση ήχου ειδοποίησης" + "Ένταση ήχου" + "Προεπιλεγμένος ήχος κλήσης" + "Προεπιλεγμένος ήχος κλήσης (%1$s)" + "Σίγαση" + "Ήχοι κλήσης" + "Άγνωστος ήχος κλήσης" + + "Υπάρχει διαθέσιμο δίκτυο Wi-Fi" + "Υπάρχουν διαθέσιμα δίκτυα Wi-Fi" + + + "Υπάρχει διαθέσιμο ανοικτό δίκτυο Wi-Fi" + "Υπάρχουν διαθέσιμα ανοικτά δίκτυα Wi-Fi" + + "Εισαγωγή χαρακτήρα" + "Άγνωστη εφαρμογή" + "Αποστολή μηνυμάτων SMS" + "Αποστέλλεται μεγάλος αριθμός μηνυμάτων SMS. Επιλέξτε \"OK\" για συνέχεια, ή \"Ακύρωση\" για διακοπή αποστολής." + "OK" + "Ακύρωση" + "Ορισμός" + "Προεπιλεγμένο" + "Δεν απαιτούνται άδειες" + "Απόκρυψη" + "Εμφάνιση όλων" + "Φόρτωση..." + "Το USB είναι συνδεδεμένο" + "Συνδέσατε το τηλέφωνό σας στον υπολογιστή μέσω USB. Επιλέξτε \"Προσάρτηση\" αν θέλετε να αντιγράψετε αρχεία μεταξύ του υπολογιστή και της κάρτας SD του τηλεφώνου." + "Προσάρτηση" + "Να μην γίνει προσάρτηση" + "Παρουσιάστηκε ένα πρόβλημα στη χρήση της κάρτας SD ως αποθηκευτικό χώρο USB." + "Το USB είναι συνδεδεμένο" + "Επιλέξτε για αντιγραφή προς/από τον υπολογιστή σας." + "Απενεργοποίηση αποθηκευτικού χώρου USB" + "Επιλογή για απενεργοποίηση αποθηκευτικού χώρου USB." + "Απενεργοποίηση αποθηκευτικού χώρου USB" + "Πριν από την απενεργοποίηση του αποθηκευτικού χώρου USB, βεβαιωθείτε ότι έχετε αποπροσαρτήσει την υποδοχή USB. Επιλέξτε \"Απενεργοποίηση\" για να απενεργοποιήσετε τον αποθηκευτικό χώρο USB." + "Απενεργοποίηση" + "Ακύρωση" + "Παρουσιάστηκε ένα πρόβλημα κατά την απενεργοποίηση του αποθηκευτικού χώρου USB. Βεβαιωθείτε ότι έχετε αποπροσαρτήσει την υποδοχή USB και προσπαθήστε ξανά." + "Διαμόρφωση κάρτας SD" + "Είστε βέβαιοι ότι θέλετε να διαμορφώσετε την κάρτα SD; Όλα τα δεδομένα στην κάρτα σας θα χαθούν." + "Διαμόρφωση" + + + + + "Επιλογή μεθόδου εισόδου" + " ABCDEFGHIJKLMNOPQRSTUVWXYZ" + " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "υποψήφιοι" + "Προετοιμασία κάρτας SD" + + + "Κενή κάρτα SD" + + + "Κατεστραμμένη κάρτα SD" + + + "Μη αναμενόμενη αφαίρεση κάρτας SD" + "Αποπροσαρτήστε την κάρτα SD πριν την αφαιρέσετε για την αποφυγή απώλειας δεδομένων." + "Η κάρτα SD μπορεί να αφαιρεθεί με ασφάλεια" + + + "Η κάρτα SD αφαιρέθηκε" + + + "Δεν βρέθηκαν δραστηριότητες που να αντιστοιχούν" + "ενημέρωση στατιστικών χρήσης στοιχείου" + "Επιτρέπει την τροποποίηση στατιστικών χρήσης στοιχείων που έχουν συλλεχθεί. Δεν πρέπει να χρησιμοποιείται από κανονικές εφαρμογές." + "Πατήστε δύο φορές για έλεγχο εστίασης" + "Σφάλμα αύξησης μεγέθους γραφικού στοιχείου" + "Μετάβαση" + "Αναζήτηση" + "Αποστολή" + "Επόμενο" + "Ολοκληρώθηκε" + "Εκτέλεση" + "Κλήση αριθμού"\n"με τη χρήση %s" + "Δημιουργία επαφής"\n"με τη χρήση του %s" + + + + + diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 84435aa8dee83..6eb1c01a8c6f4 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -21,6 +21,8 @@ "GB" "TB" "PB" + + "<sin título>" "…" "(No hay número de teléfono)" @@ -60,22 +62,17 @@ - "El Identificador de llamadas está predeterminado en restringido. Llamada siguiente: restringida" + "El identificador de llamadas está predeterminado en restringido. Llamada siguiente: restringida" "El Identificador de llamadas está predeterminado en restringido. Llamada siguiente: no restringido" - "El Identificador de llamadas está predeterminado en no restringido. Llamada siguiente: restringida" + "El identificador de llamadas está predeterminado en no restringido. Llamada siguiente: restringida" "El Identificador de llamadas está predeterminado en no restringido. Llamada siguiente: no restringido" "Servicio no suministrado." "La configuración del identificador de llamadas no se puede cambiar." - - - - - - - - - - + "Se ha cambiado el acceso restringido" + "El servicio de datos está bloqueado." + "El servicio de emergencias está bloqueado." + "El servicio de voz/SMS está bloqueado." + "Todos los servicios de voz/SMS están bloqueados." "Voz" "Datos" "FAX" @@ -84,11 +81,43 @@ "Sincronización" "Paquete" "PAD" + + + + + + + + + + + + + + + + + + + + + + + + + + + + "{0}: no se ha remitido" "{0}: {1}" "{0}: {1} después de {2} segundos" "{0}: no se ha remitido" "{0}: no se ha remitido" + + + + "Aceptar" "La página web contiene un error." "No se ha podido encontrar la URL." @@ -105,6 +134,8 @@ "No se ha podido acceder al archivo." "No se ha encontrado el archivo solicitado." "Se están procesando demasiadas solicitudes. Vuelve a intentarlo más tarde." + + "Sincronización" "Sincronización" "Demasiadas eliminaciones de %s" @@ -150,6 +181,10 @@ "Acceso y control de nivel más bajo del sistema." "Herramientas de desarrollo" "Las funciones sólo son necesarias para los desarrolladores de aplicaciones." + + + + "desactivar o modificar la barra de estado" "Admite que la aplicación desactive la barra de estado, o agregue y elimine íconos del sistema." "expandir o reducir la barra de estado" @@ -182,6 +217,14 @@ "Admite una aplicación que provoca que cualquier actividad del fondo se acerque y vuelva a alejarse. Se debe evitar utilizarlo en aplicaciones normales." "recuperar el estado interno del sistema" "Admite que la aplicación recupere el estado interno del sistema. Las aplicaciones maliciosas pueden recuperar una gran variedad de información privada y segura que normalmente nunca necesitaría." + + + + + + + + "verificar y controlar todos los lanzamientos de actividades" "Admite una aplicación que verifica y controla el lanzamiento de actividades por parte del sistema. Las aplicaciones maliciosas pueden comprometer totalmente al sistema. Este permiso sólo es necesario para el desarrollo, nunca para el uso normal del teléfono." "enviar emisión de paquete eliminado" @@ -196,6 +239,10 @@ "Admite una aplicación que controla si las actividades siempre finalizan cuando van al fondo. No se utiliza nunca en aplicaciones normales." "modificar la estadística de la batería" "Admite la modificación de estadísticas recopiladas sobre la batería. Las aplicaciones normales no deben utilizarlo." + + + + "mostrar ventanas no autorizadas" "Permite la creación de ventanas que la interfaz interna del usuario del sistema pretenda utilizar. Las aplicaciones normales no deben utilizarlo." "mostrar alertas a nivel del sistema" @@ -255,13 +302,17 @@ "leer datos del propietario" "Admite una aplicación que lee los datos del propietario del teléfono guardados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para leer los datos del propietario del teléfono." "leer datos de calendario" - "Admite una aplicación que lee todos los eventos de calendario almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas." + "Admite que una aplicación lea todos los eventos de calendario almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas." "escribir datos de calendario" "Admite una aplicación que modifica los eventos de calendario guardados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar tus datos de calendario." "crear fuentes de ubicación de prueba" "Crea fuentes de ubicación de prueba. Las aplicaciones maliciosas pueden utilizarlo para invalidar la ubicación o el estado que arrojen las fuentes de ubicación real, como GPS o proveedores de red." "acceder a comandos adicionales del proveedor del lugar" "Accede a comandos adicionales del proveedor del lugar. Las aplicaciones maliciosas pueden utilizarlo para interferir en la operación del GPS u otras fuentes de ubicación." + + + + "ubicación precisa (GPS)" "Accede a las fuentes de ubicación precisa, como el Sistema de posicionamiento global en el teléfono, si está disponible. Las aplicaciones maliciosas pueden utilizarlo para determinar donde te encuentras y puede consumir energía adicional de la batería." "ubicación aproximada (basada en la red)" @@ -269,7 +320,7 @@ "acceder a SurfaceFlinger" "Admite que la aplicación utilice funciones de bajo nivel de SurfaceFlinger." "leer el búfer de tramas" - "Admite que la aplicación que se utilizará lea el contenido del búfer de tramas." + "Admite que la aplicación que se utilizará lea el contenido del búfer de marco." "cambiar tu configuración de audio" "Admite que la aplicación modifique la configuración global de audio, como el volumen y el enrutamiento." "grabar audio" @@ -334,6 +385,10 @@ "Admite una aplicación que observa la información sobre el estado de Wi-Fi." "cambiar el estado de Wi-Fi" "Admite una aplicación que se conecta y desconecta de los puntos de acceso de Wi-Fi y que hace cambios en las redes de Wi-Fi configuradas." + + + + "administración de bluetooth" "Admite una aplicación que configura el teléfono Bluetooth local y descubre y se vincula con dispositivos remotos." "crear conexiones de Bluetooth" @@ -354,6 +409,10 @@ "Admite una aplicación para leer palabras, nombres y frases privadas que posiblemente el usuario haya almacenado en el diccionario del usuario." "escribir al diccionario definido por el usuario" "Admite una aplicación que escribe palabras nuevas en el diccionario del usuario." + + + + "Página principal" "Celular" @@ -370,6 +429,7 @@ "Otros" "Personalización" + "Celular" "Página principal" "Trabajo" @@ -410,14 +470,15 @@ "Correcto" "Lo sentimos, vuelve a intentarlo" "Cargando (%d%%)" + + "Conecta tu cargador." "No hay tarjeta SIM." "No hay tarjeta SIM en el teléfono." "Inserta una tarjeta SIM." "Red bloqueada" "La tarjeta SIM está bloqueada con PUK." - - + "Consulta la guía del usuario o comunícate con el servicio de atención al cliente." "La tarjeta SIM está bloqueada." "Desbloqueando tarjeta SIM…" "Has extraído incorrectamente tu patrón de desbloqueo %d veces. "\n\n"Vuelve a intentarlo en %d segundos." @@ -432,7 +493,8 @@ "Nombre de usuario o contraseña incorrecta." "%-l%P" "%-l%p" - "Borrar notificaciones" + + "No hay notificaciones" "Continuo" "Notificaciones" @@ -441,6 +503,8 @@ "Conecta el cargador" "Hay poca batería:" "menos de %d%% restante." + + "Error en la prueba de fábrica" "La acción FACTORY_TEST se admite solamente en paquetes instalados en /system/app." "No se ha encontrado ningún paquete que proporcione la acción FACTORY_TEST ." @@ -449,6 +513,14 @@ "JavaScript" "¿Deseas salir de esta página?"\n\n"%s"\n\n"Selecciona Aceptar para continuar o Cancelar para permanecer en la página actual." "Confirmar" + + + + + + + + "¿Quieres recordar esta contraseña en el navegador?" "Ahora no." "Recuerda" @@ -556,10 +628,6 @@ "Mediodía" "medianoche" "Medianoche" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "Seleccionar todos" @@ -597,6 +665,8 @@ "La aplicación %1$s (en proceso %2$s) no responde." "El proceso %1$s no responde." "Provocar acercamiento" + + "Espera" "Depurar" "Selecciona una acción para el texto" @@ -650,22 +720,31 @@ "Formatear tarjeta SD" "¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de tu tarjeta." "Formato" + + + + "Seleccionar método de entrada" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "candidatos" "Preparación de la tarjeta SD" - "Verificando errores" + + "Tarjeta SD vacía" - "La tarjeta SD está vacía o utiliza un filesystem no admitido." + + "Tarjeta SD dañada" - "La tarjeta SD está dañada. Es posible que debas reformatear tu tarjeta." + + "Tarjeta SD extraída de forma imprevista" "Desmontar la tarjeta SD antes de extraerla para evitar la pérdida de datos." "Tarjeta SD fácil de extraer" - "La tarjeta SD ahora se puede extraer de manera segura." + + "Tarjeta SD extraída" - "Se ha extraído la SD. Inserta una nueva tarjeta SD para aumentar el espacio de almacenamiento de tu dispositivo." + + "No se encontraron actividades coincidentes" "actualizar la estadística de uso de los componentes" "Permite la modificación de estadísticas recopiladas sobre el uso de componentes. Las aplicaciones normales no deben utilizarlo." @@ -677,8 +756,10 @@ "Siguiente" "Finalizado" "Ejecutar" - + "Marcar el número"\n"con %s" + "Crear contacto "\n"con %s" + - + diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 920ac3e5dcd0b..464e1a2bfff21 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -21,6 +21,7 @@ "GB" "TB" "PB" + "%1$s %2$s" "<sin título>" "…" "(Sin número de teléfono)" @@ -48,12 +49,18 @@ "Bloqueo de llamada" "Cambio de contraseña" "Cambio de PIN" + "Número de llamada entrante presente" + "Número de llamada entrante restringido" + "Llamada a tres" + "Rechazo de llamadas molestas no deseadas" + "Entrega de número de llamada entrante" + "No molestar" "El ID de emisor presenta el valor predeterminado de restringido. Siguiente llamada: Restringido" "El ID de emisor presenta el valor predeterminado de restringido. Siguiente llamada: No restringido" "El ID de emisor presenta el valor predeterminado de no restringido. Siguiente llamada: Restringido" "El ID de emisor presenta el valor predeterminado de no restringido. Siguiente llamada: No restringido" "El servicio no se suministra." - "El ID del emisor no se puede modificar." + "El ID de emisor no se puede modificar." "El acceso restringido se ha modificado." "El servicio de datos está bloqueado." "El servicio de emergencia está bloqueado." @@ -67,11 +74,27 @@ "Sincronización" "Paquete" "PAD" + "Indicador de itinerancia activado" + "Indicador de itinerancia desactivado" + "Indicador de itinerancia parpadeante" + "Fuera del vecindario" + "Fuera del edificio" + "Itinerancia: sistema preferido" + "Itinerancia: sistema disponible" + "Itinerancia: partner de alianza" + "Itinerancia: partner de gran calidad" + "Itinerancia: funcionalidad de servicio completa" + "Itinerancia: funcionalidad de servicio parcial" + "Banner de itinerancia activado" + "Banner de itinerancia desactivado" + "Buscando servicio" "{0}: No desviada" "{0}: {1}" "{0}: {1} transcurridos {2} segundos" "{0}: No desviada" "{0}: No desviada" + "Código de función completo" + "Se ha producido un problema de conexión o el código de la función no es válido." "Aceptar" "La página web contiene un error." "No se ha podido encontrar la URL." @@ -88,6 +111,7 @@ "No se ha podido acceder al archivo." "No se ha encontrado el archivo solicitado." "Se están procesando demasiadas solicitudes. Vuelve a intentarlo más tarde." + "El certificado se guarda en el almacén de claves del sistema." "Sincronización" "Sincronización" "Demasiadas eliminaciones de %s" @@ -109,8 +133,8 @@ "El sonido está desactivado. Activar." "El sonido está activado. Desactivar." "Modo avión" - "Modo avión ACTIVADO" - "Modo avión DESACTIVADO" + "Modo avión desactivado. Activar." + "Modo avión desactivado. Activar." "Modo seguro" "Sistema Android" "Servicios por los que tienes que pagar" @@ -133,6 +157,8 @@ "Acceso de nivel inferior y control del sistema" "Herramientas de desarrollo" "Funciones necesarias sólo para desarrolladores de aplicaciones" + "Almacenamiento" + "Acceder a la tarjeta SD" "inhabilitar o modificar la barra de estado" "Permite que las aplicaciones inhabiliten la barra de estado, o añadan y eliminen iconos del sistema." "expandir/contraer la barra de estado" @@ -165,6 +191,10 @@ "Permite que una aplicación fuerce a cualquier actividad en segundo plano a cerrarse y volver a la pantalla anterior. No debería ser necesario nunca para las aplicaciones normales." "recuperar estado interno del sistema" "Permite que la aplicación recupere el estado interno del sistema. Las aplicaciones malintencionadas pueden recuperar una amplia variedad de información protegida y privada que normalmente no deberían necesitar." + "cierre parcial" + "Pone el administrador de actividades en estado de cierre. No realiza un cierre completo." + "evitar cambios de aplicación" + "Evita que el usuario cambie a otra aplicación." "supervisar y controlar la ejecución de todas las aplicaciones" "Permite que una aplicación supervise y controle la ejecución de las actividades por parte del sistema. Las aplicaciones malintencionadas pueden vulnerar la seguridad del sistema. Este permiso sólo es necesario para tareas de desarrollo, nunca para el uso habitual del teléfono." "enviar emisión eliminada de paquete" @@ -179,6 +209,8 @@ "Permite que una aplicación controle si las actividades finalizan siempre en cuanto pasan a segundo plano. No es necesario nunca para las aplicaciones normales." "modificar estadísticas de la batería" "Permite la modificación de estadísticas recopiladas sobre la batería. No está destinado al uso por parte de aplicaciones normales." + "controlar las copias de seguridad y las restauraciones del sistema" + "Permite que la aplicación controle el mecanismo de copia de seguridad y restauración del sistema. Este permiso no está destinado a aplicaciones normales." "mostrar ventanas no autorizadas" "Permite la creación de ventanas destinadas al uso por parte de la interfaz de usuario interna del sistema. No está destinado al uso por parte de aplicaciones normales." "mostrar alertas de nivel del sistema" @@ -245,6 +277,8 @@ "Crear fuentes de origen simuladas para realizar pruebas. Las aplicaciones malintencionadas pueden utilizar este permiso para sobrescribir la ubicación o el estado devueltos por orígenes de ubicación reales, tales como los proveedores de red o GPS." "acceder a comandos de proveedor de ubicación adicional" "Acceder a comandos de proveedor de ubicación adicional. Las aplicaciones malintencionadas podrían utilizar este permiso para interferir en el funcionamiento del sistema GPS o de otras fuentes de ubicación." + "permiso para instalar un proveedor de ubicación" + "Crear fuentes de origen simuladas para realizar pruebas. Las aplicaciones malintencionadas pueden utilizar este permiso para sobrescribir la ubicación o el estado devueltos por orígenes de ubicación reales, tales como los proveedores de red o GPS, o para controlar y notificar tu ubicación a una fuente externa." "precisar la ubicación (GPS)" "Permite precisar las fuentes de ubicación como, por ejemplo, el sistema de posicionamiento global, en el teléfono, en los casos en que estén disponibles. Las aplicaciones malintencionadas pueden utilizar este permiso para determinar dónde se encuentra en usuario y pueden consumir batería adicional." "ubicación común (basada en red)" @@ -317,6 +351,8 @@ "Permite que una aplicación vea la información sobre el estado de la conectividad Wi-Fi." "cambiar estado de Wi-Fi" "Permite que una aplicación se conecte a puntos de acceso Wi-Fi y se desconecte de ellos, y realice modificaciones en las redes Wi-Fi configuradas." + "permitir recepción multidifusión Wi-Fi" + "Permite que una aplicación reciba paquetes no dirigidos directamente a tu dispositivo. Esta función puede resultar útil para descubrir servicios cercanos. Utiliza más energía que el modo de no multidifusión." "administración de Bluetooth" "Permite que una aplicación configure el teléfono Bluetooth local, y vea dispositivos remotos y sincronice el teléfono con ellos." "crear conexiones de Bluetooth" @@ -337,6 +373,8 @@ "Permite a una aplicación leer cualquier frase, palabra o nombre privado que el usuario haya almacenado en su diccionario." "escribir en el diccionario definido por el usuario" "Permite a una aplicación escribir palabras nuevas en el diccionario del usuario." + "modificar/eliminar contenido de la tarjeta SD" + "Permite que una aplicación escriba en la tarjeta SD." "Casa" "Móvil" @@ -353,6 +391,7 @@ "Otra" "Personalizar" + "Móvil" "Casa" "Trabajo" @@ -393,6 +432,8 @@ "Correcto" "Inténtalo de nuevo" "Cargando (%d%%)" + + "Conecta el cargador" "Falta la tarjeta SIM" "No se ha insertado ninguna tarjeta SIM en el teléfono." @@ -400,7 +441,7 @@ "Bloqueada para la red" "La tarjeta SIM está bloqueada con el código PUK." "Consulta la guía del usuario o ponte en contacto con el servicio de atención al cliente." - "La tarjeta SIM está bloqueada." + "Introduce el código PIN." "Desbloqueando tarjeta SIM..." "Has realizado %d intentos fallidos de creación de un patrón de desbloqueo. "\n\n"Inténtalo de nuevo dentro de %d segundos." "Has realizado %d intentos fallidos de creación del patrón de desbloqueo. Si realizas %d intentos fallidos más, se te pedirá que desbloquees el teléfono con tus credenciales de acceso de Google."\n\n" Espera %d segundos e inténtalo de nuevo." @@ -412,9 +453,10 @@ "Contraseña" "Acceder" "Nombre de usuario o contraseña no válido" - "%-l%P" - "%-l%p" - "Cerrar notificaciones" + "%-l %P" + "%-l %p" + + "No tienes notificaciones" "Entrante" "Notificaciones" @@ -423,6 +465,7 @@ "Conecta el cargador" "Se está agotando la batería:" "menos del %d%% disponible." + "¿Por qué?" "Fallo en la prueba de fábrica" "La acción FACTORY_TEST sólo es compatible con los paquetes instalados en /system/app." "No se ha encontrado ningún paquete que proporcione la acción FACTORY_TEST." @@ -431,6 +474,10 @@ "JavaScript" "¿Quieres salir de esta página?"\n\n"%s"\n\n"Selecciona \"Aceptar\" para continuar o \"Cancelar\" para permanecer en la página actual." "Confirmar" + "leer información de marcadores y del historial del navegador" + "Permite que la aplicación lea todas las URL que ha visitado el navegador y todos sus marcadores." + "escribir en marcadores y en el historial del navegador" + "Permite que una aplicación modifique la información de los marcadores o del historial del navegador almacenada en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos del navegador." "¿Deseas que el navegador recuerde esta contraseña?" "Ahora no" "Recordar" @@ -538,10 +585,6 @@ "Mediodía" "medianoche" "Medianoche" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "Seleccionar todo" @@ -579,6 +622,7 @@ "La aplicación %1$s (%2$s en curso) no está respondiendo." "El proceso %1$s no está respondiendo." "Forzar cierre" + "Informe" "Esperar" "Depurar" "Seleccionar la opción para compartir" @@ -621,8 +665,8 @@ "No activar" "Se ha producido un problema al intentar utilizar la tarjeta SD para el almacenamiento USB." "Conectado por USB" - "Seleccionar para copiar archivos al/desde el equipo" - "Desactivar almacenar en USB" + "Para copiar archivos al/desde el equipo" + "Desactivar almacenamiento USB" "Seleccionar para desactivar USB." "Desactivar almacenamiento USB" "Antes de desactivar el almacenamiento USB, asegúrate de haber desactivado el host USB. Selecciona \"Desactivar\" para desactivar el almacenamiento USB." @@ -632,26 +676,30 @@ "Formatear tarjeta SD" "¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de la tarjeta." "Formato" + + + + "Seleccionar método de introducción de texto" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "candidatos" "Preparando tarjeta SD" - "Comprobando errores" + "Comprobando errores..." "Tarjeta SD vacía" - "La tarjeta SD está vacía o utiliza un sistema de archivos incompatible." + "La tarjeta SD está vacía o su sistema de archivos es incompatible." "Tarjeta SD dañada" "La tarjeta SD está dañada. Es posible que sea necesario volver a formatearla." "La tarjeta SD se ha extraído inesperadamente." "Desactiva la tarjeta SD antes de extraerla para evitar la pérdida de datos." "Es seguro extraer la tarjeta SD." - "Ya puedes extraer la tarjeta SD." + "Puedes extraer la tarjeta SD de forma segura." "Tarjeta SD extraída" - "La tarjeta SD se ha extraído. Inserta una nueva tarjeta SD para aumentar la capacidad de almacenamiento de tu dispositivo." + "La tarjeta SD se ha extraído. Inserta una nueva." "No se ha encontrado ninguna actividad coincidente." "actualizar estadísticas de uso de componentes" "Permite la modificación de estadísticas recopiladas sobre el uso de componentes. No está destinado al uso por parte de aplicaciones normales." - "Pulsa dos veces para acceder al control de zoom." + "Da dos toques para acceder al control de zoom." "Error al aumentar el widget" "Ir" "Buscar" @@ -661,4 +709,6 @@ "Ejecutar" "Marcar número"\n"con %s" "Crear un contacto"\n"a partir de %s" + "seleccionado" + "no seleccionado" diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index ce650c1287022..6bd9389af5486 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -21,40 +21,46 @@ "Go" "To" "Po" - %1$s %2$s + "%1$s %2$s" "<sans titre>" "…" "(Aucun numéro de téléphone)" "(Inconnu)" "Messagerie vocale" "MSISDN1" - "Problème de connexion ou code MMI non valide." + "Problème de connexion ou code IHM non valide." "Le service a été activé." "Ce service a été activé pour :" "Ce service a été désactivé." "Enregistrement réussi." "Effacement réussi." "Le mot de passe est incorrect." - "MMI terminé." + "IHM terminée." "L\'ancien code PIN saisi est incorrect." - "Le code PUK saisi est incorrect." + "La clé PUK saisie est incorrecte." "Les codes PIN saisis ne correspondent pas." "Le code PIN doit compter de 4 à 8 chiffres." - "Votre carte SIM est verrouillée par code PUK. Saisissez le code PUK pour la déverrouiller." - "Saisissez le code PUK2 pour débloquer la carte SIM." - "Identifiant d\'appelant entrant" - "Identifiant d\'appelant sortant" + "Votre carte SIM est verrouillée par clé PUK. Saisissez la clé PUK pour la déverrouiller." + "Saisissez la clé PUK2 pour débloquer la carte SIM." + "Numéro de l\'appelant (entrant)" + "Numéro de l\'appelant (sortant)" "Transfert d\'appel" "Appel en attente" "Interdiction d\'appel" "Modification du mot de passe" "Modification du code PIN" - "Par défaut, les identifiants d\'appelant sont restreints. Appel suivant : restreint" - "Par défaut, les identifiants d\'appelant sont restreints. Appel suivant : non restreint" - "Par défaut, les identifiants d\'appelant ne sont pas restreints. Appel suivant : restreint" - "Par défaut, les identifiants d\'appelant ne sont pas restreints. Appel suivant : non restreint" + "Présentation du numéro d\'appelant" + "Numéro de l\'appelant masqué" + "Conférence téléphonique à trois" + "Rejeter les appels indésirables" + "Livraison du numéro d\'appel" + "Ne pas déranger" + "Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : restreint" + "Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : non restreint" + "Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : restreint" + "Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : non restreint" "Ce service n\'est pas pris en charge." - "Le paramètre Identifiant d\'appelant ne peut pas être modifié." + "Le paramètre Numéro de l\'appelant ne peut pas être modifié." "L\'accès limité a été modifié." "Le service de données est bloqué." "Le service d\'appel d\'urgence est bloqué." @@ -68,11 +74,27 @@ "Synchrones" "Paquet" "PAD" + "Indicateur d\'itinérance activé" + "Indicateur d\'itinérance désactivé" + "Indicateur d\'itinérance clignotant" + "Hors zone" + "Hors du bâtiment" + "Itinérance - Système préféré" + "Itinérance - Système disponible" + "Itinérance - Partenaire Alliance" + "Itinérance - Partenaire Premium" + "Itinérance - Tous services disponibles" + "Itinérance - Services partiellement disponibles" + "Bannière d\'itinérance activée" + "Bannière d\'itinérance désactivée" + "Recherche des services disponibles" "{0} : non transféré" "{0} : {1}" "{0} : {1} au bout de {2} secondes" "{0} : non transféré" "{0} : non transféré" + "Code de service terminé" + "Problème de connexion ou code de service non valide" "OK" "La page Web contient une erreur." "URL introuvable." @@ -89,6 +111,7 @@ "Impossible d\'accéder au fichier." "Le fichier demandé est introuvable." "Trop de requêtes sont en cours de traitement. Veuillez réessayer ultérieurement." + "Le certificat est enregistré dans le magasin de clés du système." "Synchroniser" "Synchronisation" "Trop de contenus supprimés (%s)." @@ -134,6 +157,8 @@ "Accès et contrôle de faible niveau du système." "Outils de développement" "Ces fonctionnalités sont réservées aux développeurs d\'applications." + "Stockage" + "Accès à la carte SD" "Désactivation ou modification de la barre d\'état" "Permet à une application de désactiver la barre d\'état ou d\'ajouter/supprimer des icônes système." "Agrandir/réduire la barre d\'état" @@ -166,6 +191,10 @@ "Permet à une application de forcer une autre application exécutée au premier plan à se fermer et à passer en arrière-plan. Les applications normales ne devraient jamais avoir recours à cette fonctionnalité." "Vérification de l\'état interne du système" "Permet à l\'application de récupérer l\'état interne du système. Des applications malveillantes peuvent obtenir de nombreuses informations personnelles et sécurisées auxquelles elles ne devraient pas avoir accès." + "arrêt partiel" + "Place le gestionnaire d\'activités en état d\'arrêt. N\'effectue pas un arrêt complet." + "empêcher les changements d\'applications" + "Empêche l\'utilisateur de changer d\'application." "Contrôle du lancement des applications" "Permet à une application de suivre et de contrôler la façon dont le système lance des activités. Des applications malveillantes peuvent entièrement déstabiliser le système. Cette autorisation est uniquement nécessaire au développement et non pour l\'utilisation normale du téléphone." "Envoyer une diffusion sans paquet" @@ -180,6 +209,8 @@ "Permet à une application de vérifier si des activités sont systématiquement interrompues lorsqu\'elles sont placées en tâche de fond. Cette fonctionnalité n\'est jamais utilisée par les applications normales." "Modification des statistiques de la batterie" "Autoriser la modification des statistiques de la batterie. Les applications normales n\'utilisent pas cette fonctionnalité." + "contrôler la sauvegarde et la restauration du système" + "Autorise l\'application à contrôler le mécanisme de sauvegarde et de restauration du système. Ne pas utiliser pour les applications standard." "Affichage de fenêtres non autorisées" "Permet de créer des fenêtres conçues pour l\'interface utilisateur du système interne. Les applications normales n\'utilisent pas cette fonctionnalité." "Affichage d\'alertes système" @@ -242,12 +273,14 @@ "Permet à une application de lire tous les événements de l\'agenda enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour envoyer les événements de votre agenda à d\'autres personnes." "Écriture des données de l\'agenda" "Permet à une application de modifier les événements de l\'agenda enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier les données de votre agenda." - "Création de sources géographiques fictives à des fins de test" - "Permet de créer des sources de position géographique fictives à des fins de test. Des applications malveillantes peuvent utiliser cette fonctionnalité pour remplacer la position géographique et/ou l\'état fournis par des sources réelles comme le GPS ou les fournisseurs d\'accès." + "Création de sources de positionnement fictives à des fins de test" + "Permet de créer des sources de positionnement fictives à des fins de test. Des applications malveillantes peuvent utiliser cette fonctionnalité pour remplacer la position géographique et/ou l\'état fournis par des sources réelles comme le GPS ou les fournisseurs d\'accès." "Accès aux commandes de fournisseur de position géographique supplémentaires" "Permet d\'accéder à des commandes de fournisseur de position géographique supplémentaires. Des applications malveillantes peuvent utiliser cette fonctionnalité pour interférer avec l\'utilisation du GPS ou d\'autres sources de positionnement géographique." + "autoriser l\'installation d\'un fournisseur de services de localisation" + "Créer des sources de données de localisation factices à des fins de test. Les applications malveillantes peuvent exploiter cette fonction pour remplacer la position géographique et/ou l\'état renvoyé par les sources de données de localisation réelles, telles que le GPS ou les fournisseurs réseau, ou pour surveiller et transmettre votre position géographique à une source externe." "Localisation OK (GPS)" - "Permet d\'accéder à des sources de positionnement géographique précises comme le Global Positioning System (GPS) sur le téléphone, lorsque ces services sont disponibles. Des applications malveillantes peuvent utiliser cette fonctionnalité pour déterminer l\'endroit où vous vous trouvez et augmenter la consommation de la batterie de votre téléphone." + "Permet d\'accéder à des sources de positionnement précises comme le Global Positioning System (GPS) sur le téléphone, lorsque ces services sont disponibles. Des applications malveillantes peuvent utiliser cette fonctionnalité pour déterminer l\'endroit où vous vous trouvez et augmenter la consommation de la batterie de votre téléphone." "Position géo. approximative (selon le réseau)" "Accès à des sources de positionnement approximatif (par ex. des bases de données de réseaux mobiles) pour déterminer la position géographique du téléphone, lorsque cette option est disponible. Des applications malveillantes peuvent utiliser cette fonctionnalité pour déterminer approximativement l\'endroit où vous vous trouvez." "Accès à SurfaceFlinger" @@ -279,13 +312,13 @@ "Appel direct de tout numéro de téléphone" "Permet à une application d\'appeler tout numéro de téléphone (y compris les numéros d\'urgence) sans votre intervention. Des applications malveillantes peuvent passer des appels non nécessaires ou illégitimes à des services d\'urgence." "Contrôle des notifications de mise à jour de position géo." - "Permet l\'activation/la désactivation des notifications de mises à jour de la position géographique provenant de la radio. Les applications normales n\'utilisent pas cette fonctionnalité." + "Permet l\'activation/la désactivation des notifications de mises à jour de la position géographique provenant du signal radio. Les applications normales n\'utilisent pas cette fonctionnalité." "Accès aux propriétés d\'enregistrement" "Permet un accès en lecture/écriture à des propriétés envoyées par le service d\'inscription. Les applications normales n\'utilisent pas cette fonctionnalité." "choisir les widgets" "Permet à l\'application de signaler au système quels widgets peuvent être utilisés par quelle application. Grâce à cette autorisation, les applications peuvent accorder l\'accès à des données personnelles à d\'autres applications. Cette option n\'est pas utilisée par les applications standard." "Modification de l\'état du téléphone" - "Permet à une application de contrôler les fonctionnalités téléphoniques de l\'appareil. Une application bénéficiant de cette autorisation peut changer de réseau, éteindre et allumer la radio du téléphone, etc., sans vous en avertir." + "Permet à une application de contrôler les fonctionnalités téléphoniques de l\'appareil. Une application bénéficiant de cette autorisation peut changer de réseau, éteindre et allumer le signal radio du téléphone, etc., sans vous en avertir." "Lecture de l\'état du téléphone" "Permet à l\'application d\'accéder aux fonctionnalités d\'appel du téléphone. L\'application peut alors déterminer le numéro de téléphone de l\'appareil, savoir si un appel est en cours, identifier le numéro appelé, etc." "Arrêt du mode veille sur le téléphone" @@ -295,9 +328,9 @@ "Exécution en mode Test d\'usine" "Permet d\'exécuter en tant que test fabricant de faible niveau en autorisant l\'accès au matériel du téléphone. Cette fonctionnalité est uniquement disponible lorsque le téléphone est en mode de test fabricant." "Configuration du fond d\'écran" - "Permet à une application de définir l\'arrière-plan du système." + "Permet à une application de définir le fond d\'écran du système." "Sélection de la la taille du fond d\'écran" - "Permet à une application de définir la taille d\'arrière-plan du système." + "Permet à une application de définir la taille du fond d\'écran." "Réinitialisation du système à ses paramètres d\'usine" "Permet à une application de réinitialiser entièrement le système afin de rétablir ses valeurs d\'usine et d\'effacer toutes les données, configurations et applications installées." "Sélection du fuseau horaire" @@ -318,6 +351,8 @@ "Permet à une application d\'afficher des informations concernant l\'état du Wi-Fi." "Modifier l\'état du Wi-Fi" "Permet à une application de se connecter à des points d\'accès Wi-Fi, de s\'en déconnecter et de modifier des réseaux Wi-Fi configurés." + "autoriser la réception de données en Wi-Fi multidiffusion" + "Autorise une application à recevoir des paquets qui ne sont pas directement adressés à votre mobile. Cela peut être utile pour la recherche de services disponibles à proximité. Consomme plus que le mode non multidiffusion." "Gestion Bluetooth" "Permet à une application de configurer le téléphone Bluetooth local, d\'identifier des périphériques distants et de les associer au téléphone." "Création de connexions Bluetooth" @@ -338,9 +373,11 @@ "Permet à une application de lire tous les mots, noms et expressions que l\'utilisateur a pu enregistrer dans son dictionnaire personnel." "Enregistrement dans le dictionnaire défini par l\'utilisateur" "Permet à une application d\'enregistrer de nouveaux mots dans le dictionnaire personnel de l\'utilisateur." + "modifier/supprimer le contenu de la carte SD" + "Autorise une application à écrire sur la carte SD." "Domicile" - "Mobile" + "Portable" "Bureau" "Télécopie bureau" "Télécopie domicile" @@ -354,6 +391,7 @@ "Autre" "Personnalisée" + "Mobile" "Domicile" "Bureau" @@ -389,25 +427,27 @@ "Écran verrouillé" "Appuyez sur \"Menu\" pour débloquer le téléphone ou appeler un numéro d\'urgence" "Appuyez sur \"Menu\" pour déverrouiller le téléphone." - "Dessinez un motif pour déverrouiller le téléphone" + "Dessinez un schéma pour déverrouiller le téléphone" "Appel d\'urgence" "Combinaison correcte !" "Désolé. Merci de réessayer." "Chargement (%d %%)" + + "Branchez votre chargeur." "Aucune carte SIM n\'a été trouvée." "Aucune carte SIM n\'est insérée dans le téléphone." "Insérez une carte SIM." "Réseau verrouillé" - "La carte SIM est verrouillée par code PUK." + "La carte SIM est verrouillée par clé PUK." "Veuillez consulter le guide d\'utilisation ou contacter l\'assistance clientèle." - "Téléphone verrouillé" + "La carte SIM est verrouillée." "Déblocage de la carte SIM..." - "Vous avez mal reproduit le motif de déverrouillage %d fois. "\n\n"Veuillez réessayer dans %d secondes." - "Vous avez mal saisi le motif de déverrouillage %d fois. Au bout de %d tentatives supplémentaires, vous devrez débloquer votre téléphone à l\'aide de votre identifiant Google."\n\n"Merci de réessayer dans %d secondes." + "Vous avez mal reproduit le schéma de déverrouillage %d fois. "\n\n"Veuillez réessayer dans %d secondes." + "Vous avez mal saisi le schéma de déverrouillage %d fois. Au bout de %d tentatives supplémentaires, vous devrez débloquer votre téléphone à l\'aide de votre identifiant Google."\n\n"Merci de réessayer dans %d secondes." "Réessayez dans %d secondes." - "Motif oublié ?" - "Trop de tentatives de motif !" + "Schéma oublié ?" + "Trop de tentatives !" "Pour déverrouiller le téléphone, connectez-vous à l\'aide de votre compte Google." "Nom d\'utilisateur (e-mail)" "Mot de passe" @@ -415,7 +455,8 @@ "Nom d\'utilisateur ou mot de passe incorrect." "%-l%P" "%-l%p" - "Effacer les notifications" + + "Aucune notification" "En cours" "Notifications" @@ -424,6 +465,7 @@ "Branchez le chargeur" "Le niveau de la batterie est bas :" "Batterie restante inférieure à %d%%." + "Pourquoi ?" "Échec du test usine" "L\'action FACTORY_TEST est uniquement prise en charge pour les paquets de données installés dans in/system/app." "Impossible de trouver un paquet proposant l\'action FACTORY_TEST." @@ -432,6 +474,10 @@ "JavaScript" "Vous souhaitez quitter cette page ?"\n\n"%s"\n\n"Sélectionnez OK pour continuer ou Annuler pour rester sur la page actuelle." "Confirmer" + "lire l\'historique et les favoris du navigateur" + "Autorise l\'application à lire toutes les URL auxquelles le navigateur a accédé et tous ses favoris." + "écrire dans l\'historique et les favoris du navigateur" + "Autorise une application à modifier l\'historique du navigateur ou les favoris enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonction pour effacer ou modifier les données de votre navigateur." "Voulez-vous que le navigateur se souvienne de ce mot de passe ?" "Pas maintenant" "Se souvenir du mot de passe" @@ -517,8 +563,8 @@ "jours" "heure" "heures" - "min" - "min" + "mn" + "mn" "s" "s" "semaine" @@ -539,10 +585,6 @@ "Midi" "minuit" "Minuit" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "Tout sélectionner" @@ -580,6 +622,7 @@ "L\'application %1$s (du processus %2$s) ne répond pas." "Le processus %1$s ne répond pas." "Forcer la fermeture" + "Rapport" "Attendre" "Débogage" "Sélectionner une action pour le texte" @@ -601,8 +644,8 @@ "Réseaux Wi-Fi disponibles" - "Ouvrir le réseau Wi-Fi disponible" - "Ouvrir les réseaux Wi-Fi disponibles" + "Réseau Wi-Fi ouvert disponible" + "Réseaux Wi-Fi ouverts disponibles" "Insérer un caractère" "Application inconnue" @@ -617,7 +660,7 @@ "Tout afficher" "Chargement..." "Connecté à l\'aide d\'un câble USB" - "Vous avez connecté votre téléphone à votre ordinateur à l\'aide d\'un câble USB. Sélectionnez Monter pour copier des fichiers depuis votre ordinateur vers votre carte SD ou inversement." + "Vous avez connecté votre téléphone à votre ordinateur à l\'aide d\'un câble USB. Sélectionnez Monter pour copier des fichiers de votre ordinateur vers votre carte SD, ou inversement." "Monter" "Ne pas monter" "Un problème est survenu lors de l\'utilisation de votre carte SD en tant que périphérique de stockage USB." @@ -633,6 +676,10 @@ "Formater la carte SD" "Voulez-vous vraiment formater la carte SD ? Toutes les données de cette carte seront perdues." "Format" + + + + "Sélectionner un mode de saisie" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -640,15 +687,15 @@ "Préparation de la carte SD" "Recherche d\'erreurs" "Carte SD vide" - "La carte SD est vide ou utilise un système de fichiers non pris en charge." + "La carte SD est vide ou son système de fichiers n\'est pas pris en charge." "Carte SD endommagée" - "La carte SD est endommagée. Vous devrez peut-être reformater votre carte." + "La carte SD est endommagée. Vous devrez peut-être la reformater." "Carte SD retirée inopinément" "Désactiver la carte SD avant de la retirer pour éviter toute perte de données." "La carte SD peut être retirée en toute sécurité" - "Vous pouvez désormais retirer la carte SD en toute sécurité." + "Vous pouvez retirer la carte SD en toute sécurité." "Carte SD manquante" - "Carte SD manquante. Insérez une autre carte pour augmenter la capacité de stockage." + "La carte SD a été retirée. Insérez-en une autre." "Aucune activité correspondante trouvée" "mettre à jour les données statistiques du composant" "Permet de modifier les données statistiques collectées du composant. Cette option n\'est pas utilisée par les applications standard." @@ -658,8 +705,10 @@ "Rechercher" "Envoyer" "Suivant" - "Terminé" + "OK" "Exécuter" "Composer le numéro"\n"en utilisant %s" "Ajouter un contact"\n"en utilisant %s" + "sélectionné" + "non sélectionné" diff --git a/core/res/res/values-he-rIL/donottranslate-cldr.xml b/core/res/res/values-he-rIL/donottranslate-cldr.xml index e3feb1e331463..3378ed7227ad0 100644 --- a/core/res/res/values-he-rIL/donottranslate-cldr.xml +++ b/core/res/res/values-he-rIL/donottranslate-cldr.xml @@ -61,20 +61,20 @@ יום שישי יום שבת - יום א' - יום ב' - יום ג' - יום ד' - יום ה' - יום ו' + יום א\' + יום ב\' + יום ג\' + יום ד\' + יום ה\' + יום ו\' שבת - יום א' - יום ב' - יום ג' - יום ד' - יום ה' - יום ו' + יום א\' + יום ב\' + יום ג\' + יום ד\' + יום ה\' + יום ו\' שבת א diff --git a/core/res/res/values-hr-rHR/donottranslate-cldr.xml b/core/res/res/values-hr-rHR/donottranslate-cldr.xml new file mode 100644 index 0000000000000..6f8d6e5734481 --- /dev/null +++ b/core/res/res/values-hr-rHR/donottranslate-cldr.xml @@ -0,0 +1,147 @@ + + + siječanj + veljača + ožujak + travanj + svibanj + lipanj + srpanj + kolovoz + rujan + listopad + studeni + prosinac + + siječnja + veljače + ožujka + travnja + svibnja + lipnja + srpnja + kolovoza + rujna + listopada + studenoga + prosinca + + 01. + 02. + 03. + 04. + 05. + 06. + 07. + 08. + 09. + 10. + 11. + 12. + + 1. + 2. + 3. + 4. + 5. + 6. + 7. + 8. + 9. + 10. + 11. + 12. + + nedjelja + ponedjeljak + utorak + srijeda + četvrtak + petak + subota + + ned + pon + uto + sri + čet + pet + sub + + ned + pon + uto + sri + čet + pet + sub + + n + p + u + s + č + p + s + + AM + PM + jučer + danas + sutra + + %-k:%M + %-l:%M %p + %-l:%M %^p + h:mm a + H:mm + %-e.%-m.%Y. + d.M.yyyy. + "%s.%s.%s." + %-e. %B %Y. + %H:%M:%S + %H:%M:%S %-e.%b.%Y. + %2$s %1$s + %1$s %3$s + %-e.%b.%Y. + %-e. %B + %-B + %B %Y. + %-e.%b. + %-b. + %b.%Y. + %1$s - %2$s + %2$s - %5$s + %3$s.%2$s. - %8$s.%7$s. + %1$s, %3$s.%2$s. - %6$s, %8$s.%7$s. + %3$s.%2$s.%4$s. - %8$s.%7$s.%9$s. + %1$s, %3$s.%2$s.%4$s. - %6$s, %8$s.%7$s.%9$s. + %5$s %1$s, %3$s.%2$s.%4$s. - %10$s %6$s, %8$s.%7$s.%9$s. + %5$s %3$s.%2$s. - %10$s %8$s.%7$s. + %5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s. + %5$s %3$s.%2$s.%4$s. - %10$s %8$s.%7$s.%9$s. + %3$s %1$s, %2$s - %6$s %4$s, %5$s + %1$s, %2$s - %4$s, %5$s + %3$s %2$s - %6$s %5$s + %1$s %2$s, %3$s + %2$s, %3$s + %1$s %2$s + %3$s. %2$s - %8$s. %7$s + %1$s, %3$s.%2$s. - %6$s, %8$s.%7$s. + %5$s %3$s. %2$s - %10$s %8$s. %7$s + %5$s %3$s. %2$s - %10$s %8$s. %7$s + %5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s. + %5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s. + %5$s %3$s.%2$s.%4$s. - %10$s %8$s.%7$s.%9$s. + %5$s %3$s.%2$s.%4$s. - %10$s %8$s.%7$s.%9$s. + %5$s %1$s, %3$s.%2$s.%4$s. - %10$s %6$s, %8$s.%7$s.%9$s. + %5$s %1$s, %3$s.%2$s.%4$s. - %10$s %6$s, %8$s.%7$s.%9$s. + %1$s, %3$s.%2$s.%4$s. - %6$s, %8$s.%7$s.%9$s. + %3$s. - %8$s.%2$s. + %1$s, %3$s.%2$s. - %6$s, %8$s.%7$s. + %3$s.%2$s. - %8$s.%7$s.%9$s. + %3$s. - %8$s.%2$s.%9$s. + %1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.%9$s. + %b + diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 5bfbc49431435..1a1845082238f 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -21,6 +21,7 @@ "GB" "TB" "PB" + "%1$s%2$s" "<senza nome>" "…" "(Nessun numero di telefono)" @@ -48,6 +49,12 @@ "Blocco chiamate" "Modifica password" "Modifica PIN" + "Numero chiamante presente" + "Numero chiamante con restrizioni" + "Chiamata a tre" + "Rifiuto di chiamate fastidiose non desiderate" + "Recapito numero chiamante" + "Non disturbare" "ID chiamante generalmente limitato. Prossima chiamata: limitato" "ID chiamante generalmente limitato. Prossima chiamata: non limitato" "ID chiamante generalmente non limitato. Prossima chiamata: limitato" @@ -67,11 +74,27 @@ "Sinc" "Pacchetto" "PAD" + "Indicatore roaming attivato" + "Indicatore roaming disattivato" + "Indicatore roaming lampeggiante" + "Fuori dal vicinato" + "Fuori dall\'edificio" + "Roaming - Sistema preferito" + "Roaming - Sistema disponibile" + "Roaming - Partner Alliance" + "Roaming - Partner Premium" + "Roaming - Funzionalità servizio completo" + "Roaming - Funzionalità servizio parziale" + "Banner roaming attivato" + "Banner roaming disattivato" + "Ricerca servizio" "{0}: inoltro non effettuato" "{0}: {1}" "{0}{1} dopo {2} secondi" "{0}: inoltro non effettuato" "{0}: inoltro non effettuato" + "Codice funzione completo." + "Problema di connessione o codice funzione non valido." "OK" "La pagina web contiene un errore." "Impossibile trovare l\'URL." @@ -88,6 +111,7 @@ "Impossibile accedere al file." "Impossibile trovare il file richiesto." "Troppe richieste in fase di elaborazione. Riprova più tardi." + "Il certificato viene salvato nell\'archivio chiavi del sistema." "Sinc" "Sincronizzazione" "Troppe eliminazioni di %s." @@ -108,9 +132,9 @@ "Modalità silenziosa" "Audio non attivo" "Audio attivo" - "Modalità in volo" - "Modalità in volo attiva" - "Modalità in volo non attiva" + "Modalità aereo attiva" + "Modalità aereo attiva" + "Modalità aereo non attiva" "Modalità provvisoria" "Sistema Android" "Servizi che prevedono un costo" @@ -133,6 +157,8 @@ "Accesso al sistema e controllo di livello inferiore." "Strumenti di sviluppo" "Funzionalità necessarie soltanto agli sviluppatori di applicazioni." + "Archiviazione" + "Accesso alla scheda SD." "disattivare o modificare la barra di stato" "Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema." "espansione/compressione barra di stato" @@ -165,6 +191,10 @@ "Consente a un\'applicazione di forzare la chiusura di attività in primo piano. Non dovrebbe essere mai necessario per le normali applicazioni." "recupero stato interno del sistema" "Consente all\'applicazione di recuperare lo stato interno del sistema. Le applicazioni dannose potrebbero recuperare molte informazioni riservate e protette di cui non dovrebbero avere mai bisogno." + "chiusura parziale" + "Mette il gestore delle attività in uno stato di chiusura. Non esegue una chiusura completa." + "impedire commutazione applicazione" + "Impedisce all\'utente di passare a un\'altra applicazione." "monitoraggio e controllo avvio applicazioni" "Consente a un\'applicazione di monitorare e controllare la modalità di avvio delle attività nel sistema. Le applicazioni dannose potrebbero compromettere totalmente il sistema. Questa autorizzazione è necessaria soltanto per lo sviluppo, mai per il normale utilizzo del telefono." "invio broadcast rimossi dal pacchetto" @@ -179,6 +209,8 @@ "Consente a un\'applicazione di controllare se le attività sono sempre completate quando vengono messe in secondo piano. Mai necessario per le normali applicazioni." "modifica statistiche batteria" "Consente la modifica delle statistiche sulla batteria raccolte. Da non usare per normali applicazioni." + "controllo del backup di sistema e ripristino" + "Consente all\'applicazione di controllare i backup dei sistemi e il meccanismo di ripristino. Da non usare per normali applicazioni." "visualizzazione finestre non autorizzate" "Consente la creazione di finestre destinate all\'uso nell\'interfaccia utente di sistema interna. Da non usare per normali applicazioni." "visualizzazione avvisi di sistema" @@ -245,6 +277,8 @@ "Creare fonti di localizzazione fittizie per test. Le applicazioni dannose possono sfruttare questa possibilità per sostituire la posizione e/o lo stato restituito da reali fonti di localizzazione come GPS o provider di rete." "accesso a comandi aggiuntivi del provider di localizz." "Accedere a comandi aggiuntivi del provider di localizzazione. Le applicazioni dannose possono sfruttare questa possibilità per interferire con il funzionamento del GPS o di altre fonti di localizzazione." + "autorizzazione a installare un provider di localizzazione" + "Creare fonti di localizzazione fittizie per test. Le applicazioni dannose possono sfruttare questa possibilità per sostituire la posizione e/o lo stato restituito da reali fonti di localizzazione come GPS o provider di rete oppure per monitorare e segnalare la tua posizione a una fonte esterna." "localizzazione precisa (GPS)" "Consente l\'accesso a fonti di localizzazione precisa, come il sistema GPS del telefono, se disponibile. Le applicazioni dannose possono sfruttare questa possibilità per determinare la tua posizione e, nel farlo, far esaurire più in fretta la batteria." "localizzazione approssimativa (basata sulla rete)" @@ -317,6 +351,8 @@ "Consente a un\'applicazione di visualizzare le informazioni relative allo stato della connessione Wi-Fi." "modifica stato Wi-Fi" "Consente a un\'applicazione di connettersi/disconnettersi da punti di accesso Wi-Fi e di apportare modifiche alle reti Wi-Fi configurate." + "consenti ricezione multicast Wi-Fi" + "Consente a un\'applicazione di ricevere pacchetti non direttamente indirizzati al tuo dispositivo. Può essere utile durante la ricerca di servizi offerti nelle vicinanze. Consuma di più rispetto alla modalità non multicast." "gestione Bluetooth" "Consente a un\'applicazione di configurare il telefono Bluetooth locale e di rilevare e abbinare dispositivi remoti." "creazione connessioni Bluetooth" @@ -337,6 +373,8 @@ "Consente a un\'applicazione di leggere parole, nomi e frasi private che l\'utente potrebbe aver memorizzato nel dizionario utente." "scrittura nel dizionario definito dall\'utente" "Consente a un\'applicazione di scrivere nuove parole nel dizionario utente." + "modificare/eliminare i contenuti della scheda SD" + "Consente a un\'applicazione di scrivere sulla scheda SD." "Casa" "Cellulare" @@ -353,6 +391,7 @@ "Altro" "Personalizzato" + "Cellulare" "Casa" "Ufficio" @@ -393,6 +432,8 @@ "Corretta." "Riprova" "In carica (%d%%)" + + "Collegare il caricabatterie." "Nessuna SIM presente." "Nessuna SIM presente nel telefono." @@ -414,7 +455,8 @@ "Password o nome utente non valido." "%-l%P" "%-l%p" - "Cancella notifiche" + + "Nessuna notifica" "In corso" "Notifiche" @@ -423,6 +465,7 @@ "Collegare il caricabatterie" "Batteria quasi scarica:" "energia residua inferiore a %d%%." + "Perché?" "Test di fabbrica non riuscito" "L\'azione FACTORY_TEST è supportata soltanto per i pacchetti installati in /system/app." "Nessun pacchetto trovato che fornisca l\'azione FACTORY_TEST." @@ -431,6 +474,10 @@ "JavaScript" "Uscire da questa pagina?"\n\n"%s"\n\n"Seleziona OK per continuare o Annulla per rimanere nella pagina corrente." "Conferma" + "lettura cronologia e segnalibri del browser" + "Consente all\'applicazione di leggere tutti gli URL visitati e tutti i segnalibri del browser." + "creazione cronologia e segnalibri del browser" + "Consente a un\'applicazione di modificare la cronologia o i segnalibri del browser memorizzati sul telefono. Le applicazioni dannose possono sfruttare questa possibilità per cancellare o modificare i dati del browser." "Memorizzare la password nel browser?" "Non ora" "Memorizza" @@ -538,10 +585,6 @@ "Mezzogiorno" "mezzanotte" "Mezzanotte" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "Seleziona tutto" @@ -579,9 +622,10 @@ "L\'applicazione %1$s (nel processo %2$s) non risponde." "Il processo %1$s non risponde." "Termina" + "Segnala" "Attendi" "Debug" - "Seleziona un\'azione per il testo" + "Selezione un\'opzione di invio" "Volume suoneria" "Volume app. multimediali" "Riproduzione tramite Bluetooth" @@ -632,22 +676,26 @@ "Formatta scheda SD" "Formattare la scheda SD? Tutti i dati sulla scheda verranno persi." "Formatta" + + + + "Seleziona metodo di inserimento" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "candidati" "Preparazione scheda SD" - "Ricerca errori" + "Ricerca errori." "Scheda SD vuota" - "La scheda SD è vuota o utilizza un file system non supportato." + "Scheda SD vuota o con filesystem non supportato." "Scheda SD danneggiata" - "La scheda SD è danneggiata. Potrebbe essere necessario riformattarla." + "Scheda SD danneggiata. Potrebbe essere necessario riformattarla." "Rimozione imprevista della scheda SD" "Smonta scheda SD prima della rimozione per evitare la perdita di dati." "È possibile rimuovere la scheda SD" - "È ora possibile rimuovere la scheda SD in modo sicuro." + "Puoi rimuovere la scheda SD in tutta sicurezza." "Scheda SD rimossa" - "Inserisci una nuova scheda SD per aumentare la memoria del dispositivo." + "Scheda SD rimossa. Inseriscine un\'altra." "Nessuna attività corrispondente trovata" "aggiornare le statistiche di utilizzo dei componenti" "Consente la modifica delle statistiche di utilizzo dei componenti raccolte. Da non usare per normali applicazioni." @@ -661,4 +709,6 @@ "Esegui" "Componi numero"\n"utilizzando %s" "Crea contatto"\n"utilizzando %s" + "selezionato" + "non selezionato" diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index a2e3e51846c4f..618d16b9db5c5 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -21,6 +21,8 @@ "GB" "TB" "PB" + + "<新規>" "..." "(電話番号なし)" @@ -48,6 +50,18 @@ "発信制限" "パスワードの変更" "PINの変更" + + + + + + + + + + + + "既定: 発信者番号非通知、次の発信: 非通知" "既定: 発信者番号非通知、次の発信: 通知" "既定: 発信者番号通知、次の発信: 非通知" @@ -67,11 +81,43 @@ "同期" "パケット" "PAD" + + + + + + + + + + + + + + + + + + + + + + + + + + + + "{0}:転送できません" "{0}:{1}" "{0}:{1} ({2}秒後)" "{0}:転送できません" "{0}:転送できません" + + + + "OK" "ウェブページにエラーがあります。" "URLが見つかりません。" @@ -88,6 +134,8 @@ "ファイルにアクセスできませんでした。" "要求されたファイルが見つかりませんでした。" "処理中のリクエストが多すぎます。しばらくしてからもう一度試してください。" + + "同期" "同期" "%sでの削除が多すぎます。" @@ -133,6 +181,10 @@ "システムの低レベルのアクセスと制御" "開発ツール" "アプリケーションのデベロッパーにのみ必要な機能です。" + + + + "ステータスバーの無効化や変更" "ステータスバーの無効化やシステムアイコンの追加や削除をアプリケーションに許可します。" "ステータスバーの拡大/縮小" @@ -145,9 +197,9 @@ "MMSメッセージの受信と処理をアプリケーションに許可します。悪意のあるアプリケーションがメッセージを監視したり、表示せずに削除する恐れがあります。" "SMSメッセージの送信" "SMSメッセージの送信をアプリケーションに許可します。悪意のあるアプリケーションが確認なしでメッセージを送信し、料金が発生する恐れがあります。" - "SMSやMMSの読み取り" + "SMSの読み取り" "携帯電話やSIMカードに保存したSMSメッセージの読み取りをアプリケーションに許可します。悪意のあるアプリケーションが機密メッセージを読み取る恐れがあります。" - "SMSやMMSの編集" + "SMSの編集" "携帯電話やSIMカードに保存したSMSメッセージへの書き込みをアプリケーションに許可します。悪意のあるアプリケーションがメッセージを削除する恐れがあります。" "WAPの受信" "WAPメッセージの受信と処理をアプリケーションに許可します。悪意のあるアプリケーションがメッセージを監視したり、表示せずに削除する恐れがあります。" @@ -165,6 +217,14 @@ "フォアグラウンドで実行されている操作を強制終了して戻ることをアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。" "システムの内部状態の取得" "システムの内部状態の取得をアプリケーションに許可します。悪意のあるアプリケーションが、通常は必要としない広範囲にわたる非公開の機密情報を取得する恐れがあります。" + + + + + + + + "起動中のすべてのアプリケーションの監視と制御" "システムが起動する操作の監視と制御をアプリケーションに許可します。悪意のあるアプリケーションがシステムを完全に破壊する恐れがあります。この許可は開発にのみ必要で、携帯電話の通常の使用にはまったく必要ありません。" "パッケージ削除ブロードキャストの送信" @@ -179,6 +239,10 @@ "バックグラウンドになり次第必ず操作を終了させるかどうかの制御をアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。" "電池統計情報の変国" "収集した電池統計情報の変更を許可します。通常のアプリケーションでは使用しません。" + + + + "未許可のウィンドウの表示" "内部システムのユーザーインターフェースで使用するためのウィンドウ作成を許可します。通常のアプリケーションでは使用しません。" "システムレベルの警告の表示" @@ -243,8 +307,12 @@ "端末に保存したカレンダーの予定の変更をアプリケーションに許可します。悪意のあるアプリケーションが、カレンダーデータを消去/変更する恐れがあります。" "仮の位置情報でテスト" "テスト用に仮の位置情報源を作成します。これにより悪意のあるアプリケーションが、GPS、ネットワークプロバイダなどから返される本当の位置情報や状況を改ざんする恐れがあります。" - "位置情報プロバイダのその他のコマンドへのアクセス" + "位置情報提供者の追加コマンドアクセス" "位置情報提供元の追加コマンドにアクセスします。悪意のあるアプリケーションがGPSなどの位置提供の動作を妨害する恐れがあります。" + + + + "精細な位置情報(GPS)" "GPSなど携帯電話の位置情報にアクセスします(可能な場合)。今いる場所が悪意のあるアプリケーションに検出されたり、バッテリーの消費が増える恐れがあります。" "おおよその位置情報(ネットワーク基地局)" @@ -317,6 +385,10 @@ "Wi-Fi状態に関する情報の表示をアプリケーションに許可します。" "Wi-Fi状態の変更" "Wi-Fiアクセスポイントへの接続や接続の切断、設定されたWi-Fiネットワークの変更をアプリケーションに許可します。" + + + + "Bluetoothの管理" "このBluetooth端末の設定、およびリモート端末を検出してペアに設定することをアプリケーションに許可します。" "Bluetooth接続の作成" @@ -337,6 +409,10 @@ "アプリケーションがユーザー辞書に登録されている個人的な語句や名前を読み込むことを許可します。" "ユーザー定義辞書への書き込み" "アプリケーションがユーザー辞書に新しい語句を書き込むことを許可します。" + + + + "自宅" "携帯" @@ -353,6 +429,7 @@ "その他" "カスタム" + "携帯" "自宅" "仕事" @@ -386,13 +463,15 @@ "緊急通報番号" "(通信サービスなし)" "画面ロック中" - "MENUキーでロック解除(または緊急通報)" + "MENUキーでロック解除(または緊急通報)" "MENUキーでロック解除" "ロックを解除するパターンを入力" "緊急通報" "一致しました" "やり直してください" "充電中(%d%%)" + + "充電してください。" "SIMカードが挿入されていません" "SIMカードが挿入されていません" @@ -414,15 +493,18 @@ "ユーザー名またはパスワードが正しくありません。" "%-l%P" "%-l%p" - "通知を消去" + + "通知なし" - "操作中" + "実行中" "通知" "%d%%" "充電中..." "充電してください" "電池が残り少なくなっています:" "残量%d%%以下" + + "出荷時試験が失敗" "FACTORY_TEST操作は、/system/appにインストールされたパッケージのみが対象です。" "FACTORY_TEST操作を行うパッケージは見つかりませんでした。" @@ -431,6 +513,14 @@ "JavaScript" "このページから移動しますか?"\n\n"%s"\n\n"移動する場合は[OK]、今のページに残る場合は[キャンセル]を選択してください。" "確認" + + + + + + + + "このパスワードをブラウザで保存しますか?" "今は保存しない" "保存" @@ -538,10 +628,6 @@ "正午" "午前0時" "午前0時" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "すべて選択" @@ -579,18 +665,20 @@ "%1$s%2$s)は応答していません。" "%1$sは応答していません。" "強制終了" + + "待機" "デバッグ" "アプリケーションを選択" "着信音量" "メディアの音量" "Bluetooth経由で再生中です" - "着信音量" + "通話音量" "Bluetooth着信音量" "アラームの音量" "通知音量" "音量" - "デフォルトの着信音" + "プリセット着信音" "端末の基本着信音(%1$s)" "サイレント" "着信音" @@ -632,22 +720,31 @@ "SDカードをフォーマット" "SDカードをフォーマットしてもよろしいですか?カード内のすべてのデータが失われます。" "フォーマット" + + + + "入力方法の選択" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "候補" "SDカードの準備中" - "エラーを確認中" + + "空のSDカード" - "SDカードが空か、サポート対象外のファイルシステムを使用しています。" + + "破損したSDカード" - "SDカードが破損しています。カードのフォーマットが必要な可能性があります。" + + "SDカードが予期せず取り外されました" "データの喪失を防ぐためSDカードを取り外す前にマウントを解除してください。" "SDカードを安全に取り外しました" - "SDカードを安全に取り外せます。" + + "SDカードが取り外されています" - "SDカードが取り外されました。新しいSDカードを挿入して端末のメモリを増やしてください。" + + "一致するアクティビティが見つかりません" "コンポーネント使用状況に関する統計情報の更新" "収集されたコンポーネント使用状況に関する統計情報の変更を許可します。通常のアプリケーションでは使用しません。" @@ -661,4 +758,8 @@ "実行" "%sを使って"\n"発信" "%sを使って"\n"連絡先を新規登録" + + + + diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index e2c6e570fe279..d60ebaa1cc33f 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -21,6 +21,8 @@ "GB" "TB" "PB" + + "<제목없음>" "…" "(전화번호 없음)" @@ -28,17 +30,17 @@ "음성메일" "MSISDN1" "연결에 문제가 있거나 MMI 코드가 잘못되었습니다." - "서비스가 활성화되었습니다." + "서비스를 사용하도록 설정했습니다." "사용 설정된 서비스 목록:" - "서비스가 비활성화되었습니다." + "서비스가 사용 중지되었습니다." "등록이 완료되었습니다." - "지웠습니다." + "삭제했습니다." "비밀번호가 잘못되었습니다." "MMI 완료" "이전 PIN이 올바르지 않습니다." "입력한 PUK가 올바르지 않습니다." "입력한 PIN이 일치하지 않습니다." - "4~8자리 숫자로 된 PIN을 입력하세요." + "4~ 8자리 숫자로 된 PIN을 입력하세요." "SIM 카드의 PUK가 잠겨 있습니다. 잠금해제하려면 PUK 코드를 입력하세요." "SIM 카드 잠금을 해제하려면 PUK2를 입력하세요." "수신 발신자 번호" @@ -48,6 +50,18 @@ "착발신 제한" "비밀번호 변경" "PIN 변경" + + + + + + + + + + + + "발신자 번호가 기본적으로 제한됨으로 설정됩니다. 다음 통화: 제한됨" "발신자 번호가 기본적으로 제한됨으로 설정됩니다. 다음 통화: 제한되지 않음" "발신자 번호가 기본적으로 제한되지 않음으로 설정됩니다. 다음 통화: 제한됨" @@ -56,7 +70,7 @@ "발신자 번호 설정을 변경할 수 없습니다." "제한된 액세스가 변경되었습니다." "데이터 서비스가 차단되었습니다." - "응급 서비스가 차단되었습니다." + "긴급 서비스가 차단되었습니다." "음성/SMS 서비스가 차단되었습니다." "모든 음성/SMS 서비스가 차단되었습니다." "음성" @@ -67,11 +81,43 @@ "동기화" "패킷" "PAD" - "{0}: 착신전환 안 됨" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "{0}: 착신전환 안됨" "{0}: {1}" - "{0}: {2}초 후 {1}" - "{0}: 착신전환 안 됨" - "{0}: 착신전환 안 됨" + "{0}: {1}{2}초 후" + "{0}: 착신전환 안됨" + "{0}: 착신전환 안됨" + + + + "확인" "웹페이지에 오류가 있습니다." "URL을 찾을 수 없습니다." @@ -79,7 +125,7 @@ "인증에 실패했습니다." "프록시 서버를 통한 인증에 실패했습니다." "서버에 연결하지 못했습니다." - "서버와 통신할 수 없습니다. 나중에 다시 시도하세요." + "서버와 통신할 수 없습니다. 잠시 후에 다시 시도해 주세요." "서버 연결 제한시간이 초과되었습니다." "페이지에 서버 리디렉션이 너무 많이 포함되어 있습니다." "지원되지 않는 프로토콜입니다." @@ -87,288 +133,319 @@ "URL이 올바르지 않아 페이지를 열 수 없습니다." "파일에 액세스할 수 없습니다." "요청한 파일을 찾을 수 없습니다." - "처리 중인 요청이 너무 많습니다. 잠시 후에 다시 시도하세요." + "처리 중인 요청이 너무 많습니다. 잠시 후에 다시 시도해 주세요." + + "동기화" "동기화" "%s 삭제가 너무 많습니다." - "전화기 저장공간이 꽉 찼습니다. 일부 파일을 삭제하여 저장 여유 공간을 늘리세요." + "휴대전화 저장공간이 꽉 찼습니다. 일부 파일을 삭제하여 저장 여유 공간을 늘리세요." "나" - "전화기 옵션" + "휴대전화 옵션" "무음 모드" - "무선 켜기" + "무선 사용" "무선 끄기" "화면 잠금" "끄기" "종료 중..." - "전화기가 종료됩니다." + "휴대전화가 종료됩니다." "최신 응용프로그램이 아닙니다." - "전화기 옵션" + "휴대전화 옵션" "화면 잠금" "끄기" "무음 모드" "소리 꺼짐" "소리 켜짐" - "비행기 모드" - "비행기 모드 사용 안함" - "비행기 모드 사용" + "비행 모드" + "비행 모드 사용" + "비행 모드 사용 안함" "안전 모드" "Android 시스템" "요금이 부과되는 서비스" - "응용프로그램이 요금이 부과될 수 있는 작업을 할 수 있습니다." + "응용프로그램이 요금이 부과될 수 있는 작업을 할 수 있도록 합니다." "메시지" "SMS, 이메일 및 기타 메시지를 읽고 씁니다." - "개인 정보" - "전화기에 저장된 연락처 및 캘린더에 직접 액세스합니다." + "개인정보" + "휴대전화에 저장된 주소록 및 캘린더에 직접 액세스합니다." "위치" - "물리적 위치 모니터링" + "실제 위치 모니터링" "네트워크 통신" - "응용프로그램이 다양한 네트워크 기능에 액세스할 수 있습니다." + "응용프로그램이 다양한 네트워크 기능에 액세스할 수 있도록 합니다." "Google 계정" - "사용가능한 Google 계정에 액세스합니다." + "사용 가능한 Google 계정에 액세스합니다." "하드웨어 제어" - "핸드셋의 하드웨어에 직접 액세스합니다." + "휴대전화의 하드웨어에 직접 액세스합니다." "전화 통화" "전화 통화를 모니터링, 기록 및 처리합니다." "시스템 도구" - "하위 수준의 액세스 및 시스템 제어" - "개발도구" + "시스템을 하위 수준에서 액세스하고 제어합니다." + "개발 도구" "응용프로그램 개발자에게만 필요한 기능입니다." - "상태 표시줄 사용 안 함 또는 수정" - "응용프로그램이 상태 표시줄을 비활성화하거나 시스템 아이콘을 추가 및 제거할 수 있습니다." + + + + + "상태 표시줄 사용 중지 또는 수정" + "응용프로그램이 상태 표시줄을 사용 중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 합니다." "상태 표시줄 확장/축소" - "응용프로그램이 상태 표시줄을 확장하거나 축소할 수 있습니다." + "응용프로그램이 상태 표시줄을 확장하거나 축소할 수 있도록 합니다." "발신전화 가로채기" - "응용프로그램이 발신전화를 처리하고 전화를 걸 번호를 변경할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 발신전화를 모니터링하거나, 다른 방향으로 돌리거나, 중단시킬 수 있습니다." - "SMS 받기" - "응용프로그램이 SMS 메시지를 받고 처리할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 메시지를 모니터링하거나 사용자가 보기 전에 삭제할 수 있습니다." - "MMS 받기" - "응용프로그램이 MMS 메시지를 받고 처리할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 메시지를 모니터링하거나 사용자가 보기 전에 삭제할 수 있습니다." + "응용프로그램이 발신전화를 처리하고 전화를 걸 번호를 변경할 수 있도록 합니다. 이 경우 악성 응용프로그램이 발신전화를 모니터링하거나, 다른 방향으로 돌리거나, 중단시킬 수 있습니다." + "SMS 수신" + "응용프로그램이 SMS 메시지를 받고 처리할 수 있도록 합니다. 이 경우 악성 응용프로그램이 메시지를 모니터링하거나 사용자가 보기 전에 삭제할 수 있습니다." + "MMS 수신" + "응용프로그램이 MMS 메시지를 받고 처리할 수 있도록 합니다. 이 경우 악성 응용프로그램이 메시지를 모니터링하거나 사용자가 보기 전에 삭제할 수 있습니다." "SMS 메시지 보내기" - "응용프로그램이 SMS 메시지를 보낼 수 있습니다. 악성 응용프로그램은 사용자의 확인 없이 메시지를 전송하여 요금을 부과할 수 있습니다." + "응용프로그램이 SMS 메시지를 보낼 수 있도록 합니다. 이 경우 악성 응용프로그램이 사용자의 확인 없이 메시지를 전송하여 요금을 부과할 수 있습니다." "SMS 또는 MMS 읽기" - "응용프로그램이 전화기 또는 SIM 카드에 저장된 SMS 메시지를 읽을 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 기밀 메시지를 읽을 수 있습니다." + "응용프로그램이 휴대전화 또는 SIM 카드에 저장된 SMS 메시지를 읽을 수 있도록 합니다. 이 경우 악성 응용프로그램이 기밀 메시지를 읽을 수 있습니다." "SMS 또는 MMS 편집" - "응용프로그램이 전화기 또는 SIM 카드에 저장된 SMS 메시지에 쓸 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 메시지를 삭제할 수 있습니다." - "WAP 받기" - "응용프로그램이 WAP 메시지를 받고 처리할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 메시지를 모니터링하거나 사용자가 보기 전에 삭제할 수 있습니다." + "응용프로그램이 휴대전화 또는 SIM 카드에 저장된 SMS 메시지에 쓸 수 있도록 합니다. 단, 악성 응용프로그램이 이 기능을 이용하여 메시지를 삭제할 수 있습니다." + "WAP 수신" + "응용프로그램이 WAP 메시지를 받고 처리할 수 있도록 합니다. 이 경우 악성 응용프로그램이 메시지를 모니터링하거나 사용자가 보기 전에 삭제할 수 있습니다." "실행 중인 응용프로그램 검색" - "응용프로그램이 현재 실행 중이거나 최근에 실행된 작업에 대한 정보를 검색할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 다른 응용프로그램에 대한 개인 정보를 검색할 수 있습니다." + "응용프로그램이 현재 실행 중이거나 최근에 실행된 작업에 대한 정보를 검색할 수 있도록 합니다. 이 경우 악성 응용프로그램이 다른 응용프로그램에 대한 개인 정보를 검색할 수 있습니다." "실행 중인 응용프로그램 순서 재지정" - "응용프로그램이 작업을 포그라운드나 백그라운드로 이동할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 사용자의 조작 없이 작업을 강제로 앞으로 이동할 수 있습니다." + "응용프로그램이 작업을 포그라운드나 백그라운드로 이동할 수 있도록 합니다. 이 경우 악성 응용프로그램이 사용자의 조작 없이 앞으로 이동할 수 있습니다." "응용프로그램 디버깅 사용" - "응용프로그램이 다른 응용프로그램에 대한 디버깅을 설정할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 다른 응용프로그램을 중지시킬 수 있습니다." + "응용프로그램이 다른 응용프로그램에 대해 디버깅을 사용할 수 있도록 합니다. 이 경우 악성 응용프로그램이 다른 응용프로그램을 중지시킬 수 있습니다." "UI 설정 변경" - "응용프로그램이 로케일 또는 전체 글꼴 크기 같은 현재 구성을 변경할 수 있습니다." + "응용프로그램이 로케일 또는 전체 글꼴 크기와 같은 현재 구성을 변경할 수 있도록 합니다." "다른 응용프로그램 다시 시작" - "응용프로그램이 다른 응용프로그램을 강제로 다시 시작할 수 있습니다." + "응용프로그램이 다른 응용프로그램을 강제로 다시 시작할 수 있도록 합니다." "강제로 응용프로그램 닫기" - "응용프로그램이 포그라운드에 있는 활동을 강제로 닫을 수 있습니다. 일반 응용프로그램에는 필요하지 않습니다." + "응용프로그램이 포그라운드에 있는 활동을 강제로 닫고 되돌아갈 수 있도록 합니다. 일반 응용프로그램에는 필요하지 않습니다." "시스템 내부 상태 검색" - "응용프로그램이 시스템의 내부 상태를 검색할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 일반적으로 필요하지 않은 다양한 개인 정보와 보안 정보를 검색할 수 있습니다." + "응용프로그램이 시스템의 내부 상태를 검색할 수 있도록 합니다. 단, 악성 응용프로그램이 이 기능을 이용하여 일반적으로 필요하지 않은 다양한 개인정보와 보안정보를 검색할 수 있습니다." + + + + + + + + "실행 중인 모든 응용프로그램 모니터링 및 제어" - "응용프로그램이 시스템에서 활동이 시작되는 방식을 모니터링하고 제어할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 시스템을 완전히 손상시킬 수 있습니다. 이 권한은 개발 과정에만 필요하며 일반 전화기 사용 시에는 필요하지 않습니다." + "응용프로그램이 시스템에서 활동이 시작되는 방식을 모니터링하고 제어할 수 있도록 합니다. 단, 악성 응용프로그램이 이 기능을 이용하여 시스템을 완전히 손상시킬 수 있습니다. 이 권한은 개발 과정에만 필요하며 일반 휴대전화 사용 시에는 필요하지 않습니다." "패키지 제거 브로드캐스트 보내기" - "응용프로그램이 응용프로그램 패키지가 제거되었다는 알림을 브로드캐스트할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 실행 중인 다른 응용프로그램을 중지시킬 수 있습니다." + "응용프로그램이 응용프로그램 패키지가 삭제되었다는 알림을 브로드캐스트할 수 있도록 합니다. 이 경우 악성 응용프로그램이 실행 중인 다른 응용프로그램을 중지시킬 수 있습니다." "SMS 수신 브로드캐스트 보내기" - "응용프로그램이 SMS 메시지를 받았다는 알림을 브로드캐스트할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 들어오는 SMS 메시지처럼 위장할 수 있습니다." + "응용프로그램이 SMS 메시지를 받았다는 알림을 브로드캐스트할 수 있도록 합니다. 이 경우 악성 응용프로그램이 들어오는 SMS 메시지처럼 위장할 수 있습니다." "WAP-PUSH-수신 브로드캐스트 보내기" - "응용프로그램이 WAP PUSH 메시지를 받았다는 알림을 브로드캐스트할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 MMS 메시지를 받은 것처럼 위장하거나 웹페이지의 콘텐츠를 악성 변종으로 바꿀 수 있습니다." + "응용프로그램이 WAP PUSH 메시지를 받았다는 알림을 브로드캐스트할 수 있도록 합니다. 이 경우 악성 응용프로그램이 MMS 메시지를 받은 것처럼 위장하거나 웹페이지의 콘텐츠를 악성 변종으로 몰래 바꿀 수 있습니다." "실행 중인 프로세스 수 제한" - "응용프로그램이 실행할 최대 프로세스 수를 제어할 수 있습니다. 일반 응용프로그램에는 필요하지 않습니다." + "응용프로그램이 실행할 최대 프로세스 수를 제어할 수 있도록 합니다. 일반 응용프로그램에는 필요하지 않습니다." "모든 백그라운드 응용프로그램이 닫히도록 하기" - "응용프로그램이 백그라운드로 이동한 활동을 항상 바로 마칠지 여부를 제어할 수 있습니다. 일반 응용프로그램에는 필요하지 않습니다." + "응용프로그램이 백그라운드로 이동한 활동을 항상 바로 종료할지 여부를 제어할 수 있도록 합니다. 일반 응용프로그램에는 필요하지 않습니다." "배터리 통계 수정" - "수집된 배터리 통계를 수정할 수 있습니다. 일반 응용프로그램에서는 사용하지 않습니다." + "수집된 배터리 통계를 수정할 수 있도록 합니다. 일반 응용프로그램에서는 사용할 수 없습니다." + + + + "인증되지 않은 창 표시" - "내부 시스템 사용자 인터페이스에서 사용하는 창을 만들 수 있습니다. 일반 응용프로그램에서는 사용하지 않습니다." + "내부 시스템 사용자 인터페이스에서 사용하는 창을 만들 수 있도록 합니다. 일반 응용프로그램에서는 사용하지 않습니다." "시스템 수준 경고 표시" - "응용프로그램이 시스템 경고 창을 표시할 수 있습니다. 악성 응용프로그램은 전화기 화면 전체를 차지할 수 있습니다." + "응용프로그램이 시스템 경고 창을 표시할 수 있도록 합니다. 이 경우 악성 응용프로그램이 휴대전화 화면 전체를 차지할 수 있습니다." "전체 애니메이션 속도 수정" - "응용프로그램이 언제든지 전체 애니메이션 속도를 빠르게 또는 느리게 변경할 수 있습니다." + "응용프로그램이 언제든지 전체 애니메이션 속도를 빠르게 또는 느리게 변경할 수 있도록 합니다." "응용프로그램 토큰 관리" - "응용프로그램이 일반적인 Z-순서를 무시하여 자체 토큰을 만들고 관리할 수 있습니다. 일반 응용프로그램에는 필요하지 않습니다." + "응용프로그램이 일반적인 Z-순서를 무시하여 자체 토큰을 만들고 관리할 수 있도록 합니다. 일반 응용프로그램에는 필요하지 않습니다." "키 및 컨트롤 버튼 누르기" - "응용프로그램이 입력 이벤트(예: 키 누름)를 다른 응용프로그램에 전달할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 전화기를 완전히 제어할 수 있습니다." + "응용프로그램이 입력 이벤트(예: 키 누름)를 다른 응용프로그램에 전달할 수 있도록 합니다. 이 경우 악성 응용프로그램이 휴대전화를 완전히 제어할 수 있습니다." "사용자가 입력한 내용 및 수행한 작업 기록" - "응용프로그램이 다른 응용프로그램과 상호작용할 때에도 사용자가 누르는 키(예: 비밀번호 입력)를 볼 수 있습니다. 일반 응용프로그램에는 필요하지 않습니다." - "입력 방법에 고정" - "보유자가 입력 방법의 최상위 인터페이스에 고정할 수 있습니다. 일반 응용프로그램에는 필요하지 않습니다." + "응용프로그램이 다른 응용프로그램과 상호작용할 때에도 사용자가 누르는 키(예: 비밀번호 입력)를 볼 수 있도록 합니다. 일반 응용프로그램에는 필요하지 않습니다." + "입력 방법 고정" + "보유자가 입력 방법의 최상위 인터페이스만 사용하도록 합니다. 일반 응용프로그램에는 필요하지 않습니다." "화면 방향 변경" - "응용프로그램이 언제든지 화면 회전을 변경할 수 있습니다. 일반 응용프로그램에는 필요하지 않습니다." + "응용프로그램이 언제든지 화면 회전을 변경할 수 있도록 합니다. 일반 응용프로그램에는 필요하지 않습니다." "응용프로그램에 Linux 신호 보내기" - "응용프로그램이 제공된 신호를 모든 영구 프로세스로 보내도록 요청할 수 있습니다." + "응용프로그램이 제공된 신호를 모든 영구 프로세스로 보내도록 요청할 수 있도록 합니다." "응용프로그램이 항상 실행되도록 설정" - "응용프로그램이 연결된 일부 구성요소를 지속하여 다른 응용프로그램에 사용할 수 없도록 합니다." + "응용프로그램이 연결된 일부 구성 요소를 지속하여 다른 응용프로그램에 사용할 수 없도록 합니다." "응용프로그램 삭제" - "응용프로그램이 Android 패키지를 삭제할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 중요한 응용프로그램을 삭제할 수 있습니다." + "응용프로그램이 Android 패키지를 삭제할 수 있도록 합니다. 이 경우 악성 응용프로그램이 중요한 응용프로그램을 삭제할 수 있습니다." "다른 응용프로그램의 데이터 삭제" - "응용프로그램이 사용자 데이터를 지울 수 있습니다." + "응용프로그램이 사용자 데이터를 지울 수 있도록 합니다." "다른 응용프로그램의 캐시 삭제" - "응용프로그램이 캐시 파일을 삭제할 수 있습니다." + "응용프로그램이 캐시 파일을 삭제할 수 있도록 합니다." "응용프로그램 저장공간 계산" - "응용프로그램이 해당 코드, 데이터 및 캐시 크기를 검색할 수 있습니다." + "응용프로그램이 해당 코드, 데이터 및 캐시 크기를 검색할 수 있도록 합니다." "응용프로그램 직접 설치" - "응용프로그램이 새로운 또는 업데이트된 Android 패키지를 설치할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 임의의 강력한 권한으로 새 응용프로그램을 추가할 수 있습니다." + "응용프로그램이 새로운 또는 업데이트된 Android 패키지를 설치할 수 있도록 합니다. 이 경우 악성 응용프로그램이 임의의 강력한 권한으로 새 응용프로그램을 추가할 수 있습니다." "모든 응용프로그램 캐시 데이터 삭제" - "응용프로그램이 응용프로그램 캐시 디렉토리에 있는 파일을 삭제하여 전화기의 저장공간을 늘릴 수 있습니다. 액세스는 일반적으로 시스템 프로세스로 제한됩니다." + "응용프로그램이 응용프로그램 캐시 디렉토리에 있는 파일을 삭제하여 휴대전화의 저장공간을 늘릴 수 있도록 합니다. 액세스는 일반적으로 시스템 프로세스로 제한됩니다." "시스템 로그 파일 읽기" - "응용프로그램이 시스템의 다양한 로그 파일을 읽을 수 있습니다. 이 경우 응용프로그램은 사용자가 전화기로 수행하는 작업에 대한 일반적인 정보를 검색할 수 있지만 여기에 개인 정보는 포함되어서는 안 됩니다." + "응용프로그램이 시스템의 다양한 로그 파일을 읽을 수 있도록 합니다. 이 경우 응용프로그램은 사용자가 휴대전화로 수행하는 작업에 대한 일반적인 정보를 검색할 수 있지만 여기에 개인정보는 포함되어서는 안 됩니다." "진단 그룹 소유의 리소스 읽기/작성" - "응용프로그램이 진단 그룹 소유의 리소스(예: /dev에 있는 파일)를 읽고 쓸 수 있습니다. 이 기능은 시스템 안정성 및 보안에 영향을 미칠 수 있으므로, 제조업체 또는 사업자가 하드웨어 관련 진단을 수행하는 경우에만 사용해야 합니다." - "응용프로그램 구성요소 사용 또는 사용 안 함" - "응용프로그램이 다른 응용프로그램 구성요소의 사용 여부를 변경할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 중요한 전화기 기능을 사용하지 않도록 설정할 수 있습니다. 응용프로그램 구성요소가 쓸모없게 되거나, 일관성이 없어지거나, 불안정해질 수 있으므로 이 권한을 설정할 때는 주의해야 합니다." + "응용프로그램이 진단 그룹 소유의 리소스(예: /dev에 있는 파일)를 읽고 쓸 수 있도록 합니다. 이 기능은 시스템 안정성 및 보안에 영향을 미칠 수 있으므로 제조업체 또는 사업자가 하드웨어 관련 진단을 수행하는 경우에만 사용해야 합니다." + "응용프로그램 구성 요소 사용 또는 사용 안함" + "응용프로그램이 다른 응용프로그램 구성 요소 사용 여부를 변경할 수 있도록 합니다. 이 경우 악성 응용프로그램이 중요한 휴대전화 기능을 사용하지 않도록 설정할 수 있습니다. 이 권한을 설정할 경우 응용프로그램 구성 요소가 사용 불가능하게 되거나 일관성이 맞지 않거나 불안정해질 수 있으므로 주의해야 합니다." "기본 응용프로그램 설정" - "응용프로그램이 기본 응용프로그램을 수정할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 기존 응용프로그램이 사용자의 개인 데이터를 수집하도록 스푸핑하여 실행되는 응용프로그램을 변경할 수 있습니다." + "응용프로그램이 기본 응용프로그램을 수정할 수 있도록 합니다. 이 경우 악성 응용프로그램이 사용자의 개인 정보를 수집하기 위해 기존 응용프로그램을 스푸핑하여 실행되는 응용프로그램을 몰래 변경할 수 있습니다." "전체 시스템 설정 수정" - "응용프로그램이 시스템의 설정 데이터를 수정할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 시스템 구성을 손상시킬 수 있습니다." + "응용프로그램이 시스템의 설정 데이터를 수정할 수 있도록 합니다. 이 경우 악성 응용프로그램이 시스템 구성을 손상시킬 수 있습니다." "보안 시스템 설정 수정" - "응용프로그램이 시스템 보안 설정값 데이터를 수정할 수 있습니다. 일반 응용프로그램에서는 사용하지 않습니다." + "응용프로그램이 시스템 보안 설정값 데이터를 수정할 수 있도록 합니다. 일반 응용프로그램에서는 사용하지 않습니다." "Google 서비스 지도 수정" - "응용프로그램이 Google 서비스 지도를 수정할 수 있습니다. 일반 응용프로그램에서는 사용하지 않습니다." + "응용프로그램이 Google 서비스 지도를 수정할 수 있도록 합니다. 일반 응용프로그램에서는 사용하지 않습니다." "부팅할 때 자동 시작" - "응용프로그램이 시스템 부팅이 끝난 후 바로 시작할 수 있습니다. 이 경우 전화기가 시작하는 데 시간이 오래 걸리고 응용프로그램이 항상 실행되어 전체 전화기 속도가 느려질 수 있습니다." + "응용프로그램이 시스템 부팅이 끝난 후 바로 시작할 수 있도록 합니다. 이 경우 휴대전화가 시작하는 데 시간이 오래 걸리고 응용프로그램이 항상 실행되어 전체 휴대전화 속도가 느려질 수 있습니다." "남은 브로드캐스트 보내기" - "응용프로그램이 브로드캐스트가 끝난 후에 남은 브로드캐스트를 보낼 수 있습니다. 악성 응용프로그램은 전화기가 메모리를 너무 많이 사용하도록 하여 속도를 저하시키거나 불안정하게 만들 수 있습니다." + "응용프로그램이 브로드캐스트가 끝난 후에 남은 브로드캐스트를 보낼 수 있도록 합니다. 이 경우 악성 응용프로그램이 휴대전화가 메모리를 너무 많이 사용하도록 하여 속도를 저하시키거나 불안정하게 만들 수 있습니다." "연락처 데이터 읽기" - "응용프로그램이 전화기에 저장된 모든 연락처(주소) 데이터를 읽을 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 데이터를 다른 사람에게 보낼 수 있습니다." + "응용프로그램이 휴대전화에 저장된 모든 연락처(주소) 데이터를 읽을 수 있도록 합니다. 이 경우 악성 응용프로그램이 데이터를 다른 사람에게 보낼 수 있습니다." "연락처 데이터 작성" - "응용프로그램이 전화기에 저장된 연락처(주소) 데이터를 수정할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 연락처 데이터를 지우거나 수정할 수 있습니다." + "응용프로그램이 휴대전화에 저장된 연락처(주소) 데이터를 수정할 수 있도록 합니다. 이 경우 악성 응용프로그램이 연락처 데이터를 지우거나 수정할 수 있습니다." "소유자 데이터 작성" - "응용프로그램이 전화기에 저장된 전화기 소유자 데이터를 수정할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 소유자 데이터를 지우거나 수정할 수 있습니다." + "응용프로그램이 휴대전화에 저장된 소유자 데이터를 수정할 수 있도록 합니다. 단, 악성 응용프로그램이 이 기능을 이용하여 소유자 데이터를 지우거나 수정할 수 있습니다." "소유자 데이터 읽기" - "응용프로그램이 전화기에 저장된 전화기 소유자 데이터를 읽을 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 전화기 소유자 데이터를 읽을 수 있습니다." + "응용프로그램이 휴대전화에 저장된 휴대전화 소유자 데이터를 읽을 수 있도록 합니다. 이 경우 악성 응용프로그램이 휴대전화 소유자 데이터를 읽을 수 있습니다." "캘린더 데이터 읽기" - "응용프로그램이 전화기에 저장된 모든 캘린더 일정을 읽을 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 캘린더 일정을 다른 사람에게 보낼 수 있습니다." + "응용프로그램이 휴대전화에 저장된 모든 캘린더 일정을 읽을 수 있도록 합니다. 이 경우 악성 응용프로그램이 캘린더 일정을 다른 사람에게 보낼 수 있습니다." "캘린더 데이터 작성" - "응용프로그램이 전화기에 저장된 캘린더 일정을 수정할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 캘린더 데이터를 지우거나 수정할 수 있습니다." + "응용프로그램이 휴대전화에 저장된 캘린더 일정을 수정할 수 있도록 합니다. 이 경우 악성 응용프로그램이 캘린더 데이터를 지우거나 수정할 수 있습니다." "테스트를 위해 위치 소스로 가장" - "테스트용 가짜 위치 소스를 만듭니다. 악성 응용프로그램은 이 기능을 이용하여 GPS, 네트워크 제공업체 같은 실제 위치 소스에서 반환한 위치 및/또는 상태를 덮어쓸 수 있습니다." + "테스트용 가짜 위치 소스를 만듭니다. 단, 악성 응용프로그램이 이 기능을 이용하여 GPS, 네트워크 제공업체 같은 실제 위치 소스에서 반환한 위치 및/또는 상태를 덮어쓸 수 있습니다." "추가 위치 제공업체 명령 액세스" - "추가 위치 제공업체 명령에 액세스합니다. 악성 응용프로그램은 이 기능을 이용하여 GPS 또는 기타 위치 소스의 작동을 방해할 수 있습니다." + "추가 위치 제공업체 명령에 액세스합니다. 단, 악성 응용프로그램이 이 기능을 이용하여 GPS 또는 기타 위치 소스의 작동을 방해할 수 있습니다." + + + + "자세한 (GPS) 위치" - "가능한 경우 전화기에서 GPS(범지구 위치 측정 시스템) 등의 자세한 위치 소스에 액세스합니다. 악성 응용프로그램은 이 기능을 이용하여 사용자의 위치를 측정하고 추가 배터리 전원을 소비할 수 있습니다." + "가능한 경우 휴대전화에서 GPS(범지구 위치 측정 시스템) 등의 자세한 위치 소스에 액세스합니다. 이 경우 악성 응용프로그램이 사용자의 위치를 확인하고 추가 배터리 전원을 소비할 수 있습니다." "광범위한 네트워크 기반 위치" - "전화기의 대략적인 위치를 측정하기 위해 셀룰러 네트워크 데이터베이스와 같은 광범위한 위치 소스에 액세스합니다. 악성 응용프로그램은 이 기능을 이용하여 사용자의 위치를 대략적으로 측정할 수 있습니다." + "휴대전화의 대략적인 위치를 측정하기 위해 셀룰러 네트워크 데이터베이스와 같은 광범위한 위치 소스에 액세스합니다. 이 경우 악성 응용프로그램이 사용자의 위치를 대략적으로 측정할 수 있습니다." "SurfaceFlinger 액세스" - "응용프로그램이 SurfaceFlinger의 하위 수준 기능을 사용할 수 있습니다." + "응용프로그램이 SurfaceFlinger의 하위 수준 기능을 사용할 수 있도록 합니다." "프레임 버퍼 읽기" - "응용프로그램이 프레임 버퍼의 콘텐츠를 읽을 수 있습니다." + "응용프로그램이 프레임 버퍼의 콘텐츠를 읽을 수 있도록 합니다." "오디오 설정 변경" - "응용프로그램이 볼륨 및 경로 지정 같은 전체 오디오 설정을 수정할 수 있습니다." + "응용프로그램이 볼륨 및 경로 지정 같은 전체 오디오 설정을 수정할 수 있도록 합니다." "오디오 녹음" - "응용프로그램이 오디오 레코드 경로에 액세스할 수 있습니다." + "응용프로그램이 오디오 레코드 경로에 액세스할 수 있도록 합니다." "사진 촬영" - "응용프로그램이 카메라로 사진을 찍을 수 있습니다. 이 경우 응용프로그램은 카메라에 표시되는 이미지를 언제든지 수집할 수 있습니다." - "전화기를 영구적으로 비활성화" - "응용프로그램이 전화기를 영구적으로 사용하지 않도록 설정할 수 있습니다. 이 기능은 매우 위험합니다." - "전화기 강제로 다시 부팅" - "응용프로그램이 전화기를 강제로 다시 부팅할 수 있습니다." + "응용프로그램이 카메라로 사진을 찍을 수 있도록 합니다. 이 경우 응용프로그램이 카메라에 표시되는 이미지를 언제든지 수집할 수 있습니다." + "휴대전화를 영구적으로 사용 중지" + "응용프로그램이 휴대전화를 영구적으로 사용 중지할 수 있게 합니다. 이 기능은 매우 위험합니다." + "휴대전화 강제로 다시 부팅" + "응용프로그램이 휴대전화를 강제로 다시 부팅할 수 있도록 합니다." "파일시스템 마운트 및 마운트 해제" - "응용프로그램이 이동식 저장소의 파일시스템을 마운트하고 마운트 해제할 수 있습니다." + "응용프로그램이 이동식 저장소의 파일 시스템을 마운트하고 마운트 해제할 수 있도록 합니다." "외부 저장소 포맷" "응용프로그램이 제거 가능한 저장소를 포맷하도록 합니다." "진동 제어" - "응용프로그램이 진동을 제어할 수 있습니다." + "응용프로그램이 진동을 제어할 수 있도록 합니다." "손전등 제어" - "응용프로그램이 손전등을 제어할 수 있습니다." + "응용프로그램이 손전등을 제어할 수 있도록 합니다." "하드웨어 테스트" - "응용프로그램이 하드웨어를 테스트할 목적으로 다양한 주변장치를 제어할 수 있습니다." + "응용프로그램이 하드웨어를 테스트할 목적으로 다양한 주변장치를 제어할 수 있도록 합니다." "전화번호로 직접 전화걸기" - "응용프로그램이 사용자의 조작 없이 전화번호로 전화를 걸 수 있습니다. 악성 응용프로그램은 전화요금 청구서에 예상치 못한 통화 요금이 부과되도록 할 수 있습니다. 이 권한으로 응용프로그램은 비상 전화를 걸 수 없습니다." + "응용프로그램이 사용자의 조작 없이 전화번호로 전화를 걸 수 있도록 합니다. 이 경우 악성 응용프로그램으로 인해 예상치 못한 통화 요금이 부과될 수 있습니다. 이 권한으로 응용프로그램이 비상 전화를 걸게 할 수는 없습니다." "전화번호로 직접 전화걸기" - "응용프로그램이 사용자의 조작 없이 비상 번호를 포함한 전화번호로 전화를 걸 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 응급 서비스를 불필요하거나 불법적으로 호출할 수 있습니다." + "응용프로그램이 사용자의 조작 없이 비상 번호를 포함한 전화번호로 전화를 걸 수 있도록 합니다. 이 경우 악성 응용프로그램이 응급 서비스를 불필요하거나 불법적으로 호출할 수 있습니다." "위치 업데이트 알림 제어" - "무선의 위치 업데이트 알림을 활성화하거나 비활성화할 수 있습니다. 일반 응용프로그램에서는 사용하지 않습니다." + "무선의 위치 업데이트 알림을 사용하거나 사용 중지할 수 있도록 합니다. 일반 응용프로그램에서는 사용하지 않습니다." "체크인 속성 액세스" - "체크인 서비스에서 업로드한 속성에 대한 읽기/쓰기 액세스를 허용합니다. 일반 응용프로그램에서는 사용하지 않습니다." + "체크인 서비스에서 업로드한 속성에 대한 읽기/쓰기 액세스를 허용합니다. 일반 응용프로그램에서는 사용할 수 없습니다." "위젯 선택" - "응용프로그램이 응용프로그램에서 사용할 수 있는 위젯을 시스템에 알릴 수 있습니다. 이 권한을 갖는 응용프로그램은 개인 데이터에 대한 액세스 권한을 다른 응용프로그램에 부여할 수 있습니다. 일반 응용프로그램에서는 사용하지 않습니다." - "전화기 상태 수정" - "응용프로그램이 장치의 전화 기능을 제어할 수 있습니다. 이 권한을 갖는 응용프로그램은 사용자에게 알리지 않고 네트워크를 전환하거나, 전화 무선 기능을 켜고 끌 수 있습니다." - "전화기 상태 읽기" - "응용프로그램이 장치의 전화 기능에 액세스할 수 있습니다. 이 권한을 갖는 응용프로그램은 전화기의 전화번호, 통화가 활성인지 여부, 통화가 연결된 번호 등을 확인할 수 있습니다." - "전화기가 절전 모드로 전환되지 않도록 설정" - "응용프로그램이 전화기가 절전 모드로 전환되지 않도록 할 수 있습니다." - "전화기 전원 켜고 끄기" - "응용프로그램이 전화기를 켜거나 끌 수 있습니다." + "응용프로그램이 응용프로그램에서 사용할 수 있는 위젯을 시스템에 알릴 수 있도록 합니다. 이 권한을 갖는 응용프로그램은 개인 정보에 대한 액세스 권한을 다른 응용프로그램에 부여할 수 있습니다. 일반 응용프로그램에서는 사용하지 않습니다." + "휴대전화 상태 수정" + "응용프로그램이 장치의 휴대전화 기능을 제어할 수 있도록 합니다. 이 권한을 갖는 응용프로그램은 사용자에게 알리지 않고 네트워크를 전환하거나 휴대전화 무선 기능을 켜고 끄는 등의 작업을 수행할 수 있습니다." + "휴대전화 상태 읽기" + "응용프로그램이 장치의 휴대전화 기능에 액세스할 수 있도록 합니다. 이 권한을 갖는 응용프로그램은 휴대전화의 전화번호, 통화가 활성인지 여부, 해당 통화가 연결된 번호 등을 확인할 수 있습니다." + "휴대전화가 절전 모드로 전환되지 않도록 설정" + "응용프로그램이 휴대전화가 절전 모드로 전환되지 않도록 합니다." + "휴대전화 전원 켜고 끄기" + "응용프로그램이 휴대전화를 켜거나 끌 수 있도록 합니다." "출고 테스트 모드로 실행" - "전화기 하드웨어에 대한 완전한 액세스를 허용하는 하위 수준의 제조업체 테스트로 실행됩니다. 전화기가 제조업체 테스트 모드로 실행 중일 때만 사용할 수 있습니다." + "휴대전화 하드웨어에 대한 완전한 액세스를 허용하는 하위 수준의 제조업체 테스트로 실행됩니다. 휴대전화가 제조업체 테스트 모드로 실행 중일 때만 사용할 수 있습니다." "배경화면 설정" - "응용프로그램이 시스템 배경화면을 설정할 수 있습니다." + "응용프로그램이 시스템 배경화면을 설정할 수 있도록 합니다." "배경화면 크기 힌트 설정" - "응용프로그램이 시스템 배경화면 크기 힌트를 설정할 수 있습니다." - "시스템을 공장 기본값으로 재설정" - "응용프로그램이 모든 데이터, 구성 및 설치된 응용프로그램을 지워서 시스템을 공장 기본값으로 완전히 재설정할 수 있습니다." + "응용프로그램이 시스템 배경화면 크기 힌트를 설정할 수 있도록 합니다." + "시스템을 기본값으로 재설정" + "응용프로그램이 모든 데이터, 구성 및 설치된 응용프로그램을 지워서 시스템을 완전히 초기화할 수 있도록 합니다." "표준시간대 설정" - "응용프로그램이 전화기의 표준시간대를 변경할 수 있습니다." + "응용프로그램이 휴대전화의 표준시간대를 변경할 수 있도록 합니다." "알려진 계정 검색" - "응용프로그램이 전화기에 알려진 계정 목록을 가져올 수 있습니다." + "응용프로그램이 휴대전화에 알려진 계정 목록을 가져올 수 있도록 합니다." "네트워크 상태 보기" - "응용프로그램이 모든 네트워크의 상태를 볼 수 있습니다." + "응용프로그램이 모든 네트워크의 상태를 볼 수 있도록 합니다." "인터넷에 완전히 액세스" - "응용프로그램이 네트워크 소켓을 만들 수 있습니다." + "응용프로그램이 네트워크 소켓을 만들 수 있도록 합니다." "액세스포인트 이름 설정 쓰기" - "응용프로그램이 APN의 프록시 및 포트 같은 APN 설정을 수정할 수 있습니다." + "응용프로그램이 APN의 프록시 및 포트 같은 APN 설정을 수정할 수 있도록 합니다." "네트워크 연결 변경" - "응용프로그램이 네트워크 연결 상태를 변경할 수 있습니다." + "응용프로그램이 네트워크 연결 상태를 변경할 수 있도록 합니다." "백그라운드 데이터 사용 설정 변경" - "백그라운드 데이터 사용 설정을 변경할 수 있는 권한을 응용프로그램에 부여합니다." + "응용프로그램이 백그라운드 데이터 사용 설정을 변경할 수 있도록 합니다." "Wi-Fi 상태 보기" - "응용프로그램이 Wi-Fi의 상태에 대한 정보를 볼 수 있습니다." + "응용프로그램이 Wi-Fi의 상태에 대한 정보를 볼 수 있도록 합니다." "Wi-Fi 상태 변경" - "응용프로그램이 Wi-Fi 액세스포인트에 연결하거나 연결을 끊고, 구성된 Wi-Fi 네트워크를 변경할 수 있습니다." + "응용프로그램이 Wi-Fi 액세스포인트에 연결하거나 연결을 끊고, 구성된 Wi-Fi 네트워크를 변경할 수 있도록 합니다." + + + + "Bluetooth 관리" - "응용프로그램이 로컬 Bluetooth 전화를 구성한 다음 원격 장치를 검색하여 페어링할 수 있습니다." + "응용프로그램이 로컬 Bluetooth 휴대전화를 구성한 다음 원격 장치를 검색하여 페어링할 수 있도록 합니다." "Bluetooth 연결 만들기" - "응용프로그램이 로컬 Bluetooth 전화의 구성을 보고 페어링된 장치에 연결하거나 연결을 수락할 수 있습니다." - "키 잠금 사용 안 함" - "응용프로그램이 키 잠금 및 연결된 비밀번호 보안을 비활성화할 수 있습니다. 예를 들어, 전화기가 수신전화를 받을 때 키 잠금을 비활성화했다가 통화가 끝나면 키 잠금을 다시 활성화할 수 있습니다." + "응용프로그램이 로컬 Bluetooth 전화의 구성을 보고 페어링된 장치에 연결하며 연결을 수락할 수 있도록 합니다." + "키 잠금 사용 중지" + "응용프로그램이 키 잠금 및 관련 비밀번호 보안을 사용 중지할 수 있도록 합니다. 예를 들어, 휴대전화가 수신전화를 받을 때 키 잠금을 사용 중지했다가 통화가 끝나면 키 잠금을 다시 사용할 수 있습니다." "동기화 설정 읽기" - "응용프로그램이 연락처에 대해 동기화를 활성화할지 여부 같은 동기화 설정을 읽을 수 있습니다." + "응용프로그램이 주소록에 동기화를 사용할지 여부와 같은 동기화 설정을 읽을 수 있도록 합니다." "동기화 설정 쓰기" - "응용프로그램이 연락처에 대해 동기화를 활성화할지 여부 같은 동기화 설정을 수정할 수 있습니다." + "응용프로그램이 주소록에 대해 동기화를 사용할지 여부 등의 동기화 설정을 수정할 수 있도록 합니다." "동기화 통계 읽기" - "응용프로그램이 동기화 통계(예: 실행된 동기화 기록)을 읽을 수 있습니다." + "응용프로그램이 동기화 통계(예: 실행된 동기화 기록)을 읽을 수 있도록 합니다." "가입된 피드 읽기" - "응용프로그램이 현재 동기화된 피드에 대한 상세정보를 가져올 수 있습니다." + "응용프로그램이 현재 동기화된 피드에 대한 세부정보를 가져올 수 있도록 합니다." "가입 피드 작성" - "응용프로그램이 현재 동기화된 피드를 수정할 수 있습니다. 악성 응용프로그램은 이 기능을 이용하여 동기화된 피드를 변경할 수 있습니다." - "상용자 정의 사전 읽기" - "응용프로그램이 사용자 사전에 보관되어 있을 수 있는 비공개 단어, 이름 및 구문을 읽도록 합니다." + "응용프로그램이 현재 동기화된 피드를 수정할 수 있도록 합니다. 이 경우 악성 응용프로그램이 동기화된 피드를 변경할 수 있습니다." + "사용자 정의 사전 읽기" + "응용프로그램이 사용자 사전에 보관되어 있는 비공개 단어, 이름 및 구문을 읽도록 합니다." "상용자 정의 사전에 작성" - "응용프로그램이 사용자 사전에 새 단어를 입력할 수 있습니다." + "응용프로그램이 사용자 사전에 새 단어를 입력할 수 있도록 합니다." + + + + "집" - "휴대전화" + "모바일" "회사" "회사 팩스" "집(팩스)" "호출기" "기타" - "사용자설정" + "맞춤설정" "집" "회사" "기타" - "사용자설정" + "맞춤설정" + "모바일" "집" "회사" "기타" - "사용자설정" + "맞춤설정" "집" "회사" "기타" - "사용자설정" + "맞춤설정" "회사" "기타" - "사용자설정" + "맞춤설정" "AIM" @@ -384,7 +461,7 @@ "PIN 코드가 잘못되었습니다." "잠금해제하려면 메뉴를 누른 다음 0을 누릅니다." "비상 전화번호" - "(서비스 안 됨)" + "(서비스 안됨)" "화면 잠김" "비상 전화를 걸거나 잠금해제하려면 메뉴를 누르세요." "잠금해제하려면 메뉴를 누르세요." @@ -393,18 +470,20 @@ "맞습니다." "죄송합니다. 다시 시도하세요." "충전 중(%d%%)" + + "충전기를 연결하세요." "SIM 카드가 없습니다." - "전화기에 SIM 카드가 없습니다." + "휴대전화에 SIM 카드가 없습니다." "SIM 카드를 삽입하세요." "네트워크 잠김" "SIM 카드의 PUK가 잠겨 있습니다." "사용자 가이드를 참조하거나 고객지원팀에 문의하세요." "SIM 카드가 잠겨 있습니다." "SIM 카드 잠금해제 중..." - "잠금해제 패턴을 %d회 잘못 가져왔습니다. "\n\n"%d초 후에 다시 시도하세요." - "잠금해제 패턴을 %d회 잘못 그렸습니다. %d회 더 실패하면 Google 로그인을 통해 전화기를 잠금해제하도록 요청됩니다."\n\n" %d초 후에 다시 시도하세요." - "%d초 후에 다시 입력하세요." + "잠금해제 패턴을 %d회 잘못 그렸습니다. "\n\n"%d초 후에 다시 시도하세요." + "잠금해제 패턴을 %d회 잘못 그렸습니다. %d회 더 실패하면 Google 로그인을 통해 휴대전화를 잠금해제하도록 요청됩니다. "\n\n" %d초 후에 다시 시도하세요." + "%d초 후에 다시 시도하세요." "패턴을 잊으셨나요?" "패턴을 너무 많이 시도했습니다." "잠금해제하려면 Google 계정으로 로그인하세요." @@ -414,15 +493,18 @@ "사용자 이름 또는 비밀번호가 잘못되었습니다." "%-l%P" "%-l%p" - "알림 지우기" + + "알림 없음" - "사용 중" + "진행 중" "알림" "%d%%" "충전 중..." "충전기를 연결하세요." "배터리 전원이 부족합니다." "%d%% 미만 남음" + + "출고 테스트 불합격" "FACTORY_TEST 작업은 /system/app 디렉토리에 설치된 패키지에 대해서만 지원됩니다." "FACTORY_TEST 작업을 제공하는 패키지가 없습니다." @@ -431,13 +513,21 @@ "자바스크립트" "다른 페이지를 탐색하시겠습니까?"\n\n"%s"\n\n"계속하려면 \'확인\'을 선택하고 현재 페이지에 그대로 있으려면 \'취소\'를 선택하세요." "확인" + + + + + + + + "브라우저에 이 비밀번호를 저장하시겠습니까?" "나중에" "저장" - "저장 안 함" + "안함" "페이지를 열 수 있는 권한이 없습니다." "텍스트가 클립보드에 복사되었습니다." - "자세히" + "더보기" "Menu+" "스페이스바" "입력" @@ -466,11 +556,11 @@ "%d초 후" - "1분 내" + "1분 후" "%d분 후" - "1시간 내" + "1시간 후" "%d시간 후" @@ -479,7 +569,7 @@ "1초 전" - "%d 초 전" + "%d초 전" "1분 전" @@ -495,7 +585,7 @@ "1초 후" - "%d 초 후" + "%d초 후" "1분 후" @@ -529,7 +619,7 @@ "매주 %s" "매월" "매년" - "동영상 재생 안 됨" + "동영상 재생 안됨" "죄송합니다. 이 기기로의 스트리밍에 적합하지 않은 동영상입니다." "죄송합니다. 동영상을 재생할 수 없습니다." "확인" @@ -538,10 +628,6 @@ "정오" "자정" "자정" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "모두 선택" @@ -557,35 +643,37 @@ "사전에 \'%s\' 추가" "텍스트 수정" "저장공간 부족" - "전화기 저장공간이 부족합니다." + "휴대전화 저장공간이 부족합니다." "확인" "취소" "확인" "취소" "주의" - "켜짐" - "끄기" - "작업을 수행할 때 사용하는 권한" + "사용" + "사용 안함" + "작업을 수행할 때 사용하는 응용프로그램" "이 작업에 대해 기본값으로 사용" "홈 설정 > 응용프로그램 > 응용프로그램 관리에서 기본값을 지웁니다." "작업 선택" "작업을 수행할 수 있는 응용프로그램이 없습니다." "죄송합니다." - "%1$s 응용프로그램(%2$s 프로세스)이 예상치 않게 중지되었습니다. 다시 시도하세요." - "%1$s 프로세스가 예상치 않게 중지되었습니다. 다시 시도하세요." + "%1$s 응용프로그램(%2$s 프로세스)이 예상치 않게 중지되었습니다. 다시 시도해 주세요." + "%1$s 프로세스가 예상치 않게 중지되었습니다. 다시 시도해 주세요." "죄송합니다." - "%1$s 활동(%2$s 응용프로그램)이 응답하지 않습니다." + "%2$s 활동(%1$s 응용프로그램)이 응답하지 않습니다." "%1$s 활동(%2$s 프로세스)이 응답하지 않습니다." "%1$s 응용프로그램(%2$s 프로세스)이 응답하지 않습니다." "%1$s 프로세스가 응답하지 않습니다." - "강제로 닫기" + "닫기" + + "대기" - "디버깅" + "디버그" "텍스트에 대한 작업 선택" "벨소리 볼륨" "미디어 볼륨" "Bluetooth를 통해 재생" - "통화볼륨" + "통화 볼륨" "Bluetooth 통화 볼륨" "알람 볼륨" "알림 볼륨" @@ -596,12 +684,12 @@ "벨소리" "알 수 없는 벨소리" - "Wi-Fi 네트워크 사용가능" - "Wi-Fi 네트워크 사용가능" + "Wi-Fi 네트워크 사용 가능" + "Wi-Fi 네트워크 사용 가능" - "개방형 Wi-Fi 네트워크 사용가능" - "개방형 Wi-Fi 네트워크 사용가능" + "개방형 Wi-Fi 네트워크 사용 가능" + "개방형 Wi-Fi 네트워크 사용 가능" "문자 삽입" "알 수 없는 응용프로그램" @@ -611,54 +699,67 @@ "취소" "설정" "기본값" - "권한이 필요하지 않음" + "권한 필요 없음" "숨기기" "모두 표시" "로드 중..." "USB 연결됨" - "USB를 통해 전화기를 컴퓨터에 연결했습니다. 컴퓨터와 전화기 SD 카드 간에 파일을 복사하려면 \'마운트\'를 선택하세요." + "USB를 통해 휴대전화를 컴퓨터에 연결했습니다. 컴퓨터와 휴대전화 SD 카드 간에 파일을 복사하려면 \'마운트\'를 선택하세요." "마운트" - "마운트 안 함" - "USB 저장소에 SD 카드를 사용하는 동안 문제가 발생했습니다." + "마운트 안함" + "USB 저장소로 SD 카드를 사용하는 동안 문제가 발생했습니다." "USB 연결됨" "컴퓨터에 파일을 복사하거나 컴퓨터의 파일을 복사하려면 선택합니다." "USB 저장소 끄기" "USB 저장소 끄기를 선택하세요." "USB 저장소 끄기" - "USB 저장소를 끄기 전에 반드시 USB 호스를 마운트 해제하세요. USB 저장소를 끄려면 \'끄기\'를 선택하세요." + "USB 저장소를 끄기 전에 반드시 USB 호스트에서 마운트 해제하세요. USB 저장소를 끄려면 \'끄기\'를 선택하세요." "USB 저장소 끄기" "취소" "USB 저장소를 끄는 동안 Weve에 문제가 발행했습니다. USB 호스트를 마운트 해제했는지 확인한 후 다시 시도하세요." "SD 카드 포맷" "SD 카드를 포맷하시겠습니까? 포맷하면 카드의 모든 데이터를 잃게 됩니다." "포맷" + + + + "입력 방법 선택" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "가능한 원인" "SD 카드 준비 중" - "오류 확인 중" + + "빈 SD 카드" - "SD 카드가 비어 있거나 지원되지 않는 파일시스템입니다." + + "손상된 SD 카드" - "SD 카드가 손상되었습니다. 카드를 다시 포맷하시기 바랍니다." + + "SD 카드가 예상치 않게 제거되었습니다." "데이터 손실을 피하려면 SD 카드를 제거하기 전에 마운트 해제합니다." "SD 카드를 안전하게 제거할 수 있습니다." - "이제 SD 카드를 안전하게 제거할 수 있습니다." + + "SD 카드를 제거했습니다." - "SD가 제거되었습니다. 기기의 저장 용량을 늘리려면 새 SD 카드를 삽입하세요." + + "일치하는 활동이 없습니다." - "구성요소 사용 통계 업데이트" + "구성 요소 사용 통계 업데이트" "수집된 구성요소 사용 통계를 수정할 수 있는 권한을 부여합니다. 일반 응용프로그램은 이 권한을 사용할 수 없습니다." "확대/축소하려면 두 번 탭하세요." - "위젯을 확장하는 오류가 발생했습니다." + "위젯을 확장하는 동안 오류가 발생했습니다." "이동" "검색" "전송" "다음" "완료" "실행" - "다음 번호로 전화걸기"\n": %s" - "다음 번호로 주소록 만들기"\n": %s" + "전화하기 "\n"%s에 연결" + "전화번호부에"\n"%s 추가" + + + + diff --git a/core/res/res/values-mcc204-da/strings.xml b/core/res/res/values-mcc204-da/strings.xml new file mode 100644 index 0000000000000..7d962307a3dec --- /dev/null +++ b/core/res/res/values-mcc204-da/strings.xml @@ -0,0 +1,19 @@ + + + + "nl_nl" + diff --git a/core/res/res/values-mcc204-el/strings.xml b/core/res/res/values-mcc204-el/strings.xml new file mode 100644 index 0000000000000..97bfe651ee527 --- /dev/null +++ b/core/res/res/values-mcc204-el/strings.xml @@ -0,0 +1,19 @@ + + + + "el_GR" + diff --git a/core/res/res/values-mcc204-pt-rPT/strings.xml b/core/res/res/values-mcc204-pt-rPT/strings.xml new file mode 100644 index 0000000000000..7d962307a3dec --- /dev/null +++ b/core/res/res/values-mcc204-pt-rPT/strings.xml @@ -0,0 +1,19 @@ + + + + "nl_nl" + diff --git a/core/res/res/values-mcc204-sv/strings.xml b/core/res/res/values-mcc204-sv/strings.xml new file mode 100644 index 0000000000000..7d962307a3dec --- /dev/null +++ b/core/res/res/values-mcc204-sv/strings.xml @@ -0,0 +1,19 @@ + + + + "nl_nl" + diff --git a/core/res/res/values-mcc204-tr/strings.xml b/core/res/res/values-mcc204-tr/strings.xml new file mode 100644 index 0000000000000..7d962307a3dec --- /dev/null +++ b/core/res/res/values-mcc204-tr/strings.xml @@ -0,0 +1,19 @@ + + + + "nl_nl" + diff --git a/core/res/res/values-mcc230-da/strings.xml b/core/res/res/values-mcc230-da/strings.xml new file mode 100644 index 0000000000000..d3ecdbba28ed2 --- /dev/null +++ b/core/res/res/values-mcc230-da/strings.xml @@ -0,0 +1,19 @@ + + + + "cs_cz" + diff --git a/core/res/res/values-mcc230-el/strings.xml b/core/res/res/values-mcc230-el/strings.xml new file mode 100644 index 0000000000000..97bfe651ee527 --- /dev/null +++ b/core/res/res/values-mcc230-el/strings.xml @@ -0,0 +1,19 @@ + + + + "el_GR" + diff --git a/core/res/res/values-mcc230-pt-rPT/strings.xml b/core/res/res/values-mcc230-pt-rPT/strings.xml new file mode 100644 index 0000000000000..d3ecdbba28ed2 --- /dev/null +++ b/core/res/res/values-mcc230-pt-rPT/strings.xml @@ -0,0 +1,19 @@ + + + + "cs_cz" + diff --git a/core/res/res/values-mcc230-sv/strings.xml b/core/res/res/values-mcc230-sv/strings.xml new file mode 100644 index 0000000000000..d3ecdbba28ed2 --- /dev/null +++ b/core/res/res/values-mcc230-sv/strings.xml @@ -0,0 +1,19 @@ + + + + "cs_cz" + diff --git a/core/res/res/values-mcc230-tr/strings.xml b/core/res/res/values-mcc230-tr/strings.xml new file mode 100644 index 0000000000000..d3ecdbba28ed2 --- /dev/null +++ b/core/res/res/values-mcc230-tr/strings.xml @@ -0,0 +1,19 @@ + + + + "cs_cz" + diff --git a/core/res/res/values-mcc232-da/strings.xml b/core/res/res/values-mcc232-da/strings.xml new file mode 100644 index 0000000000000..4773838f9c477 --- /dev/null +++ b/core/res/res/values-mcc232-da/strings.xml @@ -0,0 +1,19 @@ + + + + "de_at" + diff --git a/core/res/res/values-mcc232-el/strings.xml b/core/res/res/values-mcc232-el/strings.xml new file mode 100644 index 0000000000000..97bfe651ee527 --- /dev/null +++ b/core/res/res/values-mcc232-el/strings.xml @@ -0,0 +1,19 @@ + + + + "el_GR" + diff --git a/core/res/res/values-mcc232-pt-rPT/strings.xml b/core/res/res/values-mcc232-pt-rPT/strings.xml new file mode 100644 index 0000000000000..4773838f9c477 --- /dev/null +++ b/core/res/res/values-mcc232-pt-rPT/strings.xml @@ -0,0 +1,19 @@ + + + + "de_at" + diff --git a/core/res/res/values-mcc232-sv/strings.xml b/core/res/res/values-mcc232-sv/strings.xml new file mode 100644 index 0000000000000..4773838f9c477 --- /dev/null +++ b/core/res/res/values-mcc232-sv/strings.xml @@ -0,0 +1,19 @@ + + + + "de_at" + diff --git a/core/res/res/values-mcc232-tr/strings.xml b/core/res/res/values-mcc232-tr/strings.xml new file mode 100644 index 0000000000000..4773838f9c477 --- /dev/null +++ b/core/res/res/values-mcc232-tr/strings.xml @@ -0,0 +1,19 @@ + + + + "de_at" + diff --git a/core/res/res/values-mcc234-da/strings.xml b/core/res/res/values-mcc234-da/strings.xml new file mode 100644 index 0000000000000..2538b73292392 --- /dev/null +++ b/core/res/res/values-mcc234-da/strings.xml @@ -0,0 +1,19 @@ + + + + "en_gb" + diff --git a/core/res/res/values-mcc234-el/strings.xml b/core/res/res/values-mcc234-el/strings.xml new file mode 100644 index 0000000000000..97bfe651ee527 --- /dev/null +++ b/core/res/res/values-mcc234-el/strings.xml @@ -0,0 +1,19 @@ + + + + "el_GR" + diff --git a/core/res/res/values-mcc234-pt-rPT/strings.xml b/core/res/res/values-mcc234-pt-rPT/strings.xml new file mode 100644 index 0000000000000..2538b73292392 --- /dev/null +++ b/core/res/res/values-mcc234-pt-rPT/strings.xml @@ -0,0 +1,19 @@ + + + + "en_gb" + diff --git a/core/res/res/values-mcc234-sv/strings.xml b/core/res/res/values-mcc234-sv/strings.xml new file mode 100644 index 0000000000000..2538b73292392 --- /dev/null +++ b/core/res/res/values-mcc234-sv/strings.xml @@ -0,0 +1,19 @@ + + + + "en_gb" + diff --git a/core/res/res/values-mcc234-tr/strings.xml b/core/res/res/values-mcc234-tr/strings.xml new file mode 100644 index 0000000000000..2538b73292392 --- /dev/null +++ b/core/res/res/values-mcc234-tr/strings.xml @@ -0,0 +1,19 @@ + + + + "en_gb" + diff --git a/core/res/res/values-mcc260-da/strings.xml b/core/res/res/values-mcc260-da/strings.xml new file mode 100644 index 0000000000000..1161f9a6356f3 --- /dev/null +++ b/core/res/res/values-mcc260-da/strings.xml @@ -0,0 +1,19 @@ + + + + "pl_pl" + diff --git a/core/res/res/values-mcc260-el/strings.xml b/core/res/res/values-mcc260-el/strings.xml new file mode 100644 index 0000000000000..97bfe651ee527 --- /dev/null +++ b/core/res/res/values-mcc260-el/strings.xml @@ -0,0 +1,19 @@ + + + + "el_GR" + diff --git a/core/res/res/values-mcc260-pt-rPT/strings.xml b/core/res/res/values-mcc260-pt-rPT/strings.xml new file mode 100644 index 0000000000000..1161f9a6356f3 --- /dev/null +++ b/core/res/res/values-mcc260-pt-rPT/strings.xml @@ -0,0 +1,19 @@ + + + + "pl_pl" + diff --git a/core/res/res/values-mcc260-sv/strings.xml b/core/res/res/values-mcc260-sv/strings.xml new file mode 100644 index 0000000000000..1161f9a6356f3 --- /dev/null +++ b/core/res/res/values-mcc260-sv/strings.xml @@ -0,0 +1,19 @@ + + + + "pl_pl" + diff --git a/core/res/res/values-mcc260-tr/strings.xml b/core/res/res/values-mcc260-tr/strings.xml new file mode 100644 index 0000000000000..1161f9a6356f3 --- /dev/null +++ b/core/res/res/values-mcc260-tr/strings.xml @@ -0,0 +1,19 @@ + + + + "pl_pl" + diff --git a/core/res/res/values-mcc262-da/strings.xml b/core/res/res/values-mcc262-da/strings.xml new file mode 100644 index 0000000000000..9505cf4b42262 --- /dev/null +++ b/core/res/res/values-mcc262-da/strings.xml @@ -0,0 +1,19 @@ + + + + "de_de" + diff --git a/core/res/res/values-mcc262-el/strings.xml b/core/res/res/values-mcc262-el/strings.xml new file mode 100644 index 0000000000000..97bfe651ee527 --- /dev/null +++ b/core/res/res/values-mcc262-el/strings.xml @@ -0,0 +1,19 @@ + + + + "el_GR" + diff --git a/core/res/res/values-mcc262-pt-rPT/strings.xml b/core/res/res/values-mcc262-pt-rPT/strings.xml new file mode 100644 index 0000000000000..9505cf4b42262 --- /dev/null +++ b/core/res/res/values-mcc262-pt-rPT/strings.xml @@ -0,0 +1,19 @@ + + + + "de_de" + diff --git a/core/res/res/values-mcc262-sv/strings.xml b/core/res/res/values-mcc262-sv/strings.xml new file mode 100644 index 0000000000000..9505cf4b42262 --- /dev/null +++ b/core/res/res/values-mcc262-sv/strings.xml @@ -0,0 +1,19 @@ + + + + "de_de" + diff --git a/core/res/res/values-mcc262-tr/strings.xml b/core/res/res/values-mcc262-tr/strings.xml new file mode 100644 index 0000000000000..9505cf4b42262 --- /dev/null +++ b/core/res/res/values-mcc262-tr/strings.xml @@ -0,0 +1,19 @@ + + + + "de_de" + diff --git a/core/res/res/values-no-rNO/arrays.xml b/core/res/res/values-nb-rNO/arrays.xml similarity index 100% rename from core/res/res/values-no-rNO/arrays.xml rename to core/res/res/values-nb-rNO/arrays.xml diff --git a/core/res/res/values-nb-rNO/donottranslate-cldr.xml b/core/res/res/values-nb-rNO/donottranslate-cldr.xml new file mode 100644 index 0000000000000..ecf01118298f4 --- /dev/null +++ b/core/res/res/values-nb-rNO/donottranslate-cldr.xml @@ -0,0 +1,147 @@ + + + januar + februar + mars + april + mai + juni + juli + august + september + oktober + november + desember + + januar + februar + mars + april + mai + juni + juli + august + september + oktober + november + desember + + jan. + feb. + mars + apr. + mai + juni + juli + aug. + sep. + okt. + nov. + des. + + J + F + M + A + M + J + J + A + S + O + N + D + + søndag + mandag + tirsdag + onsdag + torsdag + fredag + lørdag + + søn. + man. + tir. + ons. + tor. + fre. + lør. + + søn. + man. + tir. + ons. + tor. + fre. + lør. + + S + M + T + O + T + F + L + + AM + PM + i går + i dag + i morgen + + %H.%M + %-l.%M %p + %-l.%M %^p + h.mm a + HH.mm + %d.%m.%Y + dd.MM.yyyy + "%s.%s.%s" + %-e. %B %Y + %H.%M.%S + %H.%M.%S %-e. %b %Y + %2$s %1$s + %1$s %3$s + %-e. %b %Y + %-e. %B + %-B + %B %Y + %-e. %b + %-b + %b %Y + %1$s–%2$s + %2$s–%5$s + %3$s.%2$s.–%8$s.%7$s. + %1$s %3$s.%2$s.–%6$s %8$s.%7$s. + %3$s.%2$s.%4$s–%8$s.%7$s.%9$s + %1$s %3$s.%2$s.%4$s–%6$s %8$s.%7$s.%9$s + %5$s %1$s %3$s.%2$s.%4$s–%10$s %6$s %8$s.%7$s.%9$s + %5$s %3$s.%2$s.–%10$s %8$s.%7$s. + %5$s %1$s %3$s.%2$s–%10$s %6$s %8$s.%7$s + %5$s %3$s.%2$s.%4$s–%10$s %8$s.%7$s.%9$s + %3$s %1$s %2$s–%6$s %4$s %5$s + %1$s %2$s–%4$s %5$s + %3$s %2$s–%6$s %5$s + %1$s %2$s %3$s + %2$s %3$s + %1$s %2$s + %3$s. %2$s–%8$s. %7$s + %1$s %3$s. %2$s–%6$s %8$s. %7$s + %5$s %3$s. %2$s–%10$s %8$s. %7$s + %5$s %3$s. %2$s–%10$s %8$s. %7$s + %5$s %1$s %3$s. %2$s–%10$s %6$s %8$s. %7$s + %5$s %1$s %3$s. %2$s–%10$s %6$s %8$s. %7$s + %5$s %3$s. %2$s %4$s–%10$s %8$s. %7$s %9$s + %5$s %3$s. %2$s %4$s–%10$s %8$s. %7$s %9$s + %5$s %1$s %3$s. %2$s %4$s–%10$s %6$s %8$s. %7$s %9$s + %5$s %1$s %3$s. %2$s %4$s–%10$s %6$s %8$s. %7$s %9$s + %1$s %3$s. %2$s %4$s–%6$s %8$s. %7$s %9$s + %3$s.–%8$s. %2$s + %1$s %3$s. %2$s–%6$s %8$s. %7$s + %3$s. %2$s–%8$s. %7$s %9$s + %3$s.–%8$s. %2$s %9$s + %1$s %3$s. %2$s–%6$s %8$s. %7$s %9$s + %b + diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 33d015997b34f..875b4bcd1e625 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -21,6 +21,8 @@ "GB" "TB" "PB" + + "<uten navn>" "…" "(Mangler telefonnummer)" @@ -48,22 +50,29 @@ "Samtaleblokkering" "Passordbytte" "PIN-kode-bytte" + + + + + + + + + + + + "Nummervisning er begrenset som standard. Neste anrop: Begrenset" "Nummervisning er begrenset som standard. Neste anrop: Ikke begrenset" "Nummervisning er ikke begrenset som standard. Neste anrop: Begrenset" "Nummervisning er ikke begrenset som standard. Neste anrop: Ikke begrenset" "SIM-kortet er ikke tilrettelagt for tjenesten." "Kunne ikke endre innstilling for nummervisning." - - - - - - - - - - + "Endring i begrenset tilgang" + "Datatjenesten er blokkert." + "Nødtjenesten er blokkert." + "Tale- og SMS-tjenesten er blokkert." + "Alle tale- og SMS-tjenester er blokkert." "Tale" "Data" "Fax" @@ -72,11 +81,43 @@ "Synkron" "Pakkedata" "PAD" + + + + + + + + + + + + + + + + + + + + + + + + + + + + "{0}: Ikke viderekoblet" "{0}: {1}" "{0}: {1} etter {2} sekunder" "{0}: Ikke viderekoblet" "{0}: Ikke viderekoblet" + + + + "OK" "Nettsiden inneholder en feil." "Kunne ikke finne adressen." @@ -93,6 +134,8 @@ "Kunne ikke åpne filen." "Fant ikke den forespurte filen." "For mange forespørsler blir behandlet. Prøv igjen senere." + + "Synkronisering" "Synkronisering" "For mange slettinger av %s." @@ -138,6 +181,10 @@ "Lavnivå tilgang og kontroll over systemet." "Utviklingsverktøy" "Funksjonalitet kun utviklere trenger." + + + + "deaktivere eller endre statusfeltet" "Lar applikasjonen deaktivere statusfeltet, samt legge til og fjerne systemikoner." "utvide/slå sammen statusfeltet" @@ -170,6 +217,14 @@ "Lar applikasjonen tvinge enhver aktivitet som er i forgrunnen til å lukkes og gå tilbake. Vanlige applikasjoner bør aldri trenge dette." "hente intern systemtilstand" "Lar applikasjonen hente intern tilstand fra systemet. Onsdinnede applikasjoner kan hente et bredt spekter av privat og sikker informasjon som de vanligvis aldri burde ha behov for." + + + + + + + + "overvåke og kontrollere all applikasjonsoppstart" "Lar applikasjonen overvåke og kontrollere hvordan systemet starter applikasjoner. Ondsinnede applikasjoner kan ta over systemet helt. Denne rettigheten behøves bare for utvikling, aldri for vanlig bruk av telefonen." "kringkaste melding om fjernet pakke" @@ -184,6 +239,10 @@ "Lar applikasjonen kontrollere om aktiviteter alltid avsluttes når de sendes til bakgrunnen. Behøves aldri for vanlige applikasjoner." "endre batteristatistikk" "Lar applikasjonen endre på innsamlet batteristatistikk. Ikke ment for vanlige applikasjoner." + + + + "vis uautoriserte vinduer" "Tillater at det opprettes vinduer ment for bruk av systemets interne brukergrensesnitt. Ikke ment for vanlige applikasjoner." "vise advarsler på systemnivå" @@ -250,6 +309,10 @@ "Lage falske plassingskilder for testing. Ondsinnede applikasjoner kan bruke dette for å overstyre plasseringen og/eller statusen rapportert av ekte plasseringskilder slik som GPS eller nettverksoperatører." "få tilgang til ekstra plasseringskommandoer" "Få tilgang til ekstra kommandoer for plasseringskilder. Ondsinnede applikasjoner kan bruke dette til å forstyrre GPS eller andre plasseringskilder." + + + + "nøyaktig (GPS-) plassering" "Få tilgang til nøyaktige plasseringskilder som Global Positioning System (GPS) på telefonen, når det er tilgjengelig. Ondsinnede applikasjoner kan bruke dette for å finne ut hvor du er, og kan bruke mer batteri." "grov (nettverksbasert) plassering" @@ -322,6 +385,10 @@ "Lar applikasjonen få se informasjon om tilstanden til de trådløse nettene." "endre tilstand for trådløse nettverk" "Lar applikasjonen koble til og fra trådløse aksesspunkt, og å gjøre endringer i konfigurerte trådløse nettverk." + + + + "Bluetooth-administrasjon" "Lar applikasjonen konfigurere den lokale Bluetooth-telefonen, og å oppdage og pare med andre enheter." "opprette Bluetooth-tilkoblinger" @@ -342,6 +409,10 @@ "Lar applikasjonen lese private ord, navn og uttrykk som brukeren har lagret i den brukerdefinerte ordlisten." "skrive til brukerdefinert ordliste" "Lar applikasjonen skrive nye ord til den brukerdefinerte ordlisten." + + + + "Hjemme" "Mobil" @@ -358,6 +429,8 @@ "Annen" "Egendefinert…" + + "Hjemme" "Arbeid" @@ -398,29 +471,31 @@ "Riktig!" "Beklager, prøv igjen:" "Lader (%d%%)" + + "Koble til en batterilader." "Mangler SIM-kort." "Ikke noe SIM-kort i telefonen." "Sett inn et SIM-kort." "Nettverk ikke tillatt" "SIM-kortet er PUK-låst." - - + "Se manualen eller kontakt kundeservice." "SIM-kortet er låst." "Låser opp SIM-kort…" "You have incorrectly drawn your unlock pattern %d times. "\n\n"Please try again in %d seconds." "You have incorrectly drawn your unlock pattern %d times. After %d more unsuccessful attempts, you will be asked to unlock your phone using your Google sign-in."\n\n" Please try again in %d seconds." "Prøv igjen om %d sekunder." "Glemt mønsteret?" - "Too many pattern attempts!" - "To unlock,BREAKsign in with your Google account" - "Username (email)" - "Password" - "Sign in" - "Invalid username or password." + "For mange mønsterforsøk!" + "For å låse opp, logg inn med Google-kontoen din" + "Brukernavn (e-post)" + "Passord" + "Logg inn" + "Ugyldig brukernavn eller passord." "%-l%P" "%-l%p" - "Fjern varslinger" + + "Ingen varslinger" "Aktiviteter" "Varslinger" @@ -429,6 +504,8 @@ "Koble til en lader" "Batteriet er nesten tomt:" "mindre enn %d%% igjen." + + "Factory test failed" "The FACTORY_TEST action is only supported for packages installed in /system/app." "No package was found that provides the FACTORY_TEST action." @@ -437,6 +514,14 @@ "JavaScript" "Naviger bort fra denne siden?"\n\n"%s"\n\n"Velg OK for å fortsette, eller Avbryt for å forbli på denne siden." "Bekreft" + + + + + + + + "Ønsker du at nettleseren skal huske dette passordet?" "Ikke nå" "Husk" @@ -544,14 +629,6 @@ "Middag" "midnatt" "Midnatt" - - - - - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "Merk alt" @@ -589,6 +666,8 @@ "Application %1$s (in process %2$s) is not responding." "Process %1$s is not responding." "Force close" + + "Wait" "Debug" "Select an action for text" @@ -642,22 +721,31 @@ "Formatere minnekort" "Er du sikker på at du ønsker å formatere minnekortet? Alle data på kortet vil gå tapt." "Format" + + + + "Velg inndatametode" " ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" "TAG_FONT""kandidater""CLOSE_FONT" "Forbereder minnekort" - "Sjekker for feil" + + "Tomt minnekort" - "Minnekortet er tomt eller bruker et ustøttet filsystem." + + "Skadet minnekort" - "Minnekortet er skadet. Det kan være du må formatere kortet." + + "Minnekortet ble tatt ut uventet" "Avmonter minnekortet før det tas ut, for å unngå datatap." "Trygt å ta ut minnekort" - "Minnekortet kan nå trygt tas ut." + + "Minnekortet ble tatt ut" - "Minnekortet ble tatt ut. Sett inn et nytt minnekort for å øke lagringsplassen." + + "Fant ingen tilsvarende aktiviteter" "oppdater statistikk over komponentbruk" "Tillater endring av innsamlet data om bruk av komponenter. Ikke ment for vanlige applikasjoner." @@ -673,4 +761,8 @@ + + + + diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index a418d72a882fb..cd1b460e5ac02 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -21,6 +21,7 @@ "GB" "TB" "PB" + "%1$s%2$s" "<zonder titel>" "…" "(Geen telefoonnummer)" @@ -48,6 +49,12 @@ "Oproep blokkeren" "Wachtwoordwijziging" "PIN-wijziging" + "Nummer van beller beschikbaar" + "Nummer van beller beperkt" + "Driewegs bellen" + "Ongewenste, vervelende oproepen weigeren" + "Weergave van nummer van beller" + "Niet storen" "Beller-id standaard ingesteld op \'beperkt\'. Volgende oproep: beperkt." "Beller-id standaard ingesteld op \'beperkt\'. Volgende oproep: onbeperkt." "Beller-id standaard ingesteld op \'onbeperkt\'. Volgende oproep: beperkt." @@ -67,11 +74,27 @@ "Synchroniseren" "Pakket" "PAD" + "Roamingaanduiding aan" + "Roamingaanduiding uit" + "Roamingaanduiding knippert" + "Uit de buurt" + "Buiten het gebouw" + "Roaming - Voorkeurssysteem" + "Roaming - Beschikbaar systeem" + "Roaming - Alliance-partner" + "Roaming - Premium-partner" + "Roaming - Volledige servicefunctionaliteit" + "Roaming - Gedeeltelijke servicefunctionaliteit" + "Roamingbanner aan" + "Roamingbanner uit" + "Service zoeken" "{0}: niet doorgeschakeld" "{0}: {1}" "{0}: {1} na {2} seconden" "{0}: niet doorgeschakeld" "{0}: niet doorgeschakeld" + "Functiecode voltooid." + "Verbindingsprobleem of ongeldige functiecode." "OK" "De webpagina bevat een fout." "De URL kan niet worden gevonden." @@ -88,6 +111,7 @@ "Het bestand kan niet worden geopend." "Het opgevraagde bestand is niet gevonden." "Er worden te veel aanvragen verwerkt. Probeer het later opnieuw." + "Het certificaat is opgeslagen in de opslagruimte voor sleutels van het systeem." "Synchroniseren" "Synchroniseren" "Te veel verwijderen voor %s." @@ -133,6 +157,8 @@ "Toegang tot en beheer van het systeem op lager niveau." "Ontwikkelingshulpprogramma\'s" "Functies die alleen door toepassingsontwikkelaars worden gebruikt." + "Opslagruimte" + "Toegang tot de SD-kaart." "statusbalk uitschakelen of wijzigen" "Hiermee kan een toepassing de statusbalk uitschakelen of systeempictogrammen toevoegen en verwijderen." "statusbalk uitvouwen/samenvouwen" @@ -165,6 +191,10 @@ "Hiermee kan een toepassing elke willekeurige activiteit die op de voorgrond wordt uitgevoerd, sluiten en naar de achtergrond verplaatsen. Nooit vereist voor normale toepassingen." "interne systeemstatus ophalen" "Hiermee kan een toepassing de interne status van het systeem ophalen. Schadelijke toepassingen kunnen privé- of veiligheidsgegevens ophalen die ze normaal niet nodig hebben." + "gedeeltelijke uitschakeling" + "Hiermee wordt activiteitenbeheer uitgeschakeld. Er wordt geen volledige uitschakeling uitgevoerd." + "schakelen tussen toepassingen voorkomen" + "Hiermee wordt voorkomen dat de gebruiker overschakelt naar een andere toepassing." "alle startende toepassingen bijhouden en beheren" "Hiermee kan een toepassing de manier waarop het systeem activiteiten start, bijhouden en beheren. Schadelijke toepassingen kunnen het systeem volledig in gevaar brengen. Deze machtiging is alleen voor ontwikkeling vereist, nooit voor normaal telefoongebruik." "melding verzenden dat pakket is verwijderd" @@ -179,6 +209,8 @@ "Hiermee kan een toepassing bepalen of activiteiten altijd worden afgesloten zodra deze naar de achtergrond gaan. Nooit nodig voor normale toepassingen." "accustatistieken aanpassen" "Hiermee kunnen verzamelde accustatistieken worden gewijzigd. Niet voor gebruik door normale toepassingen." + "systeemback-up en -herstel beheren" + "Hiermee kan de toepassing het mechanisme voor systeemback-up en -herstel beheren. Niet voor gebruik door normale toepassingen." "niet-geautoriseerde vensters weergeven" "Hiermee kunnen vensters worden gemaakt die door de interne systeemgebruikersinterface worden gebruikt. Niet voor gebruik door normale toepassingen." "waarschuwingen op systeemniveau weergeven" @@ -245,6 +277,8 @@ "Neplocatiebronnen voor testdoeleinden maken. Schadelijke toepassingen kunnen dit gebruiken om de locatie en/of status te overschrijven die door de echte locatiebronnen wordt aangegeven, zoals GPS of netwerkaanbieders." "toegang opdrachten aanbieder extra locaties" "Toegang tot opdrachten aanbieder extra locaties. Schadelijke toepassingen kunnen hiervan gebruik maken om de werking van GPS of andere locatiebronnen te verstoren." + "toestemming om een locatieprovider te installeren" + "Neplocatiebronnen voor testdoeleinden maken. Schadelijke toepassingen kunnen dit gebruiken om de locatie en/of status te overschrijven die door de echte locatiebronnen, zoals GPS of netwerkaanbieders, wordt aangegeven of om uw locatie bij te houden en te rapporteren aan externe bronnen." "nauwkeurige (GPS) locatie" "Toegang tot exacte locatiebronnen, zoals het Global Positioning System op de telefoon, indien beschikbaar. Schadelijke toepassingen kunnen dit gebruiken om te bepalen waar u zich bevindt en mogelijk extra acculading verbruiken." "globale (netwerkgebaseerde) locatie" @@ -317,6 +351,8 @@ "Hiermee kan een toepassing informatie over de Wi-Fi-status bekijken." "Wi-Fi-status wijzigen" "Hiermee kan een toepassing zich koppelen aan en loskoppelen van Wi-Fi toegangspunten en wijzigingen aanbrengen in geconfigureerde Wi-Fi-netwerken." + "Wi-Fi Multicast-ontvangst toestaan" + "Hiermee kan een toepassing pakketten ontvangen die niet rechtstreeks zijn geadresseerd aan uw apparaat. Dit kan handig zijn wanneer services in de buurt worden ontdekt. Dit verbruikt meer energie dan de niet-multicastmodus." "bluetooth-beheer" "Hiermee kan een toepassing de lokale Bluetooth-telefoon configureren en externe apparaten zoeken en aansluiten." "Bluetooth-verbindingen maken" @@ -337,6 +373,8 @@ "Hiermee kan een toepassing privéwoorden, namen en woordcombinaties lezen die de gebruiker heeft opgeslagen in het gebruikerswoordenboek." "schrijven naar door gebruiker gedefinieerd woordenboek" "Hiermee kan een toepassing nieuwe woorden schrijven naar het gebruikerswoordenboek." + "inhoud op de SD-kaart aanpassen/verwijderen" + "Hiermee kan een toepassing schrijven naar de SD-kaart." "Thuis" "Mobiel" @@ -353,6 +391,7 @@ "Overig" "Aangepast" + "Mobiel" "Thuis" "Werk" @@ -393,6 +432,8 @@ "Juist!" "Probeer het opnieuw" "Opladen (%d%%)" + + "Sluit de oplader aan." "Geen SIM-kaart." "Geen SIM-kaart in telefoon." @@ -414,7 +455,8 @@ "Gebruikersnaam of wachtwoord ongeldig." "%-l%P" "%-l%p" - "Meldingen wissen" + + "Geen meldingen" "Actief" "Meldingen" @@ -423,6 +465,7 @@ "Sluit de oplader aan" "De accu raakt op:" "minder dan %d%% resterend." + "Waarom?" "Fabriekstest mislukt" "De actie FACTORY_TEST wordt alleen ondersteund voor pakketten die zijn geïnstalleerd in /system/app." "Er is geen pakket gevonden dat de actie FACTORY_TEST levert." @@ -431,6 +474,10 @@ "JavaScript" "Wilt u deze pagina verlaten?"\n\n"%s"\n\n"Kies OK om door te gaan of Annuleren om op de huidige pagina te blijven." "Bevestigen" + "browsergeschiedenis en bladwijzers lezen" + "Hiermee kan een toepassing de URL\'s lezen die u via de browser heeft bezocht, evenals alle bladwijzers van de browser." + "browsergeschiedenis en bladwijzers schrijven" + "Hiermee kan een toepassing de op uw telefoon opgeslagen browsergeschiedenis of bladwijzers wijzigen. Schadelijke toepassingen kunnen hiermee uw browsergegevens verwijderen of wijzigen." "Wilt u dat de browser dit wachtwoord onthoudt?" "Niet nu" "Onthouden" @@ -538,10 +585,6 @@ "Twaalf uur \'s middags" "middernacht" "Middernacht" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "Alles selecteren" @@ -579,6 +622,7 @@ "Toepassing %1$s (in proces %2$s) reageert niet." "Proces %1$s reageert niet." "Nu sluiten" + "Rapport" "Wachten" "Foutopsporing" "Selecteer een actie voor tekst" @@ -632,22 +676,26 @@ "SD-kaart formatteren" "Weet u zeker dat u de SD-kaart wilt formatteren? Alle gegevens op uw kaart gaan dan verloren." "Formatteren" + + + + "Invoermethode selecteren" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "kandidaten" "SD-kaart voorbereiden" - "Controleren op fouten" + "Controleren op fouten." "Lege SD-kaart" - "De SD-kaart is leeg of gebruikt een niet-ondersteund bestandssysteem." + "SD-kaart is leeg of heeft een niet-ondersteund bestandssysteem." "Beschadigde SD-kaart" - "De SD-kaart is beschadigd. U moet de kaart mogelijk opnieuw formatteren." + "SD-kaart beschadigd. U moet de kaart mogelijk opnieuw formatteren." "SD-kaart onverwachts verwijderd" "Ontkoppel de SD-kaart voordat u deze verwijdert om gegevensverlies te voorkomen." "De SD-kaart kan veilig worden verwijderd" - "De SD-kaart kan nu veilig worden verwijderd." + "U kunt de SD-kaart veilig verwijderen." "SD-kaart is verwijderd" - "De SD-kaart is verwijderd. Plaats een nieuwe SD-kaart om de opslagcapaciteit van uw apparaat te vergroten." + "SD-kaart verwijderd. Plaats een nieuwe." "Geen overeenkomende activiteiten gevonden" "gebruiksstatistieken van component bijwerken" "Hiermee kunnen verzamelde gebruiksstatistieken van een component worden gewijzigd. Niet voor gebruik door normale toepassingen." @@ -661,4 +709,6 @@ "Uitvoeren" "Nummer bellen"\n"met %s" "Contact maken"\n"met %s" + "aangevinkt" + "niet aangevinkt" diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index c6c9bd07dec2f..65f3ad14d3254 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -21,6 +21,7 @@ "GB" "TB" "PB" + "%1$s %2$s" "<bez nazwy>" "…" "(Brak numeru telefonu)" @@ -41,19 +42,25 @@ "Wpisz kod PIN o długości od 4 do 8 cyfr." "Karta SIM jest zablokowana kodem PUK. Wprowadź kod PUK, aby odblokować kartę." "Wprowadź kod PUK2, aby odblokować kartę SIM." - "Identyfikator dzwoniącego przy połączeniach przychodzących" - "Identyfikator dzwoniącego przy połączeniach wychodzących" + "Identyfikator rozmówcy przy połączeniach przychodzących" + "Identyfikator rozmówcy przy połączeniach wychodzących" "Przekierowania połączeń" "Połączenia oczekujące" "Blokada dzwonienia" "Zmiana hasła" "Zmiana kodu PIN" - "Identyfikator dzwoniącego ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: zastrzeżony" - "Identyfikator dzwoniącego ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: nie zastrzeżony" - "Identyfikator dzwoniącego ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: zastrzeżony" - "Identyfikator dzwoniącego ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony" + "Numer telefonu, z którego wykonywane jest połączenie, widoczny" + "Numer telefonujący zastrzeżony" + "Połączenie dla trzech abonentów" + "Odrzucanie niepożądanych, irytujących połączeń" + "Dostarczanie numeru telefonującego" + "Nie przeszkadzać" + "Identyfikator rozmówcy ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: zastrzeżony" + "Identyfikator rozmówcy ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: nie zastrzeżony" + "Identyfikator rozmówcy ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: zastrzeżony" + "Identyfikator rozmówcy ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony" "Usługa nie jest świadczona." - "Nie można zmienić ustawienia identyfikatora dzwoniącego." + "Nie można zmienić ustawienia identyfikatora rozmówcy." "Zmieniono ograniczenie dostępu" "Usługa transmisji danych jest zablokowana." "Usługa połączeń alarmowych jest zablokowana." @@ -67,11 +74,27 @@ "Synchronizacja" "Pakiet" "PAD" + "Wskaźnik roamingu włączony" + "Wskaźnik roamingu wyłączony" + "Migający wskaźnik roamingu" + "W innej okolicy" + "Poza biurem" + "Roaming – preferowany system" + "Roaming – dostępny system" + "Roaming – partner stowarzyszony" + "Roaming – partner Premium" + "Roaming – pełna funkcjonalność usługi" + "Roaming – częściowa funkcjonalność usługi" + "Baner roamingu włączony" + "Baner roamingu wyłączony" + "Wyszukiwanie usługi" "{0}: nieprzekierowane" "{0}: {1}" "{0}: {1} po {2} sekundach" "{0}: nieprzekierowane" "{0}: nieprzekierowane" + "Wykonano kod funkcji." + "Problem z połączeniem lub nieprawidłowy kod funkcji." "OK" "Strona sieci Web zawiera błąd." "Nie można odszukać adresu URL." @@ -88,6 +111,7 @@ "Nie można uzyskać dostępu do pliku." "Nie znaleziono żądanego pliku." "Zbyt wiele żądań jest przetwarzanych. Spróbuj ponownie później." + "Certyfikat jest zapisywany w magazynie kluczy systemu." "Synchronizacja" "Synchronizuj" "Zbyt wiele usuwanych %s." @@ -108,9 +132,9 @@ "Tryb cichy" "Dźwięk jest wyłączony" "Dźwięk jest włączony" - "Tryb lotniczy" - "Tryb lotniczy jest włączony" - "Tryb lotniczy jest wyłączony" + "Tryb samolotowy" + "Tryb samolotowy jest włączony" + "Tryb samolotowy jest wyłączony" "Tryb awaryjny" "System Android" "Usługi płatne" @@ -119,8 +143,8 @@ "Czytanie i zapisywanie wiadomości SMS, e-mail i innych" "Informacje osobiste" "Bezpośredni dostęp do kontaktów i kalendarza zapisanych w telefonie." - "Twoje położenie" - "Monitorowanie fizycznego położenia" + "Twoja lokalizacja" + "Monitorowanie fizycznej lokalizacji" "Połączenia sieciowe" "Pozwól aplikacjom na dostęp do różnych funkcji sieci." "Twoje konta Google" @@ -133,6 +157,8 @@ "Dostęp i kontrola systemu niższego poziomu." "Narzędzia programistyczne" "Funkcje potrzebne jedynie programistom" + "Pamięć" + "Dostęp do karty SD." "wyłączanie lub zmienianie paska stanu" "Pozwala aplikacjom na wyłączenie paska stanu lub dodawanie i usuwanie ikon systemowych." "rozwijanie/zwijanie paska stanu" @@ -165,6 +191,10 @@ "Pozwala aplikacji na wymuszenie zamknięcia i cofnięcia dowolnej operacji działającej na pierwszym planie. Nigdy nie powinno być potrzebne normalnym aplikacjom." "pobieranie informacji o wewnętrznym stanie systemu" "Pozwala aplikacjom na pobieranie informacji o wewnętrznym stanie systemu. Szkodliwe aplikacje mogą pobrać szeroką gamę osobistych i zabezpieczonych informacji, które normalnie nie powinny im być nigdy potrzebne." + "częściowe wyłączenie" + "Przełącza menedżera aktywności w stan wyłączenia. Nie wykonuje pełnego wyłączenia." + "zapobieganie przełączaniu aplikacji" + "Zapobiega przełączaniu aplikacji na inną przez użytkownika." "monitorowanie i kontrolowanie wszystkich uruchamianych aplikacji" "Pozwala aplikacji na monitorowanie i kontrolowanie sposobu, w jaki w systemie uruchamiane są różne działania. Szkodliwe aplikacje mogą całkowicie przejąć system. Te uprawnienia potrzebne są tylko programistom, nigdy w przypadku normalnego wykorzystywania telefonu." "wysyłanie transmisji informującej o usuniętym pakiecie" @@ -179,6 +209,8 @@ "Pozwala aplikacji na kontrolowanie, czy czynności są zawsze kończone, kiedy zaczynają działać w tle. Nigdy nie jest potrzebne normalnym aplikacjom." "zmienianie statystyk dotyczących baterii" "Pozwala na zmianę zebranych statystyk dotyczących baterii. Nie do wykorzystania przez normalne aplikacje." + "kontrolowanie tworzenia i przywracania kopii zapasowych systemu" + "Umożliwia aplikacji kontrolowanie mechanizmu tworzenia i przywracania kopii zapasowych systemu. Nie jest przeznaczone do użytku dla zwykłych aplikacji." "wyświetlanie nieuwierzytelnionych okien" "Pozwala na tworzenie okien, które przeznaczone są do wykorzystania przez wewnętrzny interfejs użytkownika systemu. Nie do wykorzystania przez normalne aplikacje." "wyświetlanie ostrzeżeń systemowych" @@ -243,12 +275,14 @@ "Pozwala aplikacji na zmianę wydarzeń z kalendarza zapisanych w telefonie. Szkodliwe aplikacje mogą to wykorzystać, aby usunąć lub zmienić dane w kalendarzu." "udawanie źródeł położenia dla testów" "Tworzenie pozorowanych źródeł ustalania położenia dla testów. Szkodliwe aplikacje mogą to wykorzystać, aby zastąpić prawdziwe położenie i/lub stan zwracany przez prawdziwe źródła, takie jak GPS lub dostawcy usługi sieciowej." - "dostęp do dodatkowych poleceń dostawcy informacji o położeniu" - "Dostęp do dodatkowych poleceń dostawcy informacji o położeniu. Szkodliwe aplikacje mogą go wykorzystać, aby wpływać na działanie urządzenia GPS lub innych źródeł ustalania położenia." - "dokładne położenie (GPS)" + "dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji" + "Dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji. Szkodliwe aplikacje mogą go wykorzystać, aby wpływać na działanie urządzenia GPS lub innych źródeł ustalania lokalizacji." + "uprawnienia do instalowania dostawcy danych o lokalizacji" + "Utwórz sztuczne źródła danych o lokalizacji na potrzeby testowania. Złośliwe aplikacje mogą korzystać z tej opcji w celu zastępowania danych o lokalizacji i/lub stanie zwracanych przez prawdziwe źródła danych o lokalizacji, takie jak odbiornik GPS lub dostawcy sieciowi, bądź monitorowania i zgłaszania lokalizacji do źródeł zewnętrznych." + "dokładna lokalizacja (GPS)" "Uzyskiwanie dostępu do dokładnych źródeł ustalania położenia w telefonie, takich jak system GPS, tam, gdzie są one dostępne. Szkodliwe aplikacje mogą to wykorzystać do określenia położenia użytkownika oraz mogą zużywać więcej energii baterii." - "przybliżone ustalanie położenia (oparte o sieć)" - "Dostęp do źródeł, takich jak bazy danych sieci komórkowych, jeśli są dostępne, które pozwalają określić przybliżone położenie telefonu. Szkodliwe aplikacje mogą go wykorzystać do określenia, gdzie w przybliżeniu znajduje się użytkownik." + "przybliżone ustalanie lokalizacji (oparte o sieć)" + "Dostęp do źródeł, takich jak bazy danych sieci komórkowych, jeśli są dostępne, które pozwalają określić przybliżoną lokalizację telefonu. Szkodliwe aplikacje mogą go wykorzystać do określenia, gdzie w przybliżeniu znajduje się użytkownik." "dostęp do usługi SurfaceFlinger" "Pozwala aplikacji na wykorzystanie funkcji niskiego poziomu usługi SurfaceFlinger." "czytanie bufora ramki" @@ -277,14 +311,14 @@ "Pozwala aplikacjom na dzwonienie pod numery telefonów bez interwencji użytkownika. Szkodliwe aplikacje mogą powodować występowanie niespodziewanych połączeń na rachunku telefonicznym. Należy zauważyć, że aplikacje nie mogą dzwonić na numery alarmowe." "bezpośrednie wybieranie dowolnych numerów telefonu" "Pozwala aplikacji dzwonić na dowolny numer telefonu, włącznie z numerami alarmowymi, bez interwencji użytkownika. Szkodliwe aplikacje mogą wykonywać niepotrzebne i nielegalne połączenia z usługami alarmowymi." - "kontrolowanie powiadomień o aktualizacji położenia" - "Pozwala włączyć/wyłączyć powiadomienia o aktualizacji położenia przez radio. Nie wykorzystywane przez normalne aplikacje." + "kontrolowanie powiadomień o aktualizacjach lokalizacji" + "Pozwala włączyć/wyłączyć powiadomienia o aktualizacjach lokalizacji przez sieć bezprzewodową. Nie wykorzystywane przez normalne aplikacje." "dostęp do właściwości usługi rezerwacji" "Pozwala na dostęp z uprawnieniami do odczytu/zapisu do właściwości przesłanych przez usługę rezerwacji. Nie wykorzystywane przez normalne aplikacje." "wybieranie widżetów" "Zezwala aplikacjom na wskazywanie systemowi, które widżety mogą być używane przez inne aplikacje. Z użyciem tego pozwolenia aplikacje mogą udzielać dostępu do danych osobistych innym aplikacjom. Nie jest ono przeznaczone dla zwykłych aplikacji." "zmiana stanu telefonu" - "Pozwala aplikacji na kontrolowanie funkcji telefonu w urządzeniu. Aplikacja z tymi uprawnieniami może przełączać sieci, włączać i wyłączać radio itp. bez informowania użytkownika." + "Pozwala aplikacji na kontrolowanie funkcji telefonu w urządzeniu. Aplikacja z tymi uprawnieniami może zmieniać, włączać i wyłączać sieci bezprzewodowe itp. bez informowania użytkownika." "czytanie stanu telefonu" "Pozwala aplikacji na dostęp do funkcji telefonu w urządzeniu. Aplikacja z takim uprawnieniem może określić numer tego telefonu, czy jest nawiązane połączenie, numer, z którym jest ono nawiązane, itp." "zapobieganie przejściu telefonu w stan uśpienia" @@ -305,7 +339,7 @@ "Pozwala aplikacji na pobranie listy kont zapisanych w telefonie." "wyświetlanie stanu sieci" "Pozwala aplikacji na wyświetlanie stanu wszystkich sieci." - "pełen dostęp do Internetu" + "pełen dostęp do internetu" "Pozwala aplikacji na tworzenie gniazd sieciowych." "zapisywanie ustawień nazwy punktu dostępowego (APN, Access Point Name)" "Pozwala aplikacji na zmianę ustawień APN, takich jak serwer proxy oraz port dowolnego APN." @@ -317,6 +351,8 @@ "Pozwala aplikacji na wyświetlanie informacji o stanie Wi-Fi." "zmiana stanu Wi-Fi" "Pozwala aplikacji na łączenie i rozłączanie z punktami dostępowymi Wi-Fi oraz na dokonywanie zmian skonfigurowanych sieci Wi-Fi." + "zezwolenie na odbiór grupowych połączeń Wi-Fi" + "Umożliwia aplikacji odbieranie pakietów nieskierowanych bezpośrednio do Twojego urządzenia. Może to być przydatne przy wykrywaniu usług oferowanych w okolicy. Powoduje większe zapotrzebowanie na energię niż w trybie innym niż grupowy." "administrowanie Bluetooth" "Pozwala aplikacji na konfigurowanie lokalnego telefonu Bluetooth, wyszukiwanie urządzeń zdalnych i łączenie się z nimi." "tworzenie połączeń Bluetooth" @@ -337,6 +373,8 @@ "Zezwala aplikacji na odczytywanie wszelkich prywatnych słów, nazw i wyrażeń zapisanych przez użytkownika w swoim słowniku." "zapisywanie w słowniku zdefiniowanym przez użytkownika" "Zezwala aplikacjom na zapisywanie nowych słów w słowniku użytkownika." + "modyfikowanie/usuwanie zawartości karty SD" + "Umożliwia aplikacji zapis na karcie SD." "Dom" "Komórka" @@ -353,6 +391,7 @@ "Inne" "Niestandardowy" + "Komórka" "Dom" "Praca" @@ -393,6 +432,8 @@ "Poprawnie!" "Niestety, spróbuj ponownie" "Ładowanie (%d%%)" + + "Podłącz ładowarkę." "Brak karty SIM." "Brak karty SIM w telefonie." @@ -414,7 +455,8 @@ "Błędna nazwa użytkownika lub hasło." "%-l%P" "%-l%p" - "Wyczyść powiadomienia" + + "Brak powiadomień" "Bieżące" "Powiadomienia" @@ -423,6 +465,7 @@ "Podłącz ładowarkę" "Bateria się rozładowuje:" "pozostało mniej niż %d%%." + "Dlaczego?" "Nieudany test fabryczny" "Czynność FACTORY_TEST jest obsługiwana tylko dla pakietów zainstalowanych w katalogu /system/app." "Nie znaleziono żadnego pakietu, który zapewnia działanie FACTORY_TEST." @@ -431,6 +474,10 @@ "JavaScript" "Czy opuścić tę stronę?"\n\n"%s"\n\n"Wybierz opcję OK, aby kontynuować, lub opcję Anuluj, aby pozostać na tej stronie." "Potwierdź" + "odczyt historii i zakładek przeglądarki" + "Umożliwia aplikacji odczyt wszystkich adresów URL odwiedzonych przez przeglądarkę, a także wszystkich zakładek przeglądarki." + "zapis historii i zakładek przeglądarki" + "Umożliwia aplikacji modyfikowanie historii lub zakładek przeglądarki zapisanych w telefonie. Złośliwe aplikacje mogą używać tej opcji do usuwania lub modyfikowania danych przeglądarki." "Czy chcesz, aby zapamiętać to hasło w przeglądarce?" "Nie teraz" "Zapamiętaj" @@ -538,10 +585,6 @@ "Południe" "północ" "Północ" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "Zaznacz wszystko" @@ -579,9 +622,10 @@ "Aplikacja %1$s (w procesie %2$s) nie odpowiada." "Proces %1$s nie odpowiada." "Wymuś zamknięcie" + "Zgłoś" "Czekaj" "Debuguj" - "Wybierz czynność dla wpisanego tekstu" + "Jak wysłać tekst?" "Głośność dzwonka" "Głośność multimediów" "Odtwarzanie przez Bluetooth" @@ -590,8 +634,8 @@ "Głośność alarmu" "Głośność powiadomienia" "Głośność" - "Domyślny dzwonek" - "Domyślny dzwonek (%1$s)" + "Dzwonek domyślny" + "Dzwonek domyślny (%1$s)" "Cichy" "Dzwonki" "Nieznany dzwonek" @@ -632,22 +676,26 @@ "Formatuj kartę SD" "Czy na pewno sformatować kartę SD? Wszystkie dane na karcie zostaną utracone." "Formatuj" + + + + "Sposób wprowadzania tekstu" " AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "kandydaci" "Przygotowywanie karty SD" - "Sprawdzanie w poszukiwaniu błędów" + "Sprawdzanie w poszukiwaniu błędów." "Pusta karta SD" - "Karta SD jest pusta lub używa nieobsługiwanego systemu plików." + "Karta SD jest pusta lub zawiera nieobsługiwany system plików." "Uszkodzona karta SD" - "Karta SD jest uszkodzona. Konieczne może być przeformatowanie karty." + "Karta SD jest uszkodzona. Konieczne może być ponowne sformatowanie." "Karta SD została nieoczekiwanie wyjęta" "Odłącz kartę SD przed jej wyjęciem, aby uniknąć utraty danych." "Można bezpiecznie usunąć kartę SD" - "Można teraz bezpiecznie usunąć kartę SD." + "Możesz bezpiecznie wyjąć kartę SD." "Usunięta karta SD" - "Karta SD została usunięta. Włóż nową kartę SD, aby zwiększyć pamięć urządzenia." + "Karta SD została wyjęta. Włóż nową kartę." "Nie znaleziono pasujących działań" "aktualizowanie statystyk użycia komponentu" "Zezwala na modyfikacje zebranych statystyk użycia komponentu. Nieprzeznaczone dla zwykłych aplikacji." @@ -661,4 +709,6 @@ "Wykonaj" "Połącz"\n"z numerem %s" "Utwórz kontakt"\n"dla numeru %s" + "zaznaczone" + "niezaznaczone" diff --git a/core/res/res/values-pt-rBR/donottranslate-cldr.xml b/core/res/res/values-pt-rBR/donottranslate-cldr.xml index 47290552dd2e1..1111658ffb907 100644 --- a/core/res/res/values-pt-rBR/donottranslate-cldr.xml +++ b/core/res/res/values-pt-rBR/donottranslate-cldr.xml @@ -95,7 +95,7 @@ %-l:%M %p %-l:%M %^p h:mm a - H'h'mm + H\'h\'mm %d/%m/%Y dd/MM/yyyy "%s/%s/%s" diff --git a/core/res/res/values-pt-rPT/donottranslate-cldr.xml b/core/res/res/values-pt-rPT/donottranslate-cldr.xml index f38a2d0499d79..197cb6ed16fde 100644 --- a/core/res/res/values-pt-rPT/donottranslate-cldr.xml +++ b/core/res/res/values-pt-rPT/donottranslate-cldr.xml @@ -95,7 +95,7 @@ %-l:%M %p %-l:%M %^p h:mm a - H'h'mm + H\'h\'mm %d/%m/%Y dd/MM/yyyy "%s/%s/%s" diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml new file mode 100644 index 0000000000000..d4623f96c4d6b --- /dev/null +++ b/core/res/res/values-pt-rPT/strings.xml @@ -0,0 +1,765 @@ + + + + "B" + "KB" + "MB" + "GB" + "TB" + "PB" + + + "<sem título>" + "…" + "(Nenhum número de telefone)" + "(Desconhecido)" + "Correio de voz" + "MSISDN1" + "Problema de ligação ou código MMI inválido." + "O serviço foi activado." + "O serviço foi activado para:" + "O serviço foi desactivado." + "O registo foi bem sucedido." + "A eliminação foi bem sucedida." + "Palavra-passe incorrecta." + "MMI concluído." + "O PIN antigo que introduziu não está correcto." + "O PUK que introduziu não está correcto." + "Os PINs que introduziu não coincidem." + "Introduza um PIN entre 4 e 8 números." + "O seu cartão SIM está bloqueado com PUK. Introduza o código PUK para desbloqueá-lo." + "Introduza o PUK2 para desbloquear o cartão SIM." + "ID do Autor da Chamada" + "ID do autor da chamada efectuada" + "Encaminhamento de chamadas" + "Chamada em espera" + "Barramento de chamadas" + "Alteração de palavra-passe" + "Alteração de PIN" + + + + + + + + + + + + + "ID do autor da chamada é predefinido como restrito. Chamada seguinte: Restrita" + "ID do autor da chamada é predefinido como restrito. Chamada seguinte: Não restrita" + "ID do autor da chamada é predefinido como não restrito. Chamada seguinte: Restrita" + "ID do autor da chamada é predefinido com não restrito. Chamada seguinte: Não restrita" + "Serviço não fornecido." + "Não é possível mudar o ID do autor da chamada." + "Acesso restrito modificado" + "O serviço de dados está bloqueado." + "O serviço de emergência está bloqueado." + "O serviço de voz/SMS está bloqueado." + "Todos os serviços de voz/SMS estão bloqueados." + "Voz" + "Dados" + "FAX" + "SMS" + "Assíncronos" + "Sincronização" + "Pacote" + "PAD" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "{0}: Não reencaminhado" + "{0}: {1}" + "{0}: {1} após {2} segundos" + "{0}: Não reencaminhado" + "{0}: Não reencaminhado" + + + + + "OK" + "A página Web contém um erro." + "Não foi possível localizar o URL." + "O esquema de autenticação do site não é suportado." + "A autenticação falhou." + "A·autenticação·através·do·servidor·proxy·falhou." + "Não foi possível estabelecer a ligação ao servidor." + "O servidor falhou ao comunicar. Tente novamente mais tarde." + "Esgotou o tempo limite da ligação ao servidor." + "A página contém demasiados redireccionamentos do servidor." + "O protocolo não é suportado." + "Não foi possível estabelecer uma ligação segura." + "Não foi possível abrir a página porque o URL é inválido." + "Não foi possível aceder ao ficheiro." + "Não foi possível localizar o ficheiro pedido." + "Existem demasiados pedidos em processamento. Tente novamente mais tarde." + + + "Sincronização" + "Sincronização" + "Demasiadas eliminações de %s." + "O armazenamento do telefone está cheio! Elimine alguns ficheiros para libertar espaço." + "Eu" + "Opções do telefone" + "Modo silencioso" + "Activar sem fios" + "Desactivar sem fios" + "Bloqueio de ecrã" + "Desligar" + "A encerrar..." + "O seu telefone irá encerrar." + "Nenhuma aplicação recente." + "Opções do telefone" + "Bloqueio de ecrã" + "Desligar" + "Modo silencioso" + "Som desactivado" + "O som está activado" + "Modo de avião" + "O modo de voo está activado" + "O modo de voo está desactivado" + "Modo seguro" + "Sistema Android" + "Serviços que implicam pagamento" + "Permite às aplicações efectuar acções que implicam pagamento." + "As suas mensagens" + "Leia e escreva a sua SMS, o seu e-mail e outras mensagens." + "Os seus dados pessoais" + "Acesso directo aos seus contactos e calendário armazenados no telefone." + "A sua localização" + "Monitorizar a sua localização física" + "Comunicação de rede" + "Permite o acesso de aplicações a várias funcionalidades de rede." + "As suas Contas Google" + "Aceda às Contas Google disponíveis." + "Controlos de hardware" + "Aceda directamente ao hardware no telefone." + "Chamadas" + "Monitorize, grave e processe chamadas telefónicas." + "Ferramentas do sistema" + "Acesso e controlo de nível inferior do sistema." + "Ferramentas de desenvolvimento" + "Funcionalidades apenas necessárias para programadores de aplicações." + + + + + "desactivar ou modificar barra de estado" + "Permite à aplicação desactivar a barra de estado ou adicionar e remover ícones do sistema." + "expandir/fechar barra de estado" + "Permite à aplicação expandir ou fechar a barra de estado." + "interceptar chamadas efectuadas" + "Permite à aplicação processar chamadas efectuadas e mudar o número a marcar. Algumas aplicações maliciosas podem monitorizar, redireccionar ou impedir chamadas efectuadas." + "receber SMS" + "Permite à aplicação receber e processar mensagens SMS. Algumas aplicações maliciosas podem monitorizar as suas mensagens e eliminá-las sem mostrá-las a si." + "receber MMS" + "Permite à aplicação receber e processar mensagens MMS. Algumas aplicações maliciosas podem monitorizar as mensagens ou eliminá-las sem mostrá-las ao utilizador." + "enviar mensagens SMS" + "Permite à aplicação enviar mensagens SMS. Algumas aplicações maliciosas podem fazer com que incorra em custos, enviando mensagens sem a sua confirmação." + "ler SMS ou MMS" + "Permite à aplicação ler mensagens SMS armazenadas no seu telefone ou cartão SIM. Algumas aplicações maliciosas podem ler as suas mensagens confidenciais." + "editar SMS ou MMS" + "Permite a aplicações escrever mensagens SMS armazenadas no seu telefone ou cartão SIM. Algumas aplicações maliciosas podem eliminar as suas mensagens." + "receber WAP" + "Permite à aplicação receber e processar mensagens WAP. Algumas aplicações maliciosas podem monitorizar ou eliminá-las sem mostrá-las ao utilizador." + "obter aplicações em execução" + "Permite à aplicação obter informações sobre tarefas actualmente em execução e recentemente executadas. Pode permitir que aplicações maliciosas descubram informações privadas sobre outras aplicações." + "reordenar aplicações em execução" + "Permite a uma aplicação mover tarefas do primeiro e do segundo planos. Algumas aplicações maliciosas podem impor-se no primeiro plano sem o controlo do utilizador." + "activar depuração da aplicação" + "Permite a uma aplicação activar a depuração para outra aplicação. Algumas aplicações maliciosas podem utilizar este item para eliminar outras aplicações." + "mudar definições da IU" + "Permite a uma aplicação mudar a configuração actual como, por exemplo, a região ou o tamanho global do tipo de letra." + "reiniciar outras aplicações" + "Permite a uma aplicação efectuar o reinício forçado de outras aplicações." + "forçar fecho da aplicação" + "Permite a uma aplicação forçar qualquer actividade em primeiro plano a fechar e retroceder. Nunca deve ser necessário para aplicações normais." + "obter estado interno do sistema" + "Permite à aplicação obter o estado interno do sistema. Algumas aplicações maliciosas podem obter uma ampla variedade de dados privados e seguros de que, normalmente, nunca devem necessitar." + + + + + + + + + "monitorizar a controlar a iniciação de todas as aplicações" + "Permite a uma aplicação monitorizar e controlar a forma como o sistema inicia actividades. Algumas aplicações maliciosas podem comprometer totalmente o sistema. Esta autorização apenas é necessária para desenvolvimento, nunca para a utilização normal do telefone." + "enviar difusão de pacote removido" + "Permite a uma aplicação difundir uma notificação de que foi removido um pacote de aplicações. Algumas aplicações maliciosas podem utilizar este item para eliminar qualquer outra aplicação em execução." + "enviar difusão recebida por SMS" + "Permite a uma aplicação difundir uma notificação de que foi recebida uma mensagem SMS. Algumas aplicações maliciosas podem utilizar este item para falsificar mensagens SMS a receber." + "enviar difusão recebida através de PUSH WAP" + "Permite a uma aplicação difundir uma notificação de que foi recebida uma mensagens PUSH WAP. Algumas aplicações maliciosas podem utilizar este item para falsificar um recibo de mensagem MMS ou substituir, de forma silenciosa, o conteúdo de qualquer página Web por variantes maliciosas." + "número limite de processos em execução" + "Permite a um aplicação controlar o número máximo de processos que será executado. Nunca é necessário para aplicações normais." + "fazer com que todas as aplicações de fundo fechem" + "Permite a uma aplicação controlar se as actividades são sempre terminadas assim que passam para o fundo. Nunca é necessário para aplicações normais." + "modificar estatísticas da bateria" + "Permite a modificação das estatísticas recolhidas sobre a bateria. Não se destina a utilização por aplicações normais." + + + + + "apresentar janelas não autorizadas" + "Permite a criação de janelas destinadas a utilização pela interface de utilizador interna do sistema. Não se destina a utilização por aplicações normais." + "apresentar alertas ao nível do sistema" + "Permite a um aplicação mostrar janelas de alerta do sistema. Algumas aplicações maliciosas podem ocupar todo o ecrã do telefone." + "modificar velocidade global da animação" + "Permite a uma aplicação mudar a velocidade global da animação (animações mais rápidas ou mais lentas) em qualquer altura." + "gerir tokens de aplicações" + "Permite a aplicações criar e gerir os seus próprios tokens, ignorando a ordenação normal dos mesmos pelo eixo dos Z. Nunca deve ser necessário para aplicações normais." + "premir teclas e botões de controlo" + "Permite a uma aplicação fornecer os seus próprios eventos de entrada (toques em teclas, etc.) a outras aplicações. Algumas aplicações maliciosas podem utilizar este item para controlar o telefone." + "gravar o que utilizador escreve e as acções que efectua" + "Permite às aplicações verificar as teclas que o utilizador prime, mesmo ao interagir com outras aplicações (como, por exemplo, ao introduzir uma palavra-passe). Nunca deve ser necessário para aplicações normais." + "vincular a um método de entrada" + "Permite ao titular vincular a interface de nível superior a um método de entrada de som. Nunca deve ser necessário para aplicações normais." + "mudar orientação do ecrã" + "Permite a uma aplicação mudar a rotação do ecrã em qualquer momento. Nunca deve ser necessário para aplicações normais." + "enviar sinais Linux para aplicações" + "Permite à aplicação pedir que o sinal fornecido seja enviado a todos os processos persistentes." + "fazer com que a aplicação seja sempre executada" + "Permite a uma aplicação tornar persistentes partes da mesma, para que o sistema não possa utilizá-la para outras aplicações." + "eliminar aplicações" + "Permite a uma aplicação eliminar pacotes do Android. Algumas aplicações maliciosas podem utilizar este item para eliminar aplicações importantes." + "eliminar dados de outras aplicações" + "Permite a uma aplicação limpar dados do proprietário." + "eliminar caches de outras aplicações" + "Permite a uma aplicação eliminar ficheiros em cache." + "medir espaço de armazenamento da aplicação" + "Permite a uma aplicação obter os respectivos código, dados e tamanhos de cache" + "instalar aplicações directamente" + "Permite a uma aplicação instalar pacotes novos ou actualizados do Android. Algumas aplicações maliciosas podem utilizar este item para adicionar novas aplicações com autorizações arbitrariamente fortes." + "eliminar todos os dados da aplicações" + "Permite a uma aplicação libertar espaço de armazenamento no telefone eliminando ficheiros no directório da cache da aplicação. Geralmente, o acesso é muito limitado para processamento do sistema." + "ler ficheiros de registo do sistema" + "Permite a uma aplicação ler a partir dos diversos ficheiros de registo do sistema. Isto permite descobrir informações gerais sobre a forma como o utilizador usa o telefone, mas estas não devem conter quaisquer dados pessoais ou privados." + "ler/escrever em recursos propriedade de diag" + "Permite a uma aplicação ler e escrever em qualquer recurso que seja propriedade do grupo diag. Por exemplo, ficheiros em /dev. Isto pode afectar potencialmente a estabilidade e a segurança do sistema e deve ser utilizado APENAS para diagnósticos específicos do hardware pelo fabricante ou pelo operador." + "activar ou desactivar componentes da aplicação" + "Permite a uma aplicação mudar a opção de activar ou não um componente de outra aplicação. Algumas aplicações maliciosas podem utilizar este item para desactivar funcionalidades importantes do telefone. É necessário ter cuidado com a autorização, uma vez que é possível tornar alguns componentes de aplicações num estado inutilizável, inconsistente ou instável." + "definir aplicações preferidas" + "Permite a uma aplicação modificar as suas aplicações preferidas. Isto pode permitir que algumas aplicações maliciosas mudem, de forma silenciosa, as aplicações executadas, falsificando as aplicações existentes para recolher os seus dados privados." + "modificar definições globais do sistema" + "Permite a uma aplicação modificar os dados das definições do sistema. Algumas aplicações maliciosas podem danificar as configurações do sistema." + "modificar definições seguras do sistema" + "Permite a uma aplicação modificar os dados de definições seguras dos sistemas. Não se destina a utilização por aplicações normais." + "modificar o mapa de serviços do Google" + "Permite a uma aplicação modificar o mapa de serviços do Google. Não se destina a utilização por aplicações normais." + "iniciar automaticamente no arranque" + "Permite que uma aplicação se inicie automaticamente assim que tiver terminado o arranque do sistema. Isto pode demorar o início do telefone e permitir à aplicação abrandar todo o funcionamento do telefone, uma vez que está em constante execução." + "enviar difusão fixa" + "Permite a uma aplicação enviar difusões fixas, que permanecem após o fim da difusão. Algumas aplicações maliciosas podem tornar o telefone lento ou instável, fazendo com que utilize demasiada memória." + "ler dados de contacto" + "Permite a uma aplicação ler todos os dados de contactos (endereços) armazenados no seu telefone. Algumas aplicações maliciosas podem utilizar este item para enviar os seus dados a outras pessoas." + "escrever dados de contacto" + "Permite a uma aplicação modificar os dados de contacto (endereço) armazenados no seu telefone. Algumas aplicações maliciosas podem utilizar estes dados para apagar ou modificar os dados dos seus contactos." + "escrever dados do proprietário" + "Permite a uma aplicação modificar os dados do proprietário do telefone armazenados no seu telefone. Algumas aplicações maliciosas podem utilizar este item para apagar ou modificar dados do proprietário." + "ler dados do proprietário" + "Permite a uma aplicação modificar os dados do proprietário do telefone armazenados no seu telefone. Algumas aplicações maliciosas podem utilizar este item para ler dados do proprietário do telefone." + "ler dados do calendário" + "Permite a uma aplicação ler todos os eventos do calendário armazenados no seu telefone. Algumas aplicações maliciosas podem utilizar este item para enviar os eventos do seu calendário a outras pessoas." + "escrever dados do calendário" + "Permite a uma aplicação modificar os eventos do calendário armazenados no seu telefone. Algumas aplicações maliciosas podem utilizar este item para apagar ou modificar os dados do seu calendário." + "fontes de localização fictícias para teste" + "Crie fontes de localização fictícias para fins de teste. Algumas aplicações maliciosas podem utilizar este item para substituir a localização e/ou o estado devolvido por fontes de localização reais, tais como fornecedores de GPS ou de Rede." + "aceder a comandos adicionais do fornecedor de localização" + "Aceda a comandos adicionais do fornecedor de localização. Algumas aplicações maliciosas podem utilizar este item para interferir com o funcionamento do GPS ou de outras fontes de localização." + + + + + "localização exacta (GPS)" + "Aceder a fontes de localização específicas, tais como o Sistema de Posicionamento Global (GPS), no telefone, se disponível. Algumas aplicações maliciosas podem utilizar este item para determinar a localização do utilizador e podem consumir energia adicional da bateria." + "localização aproximada (baseada na rede)" + "Aceda a fontes de localização aproximadas, tais como a base de dados da rede celular, para determinar uma localização aproximada do telefone, se disponível. Algumas aplicações maliciosas podem utilizar este item para determinar aproximadamente onde o utilizador se encontra." + "aceder a SurfaceFlinger" + "Permite às aplicações utilizar funcionalidades de SurfaceFlinger de nível inferior." + "ler memória intermédia de fotogramas" + "Permite·à·aplicação·ler·o·conteúdo·da·memória·intermédia·de·fotogramas." + "mudar as suas definições de áudio" + "Permite à aplicação modificar as definições de áudio globais, tais como o volume e o encaminhamento." + "gravar áudio" + "Permite à aplicação aceder ao caminho de gravação de áudio." + "tirar fotografias" + "Permite à aplicação tirar fotografias com a câmara. Isto permite que a aplicação recolha imagens captadas pela câmara em qualquer momento." + "desactivar telefone de forma permanente" + "Permite à aplicação desactivar permanentemente todo o telefone. Esta acção é muito perigosa." + "forçar reinício do telefone" + "Permite à aplicação forçar o reinício do telefone." + "montar e desmontar sistemas de ficheiros" + "Permite à aplicação montar e desmontar sistemas de ficheiros para armazenamento removível." + "formatar armazenamento externo" + "Permite a uma aplicação formatar o armazenamento removível." + "controlar vibrador" + "Permite à aplicação controlar o vibrador." + "controlar lanterna" + "Permite à aplicação controlar a lanterna." + "testar hardware" + "Permite à aplicação controlar vários periféricos para fins de teste de hardware." + "marcar números de telefone directamente" + "Permite à aplicação marcar números de telefone sem a intervenção do utilizador. Algumas aplicações maliciosas podem provocar o aparecimento de chamadas inesperadas na sua conta telefónica. Tenha em atenção que isto não permite à aplicação marcar números de emergência." + "marcar directamente quaisquer números de telefone" + "Permite à aplicação marcar qualquer número de telefone, incluindo números de emergência, sem a intervenção do utilizador. Algumas aplicações maliciosas podem efectuar chamadas desnecessárias e ilegais para serviços de emergência." + "controlar notificações de actualização de localização" + "Permite a activação/desactivação de notificações de actualização de localização a partir do rádio. Não se destina a utilização por aplicações normais." + "aceder a propriedades de verificação" + "Permite acesso de leitura/escrita a propriedades carregadas pelo serviço de verificação. Não se destina a utilização por aplicações normais." + "escolher miniaplicações" + "Permite à aplicação informar o sistema acerca das miniaplicações que podem ser utilizadas com cada aplicação. Com esta autorização, algumas aplicações podem conceder acesso a dados pessoais a outras aplicações. Não se destina a utilização por aplicações normais." + "modificar estado do telefone" + "Permite à aplicação controlar as funcionalidades do telefone do dispositivo. Uma aplicação com esta autorização pode alternar entre redes, ligar e desligar o rádio do telefone, etc., sem nunca notificar o utilizador." + "ler estado do telefone" + "Permite à aplicação aceder às funcionalidades do dispositivo. Uma aplicação com esta autorização pode determinar o número deste telefone, se existe uma chamada activa, o número a que a essa chamada está ligada, entre outras." + "impedir que o telefone entre em inactividade" + "Permite a uma aplicação impedir o telefone de entrar em inactividade." + "ligar ou desligar o telefone" + "Permite a uma aplicação ligar ou desligar o telefone." + "executar em modo de teste de fábrica" + "Executar como um teste de nível inferior do fabricante, permitindo o acesso total ao hardware do telefone. Apenas disponível quando um telefone está em execução em modo de teste do fabricante." + "definir imagem de fundo" + "Permite à aplicação definir a imagem de fundo do sistema." + "definir sugestões de tamanho da imagem de fundo" + "Permitir que a aplicação defina as sugestões de tamanho da imagem de fundo do sistema." + "repor definições de fábrica do sistemas" + "Permite a uma aplicação repor totalmente as definições de fábrica do sistema, apagando todos os dados, configurações e aplicações instaladas." + "definir fuso horário" + "Permite a uma aplicação mudar o fuso horário do telefone." + "descobrir contas reconhecidas" + "Permite a uma aplicação obter a lista de contas reconhecidas pelo telefone." + "ver estado da rede" + "Permite a uma aplicação ver o estado de todas as redes." + "acesso total à Internet" + "Permite a uma aplicação criar sockets de rede." + "escrever definições de Nome do ponto de acesso" + "Permite a uma aplicaçaõ modificar as definições de APN, tais como Proxy e Porta de qualquer APN." + "mudar conectividade de rede" + "Permite a uma aplicação mudar o estado da conectividade de rede." + "mudar definição de utilização de dados de segundo plano" + "Permite a uma aplicação mudar a definição de utilização de dados de segundo plano." + "ver estado de Wi-Fi" + "Permite a uma aplicação ver as informações acerca do estado do Wi-Fi." + "mudar estado de Wi-Fi" + "Permite a uma aplicação ligar e desligar de pontos de acesso de Wi-Fi, bem como efectuar alterações a redes Wi-Fi configuradas." + + + + + "administração de bluetooth" + "Permite a uma aplicação configurar o telefone Bluetooth local, bem como descobrir e emparelhar com dispositivos remotos." + "criar ligações Bluetooth" + "Permite a uma aplicação ver a configuração do telefone Bluetooth local, bem como efectuar e aceitar ligações com dispositivos emparelhados." + "desactivar bloqueio de teclas" + "Permite a uma aplicação desactivar o bloqueio de teclas e qualquer segurança por palavra-passe associada. Um exemplo legítimo é a desactivação do bloqueio de teclas pelo telefone ao receber uma chamada, reactivando, em seguida, o bloqueio de teclas ao terminar a chamada." + "ler definições de sincronização" + "Permite a uma aplicação ler as definições de sincronização como, por exemplo, se a sincronização está activada para Contactos." + "definições de sincronização de escrita" + "Permite a uma aplicação modificar as definições de sincronização como, por exemplo, se a sincronização está activada para Contactos." + "ler estatísticas de sincronização" + "Permite a uma aplicação ler as estatísticas de sincronização, por exemplo, o histórico de sincronizações ocorridas." + "ler feeds subscritos" + "Permite a uma aplicação obter detalhes acerca dos feeds actualmente sincronizados." + "escrever feeds subscritos" + "Permite a uma aplicação modificar os seus feeds actualmente sincronizados. Isto pode permitir a uma aplicação maliciosa alterar os seus feeds sincronizados." + "ler dicionário definido pelo utilizador" + "Permite a uma aplicação ler quaisquer palavras, nomes e expressões privadas que o utilizador possa ter armazenado no dicionário do utilizador." + "escrever no dicionário definido pelo utilizador" + "Permite a uma aplicação escrever novas palavras no dicionário do utilizador." + + + + + + "Residência" + "Móvel" + "Emprego" + "Fax do emprego" + "Fax da residência" + "Pager" + "Outro" + "Personalizado" + + + "Residência" + "Emprego" + "Outro" + "Personalizado" + + "Móvel" + + "Residência" + "Emprego" + "Outro" + "Personalizado" + + + "Residência" + "Emprego" + "Outro" + "Personalizado" + + + "Emprego" + "Outro" + "Personalizado" + + + "AIM" + "Windows Live" + "Yahoo" + "Skype" + "QQ" + "Google Talk" + "ICQ" + "Jabber" + + "Introduzir código PIN" + "Código PIN incorrecto!" + "Para desbloquear, prima Menu e, em seguida, 0." + "Número de emergência" + "(Nenhum serviço)" + "Ecrã bloqueado." + "Prima Menu para desbloquear ou efectuar uma chamada de emergência." + "Prima Menu para desbloquear." + "Desenhar padrão para desbloquear" + "Chamada de emergência" + "Correcto!" + "Lamentamos, tente novamente" + "A carregar (%d%%)" + + + "Ligue o carregador." + "Nenhum cartão SIM." + "Nenhum cartão SIM no telefone." + "Introduza um cartão SIM." + "Rede bloqueada" + "O cartão SIM está bloqueado por PUK" + "Consulte o Manual de utilizador ou contacte a Assistência a clientes." + "O cartão SIM está bloqueado." + "A desbloquear cartão SIM..." + "Efectuou incorrectamente o seu padrão de desbloqueio %d vezes. "\n\n"Tente novamente dentro de %d segundos." + "Efectuou incorrectamente o seu padrão de desbloqueio %d vezes. Após outras %d tentativas sem sucesso, ser-lhe-á pedido para desbloquear o telefone utilizando o seu início de sessão no Google."\n\n" Tente novamente dentro de %d segundos." + "Tente novamente dentro de %d segundos." + "Esqueceu-se do padrão?" + "Demasiadas tentativas de efectuar o padrão!" + "Para desbloquear, inicie sessão com a sua Conta Google" + "Nome de utilizador (e-mail)" + "Palavra-passe" + "Iniciar sessão" + "Nome de utilizador ou palavra-passe inválidos." + "%-l %P" + "%-l %p" + + + "Sem notificações" + "Em curso" + "Notificações" + "%d %%" + "A carregar..." + "Ligue o carregador" + "A bateria está a ficar fraca:" + "resta menos de %d%%." + + + "O teste de fábrica falhou" + "A acção FACTORY_TEST apenas é suportada para pacotes instalados em /system/app." + "Não foi localizado qualquer pacote que forneça a acção FACTORY_TEST." + "Reiniciar" + "A página em \"%s\" indica:" + "JavaScript" + "Navegar para outra página?"\n\n"%s"\n\n"Seleccione OK para continuar ou Cancelar para permanecer na página actual." + "Confirmar" + + + + + + + + + "Quer que o browser memorize esta palavra-passe?" + "Agora não" + "Lembrar" + "Nunca" + "Não tem autorização para abrir esta página." + "Texto copiado para a área de transferência." + "Mais" + "Menu+" + "espaço" + "introduzir" + "eliminar" + "Pesquisar" + "Há 1 mês" + "Há·mais·de·1·mês" + + "Há 1 segundo" + "Há %d segundos" + + + "Há 1 minuto" + "Há %d minutos" + + + "Há 1 hora" + "Há %d horas" + + + "ontem" + "Há %d dias" + + + "daqui a 1 segundo" + "daqui a %d segundos" + + + "daqui a 1 minuto" + "daqui a %d minutos" + + + "daqui a 1 hora" + "daqui a %d horas" + + + "amanhã" + "daqui a %d dias" + + + "Há 1 seg" + "Há %d seg" + + + "há 1 min" + "Há %d min" + + + "Há 1 hora" + "Há %d horas" + + + "ontem" + "Há %d dias" + + + "daqui a 1 seg" + "daqui a %d seg" + + + "daqui a 1 min" + "daqui a %d min" + + + "daqui a 1 hora" + "em %d horas" + + + "amanhã" + "daqui a %d dias" + + "a %s" + "às %s" + "em %s" + "dia" + "dias" + "hora" + "horas" + "minutos" + "min" + "seg" + "seg" + "semana" + "semanas" + "ano" + "anos" + "Todos os dias úteis (Seg-Sex)" + "Diariamente" + "Semanalmente à/ao %s" + "Mensalmente" + "Anualmente" + "Impossível reproduzir vídeo" + "Lamentamos, este vídeo não é válido para transmissão em sequência neste dispositivo." + "Lamentamos, não é possível reproduzir este vídeo." + "OK" + "%1$s, %2$s" + "meio-dia" + "Meio-dia" + "meia-noite" + "Meia-noite" + "%1$02d:%2$02d" + "%1$d:%2$02d:%3$02d" + "Seleccionar tudo" + "Seleccionar texto" + "Parar selecção de texto" + "Cortar" + "Cortar tudo" + "Copiar" + "Copiar tudo" + "Colar" + "Copiar URL" + "Método de entrada" + "Adicionar \"%s\" ao dicionário" + "Editar texto" + "Pouco espaço livre" + "O espaço de armazenamento do telefone está a ficar reduzido." + "OK" + "Cancelar" + "OK" + "Cancelar" + "Atenção" + "Activado" + "Desactivar" + "Concluir acção utilizando" + "Utilizar por predefinição para esta acção." + "Limpar predefinição em Definições iniciais > Aplicações > Gerir aplicações." + "Seleccionar uma acção" + "Nenhuma aplicação pode efectuar esta acção." + "Lamentamos." + "A aplicação %1$s (processo %2$s) parou de forma inesperada. Tente novamente." + "O processo %1$s parou de forma inesperada. Tente novamente." + "Lamentamos!" + "A actividade %1$s (na aplicação %2$s) não está a responder." + "A actividade %1$s (no processo %2$s) não está a responder." + "A aplicação %1$s (no processo %2$s) não está a responder." + "O processo %1$s não está a responder." + "Forçar fecho" + + + "Esperar" + "Depuração" + "Seleccionar uma acção para texto" + "Volume da campainha" + "Volume de multimédia" + "A reproduzir através de Bluetooth" + "Volume da chamada recebida" + "Volume de chamada recebida em Bluetooth" + "Volume do alarme" + "Volume de notificações" + "Volume" + "Toque predefinido" + "Toque predefinido (%1$s)" + "Silencioso" + "Toques" + "Toque desconhecido" + + "Rede Wi-Fi disponível" + "Redes Wi-Fi disponíveis" + + + "Rede Wi-Fi aberta disponível" + "Abrir redes Wi-Fi disponíveis" + + "Introduzir carácter" + "Aplicação desconhecida" + "A enviar mensagens SMS" + "Está a ser enviado um grande número de mensagens SMS. Seleccione \"OK\" para continuar ou \"Cancelar\" para parar o envio." + "OK" + "Cancelar" + "Definir" + "Predefinido" + "Não são necessárias permissões" + "Ocultar" + "Mostrar tudo" + "A carregar..." + "Ligado através de USB" + "Ligou o telefone ao computador através de USB. Seleccione \"Montar\" se pretender copiar ficheiros entre o computador e o cartão SD do telefone." + "Montar" + "Não montar" + "Existe um problema ao utilizar o cartão SD para armazenamento USB." + "Ligado através de USB" + "Seleccione para copiar ficheiro para/do seu computador." + "Desactivar armazenamento USB" + "Opte por desactivar o armazenamento USB." + "Desactivar armazenamento USB" + "Antes de desactivar o armazenamento USB, certifique-se de que o desmontou no anfitrião USB. Seleccione \"Desactivar\" para desactivar o armazenamento USB." + "Desactivar" + "Cancelar" + "Detectámos um problema ao desactivar o armazenamento USB. Verifique para se certificar de que desmontou o anfitrião USB e, em seguida, tente novamente." + "Formatar cartão SD" + "Tem a certeza de que pretende formatar o cartão SD? Perder-se-ão todos os dados no cartão." + "Formatar" + + + + + "Seleccionar método de entrada" + " ABCDEFGHIJKLMNOPQRSTUVWXYZ" + " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "candidatos" + "A preparar cartão SD" + + + "Cartão SD vazio" + + + "Cartão SD danificado" + + + "Cartão SD removido de forma inesperada" + "Desmonte o cartão SD antes de retirá-lo para evitar a perda de dados." + "É seguro retirar o cartão SD" + + + "Cartão SD removido" + + + "Nenhuma actividade correspondente encontrada" + "actualizar estatísticas de utilização de componentes" + "Permite a modificação de estatísticas de utilização de componentes recolhidas. Não se destina a utilização por aplicações normais." + "Tocar duas vezes para controlar o zoom" + "Erro ao inchar miniaplicação" + "Ir" + "Pesquisar" + "Enviar" + "Seguinte" + "Concluído" + "Executar" + "Marcar número"\n"utilizando %s" + "Criar contacto"\n"utilizando %s" + + + + + diff --git a/core/res/res/values-pt/donottranslate-cldr.xml b/core/res/res/values-pt/donottranslate-cldr.xml index 47290552dd2e1..1111658ffb907 100644 --- a/core/res/res/values-pt/donottranslate-cldr.xml +++ b/core/res/res/values-pt/donottranslate-cldr.xml @@ -95,7 +95,7 @@ %-l:%M %p %-l:%M %^p h:mm a - H'h'mm + H\'h\'mm %d/%m/%Y dd/MM/yyyy "%s/%s/%s" diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index c5c5bbbdf66e6..97d7596b690b9 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -16,11 +16,13 @@ "B" - "KB" + "Kb" "MB" "GB" "TB" "PB" + + "<sem título>" "…" "(Nenhum número de telefone)" @@ -31,23 +33,23 @@ "O serviço foi ativado." "O serviço foi ativado para:" "O serviço foi desativado." - "O registro foi bem-sucedido." + "Registro bem-sucedido." "Exclusão bem-sucedida." - "Senha incorreta" - "MMI completo." + "Senha incorreta." + "MMI concluído." "O PIN antigo digitado não está correto." "O PUK digitado não está correto." "Os PINs digitados não correspondem." "Digite um PIN com 4 a 8 números." - "Seu cartão SIM está bloqueado pelo código PUK. Digite o PUK para desbloqueá-lo." - "Digite PUK2 para desbloquear cartão SIM." - "ID do chamador" - "ID de quem realiza a chamada" - "Transferência de chamada" + "O seu cartão SIM está bloqueado por um PUK. Digite o código PUK para desbloqueá-lo." + "Digite o PUK2 para desbloquear o cartão SIM." + "ID do chamador de entrada" + "ID do chamador de saída" + "Encaminhamento de chamada" "Chamada em espera" - "Bloqueio de chamada" + "Bloqueio de chamadas" "Alteração da senha" - "Alteração de PIN" + "Alteração do PIN" @@ -60,22 +62,17 @@ - "ID do chamador assume o padrão de restrito. Próxima chamada: restrita" - "ID do chamador assume o padrão de restrito. Próxima chamada: não restrita" - "ID do chamador assume o padrão de não restrito. Próxima chamada: restrita" - "ID do chamador assume o padrão de não restrito. Próxima chamada: não restrita" - "Serviço não fornecido" - "A configuração da ID do chamador não pode ser alterada." - - - - - - - - - - + "O ID do chamador assume o padrão de restrito. Próxima chamada: Restrita" + "O ID do chamador assume o padrão de restrito. Próxima chamada: Não restrita" + "O ID do chamador assume o padrão de não restrito. Próxima chamada: Restrita" + "O ID do chamador assume o padrão de não restrito. Próxima chamada: Não restrita" + "O serviço não foi habilitado." + "A configuração do ID do chamador não pode ser alterada." + "Acesso restrito alterado" + "O serviço de dados está bloqueado." + "O serviço de emergência está bloqueado." + "O serviço de voz/SMS está bloqueado." + "Todos os serviços de voz/SMS estão bloqueados." "Voz" "Dados" "FAX" @@ -112,11 +109,11 @@ - "{0}: Não transferido" + "{0}: Não encaminhado" "{0}: {1}" "{0}: {1} após {2} segundos" - "{0}: Não transferido" - "{0}: Não transferido" + "{0}: Não encaminhado" + "{0}: Não encaminhado" @@ -124,104 +121,102 @@ "OK" "A página da web contém um erro." "Não foi possível encontrar o URL." - "O esquema de autenticação não é suportado." + "O esquema de autenticação do site não é suportado." "Falha na autenticação." - "Falha na autenticação pelo servidor proxy." + "Falha na autenticação por meio do servidor proxy." "Falha na conexão com o servidor." - "Falha de comunicação com o servidor. Tente novamente mais tarde." - "Tempo limite da conexão com o servidor esgotado." + "Falha de comunicação do servidor. Tente novamente mais tarde." + "O tempo limite de conexão com o servidor esgotou." "A página contém muitos redirecionamentos do servidor." "O protocolo não é suportado." "Não foi possível estabelecer uma conexão segura." - "A página não pode ser aberta, pois o URL é inválido." + "Não foi possível abrir a página porque o URL é inválido." "Não foi possível acessar o arquivo." "O arquivo solicitado não foi encontrado." - "Muitas solicitações sendo processadas. Tente novamente mais tarde." + "Há muitas solicitações sendo processadas. Tente novamente mais tarde." + + "Sincronizar" "Sincronizar" - "Muitas exclusões do %s." + "Muitas exclusões de %s." "O armazenamento do telefone está cheio! Exclua alguns arquivos para liberar espaço." "Eu" "Opções do telefone" "Modo silencioso" - "Ativar rede sem fio" + "Ativar sem fio" "Desativar a rede sem fio" - "Bloqueio de tela" + "Bloquear tela" "Desligar" - "Desligando…" - "Seu telefone desligará" + "Encerrando…" + "O seu telefone será desligado." "Nenhum aplicativo recente." "Opções do telefone" - "Bloqueio de tela" + "Bloquear tela" "Desligar" "Modo silencioso" - "O som está DESLIGADO" + "Som DESATIVADO" "O som está ATIVADO" - - - - - - + "Modo de avião" + "Modo de avião ATIVADO" + "Modo de avião DESATIVADO" "Modo de segurança" - - - "Serviços que custam dinheiro" - "Permite que os aplicativos façam coisas que podem custar dinheiro." + "Sistema Android" + "Serviços que geram gastos" + "Permite que os aplicativos façam coisas que possam gerar gastos." "Suas mensagens" - "Ler e gravar suas mensagens SMS, e-mail e outras mensagens." + "Lê e grava o seu SMS, e-mail e outras mensagens." "Suas informações pessoais" - "Acesso direto aos seus contatos e calendário armazenados no telefone." - "Sua localização" - "Monitore seu local físico" - "Comunicação de rede" + "Acessa diretamente os seus contatos e agenda armazenados no telefone." + "Seu local" + "Monitora o seu local físico." + "Comunicação da rede" "Permite que os aplicativos acessem diversos recursos de rede." - "Suas contas do Google" - "Acesse as contas do Google disponíveis." + "Suas Contas do Google" + "Acessar as Contas do Google disponíveis." "Controles de hardware" - "Acesso direto ao hardware no handset." + "Acessa o hardware diretamente no aparelho." "Chamadas telefônicas" - "Monitorar, registrar e processar chamadas telefônicas." + "Monitora, registra e processa chamadas telefônicas." "Ferramentas do sistema" "Acesso de nível inferior e controle do sistema." "Ferramentas de desenvolvimento" - "Recursos necessários apenas aos desenvolvedores de aplicativo." + "Recursos necessários apenas para desenvolvedores de aplicativo." "desativar ou modificar a barra de status" - "Permite que os aplicativos desativem a barra de status ou adicionem e removam ícones do sistema." + "Permite que o aplicativo desative a barra de status ou adicione e remova ícones do sistema." "expandir/recolher barra de status" - "Permite que um aplicativo expanda ou recolha a barra de status." - "Interceptar chamadas realizadas" - "Permite que aplicativos processem chamadas realizadas e alterem o número a ser discado. Aplicativos maliciosos podem monitorar, redirecionar ou impedir chamadas realizadas." + "Permite que o aplicativo expanda ou recolha a barra de status." + "interceptar chamadas enviadas" + "Permite que o aplicativo processe chamadas enviadas e altere o número a ser discado. Aplicativos maliciosos podem monitorar, redirecionar ou impedir a realização de chamadas." "receber SMS" - "Permite que o aplicativo receba e processe mensagens SMS. Aplicativos maliciosos podem monitorar suas mensagens ou excluí-las sem mostrá-las a você." + "Permite que o aplicativo receba e processe mensagens SMS. Aplicativos maliciosos podem monitorar as suas mensagens ou excluí-las sem mostrá-las a você." "receber MMS" - "Permite que o aplicativo receba e processe mensagens MMS. Aplicativos maliciosos podem monitorar suas mensagens ou excluí-las sem mostrá-las a você." + "Permite que o aplicativo receba e processe mensagens MMS. Aplicativos maliciosos podem monitorar as suas mensagens ou excluí-las sem mostrá-las a você." "enviar mensagens SMS" - "Permite que os aplicativos enviem mensagens SMS. Os aplicativos maliciosos podem causar prejuízo financeiro a você ao enviar mensagens sem a sua confirmação." + "Permite que o aplicativo envie mensagens SMS. Aplicativos maliciosos podem gerar gastos enviando mensagens sem a sua confirmação." "ler SMS ou MMS" - "Permite que um aplicativo leia mensagens SMS armazenadas no seu telefone ou cartão SIM. Aplicativos maliciosos podem ler suas mensagens confidenciais." + "Permite que o aplicativo leia mensagens SMS armazenadas no seu telefone ou cartão SIM. Aplicativos maliciosos podem ler as suas mensagens confidenciais." "editar SMS ou MMS" - "Permite que um aplicativo grave mensagens SMS armazenadas no seu telefone ou cartão SIM. Aplicativos maliciosos podem excluir suas mensagens." + "Permite que o aplicativo grave mensagens SMS armazenadas no seu telefone ou cartão SIM. Aplicativos maliciosos podem excluir suas mensagens." "receber WAP" - "Permite que o aplicativo receba e processe mensagens WAP. Aplicativos maliciosos podem monitorar suas mensagens ou excluí-las sem mostrá-las a você." + "Permite que o aplicativo receba e processe mensagens WAP. Aplicativos maliciosos podem monitorar as suas mensagens ou excluí-las sem mostrá-las a você." "recuperar aplicativos em execução" - "Permite que os aplicativos recuperem informações sobre as tarefas em execução no momento ou recentemente. Pode permitir que aplicativos maliciosos descubram informações particulares sobre outros aplicativos." - "reorganizar os aplicativos em execução" - "Permite que um aplicativo mova as tarefas para o primeiro ou segundo plano. Os aplicativos maliciosos podem forçar sua permanência no primeiro plano sem o seu controle." + "Permite que o aplicativo recupere as informações sobre tarefas em execução no momento ou recentemente. Pode permitir que aplicativos maliciosos descubram informações particulares sobre outros aplicativos." + "reorganizar aplicativos em execução" + "Permite que um aplicativo mova as tarefas para o primeiro e para o segundo planos. Aplicativos maliciosos podem se forçar à frente sem o seu controle." "ativar depuração do aplicativo" "Permite que um aplicativo ative a depuração de outro aplicativo. Aplicativos maliciosos podem usar isso para encerrar outros aplicativos." - "alterar as configurações da sua IU" - "Permite que um aplicativo mude a configuração atual, como a localidade ou o tamanho geral de fonte." + "alterar as suas configurações de UI" + "Permite que um aplicativo altere a configuração atual, como a localidade ou tamanho geral da fonte." "reiniciar outros aplicativos" - "Permite que um aplicativo reinicie outros aplicativos forçosamente." + "Permite que um aplicativo reinicie forçosamente outros aplicativos." "forçar fechamento do aplicativo" - "Permite que um aplicativo force qualquer atividade que esteja em primeiro plano a fechar e voltar. Normalmente não é necessário para aplicativos normais." - "recuperar estado interno do sistema" - "Permite que um aplicativo recupere o estado interno do sistema. Aplicativos maliciosos podem recuperar um ampla variedade de informações privadas e seguras, as quais não deveriam precisar normalmente." + "Permite que um aplicativo force o fechamento de qualquer atividade que esteja em primeiro plano. Aplicativos normais não devem precisar disso em momento algum." + "recuperar o estado interno do sistema" + "Permite que um aplicativo recupere o estado interno do sistema. Aplicativos maliciosos podem recuperar uma grande variedade de informações privadas e de segurança que normalmente não precisariam." @@ -230,238 +225,227 @@ - "monitorar e controle toda inicialização de aplicativo" - "Permite que um aplicativo monitore e controle como o sistema inicia as atividades. Os aplicativos maliciosos podem comprometer completamente o sistema. Esta permissão é necessária apenas para desenvolvimento, nunca para uso normal do telefone." - "enviar transmissão de pacote removido" - "Permite que um aplicativo transmita uma notificação de que o pacote de um aplicativo foi removido. Aplicativos maliciosos podem usar isso para encerrar outro aplicativo em execução." - "enviar transmissão de SMS recebido" + "monitorar e controlar toda inicialização de aplicativo" + "Permite que um aplicativo monitore e controle a maneira como o sistema inicia as atividades. Aplicativos maliciosos podem comprometer todo o sistema. Essa permissão é necessária apenas para desenvolvimento, nunca para uso normal do telefone." + "enviar transmissão removida do pacote" + "Permite que um aplicativo transmita uma notificação informando que um pacote de aplicativo foi removido. Aplicativos maliciosos podem usar isso para encerrar qualquer outro aplicativo em execução." + "enviar transmissão SMS recebida" "Permite que um aplicativo transmita uma notificação de que uma mensagem SMS foi recebida. Aplicativos maliciosos podem usar isso para forjar o recebimento de mensagens SMS." - "enviar transmissão de WAP-PUSH recebido" - "Permite que um aplicativo transmita uma notificação de que uma mensagem WAP PUSH foi recebida. Aplicativos maliciosos podem usar isso para forjar o recebimento de uma mensagem MMS ou substituir silenciosamente o conteúdo de qualquer página da web por variantes maliciosas." - "limitar o número de processos em execução" - "Permite que um aplicativo controle o número máximo de processos que serão executados. Nunca é necessário para aplicativos normais." - "fazer todos os aplicativos em segundo plano fechar" - "Permite que um aplicativo controle se as atividades são sempre concluídas assim que vão para o segundo plano. Nunca é necessário para aplicativos normais." - "Modificar as estatísticas da bateria" - "Permite a modificação das estatísticas coletadas sobre a bateria. Não deve ser usado em aplicativos normais." + "enviar transmissão WAP-PUSH recebida" + "Permite que um aplicativo transmita uma notificação de que uma mensagem WAP PUSH foi recebida. Aplicativos maliciosos podem usar isso para forjar o recebimento de mensagem MMS ou substituir silenciosamente o conteúdo de qualquer página da web por variantes maliciosas." + "limitar número de processos em execução" + "Permite que um aplicativo controle o número máximo de processos que serão executados. Aplicativos normais não precisam disso em momento algum." + "fechar todos os aplicativos em segundo plano" + "Permite que um aplicativo controle se as atividades são sempre concluídas assim que vão para o segundo plano. Aplicativos normais não precisam disso em momento algum." + "modificar estatísticas da bateria" + "Permite a modificação das estatísticas de bateria coletadas. Não deve ser usado por aplicativos normais." "exibir janelas não autorizadas" - "Permite a criação de janelas que devem ser usadas pela interface de usuário do sistema interno. Normalmente não é necessário para aplicativos normais." - "exibir alertas do nível do sistema" + "Permite a criação de janelas destinadas ao uso pela interface de usuário do sistema interno. Não deve ser usado por aplicativos normais." + "exibir alertas de nível do sistema" "Permite que um aplicativo mostre janelas de alerta do sistema. Aplicativos maliciosos podem assumir o controle de toda a tela do telefone." - "modificar a velocidade de animação global" - "Permite que um aplicativo altere a velocidade de animação global (animações mais rápidas ou mais lentas) a qualquer momento." - "gerenciar os símbolos do aplicativo" - "Permite que um aplicativo crie e gerencie seus próprio símbolos, ignorando a ordem-Z (Z-ordering). Normalmente não é necessário para aplicativos normais." + "modificar velocidade de animação global" + "Permite que um aplicativo altere a velocidade de animação global (animação mais rápida ou mais lenta) a qualquer momento." + "gerenciar tokens do aplicativo" + "Permite que os aplicativos criem e gerenciem seus próprios tokens, ignorando a ordem Z normal. Aplicativos normais não devem precisar disso em momento algum." "pressionar as teclas e os botões de controle" - "Permite que um aplicativo proporcione seus próprios eventos de entrada (pressionamentos de tecla etc.) a outros aplicativos. Aplicativos maliciosos podem usar isso para assumir o controle do telefone." - "registrar o que você digita e as ações que executa" - "Permite que os aplicativos observem as teclas que você pressiona ao interagir com outro aplicativo (como ao digitar uma senha). Normalmente não é necessário para aplicativos normais." - "aderir a um método de entrada" - "Permite que o portador se vincule à interface de nível superior de um método de entrada. Normalmente não é necessário em aplicativos normais." + "Permite que um aplicativo use seus próprios eventos de entrada (pressionamentos de teclas etc.) em outros aplicativos. Aplicativos maliciosos podem usar isso para assumir o controle do telefone." + "registrar o que você digita e as ações que realiza" + "Permite que os aplicativos vejam as teclas que você pressiona, mesmo quando estiver interagindo com outro aplicativo (como ao digitar uma senha). Aplicativos normais não devem precisar disso em momento algum." + "vincular a um método de entrada" + "Permite que o detentor se sujeite à interface de nível superior de um método de entrada. Aplicativos normais não devem precisar disso em momento algum." "alterar orientação da tela" - "Permite que um aplicativo altere a rotação da tela a qualquer momento. Normalmente não é necessário para aplicativos normais." - "enviar sinais de Linux aos aplicativos" + "Permite que um aplicativo altere a rotação da tela a qualquer momento. Aplicativos normais não devem precisar disso em momento algum." + "enviar sinais de Linux para os aplicativos" "Permite que o aplicativo solicite que o sinal fornecido seja enviado a todos os processos persistentes." - "fazer com que o aplicativo execute sempre" - "Permite que um aplicativo torne partes dele mesmo persistentes, para que o sistema não possa usá-lo para outros aplicativos." + "executar sempre o aplicativo" + "Permite que um aplicativo torne partes de si mesmo persistentes, de modo que o sistema não possa usar essas partes para outros aplicativos." "excluir aplicativos" "Permite que um aplicativo exclua pacotes do Android. Aplicativos maliciosos podem usar isso para excluir aplicativos importantes." - "excluir os dados de outros aplicativos" + "excluir dados de outros aplicativos" "Permite que um aplicativo limpe os dados do usuário." - "excluir o cache de outros aplicativos" - "Permite que um aplicativo exclua arquivos armazenados em cache." - "medir o espaço de armazenamento do aplicativo" - "Permite que um aplicativo recupere seu código, dados e tamanho de cache" - "instalar os aplicativos diretamente" - "Permite que um aplicativo instale pacotes novos ou atualizados do Android. Aplicativos maliciosos podem usar isso para adicionar novos aplicativos com permissões aleatórias avançadas." - "excluir todos os dados do cache do aplicativo" - "Permite que um aplicativo libere espaço de armazenamento do telefone excluindo arquivos no diretório de cache do aplicativo. O acesso é normalmente restrito ao processo do sistema." - "ler arquivos do registro do sistema" - "Permite que um aplicativo leia os diversos arquivos de registro do sistema. Isso permite que ele descubra informações gerais sobre o que você está fazendo com o telefone, mas esses arquivos não devem conter informações pessoais ou privadas." - "ler/gravar em recursos que pertencem ao diagnóstico" - "Permite que um aplicativo leia e grave em qualquer recurso que pertença ao grupo diag; por exemplo, arquivos em /dev. Isso poderia afetar a estabilidade e a segurança do sistema. Por isso, SÓ deve ser usado para diagnósticos específicos do hardware pelo fabricante ou operador." - "ativar ou desativar componentes do aplicativo" - "Permite que um aplicativo altere a ativação ou desativação de um componente de outro aplicativo. Aplicativos maliciosos podem usar isso para desativar recursos importantes do telefone. É preciso ter permissão e cuidado no uso, pois é possível deixar os componentes do aplicativo em um estado inutilizável, inconsistente ou instável." - "definir aplicativos preferidos" - "Permite que um aplicativo modifique seus aplicativos preferidos. Isso pode permitir que aplicativos maliciosos alterem silenciosamente os aplicativos em execução, falsificando seus aplicativos existentes para coletar seus dados privados." + "excluir os caches de outros aplicativos" + "Permite que um aplicativo exclua os arquivos do cache." + "medir espaço de armazenamento do aplicativo" + "Permite que um aplicativo recupere seu código, seus dados e os tamanhos do cache." + "instalar diretamente os aplicativos" + "Permite que um aplicativo instale pacotes novos ou atualizados do Android. Aplicativos maliciosos podem usar isso para adicionar novos aplicativos com permissões arbitrariamente avançadas." + "excluir todos os dados de cache do aplicativo" + "Permite que um aplicativo libere o espaço de armazenamento do telefone excluindo arquivos no diretório de cache do aplicativo. O acesso é normalmente muito restrito para o processo do sistema." + "ler arquivos de registro do sistema" + "Permite que um aplicativo leia os diversos arquivos de registro do sistema. Isso permite que ele descubra informações gerais sobre o que você está fazendo com o telefone, porém esses arquivos não devem conter informações pessoais ou privadas." + "ler/gravar em recursos pertencentes ao diag" + "Permite que um aplicativo leia e grave em qualquer recurso que pertença ao grupo de diagnósticos; por exemplo, arquivos em /dev. Isso possivelmente pode afetar a estabilidade e a segurança do sistema. Isso deve ser usado APENAS para diagnósticos específicos do hardware realizados pelo fabricante ou pelo operador." + "ativar ou desativar os componentes do aplicativo" + "Permite que um aplicativo altere se um componente de outro aplicativo está ativado ou não. Aplicativos maliciosos podem usar isso para desativar recursos de telefone importantes. É preciso ter cuidado com a permissão, pois é possível deixar os componentes do aplicativo em um estado inutilizável, inconsistente ou instável." + "definir os aplicativos preferidos" + "Permite que um aplicativo modifique os seus aplicativos preferidos. Isso pode permitir que aplicativos maliciosos alterem silenciosamente os aplicativos em execução, falsificando os seus aplicativos existentes para coletar os seus dados particulares." "modificar configurações globais do sistema" - "Permite que um aplicativo modifique os dados da configuração do sistema. Aplicativos maliciosos podem corromper a configuração do sistema." - "modificar configurações de segurança do sistema" - "Permite que um aplicativo modifique os dados das configurações de segurança dos sistemas. Não deve ser usado em aplicativos normais." + "Permite que um aplicativo modifique os dados de configuração do sistema. Aplicativos maliciosos podem corromper a configuração do seu sistema." + "modificar configurações do sistema de segurança" + "Permite que um aplicativo modifique os dados de configuração de segurança dos sistemas. Não deve ser usado por aplicativos normais." "modificar o mapa de serviços do Google" - "Permite que um aplicativo modifique o mapa de serviços do Google. Não deve ser usado em aplicativos normais." + "Permite que um aplicativo modifique o mapa de serviços do Google. Não deve ser usado por aplicativos normais." "iniciar automaticamente na inicialização" - "Permite que um aplicativo se inicie assim que o sistema termina de inicializar. Isso pode causar uma demora na inicialização do telefone e faz com que todo o telefone fique mais lento pela execução contínua do aplicativo." - "enviar transmissão complexa" - "Permite que um aplicativo envie transmissões persistentes, as quais permanecem após o término da transmissão. Aplicativos maliciosos podem tornar o telefone lento ou instável fazendo com que use muita memória." - "ler dados de contato" - "Permite que um aplicativo leia todos os dados de contato (endereço) armazenados no telefone. Aplicativos maliciosos podem usar isso para enviar seus dados a outras pessoas." + "Permite que um aplicativo inicie assim que o sistema conclui a inicialização. Isso pode retardar a inicialização do telefone e permitir que o aplicativo deixe o telefone mais lento por estar sempre em execução." + "enviar transmissão persistente" + "Permite que um aplicativo envie uma transmissão persistente, que permanece após o término da transmissão. Aplicativos maliciosos podem tornar o telefone lento ou instável fazendo com que ele use muita memória." + "ler dados do contato" + "Permite que um aplicativo leia todos os dados de contato (endereço) armazenados no seu telefone. Aplicativos maliciosos podem usar isso para enviar os seus dados para outras pessoas." "gravar dados de contato" - "Permite que um aplicativo modifique os dados de contato (endereço) armazenados no telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar seus dados de contato." + "Permite que um aplicativo modifique os dados de contato (endereço) armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar os seus dados de contato." "gravar dados do proprietário" - "Permite que um aplicativo modifique os dados do proprietário do telefone armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar os dados do proprietário." + "Permite que um aplicativo modifique os dados de proprietário do telefone armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar dados do proprietário." "ler dados do proprietário" - "Permite que um aplicativo leia os dados do proprietário do telefone armazenados no seu telefone. Aplicativos maliciosos podem usar isso para ler os dados do proprietário." - "ler os dados do calendário" - "Permite que um aplicativo leia todos os eventos de calendário armazenados no seu telefone. Aplicativos maliciosos podem usar isso para enviar os eventos do seu calendário a outras pessoas." - "gravar dados do calendário" - "Permite que um aplicativo modifique os eventos do calendário armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar seus dados de contato." - "imitar fontes de localização para teste" - "Criar imitação de fontes de localização para teste. Os aplicativos maliciosos podem usar isso para sobrescrever o local e/ou status retornado pelas fontes de localização reais como GPS ou provedores de rede." - "acessar comandos extra do provedor de localização" - "Acessar comandos extra de fornecedor de localização. Aplicativos maliciosos podem usar isso para interferir com a operação do GPS ou com outras fontes de localização." + "Permite que um aplicativo leia os dados de proprietário do telefone armazenados no seu telefone. Aplicativos maliciosos podem usar isso para ler os dados de proprietário do telefone." + "ler dados da agenda" + "Permite que um aplicativo leia todos os eventos da agenda armazenados no seu telefone. Aplicativos maliciosos podem usar isso para enviar eventos da sua agenda para outras pessoas." + "gravar dados da agenda" + "Permite que um aplicativo modifique os eventos da agenda armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar os seus dados da agenda." + "fontes de locais fictícios para teste" + "Cria fontes de locais fictícios para teste. Aplicativos maliciosos podem usar isso para substituir o local e/ou o status retornado pelas fontes de locais reais como GPS ou provedores de rede." + "acessar comandos extras do provedor de localização" + "Acessa comandos extras do provedor de localização. Aplicativos maliciosos podem usar isso para interferir na operação do GPS ou de outras fontes de localização." "Localização precisa (GPS)" - "Acesse fontes de localização precisa como o sistema GPS (Global Positioning System) no telefone, quando estiver disponível. Aplicativos maliciosos podem usar isso para determinar onde você está e também pode consumir energia da bateria." - "Local inadequado (com base na rede)" - "Acessar fontes de localização aproximada como o banco de dados de rede de celular para determinar a localização aproximada de um telefone, quando houver disponibilidade. Aplicativos maliciosos podem usar isso para determinar sua localização aproximada." + "Acessa fontes de localização precisa como o GPS (Global Positioning System) no telefone, onde disponível. Aplicativos maliciosos podem usar isso para determinar onde você está e podem consumir energia adicional da bateria." + "local aproximado (com base na rede)" + "Acessa fontes de localização aproximada como o banco de dados de rede celular para determinar a localização aproximada de um telefone, onde disponível. Aplicativos maliciosos podem usar isso para determinar aproximadamente onde você está." "acessar SurfaceFlinger" - "Permite que o aplicativo use os recursos de nível inferior do SurfaceFlinger." - "ler buffer do quadro" - "Permite que o aplicativo leia o conteúdo do buffer do quadro." - "alterar as configurações do seu áudio" - "Permite que o aplicativo modifique as configurações de áudio globais como volume e roteamento." + "Permite que o aplicativo use recursos de nível inferior do SurfaceFlinger." + "ler o buffer do frame" + "Permite que o aplicativo a ser usado leia o conteúdo do buffer de frame." + "alterar as suas configurações de áudio" + "Permite que o aplicativo modifique as configurações globais de áudio como volume e roteamento." "gravar áudio" - "Permite que o aplicativo acesso o caminho do registro de áudio." + "Permite que um aplicativo acesse o caminho de gravação do áudio." "tirar fotos" - "Permite que o aplicativo tire fotos com a câmera. Isso permite que o aplicativo colete imagens exibidas pela câmera a qualquer momento." + "Permite que o aplicativo tire fotos com a câmera. Isso permite que o aplicativo colete imagens vistas pela câmera a qualquer momento." "desativar permanentemente o telefone" - "Permite que o aplicativo desative todo o telefone permanentemente. Isso é muito perigoso." - "forçar reinicializarão do telefone" + "Permite que o aplicativo desative o telefone inteiro permanentemente. Isso é muito perigoso." + "forçar reinicialização do telefone" "Permite que o aplicativo force a reinicialização do telefone." "montar e desmontar sistemas de arquivos" - "Permite que o aplicativo monte e desmonte sistemas de arquivos para armazenamento removível." - - - - - "controlar vibrador" + "Permite que o aplicativo monte e desmonte arquivos de sistema para armazenamento removível." + "formatar armazenamento externo" + "Permite que o aplicativo formate o armazenamento removível." + "controlar o vibrador" "Permite que o aplicativo controle o vibrador." "controlar lanterna" "Permite que o aplicativo controle a lanterna." "testar hardware" - "Permite que o aplicativo controle diversos periféricos para teste de hardware." - "chamar números de telefone diretamente" - "Permite que o aplicativo chame números de telefone sem sua intervenção. Aplicativos maliciosos podem causar a aparição de chamadas inesperadas na conta do seu telefone. Observe que isso não permite que o aplicativo ligue para números de emergência." - "chamar quaisquer números de telefone diretamente" - "Permite que o aplicativo chame qualquer número de telefone, incluindo números de emergência, sem sua intervenção. Aplicativos maliciosos podem fazer chamadas desnecessárias e ilegais para serviços de emergência." - "controlar notificações de atualização de localização" - "Permite a ativação/desativação das notificações sobre atualização de localização pelo rádio. Não deve ser usado em aplicativos normais." + "Permite que o aplicativo controle diversos periféricos para teste do hardware." + "chamar diretamente os números de telefone" + "Permite que o aplicativo ligue para números de telefones sem a sua intervenção. Aplicativos maliciosos podem causar chamadas inesperadas na conta do seu telefone. Observe que isso não permite que o aplicativo ligue para números de emergência." + "chamar diretamente quaisquer números de telefone" + "Permite que o aplicativo ligue para qualquer número de telefone, incluindo números de emergência, sem a sua intervenção. Aplicativos maliciosos podem fazer chamadas desnecessárias e ilegais para serviços de emergência." + "controlar as notificações de atualização do local" + "Permite a ativação/desativação de notificações de atualização do local a partir do rádio. Não deve ser usado por aplicativos normais." "acessar propriedades de verificação" - "Permite acesso de leitura/gravação às propriedades enviadas pelo serviço de verificação. Não deve ser usado em aplicativos normais." - - - - + "Permite o acesso de leitura/gravação às propriedades enviadas pelo serviço de verificação. Não deve ser usado por aplicativos normais." + "escolher widgets" + "Permite que o aplicativo informe ao sistema quais widgets podem ser usados por quais aplicativos. Com essa permissão, os aplicativos podem conceder acesso aos dados pessoais a outros aplicativos. Não deve ser usado por aplicativos normais." "modificar estado do telefone" - "Permite que o aplicativo controle os recursos do telefone do dispositivo. Um aplicativo com essa permissão pode alternar entre redes, ligar e desligar o rádio e executar ações parecidas sem o notificar." + "Permite que o aplicativo controle os recursos de telefone do dispositivo. Um aplicativo com essa permissão pode alternar redes, ligar e desligar o rádio do telefone e outras ações parecidas sem notificá-lo." "ler estado do telefone" - "Permite que o aplicativo acesse os recursos do telefone do aparelho. Um aplicativo com essa permissão pode determinar o número deste telefone, se uma chamada está ativa, o número com o qual está chamada está conectada e outras coisas semelhantes." - "impedir que o telefone entre em repouso" - "Permite que um aplicativo impeça o telefone de entrar em repouso." + "Permite que o aplicativo acesse os recursos de telefone do dispositivo. Um aplicativo com essa permissão pode determinar o número desse telefone, se uma chamada está ativa, o número ao qual a chamada está conectada e outras informações parecidas." + "impedir modo de inatividade do telefone" + "Permite que um aplicativo impeça o telefone de entrar no modo de inatividade." "ligar ou desligar o telefone" - "Permite que o aplicativo ligue ou desligue o telefone." + "Permite que o aplicativo ative ou desative o telefone." "executar no modo de teste de fábrica" - "Executar como um teste de fabricante de nível inferior, permitindo o acesso completo ao hardware do telefone. Disponível apenas quando um telefone está executando no modo de teste de fábrica." + "Executa como um teste do fabricante de nível inferior, permitindo o acesso completo ao hardware do telefone. Disponível apenas quando um telefone está em execução no modo de teste do fabricante." "definir papel de parede" "Permite que o aplicativo defina o papel de parede do sistema." - "definir dicas de tamanho de papel de parede" + "definir dicas de tamanho do papel de parede" "Permite que o aplicativo defina as dicas de tamanho do papel de parede do sistema." - "reiniciar o sistema com o padrão de fábrica" - "Permite que um aplicativo reinicie completamente o sistema com suas configurações de fábrica, apagando todos os dados, configuração e aplicativos instalados." + "redefinir o sistema para os padrões de fábrica" + "Permite que um aplicativo redefina completamente o sistema para as configurações de fábrica, apagando todos os dados, configuração e aplicativos instalados." "definir fuso horário" "Permite que um aplicativo altere o fuso horário do telefone." "descobrir contas conhecidas" "Permite que um aplicativo obtenha a lista de contas conhecidas pelo telefone." - "exibir estado da rede" - "Permite que um aplicativo exiba o estado de todas as redes." - "acesso total à Internet" + "ver estado da rede" + "Permite que um aplicativo veja o estado de todas as redes." + "acesso total da internet" "Permite que um aplicativo crie soquetes de rede." - "gravar configurações de Nome do ponto de acesso" - "Permite que um aplicativo modifique as configurações de APN, como Proxy e a Porta de qualquer APN." + "gravar as configurações do Nome do ponto de acesso" + "Permite que um aplicativo modifique as configurações de APN, como Proxy e Porta de qualquer APN." "alterar conectividade da rede" - "Permite que um aplicativo mude o estado da conectividade da rede." - - - - - "exibir estado da rede Wi-Fi" - "Permite que um aplicativo exiba as informações sobre o estado da rede Wi-Fi." - "Alterar estado de Wi-Fi" + "Permite que um aplicativo altere o estado da conectividade de rede." + "alterar configuração de uso dos dados de segundo plano" + "Permite que um aplicativo altere a configuração de uso dos dados de segundo plano." + "visualizar estado da rede Wi-Fi" + "Permite que um aplicativo veja as informações sobre o estado de Wi-Fi." + "alterar o estado de Wi-Fi" "Permite que um aplicativo se conecte e desconecte dos pontos de acesso Wi-Fi e faça alterações nas redes Wi-Fi configuradas." - "administração do bluetooth" - "Permite que um aplicativo configure o telefone Bluetooth local, além de descobrir e parear com dispositivos remotos." + "administração de Bluetooth" + "Permite que um aplicativo configure o telefone Bluetooth local, descubra e pareie com dispositivos remotos." "criar conexões Bluetooth" - "Permite que um aplicativo exiba a configuração do telefone Bluetooth local e faça e aceite conexões com os dispositivos pareados." - "desativar bloqueio de teclado" - "Permite que um aplicativo desative o bloqueio do teclado e qualquer segurança de senha associada. Um exemplo legítimo disso é o telefone desativando o bloqueio do teclado ao receber uma chamada e reativando o bloqueio ao final da chamada." - "ler configurações de sincronização" - "Permite que um aplicativo leia as configurações de sincronização, por exemplo se a sincronização está ativada para Contatos." + "Permite que um aplicativo veja a configuração do telefone Bluetooth local e que possa fazer e aceitar conexões com dispositivos pareados." + "desativar o bloqueio de teclas" + "Permite que um aplicativo desative o bloqueio de teclas e qualquer segurança por senha associada. Um exemplo legítimo disso é a desativação do bloqueio de teclas pelo telefone ao receber uma chamada e a reativação do bloqueio quando a chamada é finalizada." + "ler as configurações de sincronização" + "Permite que um aplicativo leia as configurações de sincronização, como se a sincronização está ativada para Contatos." "gravar configurações de sincronização" - "Permite que um aplicativo modifique as configurações de sincronização, por exemplo se a sincronização está ativada para Contatos." + "Permite que um aplicativo modifique as configurações de sincronização, como a ativação da sincronização para Contatos." "ler estatísticas de sincronização" - "Permite que um aplicativo leia as estatísticas de sincronização; por exemplo, o histórico de sincronizações realizadas." + "Permite que um aplicativo leia as estatísticas de sincronização; por exemplo, o histórico de sincronizações ocorridas." "ler feeds inscritos" - "Permite que um aplicativo obtenha detalhes sobre os feeds sincronizados atualmente." + "Permite que um aplicativo obtenha detalhes sobre os feeds sincronizados no momento." "gravar feeds inscritos" - "Permite que um aplicativo modifique seus feeds sincronizados recentemente. Isso poderia permitir que um aplicativo malicioso alterasse seus feeds sincronizados." - - - - - - - - + "Permite que um aplicativo modifique os seus feeds atualmente sincronizados. Isso pode permitir que um aplicativo malicioso altere os seus feeds sincronizados." + "ler dicionário definido pelo usuário" + "Permite que um aplicativo leia quaisquer palavras, nomes e frases particulares armazenados pelo usuário no dicionário do usuário." + "gravar no dicionário definido pelo usuário" + "Permite que um aplicativo grave novas palavras no dicionário do usuário." - "Página Inicial" + "Página inicial" "Celular" "Trabalho" - "Fax comercial" + "Fax do trabalho" "Fax doméstico" "Pager" - "Outro" - "Personalizar" + "Outros" + "Personalizado" - "Página Inicial" + "Página inicial" "Trabalho" - "Outro" - "Personalizar" + "Outros" + "Personalizado" - - + "Celular" - "Página Inicial" + "Página inicial" "Trabalho" - "Outro" - "Personalizar" + "Outros" + "Personalizado" - "Página Inicial" + "Página inicial" "Trabalho" - "Outro" - "Personalizar" + "Outros" + "Personalizado" "Trabalho" - "Outro" - "Personalizar" + "Outros" + "Personalizado" "AIM" @@ -475,76 +459,80 @@ "Digite o código PIN" "Código PIN incorreto!" - "Para desbloquear, pressione Menu e 0." + "Para desbloquear, pressione Menu e, em seguida, 0." "Número de emergência" "(Sem serviço)" "Tela bloqueada." - "Pressione Menu para desbloquear ou fazer chamada de emergência." + "Pressione Menu para desbloquear ou fazer uma chamada de emergência." "Pressione Menu para desbloquear." - "Desenhar padrão para desbloqueio" + "Desenhe o padrão para desbloquear" "Chamada de emergência" "Correto!" - "Sentimos muito, tente novamente" - + "Tente novamente" + "Carregando (%d%%)" + - "Conecte o carregador." + "Conecte o seu carregador." "Sem cartão SIM." "Não há um cartão SIM no telefone." "Insira um cartão SIM." "Rede bloqueada" "O cartão SIM está bloqueado pelo PUK." - - + "Consulte o Guia do Usuário ou entre em contato com o Serviço de atendimento ao cliente." "O cartão SIM está bloqueado." - "Desbloqueando cartão SIM…" - "Você desenhou incorretamente seu padrão de desbloqueio %d vezes. "\n\n"Tente novamente em %d segundos." - "Você desenhou seu padrão de desbloqueio incorretamente %d vezes. Após mais %d tentativas sem êxito, você receberá uma solicitação para desbloquear o telefone usando seu login do Google."\n\n" Tente novamente em %d segundos." - "Tentar novamente em %d segundos." + "Desbloqueando o cartão SIM…" + "Você desenhou incorretamente o seu padrão de desbloqueio %d vezes. "\n\n"Tente novamente em %d segundos." + "Você desenhou o seu padrão de desbloqueio incorretamente %d vezes. Mais %d tentativas incorretas e você receberá uma solicitação para desbloquear o seu telefone usando o seu login do Google."\n\n" Tente novamente em %d segundos." + "Tente novamente em %d segundos." "Esqueceu o padrão?" "Muitas tentativas de padrão!" - - + "Para desbloquear, faça login com a sua Conta do Google." "Nome de usuário (e-mail)" "Senha" "Fazer login" "Nome de usuário ou senha inválida." - + "%-l%P" + "%-l%p" + - - - "Limpar notificações" - "Sem modificações" + "Sem notificações" "Em andamento" "Notificações" - - + "%d%%" "Carregando..." "Conecte o carregador" - "A carga da bateria está ficando baixa:" + "A bateria está ficando baixa:" "menos de %d%% restantes." + + "Falha no teste de fábrica" "A ação FACTORY_TEST é suportada apenas para pacotes instalados em /system/app." - "Nenhum pacote foi encontrado que forneça a ação FACTORY_TEST." + "Nenhum pacote que forneça a ação FACTORY_TEST foi encontrado." "Reiniciar" - - - - - - + "A página em \"%s\" mostra:" + "JavaScript" + "Deseja sair desta página?"\n\n"%s"\n\n"Selecione OK para continuar ou Cancelar para permanecer na página atual." "Confirmar" - "Deseja que o navegador se lembre desta senha?" - "Não agora" - "Lembre-se" + + + + + + + + + "Deseja que o navegador lembre desta senha?" + "Agora não" + "Lembrar" "Nunca" - "Você não tem permissão para abrir essa página." + "Você não tem permissão para abrir esta página." "Texto copiado para a área de transferência." "Mais" "Menu+" "espaço" "enter" "excluir" - "Procurar" + "Pesquisar" "1 mês atrás" "Antes de 1 mês atrás" @@ -552,11 +540,11 @@ "%d segundos atrás" - "1 minute atrás" + "1 minuto atrás" "%d minutos atrás" - "1 hora trás" + "1 hora atrás" "%d horas atrás" @@ -573,55 +561,69 @@ "em 1 hora" - "em %d horas" + "Em %d horas" "amanhã" "em %d dias" - - - - - - - - - - - - - - - - + + "1 seg. atrás" + "%d segundos\n atrás" + + + "1 minuto atrás" + "%d minutos atrás" + + + "1 hora atrás" + "%d horas atrás" + + + "ontem" + "%d dias atrás" + + + "em 1 segundo" + "em %d segundos" + + + "em 1 minuto" + "em %d minutos" + + + "em 1 hora" + "em %d horas" + + + "amanhã" + "em %d dias" + "em %s" - "a %s" + "às %s" "em %s" "dia" "dias" "hora" "horas" - "minuto" - "minutos" - "segundos" + "min." + "min." + "seg." "segundos" "semana" "semanas" "ano" "anos" - "Todo dia de semana (Seg–Sex)" + "Todos os dias da semana (de segunda a sexta)" "Diariamente" - "Semanalmente em %s" + "Semanalmente na %s" "Mensalmente" "Anualmente" "Não é possível reproduzir o vídeo" - - - "Sentimos muito, este vídeo não pode ser reproduzido." + "Este vídeo não é válido para transmissão com este dispositivo." + "Este vídeo não pode ser reproduzido." "OK" - - + "%1$s, %2$s" "meio-dia" "Meio-dia" "meia-noite" @@ -630,7 +632,7 @@ "%1$d:%2$02d:%3$02d" "Selecionar tudo" "Selecionar texto" - "Interromper seleção de texto" + "Parar seleção de texto" "Recortar" "Recortar tudo" "Copiar" @@ -638,154 +640,124 @@ "Colar" "Copiar URL" "Método de entrada" - - + "Adicionar \"%s\" ao dicionário" "Editar texto" "Pouco espaço" - "O espaço de armazenamento do telefone está diminuindo." + "O espaço de armazenamento do telefone está ficando baixo." "OK" "Cancelar" "OK" "Cancelar" - - - "LIGAR" - "DESLIGADO" - "Completar ação usando" - "Use por padrão para esta ação." - "Limpar o padrão nas Configurações da página inicial> Aplicativos > Gerenciar aplicativos." - "Selecione uma ação" - "Nenhum aplicativo pode executar essa ação." - "Sentimos muito." - "O aplicativo %1$s(processo %2$s) parou inesperadamente. Tente novamente." + "Atenção" + "ATIVADO" + "DESATIVADO" + "Complete a ação usando" + "Use o como padrão para esta ação." + "Limpar o padrão em Configurações da página inicial > Aplicativos > Gerenciar aplicativos." + "Selecionar uma ação" + "Nenhum aplicativo pode realizar esta ação." + "Desculpe!" + "O aplicativo %1$s (processo %2$s) parou inesperadamente. Tente novamente." "O processo %1$s parou inesperadamente. Tente novamente." - "Sentimos muito." + "Desculpe!" "A atividade %1$s (no aplicativo %2$s) não está respondendo." - "A atividade %1$s (%2$s em processamento) não está respondendo." - "O aplicativo %1$s (%2$s em processamento) não está respondendo." + "A atividade %1$s (no processo %2$s) não está respondendo." + "O aplicativo %1$s (no processo %2$s) não está respondendo." "O processo %1$s não está respondendo." "Forçar fechamento" - "Aguarde" - "Depuração" - "Selecione uma ação para texto" + "Aguardar" + "Depurar" + "Selecione uma ação para o texto" "Volume da campainha" "Volume da mídia" - "Reprodução usando Bluetooth" - "Volume da chamada recebida" - - + "Reproduzindo por meio de Bluetooth" + "Volume na chamada" + "Volume de chamada Bluetooth" "Volume do alarme" "Volume da notificação" "Volume" - "Ringtone padrão" - "Ringtone padrão (%1$s)" + "Toque padrão" + "Toque padrão (%1$s)" "Silencioso" - "Ringtones" - "Ringtone desconhecido" + "Toques" + "Toque desconhecido" "Rede Wi-Fi disponível" "Redes Wi-Fi disponíveis" - "Redes Wi-Fi abertas disponíveis" + "Rede Wi-Fi aberta disponível" "Redes Wi-Fi abertas disponíveis" "Inserir caractere" "Aplicativo desconhecido" - "Envio de mensagens SMS" - "Uma grande quantidade de mensagens SMS está sendo enviada. Selecione \"OK\" para continuar ou \"Cancelar\" para parar de enviar." + "Enviando mensagens SMS" + "Muitas mensagens SMS estão sendo enviadas. Selecione \"OK\" para continuar ou \"Cancelar\" para interromper o envio." "OK" "Cancelar" "Definir" "Padrão" - "Nenhuma permissão é necessária" + "Nenhuma permissão necessária" "Ocultar" - "Mostrar tudo" - "Carregando…" - "Conectado via USB" - "Você conectou o telefone ao seu computador via USB. Selecione \"Montar\" se quiser copiar os arquivos entre seu computador e o cartão SD do telefone." + "Mostrar todas" + "Carregando..." + "Conectado por USB" + "Você conectou o telefone ao computador via USB. Selecione \"Montar\" se quiser copiar arquivos entre o computador e o cartão SD do seu telefone." "Montar" "Não montar" "Há um problema com o uso do seu cartão SD para armazenamento USB." - "Conectado via USB" - "Selecione para copiar os arquivos para/do computador." - + "Conectado por USB" + "Selecione para copiar arquivos para/do seu computador." + "Desativar o armazenamento USB" + "Selecione para desativar o armazenamento USB." + "Desativar o armazenamento USB" + "Antes de desativar o armazenamento USB, desmonte o host USB. Selecione \"Desativar\" para desativar o armazenamento USB." + "Desativar" + "Cancelar" + "Encontramos um problema ao desativar o armazenamento USB. Verifique se desmontou o host USB e tente novamente." + "Formatar cartão SD" + "Tem certeza de que deseja formatar o cartão SD? Todos os dados no seu cartão serão perdidos." + "Formatar" + - - - - - - - - - - - - - - - - - + "Selecionar método de entrada" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - + "candidatos" + "Preparando o cartão SD" + - + "Cartão SD em branco" + - + "Cartão SD danificado" + - + "Cartão SD removido inesperadamente." + "Desmonte o cartão SD antes da remoção para evitar a perda de dados." + "O cartão SD já pode ser removido com segurança." + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + "Cartão SD removido" + + "Nenhum atividade correspondente foi encontrada" + "atualizar estatísticas de uso do componente" + "Permite a modificação das estatísticas de uso do componente coletadas. Não deve ser usado por aplicativos normais." + "Toque duas vezes para ter controle do zoom" + "Erro ao aumentar o widget" + "Ir" + "Pesquisar" + "Enviar" + "Próximo" + "Concluído" + "Executar" + "Discar número"\n"usando %s" + "Criar contato "\n"usando %s" diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 048f6b1c20d04..03284c15d33e2 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -15,328 +15,404 @@ --> - "б" - "Кб" - "Мб" - "Гб" - "Тб" - "Пб" + "Б" + "КБ" + "МБ" + "ГБ" + "TБ" + "ПБ" + + "<без названия>" "…" "(Нет номера телефона)" "(Неизвестно)" "Голосовая почта" "MSISDN1" - "Проблема с подключением или недействительный код MMI." + "Неполадки подключения или неверный код MMI." "Служба включена." - "Служба включена для следующего:" + "Служба подключена для:" "Служба отключена." - "Регистрация прошла успешно." - "Удаление прошло успешно." + "Регистрация пройдена успешно." + "Удаление выполнено успешно." "Неверный пароль." - "Код MMI завершен." - "Указан неверный старый PIN." - "Указан неверный PUK." - "Указанные PIN-коды не совпадают." - "Введите PIN, содержащий от 4 до 8 цифр." - "Ваша SIM-карта заблокирована PUK-кодом. Введите PUK, чтобы разблокировать ее." - "Введите PUK2 для разблокирования SIM-карты." - "Идентификатор звонящего" - "Идентификатор принимающего вызов" - "Перенаправление вызовов" - "Ожидание вызова" + "Запрос MMI завершен." + "Введен неверный старый PUK." + "Введен неверный PUK." + "Введенные PIN-коды не совпадают." + "Введите PIN-код (от 4 до 8 цифр)." + "SIM-карта заблокирована с помощью кода PUK. Для разблокировки введите код PUK." + "Для разблокировки SIM-карты введите PUK2." + "Идентификация вызывающего абонента" + "Идентификация звонящего абонента" + "Переадресация вызова" + "Параллельный вызов" "Запрет вызовов" - "Изменение пароля" - "Изменение PIN" - "Идентификатор звонящего по умолчанию ограничен. Следующий вызов: ограничен" - "Идентификатор звонящего по умолчанию ограничен. Следующий вызов: не ограничен" - "Идентификатор звонящего по умолчанию не ограничен. Следующий вызов: ограничен" - "Идентификатор звонящего по умолчанию не ограничен. Следующий вызов: не ограничен" + "Смена пароля" + "Смена PIN" + + + + + + + + + + + + + "Идентификация абонента по умолчанию запрещена. След. вызов: запрещена" + "Идентификация абонента по умолчанию запрещена. След. вызов: разрешена" + "Идентификация абонента по умолчанию не запрещена. След. вызов: запрещена" + "Идентификация абонента по умолчанию не запрещена. След. вызов: разрешена" "Услуга не предоставляется." - "Нельзя изменить настройки идентификатора звонящего." + "Невозможно изменить настройку идентификации абонента." "Ограничения доступа изменены" "Служба данных заблокирована." - "Аварийная служба заблокирована." + "Служба экстренной помощи заблокирована." "Служба передачи SMS/голосовых сообщений заблокирована." "Все службы передачи SMS/голосовых сообщений заблокированы." - "Голос" + "Голосовая связь" "Данные" "ФАКС" "SMS" "Асинхр." - "Синхронизация" - "Пакетные данные" + "Синхр." + "Пакет" "PAD" - "{0}: не перенаправлено" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "{0}: не переадресовано" "{0}: {1}" - "{0}: {1} через {2} сек." - "{0}: не перенаправлено" - "{0}: не перенаправлено" + "{0}: {1} через {2} с." + "{0}: Не переадресовано" + "{0}: Не переадресовано" + + + + "ОК" - "Веб-страница содержит ошибку." - "Не удается найти URL." + "Ошибка на веб-странице." + "Не удалось найти URL." "Схема аутентификации сайта не поддерживается." - "Не удалось выполнить аутентификацию." + "Не удалось провести аутентификацию." "Не удалось выполнить аутентификацию через прокси-сервер." - "Не удалось связаться с сервером." - "Сервер не отвечает. Повторите попытку позже." - "Время подключения к серверу истекло." - "Страница содержит слишком много перенаправлений." - "Протокол не поддерживается" - "Невозможно установить безопасное соединение." - "Невозможно открыть страницу, поскольку URL недействителен." - "Нет доступа к файлу." - "Нужный файл не найден." - "Обрабатывается слишком много запросов. Повторите попытку позже." - "Синхронизация" - "Синхронизация" + "Не удалось подключиться к серверу." + "Сервер не отвечает. Повторите попытку позднее." + "Время ожидания соединения с сервером истекло." + "Страница содержит слишком много перенаправлений сервера." + "Этот протокол не поддерживается." + "Не удалось установить безопасное соединение." + "Не удалось открыть страницу. Указан недопустимый URL." + "Не удается получить доступ к файлу." + "Не удалось найти указанные файлы." + "Обрабатывается слишком много запросов. Повторите попытку позднее." + + + "Синхр." + "Синхр." "Слишком много удалений %s." - "Память телефона полна! Удалите какие-нибудь файлы, чтобы освободить место." + "Память телефона заполнена! Удалите файлы, чтобы освободить место." "Я" "Параметры телефона" "Беззвучный режим" "Включить беспроводную связь" - "Отключить беспроводную связь" - "Заблокировать экран" - "Отключить питание" - "Идет выключение…" - "Телефон будет выключен." - "Нет новых приложений." + "Отключить беспроводное соединение" + "Блокировка экрана" + "Выключить связь" + "Выключение..." + "Телефон будет отключен." + "Нет последних приложений." "Параметры телефона" - "Заблокировать экран" + "Блокировка экрана" "Отключить питание" "Беззвучный режим" - "Звук выключен" - "Звук включен" + "Звук ВЫКЛ" + "Звук ВКЛЮЧЕН" "Режим полета" "Режим полета ВКЛЮЧЕН" "Режим полета ВЫКЛЮЧЕН" "Безопасный режим" "Система Android" - "Платные службы" - "Разрешить приложениям выполнять действия, за которые может взиматься плата." + "Платные услуги" + "Разрешать приложениям использовать платные услуги." "Сообщения" - "Чтение и запись SMS, электронной почты и других сообщений." + "Считывать и записывать SMS, электронные письма и другие сообщения." "Личная информация" - "Прямой доступ к вашим контактам и календарю, сохраненным на телефоне." + "Прямой доступ к контактам и событиям календаря, сохраненным в памяти телефона." "Ваше местоположение" - "Наблюдение за вашим местоположением" - "Связь с сетью" - "Разрешить приложениям использовать сетевые функции." + "Отслеживание физического местоположения" + "Сетевой обмен данными" + "Позволяет приложениям получать доступ к различным сетевым функциям." "Ваши аккаунты Google" - "Доступ к имеющимся аккаунтам Google." - "Управление оборудованием" - "Прямой доступ к оборудованию телефона." + "Входить в доступные аккаунты Google." + "Элементы управления аппаратным обеспечением" + "Прямой доступ к аппаратному обеспечению телефона." "Телефонные вызовы" - "Слежение, запись и обработка вызовов." + "Отслеживать, записывать и обрабатывать телефонные звонки." "Системные инструменты" - "Доступ и управление системой на низком уровне." - "Средства для разработки" + "Доступ нижнего уровня и управление системой." + "Инструменты разработки" "Функции, необходимые только разработчикам приложений." - "отключать или изменять панель состояния" - "Разрешает приложению отключать панель состояния или добавлять и удалять системные значки." - "разворачивать/сворачивать панель состояния" - "Разрешает приложению разворачивать и сворачивать панель состояния." + + + + + "отключить или изменить строку состояния" + "Позволяет приложению отключать строку состояния или добавлять/удалять системные значки." + "разворачивать/сворачивать строку состояния" + "Позволяет приложению разворачивать или сворачивать строку состояния." "перехватывать исходящие вызовы" - "Разрешает приложению обрабатывать исходящие вызовы и изменять набираемый номер. Вредоносное ПО может следить, перенаправлять или блокировать исходящие вызовы." + "Позволяет приложению обрабатывать исходящие вызовы и изменять набираемый номер. Вредоносные приложения могут отслеживать, перенаправлять или запрещать исходящие вызовы." "получать SMS" - "Разрешает приложениям получать и обрабатывать сообщения SMS. Вредоносное ПО может отслеживать ваши сообщения или удалять до того, как вы их увидите." + "Позволяет приложению получать и обрабатывать SMS-сообщения. Вредоносные приложения могут отслеживать ваши сообщения или удалять их, не показывая вам." "получать MMS" - "Разрешает приложениям получать и обрабатывать сообщения MMS. Вредоносное ПО может отслеживать ваши сообщения или удалять их, не показав вам." - "отправлять SMS" - "Разрешает приложениям отправлять SMS. Вредоносное ПО может тратить ваши деньги, отправляя сообщения без вашего ведома." - "читать SMS и MMS" - "Разрешает приложению записывать SMS, сохраненные в телефоне или на SIM-карте. Вредоносное ПО может читать конфиденциальные сообщения." - "изменять SMS и MMS" - "Разрешает приложению записывать данные в SMS, сохраненные в телефоне или на SIM-карте. Вредоносное ПО может удалять сообщения." - "получать через WAP" - "Разрешает приложениям получать и обрабатывать сообщения WAP. Вредоносное ПО может отслеживать ваши сообщения или удалять до того, как вы их увидите." - "получать работающие приложения" - "Разрешает приложению получать информацию о работающих и недавно выполненных задачах. Может позволить вредоносному ПО получать конфиденциальную информацию о других приложениях." - "переупорядочивать работающие приложения" - "Разрешает приложению изменять приоритет задач. Вредоносное ПО может выходить на передний план без вашего разрешения." - "включать отладку приложений" - "Разрешает приложению включать отладку других приложений. Вредоносное ПО может таким образом закрывать другие приложения." - "изменять настройки интерфейса" - "Позволяет приложению изменять текущую конфигурацию, например локаль и общий размер шрифта." + "Позволяет приложению получать и обрабатывать MMS-сообщения. Вредоносные приложения могут отслеживать ваши сообщения или удалять их, не показывая вам." + "отправлять SMS-сообщения" + "Позволяет приложению отправлять SMS-сообщения. Вредоносные приложения могут отправлять сообщения без уведомления, что приведет к непредвиденным расходам." + "считывать SMS или MMS" + "Позволяет приложению считывать SMS-сообщения, сохраненные на телефоне или SIM-карте. Вредоносные приложения могут считывать конфиденциальные сообщения." + "изменить SMS или MMS" + "Позволяет приложению перезаписывать SMS-сообщения, сохраненные на телефоне или SIM-карте. Вредоносные приложения могут удалить сообщения." + "получать WAP" + "Позволяет приложению получать и обрабатывать WAP-сообщения. Вредоносные приложения могут отслеживать ваши сообщения или удалять их, не показывая вам." + "извлечь запущенные приложения" + "Позволяет приложению получать сведения о последних и текущих задачах. Вредоносные приложения могут получить доступ к конфиденциальной информации о других приложениях." + "изменять порядок запущенных приложений" + "Позволяет приложению переключать режим выполнения задачи с активного на фоновый. Вредоносные приложения могут установить для себя активный режим без уведомления." + "запускать отладку приложения" + "Позволяет приложению запускать процесс отладки другого приложения. Вредоносные приложения могут использовать эту возможность для остановки других приложений." + "изменять настройки пользовательского интерфейса" + "Позволяет приложению изменять текущую конфигурацию, например региональные настройки или размер шрифта." "перезапускать другие приложения" - "Разрешает приложению принудительно перезапускать другие приложения." + "Позволяет приложению принудительно перезапускать другие приложения." "принудительно закрывать приложения" - "Позволяет приложению принудительно закрывать и переводить в фоновый режим действия, работающие на переднем плане. Не требуется обычным приложениям." - "получать внутреннее состояние системы" - "Разрешает приложениям получать внутреннее состояние системы. Вредоносное ПО может получать множество личной и защищенной информации, которая обычно не была бы им доступна." - "наблюдать и управлять запуском всех приложений" - "Разрешает приложению следить и управлять тем, как система запускает действия. Вредоносное ПО может полностью нарушить работу системы. Это разрешение нужно только для разработки, но не при обычном использовании телефона." - "отправлять оповещения об удалении пакетов" - "Позволяет приложению распространять уведомление об удалении пакета приложения. Вредоносное ПО может использовать это для остановки любых других работающих приложений." - "отправлять оповещения о получении SMS" - "Разрешает приложению распространять уведомление о том, что получено сообщение SMS. Вредоносное ПО может пользоваться этим для фальсификации входящих сообщений SMS." - "отправлять оповещения о получении WAP-PUSH" - "Разрешает приложению распространять уведомление о получении сообщения WAP PUSH. Вредоносное ПО может использовать это для подделки отчета о получении MMS или просто заменять содержание любой веб-страницы вредоносными вариантами." - "ограничивать количество выполняемых процессов" - "Позволяет приложению контролировать максимальное количество выполняемых процессов. Не требуется обычным приложениям." - "закрывать все фоновые приложения" - "Разрешает приложению следить, чтобы действия всегда завершались после перехода в фоновый режим. Не требуется обычным приложениям." - "изменять данные о батарее" - "Разрешает изменять данные о батарее. Не используется обычными приложениями." - "отображать неавторизованные окна" - "Разрешает создавать окна, используемые внутренним системным интерфейсом пользователя. Не для использования обычными программами." - "отображать системные предупреждения" - "Разрешает приложению показывать окна системных предупреждений. Вредоносное ПО может захватить весь экран телефона." - "изменять общую скорость анимации" - "Позволяет приложению в любой момент изменять общую скорость анимации (ускорять и замедлять анимацию)." + "Позволяет приложению принудительно закрыть или вернуть в исходное состояние процессы, выполняемые в активном режиме. Не требуется для обычных приложений." + "извлекать данные о внутреннем состоянии системы" + "Позволяет приложению извлекать внутренние сведения о состоянии системы. Вредоносные приложения смогут извлечь разнообразные личные и защищенные сведения, в которых обычно нет необходимости." + + + + + + + + + "отслеживать и управлять запуском всех приложений" + "Позволяет приложению отслеживать и управлять способом подключения системы. Вредоносные приложения могут разгласить конфиденциальную информацию о системе. Это разрешение необходимо только при разработке, но не при обычной работе с телефоном." + "отправлять рассылку об удалении пакета" + "Позволяет приложению выполнять рассылку уведомлений об удалении пакета приложения. Вредоносные приложения могут использовать эту возможность для остановки всех остальных выполняющихся приложений." + "отправлять рассылку уведомлений о получении SMS" + "Позволяет приложению отправлять уведомления о получении SMS-сообщения. Вредоносные приложения могут использовать эту возможность для имитации получения SMS -сообщений." + "отправлять рассылку уведомлений о получении WAP-сообщений поставщика услуг" + "Позволяет приложению отправлять уведомления о получении WAP-сообщения поставщика услуг. Вредоносные приложения могут использовать эту возможность для имитации получения MMS-сообщения или замены содержимого любой веб-страницы на вредоносное без уведомления." + "ограничивать количество запущенных процессов" + "Позволяет приложению управлять максимальным количеством выполняемых процессов. Не требуется для обычных приложений." + "закрывать все приложения, работающие в фоновом режиме" + "Позволяет приложению контролировать, были ли действия завершены сразу же после их перехода в фоновый режим. Не требуется для обычных приложений." + "изменять статистику батареи" + "Позволяет изменять собранную статистику батареи. Не предназначено для использования обычными приложениями." + + + + + "показывать неавторизованные окна" + "Разрешает создание окон, предназначенных для использования внутренним пользовательским интерфейсом системы. Не предназначено для использования обычными приложениями." + "показывать оповещения системного уровня" + "Позволяет приложению отображать окна предупреждений системы. Вредоносные приложения смогут получить контроль над всем экраном телефона." + "изменять глобальную скорость анимации" + "Позволяет приложению в любое время изменять общую скорость анимации (ускоренная или замедленная анимация)." "управлять маркерами приложений" - "Разрешает приложениям создавать и управлять собственными маркерами вместо обычного порядка Z. Не требуется обычным приложениям." - "нажимать на клавиши и кнопки управления" - "Позволяет приложению передавать другим приложениям собственные события ввода (нажатия клавиш и т.д.). Вредоносное ПО может воспользоваться этим для захвата телефона." - "записывать нажимаемые клавиши и действия" - "Разрешает приложениям отслеживать нажимаемые клавиши даже при работе в другом приложении (например набор пароля). Никогда не используется обычными приложениями." - "выполнять привязку к способу ввода" - "Разрешает владельцу привязку к интерфейсу верхнего уровня способа ввода. Не требуется обычным приложениям." - "изменять положение экрана" - "Позволяет приложению в любой момент изменять положение экрана. Не требуется обычным приложениям." - "отправлять приложениям Linux-сигналы" - "Разрешает приложению запрашивать отправку поступающего сигнала всем постоянным процессам." - "выполнять приложение постоянно" - "Позволяет приложению переводить свои компоненты в постоянное состояние так, что система не сможет использовать их для других приложений." + "Позволяет приложениям создавать собственные маркеры и управлять ими, обходя обычное Z-упорядочивание. Не требуется для обычных приложений." + "отрабатывать нажатия клавиш и кнопок управления" + "Позволяет приложению передавать собственные события ввода (например, нажатия клавиш) в другие приложения. Вредоносные приложения могут использовать эту возможность для установки полного контроля над телефоном." + "записывать вводимый текст и совершаемые действия" + "Позволяет приложению распознавать нажатые пользователем клавиши даже при работе с другим приложением (например, при вводе пароля). Не требуется для обычных приложений." + "связывать с методом ввода" + "Позволяет выполнять привязку к интерфейсу ввода верхнего уровня. Не требуется для обычных приложений." + "изменять ориентацию экрана" + "Позволяет приложению изменять ориентацию экрана в любое время. Не требуется для обычных приложений." + "отправлять приложениям сигналы Linux" + "Позволяет приложению направлять запрос на передачу предоставленного сигнала всем постоянным процессам." + "запускать постоянную работу приложения" + "Позволяет приложению сделать свои компоненты постоянными, благодаря чему система не может использовать их для других приложений." "удалять приложения" - "Разрешает приложению удалять пакеты Android. Вредоносное ПО может воспользоваться этим для удаления важных приложений." + "Позволяет приложению удалять пакеты Android. Вредоносные приложения могут использовать эту возможность для удаления важных приложений." "удалять данные других приложений" - "Разрешает приложению удалять данные пользователя." - "удалять кэш других приложений" + "Позволяет приложению удалять данные пользователя." + "очищать кэши других приложений" "Позволяет приложению удалять файлы из кэша." - "измерять место для хранения данных приложений" - "Разрешает приложению получать размеры своего кода, данных и кэша" - "напрямую устанавливать приложения" - "Разрешает приложению устанавливать новые или обновленные пакеты Android. Вредоносное ПО может использовать это для добавления новых приложений с абсолютными полномочиями." + "определять объем памяти приложений" + "Позволяет приложению получать сведения о размере кода, данных и кэша." + "устанавливать приложения непосредственно" + "Позволяет приложению устанавливать новые или обновленные пакеты Android. Вредоносные приложения могут использовать эту возможность для добавления новых приложений со сколь угодно высоким уровнем разрешения." "удалять все данные из кэша приложений" - "Разрешает приложению освобождать место на телефоне, удаляя файлы из каталога кэша приложения. Обычно доступ разрешен только системным процессам." - "читать файлы системного журнала" - "Разрешает приложению считывать различные файлы журналов системы. Это позволяет получать сведения о том, что вы делаете с телефоном, но в этих файлах не должно быть личной или конфиденциальной информации." - "считывать и записывать ресурсы, принадлежащих diag" - "Разрешает приложению считывать и записывать в любой ресурс, принадлежащий группе diag, например файлы в /dev. Это может влиять на стабильность и безопасность системы. Следует использовать ТОЛЬКО при диагностике оборудования производителем или оператором." - "включать и выключать компоненты приложений" - "Разрешает приложению включать или отключать компоненты другого приложения. Вредоносное ПО сможет отключать важные функции телефона. Эту возможность следует использовать с осторожностью, так как можно привести компоненты приложений в нерабочее, несовместимое или нестабильное состояние." - "задавать предпочитаемые приложения" - "Позволяет приложению изменять предпочитаемые приложения. Это может позволить вредоносному ПО незаметно изменить работающие приложения поддельными и собрать ваши личные данные." - "изменять глобальные настройки системы" - "Разрешает приложению изменять данные настройки системы. Вредоносное ПО может повредить конфигурацию вашей системы." - "изменять защищенные настройки системы" - "Разрешает приложению изменять данные в защищенных настройках системы. Не используется обычными приложениями." - "изменять карту служб Google" - "Разрешает приложению изменять карту служб Google. Не используется обычными приложениями." - "автоматически запускаться при загрузке" - "Разрешает приложению запускаться сразу после загрузки системы. Это может увеличить время запуска телефона, а постоянная работа приложения может снизить общую скорость работы." - "отправлять постоянное оповещение" - "Разрешает приложению отправлять постоянные оповещения, остающиеся после окончания рассылки. Вредоносное ПО может замедлить работу телефона или привести к нестабильности, используя слишком много памяти." - "считывать данные контактов" - "Разрешает приложению считывать полную контактную информацию (адрес), сохраненную в вашем телефоне. Может использоваться вредоносным ПО для отправки этих данных другим людям." - "записывать данные контактов" - "Разрешает приложению изменять контактную информацию (адрес), сохраненную в телефоне. Вредоносное ПО может использовать это для удаления или изменения данных контактов." - "записывать данные о владельце" - "Разрешает приложению изменять данные о владельце, сохраненные в телефоне. Вредоносное ПО может использовать это для удаления или изменения данных о владельце." + "Позволяет приложению освобождать память телефона с помощью удаления файлов из каталога кэша приложений. Обычно это разрешается только системным процессам." + "считывать системные файлы журналов" + "Позволяет приложению считывать информацию из различных журналов системы. Приложение может получить сведения о работе пользователя с телефоном, но они не должны содержать какой-либо личной или конфиденциальной информации." + "считывать/записывать данные в ресурсы, принадлежащие группе диагностики" + "Позволяет приложению считывать и записывать данные в любые ресурсы, принадлежащие группе диагностики (например, файлы в каталоге /dev). Это может повлиять на стабильность и безопасность системы. Эта возможность может быть использована ТОЛЬКО производителем или оператором для диагностики аппаратного обеспечения." + "включать или отключать компоненты приложения" + "Позволяет приложению отключать или включать компоненты другого приложения. Вредоносные приложения могут использовать это разрешение для отключения важных возможностей телефона. Это разрешение следует использовать с осторожностью, так как это может привести к несовместимости, нестабильности и неработоспособности компонентов приложения." + "выбирать предпочтительные приложения" + "Позволяет приложению изменять предпочтительные приложения. Вредоносные приложения могут использовать эту возможность для незаметного изменения запущенных приложений и для сбора конфиденциальной информации с помощью имитации подключения существующих приложений." + "изменить общие настройки системы" + "Позволяет приложению изменять данные настроек системы. Вредоносные приложения могут повредить конфигурацию системы." + "изменять настройки системы безопасности" + "Позволяет приложению изменять данные настроек безопасности системы. Не предназначено для использования обычными приложениями." + "изменить карту служб Google" + "Позволяет приложению изменять карту служб Google. Не предназначено для использования обычными приложениями." + "автоматически запускать при загрузке" + "Позволяет приложению запускаться сразу же по завершении загрузки. Это может увеличить время запуска телефона и замедлить его работу в связи с постоянной работой приложения." + "отправить несрочную рассылку" + "Позволяет приложению отправлять несрочные рассылки, которые остались по завершении данной рассылки. Вредоносные приложения могут замедлить работу телефона или сделать ее нестабильной с помощью использования слишком большого объема памяти." + "считывать данные контакта" + "Позволяет приложению считывать все данные контактов (адресов), сохраненные в памяти телефона. Вредоносные приложения могут использовать эту возможность для передачи данных посторонним лицам." + "перезаписывать данные контакта" + "Позволяет приложению изменять данные (адрес) контакта, сохраненные в памяти телефона. Вредоносные приложения могут использовать эту возможность для удаления или изменения данных контакта." + "перезаписывать данные о владельце" + "Позволяет приложению изменять сведения о владельце, сохраненные на телефоне. Вредоносные приложения могут использовать эту возможность для удаления или изменения данных владельца." "считывать данные о владельце" - "Разрешает приложению считывать данные о владельце, сохраненные в телефоне. Вредоносное ПО может использовать это для чтения данных о владельце." + "Позволяет приложению считывать сведения о владельце, сохраненные в памяти телефона. Вредоносные приложения могут использовать эту возможность для считывания данных владельца." "считывать данные календаря" - "Разрешает приложению считывать все события календаря, сохраненные в телефоне. Вредоносное ПО может использовать это для отправки событий вашего календаря другим людям." + "Позволяет приложению считывать все события календаря, сохраненные на телефоне. Вредоносные приложения могут использовать эту возможность для передачи ваших событий календаря посторонним лицам." "записывать данные календаря" - "Позволяет приложению изменять сохраненные в телефоне события календаря. Вредоносное ПО сможет стирать или изменять данные календаря." - "имитировать источники данных о положении для тестирования" - "Создание имитаций источников данных о местоположении для тестирования. Вредоносное ПО может использовать это для изменения данных о местоположении и/или состоянии, сообщаемых настоящими источниками таких данных, например GPS или оператором связи." - "получать доступ к дополнительным командам местоположения от поставщика связи" - "Доступ к дополнительным командам местоположения от поставщика связи. Это дает вредоносному ПО возможность мешать работе GPS или других источников данных о местоположении." - "определять точное местоположение (GPS)" - "Доступ к имеющимся источникам точных данных о местоположении телефона, например к GPS. Вредоносное ПО сможет узнать, где вы находитесь, а также истратить заряд батареи." - "определять приблизительное местоположение (на основе данных сети)" - "Доступ (при наличии) к источникам сведений о приблизительном расположении, например базам данных сотовой сети. Вредоносное ПО может использовать эту функцию для того, чтобы определять ваше местоположение." - "открывать SurfaceFlinger" - "Разрешает приложению использовать функции SurfaceFlinger низкого уровня." - "считывать данные из буфера фреймов" - "Разрешает приложению считывать содержание буфера фрейма." - "изменять настройки звука" - "Разрешает приложениям изменять глобальные настройки звука, например громкость и маршрут сигнала." - "записывать звук" - "Разрешает приложению получать доступ к пути записи звука." + "Позволяет приложению изменять события календаря, сохраненные на телефоне. Вредоносные приложения могут использовать эту возможность для удаления или изменения событий календаря." + "копировать источники мест для проверки" + "Создавать копии источников данных о местоположении для проверки. Вредоносные приложения могут использовать эту возможность для перезаписи места и/или состояния, возвращаемого действительными источниками данных о местоположении, такими как GPS или операторы связи." + "получать доступ к дополнительным командам источника данных о местоположении" + "Получать доступ к дополнительным командам поставщика данных о местоположении. Вредоносные приложения могут использовать эту возможность для вмешательства в работу GPS или других источников места." + + + + + "точное местоположение (GPS)" + "Получать доступ к источникам точного местоположения, таким как GPS, если возможно. Вредоносные приложения могут использовать это разрешение для определения вашего местоположения и расходовать ресурс батареи." + "отслеживать местоположение по сигналам сети" + "Получать доступ к источникам данных о местоположении, таким как база данных сотовой сети, для определения приблизительного местоположения телефона, если возможно. Вредоносные приложения могут использовать эту возможность для определения вашего приблизительного местоположения." + "получать доступ к SurfaceFlinger" + "Позволяет приложению использовать функции SurfaceFlinger нижнего уровня." + "считывать буфер фреймов" + "Позволяет приложению использовать функцию чтения содержимого буфера фреймов." + "изменять настройки аудио" + "Позволяет приложению изменять глобальные аудионастройки, такие как громкость и маршрутизацию." + "записывать аудио" + "Позволяет приложению получать доступ к пути аудиозаписи." "снимать фотографии" - "Разрешает приложению делать снимки с помощью камеры. Это позволяет приложению в любой момент записывать то, что видно через камеру." - "отключать телефон навсегда" - "Разрешает приложению навсегда отключить телефон. Это очень опасно." + "Позволяет приложению делать снимки с помощью камеры. Это разрешение позволяет приложению в любое время собирать изображения, видимые через объектив камеры." + "отключать телефон" + "Позволяет данному приложению отключить телефон навсегда. Это очень опасно." "принудительно перезагружать телефон" - "Разрешает приложению принудительно перезагружать телефон." - "подключаться и отключаться от файловых систем" - "Разрешает приложению подключаться и отключаться от файловых систем съемных устройств хранения." + "Позволяет приложению принудительно перезагружать телефон." + "монтировать и удалять файловые системы" + "Позволяет приложению монтировать и удалять файловые системы съемных носителей." "форматировать внешний накопитель" "Позволяет приложению форматировать съемный накопитель." - "управлять вибрацией" - "Разрешает приложению управлять вибровызовом." - "управлять фонарем" - "Разрешает приложению управлять фонарем." - "проверять оборудование" - "Разрешает приложению управлять внешними устройствами для тестирования оборудования." - "напрямую вызывать телефонные номера" - "Разрешает приложениям вызывать телефонные номера без вашего участия. Вредоносное ПО может выполнять вызовы, за которые придется платить. Заметьте, что это не разрешает приложению вызывать номера экстренных служб." - "напрямую вызывать любые телефонные номера" - "Разрешает приложению вызывать любой номер, включая экстренные, без вашего участия. Вредоносное ПО может совершать ненужные и незаконные вызовы в службы неотложной помощи." + "управлять вибровызовом" + "Позволяет приложению управлять виброзвонком." + "управлять вспышкой" + "Позволяет приложению управлять вспышкой." + "проверять аппаратное обеспечение" + "Позволяет приложению управлять различными периферийными устройствами для проверки аппаратного обеспечения." + "посылать прямые вызовы на номера телефонов" + "Позволяет приложению вызывать телефонные номера без вмешательства пользователя. Вредоносные приложения могут осуществлять нежелательные вызовы. Это разрешение не позволяет приложению совершать вызовы служб экстренной помощи." + "посылать прямые вызовы на любые номера" + "Позволяет приложению осуществлять вызов любого номера, включая номера экстренной помощи, без вмешательства пользователя. Вредоносные приложения могут осуществить нежелательные или незаконные вызовы служб экстренной помощи." "управлять уведомлениями об обновлении местоположения" - "Разрешает включение/отключение уведомлений о местоположении по радиосвязи. Не используется обычными приложениями." - "открывать свойства проверки" - "Разрешает доступ на чтение и запись к свойствам, загруженным службой проверки. Не используется обычными приложениями." + "Позволяет включать/отключать отправку уведомлений об обновлениях местоположения по радиосвязи. Не предназначено для использования обычными приложениями." + "получать доступ к свойствам регистрации" + "Позволяет получать доступ для чтения/записи свойств, загруженных службой регистрации. Не предназначено для использования обычными приложениями." "выбирать виджеты" "Позволяет приложению сообщить системе, какие приложения могут использовать какие виджеты. Это разрешение позволяет приложениям предоставлять другим приложениям доступ к личной информации. Не предназначено для использования обычными приложениями." "изменять состояние телефона" - "Позволяет приложению управлять телефонными функциями устройства. Приложение с такими полномочиями может переключать сети, включать и выключать радиосвязь и т.д., не сообщая вам об этом." + "Позволяет приложению управлять функциями телефона в устройстве. Приложение, обладающее этим разрешением, может переключать сети, включать и выключать радио на телефоне и выполнять другие подобные действия без соответствующего уведомления." "считывать состояние телефона" - "Разрешает приложению использовать телефонные функции устройства. Приложение с такими полномочиями может определить номер данного телефона, наличие вызова, номер, с которым связан вызов и так далее." - "предотвращать переход телефона в режим ожидания" - "Разрешает приложению блокировать переход телефона в режим ожидания." - "включать и отключать телефон" - "Позволяет приложениям включать и выключать телефон." - "работа в режиме заводского тестирования" - "Работа в качестве теста производителя низкого уровня, что дает полный доступ к оборудованию телефона. Доступно только при работе телефона в режиме теста производителя." + "Позволяет приложению получить доступ к функциям телефона на устройстве. Приложение с таким разрешением может определить номер телефона устройства, наличие активного вызова, номер вызываемого/вызывающего абонента и тому подобное." + "предотвратить переключение телефона в спящий режим" + "Позволяет приложению запретить переход телефона в спящий режим" + "включать и выключать питание телефона" + "Позволяет приложению включать и отключать телефон." + "запустить в тестовом режиме" + "Выполнить стандартную проверку нижнего уровня, обеспечивающую полный доступ к аппаратному обеспечению телефона. Доступно, только в режиме стандартной проверки." "устанавливать фоновый рисунок" - "Разрешает приложению устанавливать системный фоновый рисунок." - "устанавливать подсказки по размеру фонового рисунка" - "Разрешает приложению устанавливать системные подсказки по размеру фонового рисунка." - "выполнять сброс системы и восстановление заводских настроек" - "Разрешает приложению полностью сбрасывать настройки системы до заводских, удаляя все данные, конфигурацию и установленные приложения." - "устанавливать часовой пояс" - "Разрешает приложению изменять часовой пояс телефона." + "Позволяет данному приложению устанавливать системный фоновый рисунок." + "давать рекомендации по размеру фоновых рисунков" + "Позволяет данному приложению устанавливать советы по размеру фоновых рисунков." + "восстанавливать параметры системы по умолчанию, установленные на заводе-изготовителе" + "Позволяет приложению восстановить стандартные настройки системы, удалив все данные, конфигурацию и установленные приложения." + "настраивать часовой пояс" + "Позволяет приложению изменять часовой пояс телефона." "обнаруживать известные аккаунты" - "Разрешает приложению получать список аккаунтов, известных телефону." + "Позволяет приложению получать список аккаунтов, известных телефону." "просматривать состояние сети" - "Позволяет приложению видеть состояние всех сетей." - "обладать полным доступом в Интернет" + "Позволяет приложению просматривать состояние всех сетей." + "неограниченный доступ в Интернет" "Позволяет приложению создавать сетевые сокеты." - "записывать настройки названий точек доступа" - "Разрешает приложению изменять настройки APN, например прокси и порт любого APN." - "изменять подключение к сети" - "Позволяет приложению изменять подключение к сети." - "изменить настройку использования фоновых данных" - "Позволяет приложению изменять настройку использования фоновых данных." + "записывать настройки имени точки доступа" + "Позволяет приложению изменять настройки APN, такие как прокси-сервер и порт любого APN." + "изменять настройки подключения к сети" + "Позволяет приложению изменять состояние подключаемости сети." + "изменить настройку использования данных в фоновом режиме" + "Позволяет приложению изменять настройку использования данных в фоновом режиме." "просматривать состояние Wi-Fi" - "Разрешает приложению просматривать сведения о состоянии Wi-Fi." + "Позволяет приложению просматривать сведения о состоянии Wi-Fi." "изменять состояние Wi-Fi" - "Разрешает приложению подключаться и отключаться от точек доступа Wi-Fi и вносить изменения в настроенные сети Wi-Fi." - "управлять Bluetooth" - "Разрешает приложению настраивать локальный телефон с Bluetooth, а также обнаруживать удаленные устройства и соединяться с ними." - "создавать Bluetooth-подключения" - "Позволяет приложению просматривать конфигурацию локального телефона Bluetooth, создавать и разрешать подключение к связанным устройствам." + "Позволяет приложению подключаться к точкам доступа Wi-Fi и отключаться от них, а также вносить изменения в конфигурацию сетей Wi-Fi." + + + + + "управление Bluetooth" + "Позволяет приложению настраивать локальный телефон Bluetooth, обнаруживать и выполнять сопряжение удаленных устройств." + "создавать подключения Bluetooth" + "Позволяет приложению просматривать конфигурацию локального телефона Bluetooth, создавать подключения с сопряженными устройствами." "отключать блокировку клавиатуры" - "Разрешает приложению отключать блокировку клавиш и связанную с ней защиту паролем. Пример нормального использования – отключение блокировки телефоном, когда он принимает вызов, и ее включение после окончания вызова." + "Позволяет приложению отключить блокировку клавиатуры и другие функции защиты паролем. Примером допустимого использования этой функции является отключение блокировки клавиатуры при получении входящего вызова и включение блокировки после завершения разговора." "считывать настройки синхронизации" - "Разрешает приложению считывать настройки синхронизации, например наличие синхронизации контактов." + "Позволяет приложению считывать настройки синхронизации, такие как включение синхронизации Контактов." "записывать настройки синхронизации" - "Разрешает приложению изменять настройки синхронизации, например синхронизацию контактов." - "считывать данные о синхронизации" - "Разрешает приложению считывать данные о синхронизации, например историю выполненных синхронизаций." - "считывать фиды с подпиской" - "Позволяет приложению получать сведения о синхронизированных фидах." - "записывать фиды с подпиской" - "Разрешает приложению изменять ваши синхронизированные фиды. Это может позволить вредоносному ПО изменять ваши синхронизированные фиды." + "Позволяет приложению изменять настройки синхронизации, например включение синхронизации Контактов." + "считывать статистику синхронизации" + "Позволяет приложению считывать статистику синхронизации, например историю произведенных синхронизаций." + "считывать каналы, на которые есть подписка" + "Позволяет приложению получить сведения о последних синхронизированных каналах." + "изменять каналы, на которые есть подписка" + "Позволяет приложению изменять синхронизированные каналы. Вредоносные приложения могут использовать эту возможность для изменения синхронизированных каналов." "выполнять чтение из пользовательского словаря" "Позволяет приложению считывать любые слова, имена и фразы личного пользования, которые могут храниться в пользовательском словаре." "записывать в пользовательский словарь" "Позволяет приложению записывать новые слова в пользовательский словарь." + + + + "Домашний" "Мобильный" @@ -344,31 +420,32 @@ "Рабочий факс" "Домашний факс" "Пейджер" - "Другое" "Другой" + "Особый" "Домашний" "Рабочий" - "Другое" "Другой" + "Особый" + "Мобильный" "Домашний" "Рабочий" - "Другое" "Другой" + "Особый" "Домашний" "Рабочий" "Другое" - "Другой" + "Особый" "Рабочий" - "Другое" "Другой" + "Особый" "AIM" @@ -382,72 +459,85 @@ "Введите PIN-код" "Неверный PIN-код!" - "Для разблокировки нажмите Menu и 0." + "Для разблокировки нажмите \"Меню\", а затем 0." "Номер экстренной службы" - "(Вне зоны обслуживания)" + "(Сеть не найдена)" "Экран заблокирован." - "Нажмите Menu для разблокировки или выполните экстренный вызов." - "Чтобы снять блокировку, нажмите Menu." - "Для разблокировки воспроизведите комбинацию" - "Экстренный вызов" - "Верно!" - "Неверно, попробуйте еще раз" + "Нажмите \"Меню\", чтобы разблокировать экран или вызвать службу экстренной помощи." + "Для разблокировки нажмите \"Меню\"." + "Для разблокировки введите графический ключ" + "Вызов службы экстренной помощи" + "Правильно!" + "Повторите попытку" "Идет зарядка (%d%%)" + + "Подключите зарядное устройство." "Нет SIM-карты." - "В телефоне нет SIM-карты." + "SIM-карта не установлена." "Вставьте SIM-карту." - "Заблокирована сетью" - "SIM-карта заблокирована PUK-кодом." + "Сеть заблокирована" + "SIM-карта заблокирована с помощью кода PUK." "См. руководство пользователя или свяжитесь со службой поддержки." "SIM-карта заблокирована." - "Разблокировка SIM-карты..." - "Вы неправильно воспроизвели комбинацию разблокировки %d раз. "\n\n"Повторите попытку через %d сек." - "Вы неверно воспроизвели комбинацию разблокировки %d раз(а). После %d неудачных попыток(ки) придется разблокировать телефон с помощью входа Google."\n\n" Повторите попытку через %d сек." - "Повторите попытку через %d сек." - "Забыли комбинацию?" - "Слишком много попыток ввести комбинацию!" + "Разблокировка SIM-карты…" + "Количество неудачных попыток ввода графического ключа разблокировки: %d. "\n\n"Повторите попытку через %d с." + "Количество неудачных попыток ввода графического ключа разблокировки: %d. После %d неудачных попыток вам будет предложено разблокировать телефон с помощью учетных данных Google.\n "\n\n" Повторите попытку через %d с." + "Повторите попытку через %d с." + "Забыли графический ключ?" + "Слишком много попыток ввода графического ключа!" "Для разблокировки войдите с помощью своего аккаунта Google" - "Имя пользователя (адрес электронной почты)" + "Имя пользователя (электронная почта)" "Пароль" - "Войти" - "Недействительное имя пользователя или пароль." + "Вход" + "Неверное имя пользователя или пароль." "%-l%P" "%-l%p" - "Очистить уведомления" + + "Нет уведомлений" "Текущие" "Уведомления" "%d%%" "Идет зарядка..." "Подключите зарядное устройство" - "Батарея садится:" - "осталось менее %d%%." - "Ошибка заводского теста" - "Действие FACTORY_TEST поддерживается только для пакетов, установленных в папке /system/app." - "Пакет, предоставляющий действие FACTORY_TEST, не найден." - "Перезагрузить" + "Батарея разряжена:" + "осталось менее %d%%" + + + "Не удалось провести стандартный тест" + "Действие FACTORY_TEST поддерживается только для пакетов, установленных в /system/app." + "Пакет, обеспечивающий действие FACTORY_TEST, не найден." + "Перезагрузка" "На странице по адресу \"%s\" сказано:" "JavaScript" "Перейти с этой страницы?"\n\n"%s"\n\n"Нажмите \"ОК\", чтобы продолжить, или \"Отмена\", чтобы остаться на текущей странице." - "Подтверждение" - "Сохранить этот пароль в браузере?" + "Подтвердите" + + + + + + + + + "Вы хотите, чтобы браузер запомнил этот пароль?" "Не сейчас" "Запомнить" "Никогда" - "У вас нет разрешения открывать эту страницу." + "У вас нет разрешения на открытие этой страницы." "Текст скопирован в буфер обмена." - "Еще" - "Мenu+" - "место" + "Дополнительно" + "Меню+" + "пробел" "ввод" "удалить" "Поиск" "1 месяц назад" - "Больше 1 месяца назад" + "Более месяца назад" "1 секунду назад" - "%d сек. назад" + "%d с. назад" "1 минуту назад" @@ -463,7 +553,7 @@ "через 1 секунду" - "через %d сек." + "через %d с." "через 1 минуту" @@ -471,7 +561,7 @@ "через 1 час" - "через %d час." + "через %d ч." "завтра" @@ -494,8 +584,8 @@ "%d дн. назад" - "через 1 сек." - "через %d сек." + "через 1 с." + "через %d с." "через 1 мин." @@ -503,50 +593,46 @@ "через 1 час" - "через %d час." + "через %d ч." "завтра" "через %d дн." - "%s" + "в %s" "в %s" - "в %s" - "день" - "дни" - "час" - "часы" - "мин" + "через %s" + "дн." + "дн." + "ч." + "ч." + "мин." "мин." - "сек" - "сек." - "неделя" - "недели" - "год" - "годы" - "По рабочим дням (пн-пт)" + "с." + "с." + "нед." + "нед." + "г." + "г." + "Каждый рабочий день (пн-пт)" "Ежедневно" - "Еженедельно в: %s" + "Еженедельно, %s" "Ежемесячно" "Ежегодно" - "Не удается воспроизвести видео" - "К сожалению, это видео не подходит для потокового воспроизведения на данном устройстве." - "К сожалению, это видео нельзя воспроизвести." + "Не удалось воспроизвести видео" + "Это видео не подходит для потокового воспроизведения на данном устройстве." + "Невозможно воспроизвести видео." "ОК" "%1$s, %2$s" "полдень" "Полдень" "полночь" "Полночь" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "Выбрать все" "Выбрать текст" - "Прекратить выбор текста" + "Остановить выделение текста" "Вырезать" "Вырезать все" "Копировать" @@ -555,9 +641,9 @@ "Копировать URL" "Способ ввода" "Добавить \"%s\" в словарь" - "Правка текста" + "Изменить текст" "Недостаточно места" - "В памяти телефона осталось мало места." + "Заканчивается место в памяти телефона." "ОК" "Отмена" "ОК" @@ -565,48 +651,50 @@ "Внимание" "ВКЛ" "ВЫКЛ" - "Выполнить действие с помощью" - "Использовать для этого действия по умолчанию." - "Значения по умолчанию можно сбросить в разделе Настройки главного экрана > Приложения > Управление приложениями." + "Завершить действие с помощью" + "Использовать по умолчанию для этого действия." + "Удалить настройки по умолчанию: главный экран > \"Настройки\" > \"Приложения\" > \"Управление приложениями\"." "Выберите действие" - "Нет приложений, которые могли бы выполнить это действие." - "Ой!" - "Приложение %1$s (процесс %2$s) неожиданно остановилось. Повторите попытку." - "Процесс %1$s неожиданно остановился. Повторите попытку." - "Ой!" + "Это действие не может выполнять ни одно приложение." + "Ошибка приложения!" + "Произошла неожиданная остановка приложения %1$s (процесс %2$s). Повторите попытку." + "Произошла неожиданная остановка процесса %1$s. Повторите попытку." + "Извините!" "Действие %1$s (в приложении %2$s) не отвечает." "Действие %1$s (в процессе %2$s) не отвечает." "Приложение %1$s (в процессе %2$s) не отвечает." "Процесс %1$s не отвечает." - "Закрыть принудительно" - "Подождать" - "Отладка" + "Принудительное закрытие" + + + "Подождите" + "Выполнить отладку" "Выберите действие для текста" "Громкость звонка" - "Громкость звука мультимедиа" - "Воспроизводится через Bluetooth" - "Громкость звонка" + "Громкость мультимедиа" + "Воспроизведение по каналу Bluetooth" + "Громкость входящего вызова" "Громкость входящего вызова Bluetooth" - "Громкость будильника" + "Громкость сигнала предупреждения" "Громкость уведомления" "Громкость" - "Мелодия звонка по умолчанию" - "Мелодия звонка по умолчанию (%1$s)" - "Тишина" - "Мелодии звонка" - "Неизвестная мелодия звонка" + "Мелодия по умолчанию" + "Мелодия по умолчанию (%1$s)" + "Без звука" + "Мелодии" + "Неизвестная мелодия" "Доступна сеть Wi-Fi" - "Доступны сети Wi-Fi" + "Доступна сеть Wi-Fi" - "Доступна открытая сеть Wi-Fi" - "Доступны открытые сети Wi-Fi" + "Найдена доступная сеть Wi-Fi" + "Найдены доступные сети Wi-Fi" - "Вставка символа" + "Введите символ" "Неизвестное приложение" - "Отправка SMS" - "Отправляется большое количество сообщений SMS. Выберите \"ОК\", чтобы продолжить, или \"Отмена\", чтобы остановить отправку." + "Отправка SMS-сообщений" + "Отправляется большое количество SMS-сообщений. Нажмите \"ОК\" для продолжения или \"Отмена\" для прекращения отправки." "ОК" "Отмена" "Установить" @@ -615,39 +703,48 @@ "Скрыть" "Показать все" "Идет загрузка…" - "Подключение через USB" - "Вы подключили телефон к компьютеру через USB. Выберите \"Подключиться\" для копирования файлов между компьютером и картой SD телефона." - "Подключиться" - "Не подключаться" - "Не удается использовать карту SD в качестве USB-хранилища." - "Подключение через USB" - "Выберите для копирования файлов на/с компьютера." + "устройство USB подключено" + "Телефон подключен к компьютеру через порт USB. Если необходимо копировать файлы с компьютера на SD-карту телефона (или наоборот), выберите \"Установить\"." + "Смонтировать" + "Не монтировать" + "При использовании SD-карты как USB-накопителя возникла неполадка." + "устройство USB подключено" + "Выберите копирование файлов на компьютер или с компьютера." "Выключить USB-накопитель" "Выберите, чтобы выключить USB-накопитель." "Выключить USB-накопитель" "Перед выключением USB-накопителя обязательно отключите USB-хост. Выберите \"Выключить\", чтобы выключить USB-накопитель." "Выключить" "Отмена" - "При выключении USB-накопителя произошла проблема. Убедитесь, что USB-хост отключен, и повторите попытку." + "При выключении USB-накопителя произошла неполадка. Убедитесь, что USB-хост отключен, и повторите попытку." "Форматировать карту SD" "Отформатировать карту SD? Все данные, находящиеся на карте, будут уничтожены." "Формат" - "Выбор способа ввода" - " АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЫЭЮЯ" - " 0123456789АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЫЭЮЯ" - "кандидаты" + + + + + "Выберите способ ввода" + " ABCDEFGHIJKLMNOPQRSTUVWXYZ" + " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "варианты" "Подготовка карты SD" - "Поиск ошибок" + + "Пустая карта SD" - "Карта SD пуста или использует неподдерживаемую файловую систему." + + "Поврежденная карта SD" - "Карта SD повреждена. Может потребоваться переформатировать ее." + + "Карта SD неожиданно извлечена" "Перед извлечением карты SD отключите ее во избежание потери данных." "Безопасное удаление карты SD" - "Теперь карту SD можно безопасно удалить." - "Карта SD удалена" - "Карта SD была удалена. Для увеличения емкости устройства вставьте новую карту SD." + + + "Отсутствует карта SD" + + "Подходящих действий не найдено" "обновлять статистику использования компонентов" "Позволяет изменять собранную статистику использования компонентов. Не предназначено для использования обычными приложениями." @@ -661,4 +758,8 @@ "Выполнить" "Набрать номер"\n"%s" "Создать контакт"\n"с номером %s" + + + + diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml new file mode 100644 index 0000000000000..383126a68fdf4 --- /dev/null +++ b/core/res/res/values-sv/strings.xml @@ -0,0 +1,765 @@ + + + + "B" + "kB" + "MB" + "GB" + "TB" + "PB" + + + "<utan titel>" + "…" + "(Inget telefonnummer)" + "(Okänd)" + "Röstbrevlåda" + "MSISDN1" + "Anslutningsproblem eller ogiltig MMI-kod." + "Tjänsten har aktiverats." + "Tjänsten har aktiverats för:" + "Tjänsten har inaktiverats." + "Registreringen slutförd." + "Radering lyckades." + "Fel lösenord." + "MMI slutförd." + "Den gamla PIN-koden som du angav är fel." + "PUK-koden som du angav är fel." + "PIN-koderna som du angav matchar inte." + "Ange en PIN-kod som är 4 till 8 siffror." + "Ditt SIM-kort är PUK-låst. Ange PUK-koden om du vill låsa upp det." + "Ange PUK2-koden för att häva spärren av SIM-kortet." + "Nummerpresentatör för inkommande samtal" + "Nummerpresentatör för utgående samtal" + "Vidarebefordra samtal" + "Samtal väntar" + "Samtalsspärr" + "Byt lösenord" + "Byt PIN-kod" + + + + + + + + + + + + + "Nummerpresentatören är begränsad som standard. Nästa samtal: Begränsad" + "Nummerpresentatörens standardinställning är begränsad. Nästa samtal: Inte begränsad" + "Nummerpresentatörens standardinställning är inte begränsad. Nästa samtal: Begränsad" + "Nummerpresentatörens standardinställning är inte begränsad. Nästa samtal: Inte begränsad" + "Tjänsten är inte etablerad." + "Det går inte att ändra inställningen för nummerpresentatör." + "Begränsad åtkomst har ändrats" + "Datatjänsten är blockerad." + "Räddningstjänsten är blockerad." + "Tjänsten röst/SMS är blockerad." + "Alla röst-/SMS-tjänster har blockerats." + "Röst" + "Data" + "FAX" + "SMS" + "Asynkront" + "Synkronisera" + "Paket" + "PAD" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "{0}: Vidarebefordras inte" + "{0}: {1}" + "{0}{1} efter {2} sekunder" + "{0}. Vidarebefordras inte" + "{0}: Vidarebefordras inte" + + + + + "OK" + "Webbsidan innehåller ett fel." + "Webbadressen kunde inte hittas." + "Webbplatsens autentiseringsmetod stöds inte." + "Det gick inte att autentisera." + "Det gick inte att autentisera via proxyservern." + "Det gick inte att ansluta till servern." + "Servern kommunicerade inte. Försök igen senare." + "Anslutningen till servern har kopplats ifrån." + "Sidan innehåller för många serveromdirigeringar." + "Protokollet stöds inte." + "Det gick inte att upprätta en säker anslutning." + "Sidan kunde inte öppnas eftersom webbadressen är ogiltig." + "Det gick inte att komma åt filen." + "Den begärda filen hittades inte." + "För många begäranden bearbetas. Försök igen senare." + + + "Synkronisera" + "Synkronisera" + "För många %s-borttagningar." + "Telefonens lagringsutrymme är fullt! Radera några filer för att frigöra utrymme." + "Jag" + "Telefonalternativ" + "Tyst läge" + "Aktivera trådlöst" + "Inaktivera trådlöst" + "Skärmlås" + "Stäng av" + "Avslutar…" + "Din telefon stängs av." + "Inga nya program." + "Telefonalternativ" + "Skärmlås" + "Stäng av" + "Tyst läge" + "Ljudet är AV" + "Ljudet är PÅ" + "Flygplansläge" + "Flygplansläge är AKTIVERAT" + "Flygplansläge är INAKTIVERAT" + "Säkert läge" + "Android-system" + "Tjänster som kostar pengar" + "Tillåter att program gör saker som kostar pengar." + "Dina meddelanden" + "Läs och skriv SMS, e-post och andra meddelanden." + "Dina personliga uppgifter" + "Direktåtkomst till dina kontakter och kalendern som har lagrats på telefonen." + "Din plats" + "Övervaka din fysiska plats" + "Nätverkskommunikation" + "Tillåt att program kommer åt olika nätverksfunktioner." + "Dina Google-konton" + "Få åtkomst till tillgängliga Google-konton." + "Kontroller för maskinvara" + "Direkt åtkomst till maskinvara på handenheten." + "Telefonsamtal" + "Övervaka, spela in och bearbeta telefonsamtal" + "Systemverktyg" + "Åtkomst och kontroll av systemet på lägre nivå." + "Utvecklingsverktyg" + "Funktioner som endast behövs för programutvecklare." + + + + + "inaktivera eller ändra statusfält" + "Tillåter att programmet inaktiverar statusfältet eller lägger till och tar bort systemikoner." + "expandera/komprimera statusfält" + "Tillåter att program expanderar eller komprimerar statusfältet." + "spärra utgående samtal" + "Tillåter att program hanterar utgående samtal och ändrar numret som ska ringas upp. Skadliga program kan övervaka, omdirigera eller förhindra utgående samtal." + "ta emot SMS" + "Tillåter att program tar emot och bearbetar SMS-meddelanden. Skadliga program kan övervaka dina meddelanden eller ta bort dem utan att visa dem för dig." + "ta emot MMS" + "Tillåter att program tar emot och bearbetar MMS-meddelanden. Skadliga program kan övervaka dina meddelanden eller ta bort dem innan du har sett dem." + "skicka SMS" + "Tillåter att programmet skickar SMS-meddelanden. Skadliga program kan skicka meddelanden utan ditt godkännande vilket kan kosta pengar." + "läsa SMS eller MMS" + "Tillåter att program läser SMS-meddelanden som sparats på din telefon eller SIM-kort. Skadliga program kan läsa dina konfidentiella meddelanden." + "redigera SMS eller MMS" + "Tillåter att program skriver till SMS-meddelanden som lagrats på din telefon eller SIM-kort. Skadliga program kan radera dina meddelanden." + "ta emot WAP" + "Tillåter att program tar emot och bearbetar WAP-meddelanden. Skadliga program kan övervaka dina meddelanden eller ta bort dem utan att visa dem för dig." + "hämta program som körs" + "Tillåter att program hämtar information om uppgifter som körs och har körts. Skadliga program kan upptäcka privat information om andra program." + "byt ordning på program som körs" + "Tillåter att ett program flyttar uppgifter till förgrunden eller bakgrunden. Skadliga program kan tvinga sig till förgrunden utan att du kan styra det." + "aktivera felsökning av program" + "Tillåter att ett program aktiverar felsökning för ett annat program. Skadliga program kan använda detta för att avsluta andra program." + "ändra dina gränssnittsinställningar" + "Tillåter att ett program ändrar den aktuella konfigurationen, till exempel språk eller övergripande teckenformat." + "starta om andra program" + "Tillåter att ett program framtvingar omstart av andra program." + "tvinga program att avsluta" + "Tillåter att ett program tvingar en aktivitet som finns i förgrunden att avsluta och gå tillbaka. Behövs inte för vanliga program." + "hämta systemets interna status" + "Tillåter att ett program hämtar systemets interna status. Skadliga program kan hämta privat och skyddad information som de normalt aldrig ska behöva." + + + + + + + + + "övervaka och styra alla program som öppnas" + "Tillåter att ett program övervakar och styr hur systemet startar aktiviteter. Skadliga program kan bryta systemet helt. Den här behörigheten behövs bara för programmering, aldrig för vanlig telefonanvändning." + "skicka meddelande om borttaget paket" + "Tillåter att ett program skickar ett meddelande om att ett programpaket har tagits bort. Skadliga program kan använda detta för att avsluta alla andra program som körs." + "skicka SMS-mottagen sändning" + "Tillåter att ett program sänder ut en avisering när SMS tas emot. Skadliga program kan använda detta för att förfalska inkommande SMS-meddelanden." + "skicka WAP-PUSH-mottagen sändning" + "Tillåter att ett program skickar ut en avisering när ett WAP PUSH-meddelande tas emot. Skadliga program kan använda detta för att förfalska mottagning av MMS eller för att obemärkt byta ut innehållet på en webbsida mot skadligt innehåll." + "begränsa antalet processer som körs" + "Tillåter att ett program styr högsta antalet processer som körs. Behövs inte för vanliga program." + "gör så att alla bakgrundsprogram stängs" + "Tillåter att ett program bestämmer om aktiviteter alltid är slutförda när de hamnar i bakgrunden. Ska inte behövas för vanliga program." + "ändra batteristatistik" + "Tillåter att samlad batteristatistik ändras. Används inte av vanliga program." + + + + + "visa otillåtna fönster" + "Tillåter att fönster skapas och används av det interna systemgränssnittet. Används inte av vanliga program." + "visa varningar på systemnivå" + "Tillåter att ett program visar fönster med systemvarningar. Skadliga program kan överta hela telefonens skärm." + "ändra global animeringshastighet" + "Tillåter att ett program när som helst ändrar den globala animeringshastigheten (snabbare eller långsammare)." + "hantera programtoken" + "Tillåter att program skapar och hanterar egna token och förbigår normala Z-beställningar. Behövs inte för vanliga program." + "trycka på knappar och styrknappar" + "Tillåter att ett program levererar egna inmatningshändelser (knapptryckningar, osv.) till andra program. Skadliga program använder detta för att kapa telefonen." + "registrera vad du skriver och vilka åtgärder du vidtar" + "Tillåter att program övervakar knapparna som du trycker på, till och med när du använder andra program (till exempel när du anger ett lösenord). Ska inte behövas för vanliga program." + "binda till en metod för indata" + "Innehavaren tillåts att binda till den översta nivåns gränssnitt för en inmatningsmetod. Ska inte behövas för vanliga program." + "ändra bildskärmens rikting" + "Tillåter att ett program när som helst ändrar skärmens rotering. Behövs inte för vanliga program." + "skicka Linux-signaler till program" + "Tillåter att programmet begär att den angivna signalen skickas till alla beständiga processer." + "se till att programmet alltid körs" + "Tillåter att ett program gör vissa delar beständiga så att systemet inte kan använda det för andra program." + "ta bort program" + "Tillåter att ett program tar bort Android-paket. Skadliga program kan använda detta för att ta bort viktiga program." + "ta bort de andra programmens uppgifter" + "Tillåter att ett program tar bort användardata." + "ta bort de andra programmens cacheminnen" + "Tillåter att ett program raderar cachefiler." + "mäta telefonens lagringsutrymme" + "Tillåter att ett program hämtar kod, data och cachestorlekar" + "installera program direkt" + "Tillåter att ett program installerar nya eller uppdaterade Android-paket. Skadliga program kan använda detta för att lägga till nya program med godtyckliga och starka behörigheter." + "ta bort cacheinformation för alla program" + "Tillåter att ett program frigör lagringsutrymme i telefonen genom att ta bort filer i programmets katalog för cachelagring. Åtkomst är mycket begränsad, vanligtvis till systemprocesser." + "läsa systemets loggfiler" + "Tillåter att ett program läser från systemets olika loggfiler. Det innebär att programmet kan upptäcka allmän information om vad du gör med telefonen, men den bör inte innehålla personlig eller privat information." + "läsa/skriva till resurser som ägs av diag" + "Tillåter att ett program läser och skriver till en resurs som ägs av diag-gruppen; till exempel filer i /dev. Detta kan eventuellt påverka systemets stabilitet och säkerhet. Detta bör ENDAST används av tillverkaren eller operatören för maskinvaruspecifik diagnostik." + "aktivera eller inaktivera programkomponenter" + "Tillåter att ett program ändrar inställningen för om en komponent i ett annat program har aktiverats eller inte. Skadliga program kan använda detta för att inaktivera viktiga telefonfunktioner. Var försiktig med behörigheten, eftersom programkomponenter kan bli oanvändbara, inkonsekventa eller ostabila." + "ange önskade program" + "Tillåter att ett program ändrar dina önskade program. Skadliga program kan utan varning ändra de program som körs och förfalska dina befintliga program så att de samlar privata data från dig." + "ändra globala systeminställningar" + "Tillåter att ett program ändrar systemets inställningar. Skadliga program kan skada systemets konfiguration." + "ändra skyddade systeminställningar" + "Tillåter att ett program ändrar systemets data för skyddade inställningar. Används inte av vanliga program." + "ändra kartan för Googles tjänster" + "Tillåter att ett program ändrar kartan för Google-tjänster. Används inte av vanliga program." + "starta automatiskt vid systemstart" + "Tillåter att ett program startar när systemet har startats om. Detta kan innebära att det tar längre tid att starta om telefonen och att telefonen blir långsammare i och med att programmet hela tiden körs i bakgrunden." + "Skicka sticky broadcast" + "Tillåter att ett program skickar sticky broadcasts, som finns kvar när sändningen är slut. Skadliga program kan göra telefonen seg eller instabil genom att se till att den använder för mycket minne." + "läsa kontaktinformation" + "Tillåter att ett program läser alla kontaktuppgifter (adresser) som har lagrats på din telefon. Skadliga program kan använda detta för att skicka dina data till andra personer." + "skriva kontaktuppgifter" + "Tillåter att ett program ändrar kontaktuppgifter (adress) som har lagrats på din telefon. Skadliga program kan använda detta för att radera eller ändra kontaktuppgifter." + "skriva ägarinformation" + "Tillåter att ett program ändrar information om telefonens ägare som har lagrats på din telefon. Skadliga program kan använda detta för att radera eller ändra ägaruppgifter." + "läsa information om ägare" + "Tillåter att ett program läser information om telefonens ägare som har lagrats på telefonen. Skadliga program kan använda detta för att läsa telefonens ägaruppgifter." + "läsa kalenderinformation" + "Tillåter att ett program läser alla händelser i kalendern som har lagrats på din telefon. Skadliga program kan använda detta för att skicka din kalender till andra personer." + "skriva kalenderdata" + "Tillåter att ett program ändrar kalenderuppgifterna som har lagrats på din telefon. Skadliga program kan använda detta för att radera eller ändra kalenderuppgifter." + "skenplatser för att testa" + "Skapa skenplatser för att testa. Skadliga program kan använda detta för att åsidosätta platsen och/eller statusen som returneras av riktiga platser, till exempel GPS- eller nätverksleverantörer." + "få åtkomst till extra kommandon för platsleverantör" + "Få åtkomst till extra kommandon för platsleverantörer. Skadliga program kan använda detta för att störa hur GPS eller andra platskällor fungerar." + + + + + "hitta plats (GPS)" + "Få åtkomst till detaljerade platskällor som Global Positioning System på telefonen, om det är tillgängligt. Skadliga program kan använda detta för att identifiera var du befinner dig, vilket drar mycket batteri." + "grov (nätverksbaserad) plats" + "Få åtkomst till grova platser, till exempel mobilnätverkets databas, för att bestämma ungefärlig plats för en telefon. Skadliga program kan använda detta för att avgöra ungefär var du befinner dig." + "få åtkomst till SurfaceFlinger" + "Tillåter att program använder lågnivåfunktioner i SurfaceFlinger." + "läsa rambuffert" + "Tillåter att program använder innehållet i rambufferten." + "ändra dina ljudinställningar" + "Tillåter att ett program ändrar globala ljudinställningar, till exempel volym och routning." + "spela in ljud" + "Tillåter att program får åtkomst till sökvägen för ljudinspelning." + "ta bilder" + "Tillåter att program tar kort med kameran. Då kan programmet när som helst samla bilderna som visas i kameran." + "inaktivera telefonen permanent" + "Tillåter att programmet inaktiverar hela telefonen permanent. Detta är mycket farligt." + "tvinga omstart av telefon" + "Tillåter att ett program tvingar telefonen att starta om." + "montering och demontering av filsystem" + "Tillåter att programmet monterar och demonterar filsystem för flyttbara lagringsmedia." + "formatera extern lagring" + "Tillåter att programmet formaterar flyttbara lagringsmedia." + "kontrollera vibration" + "Tillåter att programmet styr vibratorn." + "styra lampa" + "Tillåter att programmet styr lampan." + "testa maskinvara" + "Tillåter att ett program styr kringutrustning i syfte att testa maskinvara." + "ringa telefonnummer direkt" + "Tillåter att programmet ringer telefonnummer utan åtgärd från dig. Skadliga program kan orsaka oväntade samtal på din telefonräkning. Observera att programmet inte tillåts att ringa nödsamtal." + "ringa telefonnummer direkt" + "Tillåter att programmet ringer ett telefonnummer, inklusive nödnummer, utan att du behöver göra något. Skadliga program kan ringa onödiga och olagliga samtal till räddningtjänsten." + "styra meddelanden för platsuppdatering" + "Tillåter aktivering och inaktivering av avisering om platsuppdatering i radion. Används inte av vanliga program." + "få åtkomst till incheckningsegenskaper" + "Tillåter läs/skrivåtkomst till egenskaper som läggs upp via incheckningstjänsten. Används inte av vanliga program." + "välja widgetar" + "Tillåter att programmet instruerar systemet vilka widgetar som kan användas av vilket program. Med den här behörigheten kan åtkomst till personliga data beviljas andra program. Används inte av vanliga program." + "ändra telefonstatus" + "Tillåter att programmet styr enhetens telefonfunktioner. Ett program med denna behörighet kan växla nätverk, aktivera och inaktivera telefonens radio och så vidare utan att ens meddela dig." + "läsa telefonstatus" + "Tillåter att programmet kommer åt enhetens telefonfunktioner. Ett program som har den här behörigheten kan identifiera telefonens telefonnummer, om ett samtal pågår, numret som samtalet är kopplat till och så vidare." + "förhindra att telefonen sätts i viloläge" + "Tillåter att ett program förhindrar att telefonen går in i viloläge." + "sätta på eller stänga av telefonen" + "Tillåter att ett program sätter på eller stänger av telefonen." + "kör i fabrikstestläge" + "Köra som ett testläge för tillverkaren på låg nivå. På så sätt får du fullständig åtkomst till telefonens maskinvara. Är endast tillgänglig när telefonen körs i tillverkarens testläge." + "ange bakgrund" + "Tillåter att programmet anger systemets bakgrund." + "ange tips för bakgrundsstorlek" + "Tillåter att programmet ger tips om systemets bakgrundsstorlek." + "återställa systemets fabriksinställningar" + "Tillåter att ett program helt återställer systemets fabriksinställningar. Alla data, inställningar och installerade program raderas." + "ange tidszon" + "Tillåter att ett program ändrar telefonens tidszon." + "upptäcka kända konton" + "Tillåter att ett program hämtar en lista över konton som telefonen känner till." + "visa nätverksstatus" + "Tillåter att ett program ser status för alla nätverk." + "fullständig Internetåtkomst" + "Tillåter att ett program skapar nätverksuttag." + "skriva inställningar för åtkomstpunktens namn" + "Tillåter att ett program ändrar APN-inställningarna, till exempel Proxy och Port för alla APN." + "ändra nätverksanslutning" + "Tillåter att ett program ändrar statusens nätverksanslutning." + "ändra inställningar för användning av bakgrundsdata" + "Tillåter att ett program ändrar inställningen för användning av bakgrundsdata." + "visa Wi-Fi-status" + "Tillåter att ett program visar information om statusen för Wi-Fi." + "byta Wi-Fi-status" + "Tillåter att ett program ansluter till och kopplar från Wi-Fi-åtkomstpunkter och gör ändringar i konfigurerade Wi-Fi-nätverk." + + + + + "administrera bluetooth" + "Tillåter att ett program konfigurerar den lokala Bluetooth-telefonen samt upptäcker och parkopplar den med fjärranslutna enheter." + "skapa Bluetooth-anslutningar" + "Tillåter att ett program ser den lokala Bluetooth-telefonens konfiguration, och skapar och accepterar anslutningar med parkopplade enheter." + "inaktivera tangentlås" + "Tillåter att ett program inaktiverar tangentlåset och tillhörande lösenordsskydd. Ett exempel på detta är att telefonen inaktiverar tangentlåset vid inkommande samtal och sedan aktiverar det igen när samtalet är avslutat." + "läsa synkroniseringsinställningar" + "Tillåter att ett program läser synkroniseringsinställningarna, till exempel om synkronisering har aktiverats för kontakter." + "skriva synkroniseringsinställningar" + "Tillåter att ett program ändrar synkroniseringsinställningarna, till exempel om synkronisering har aktiverats för kontakter." + "läsa synkroniseringsstatistik" + "Tillåter att ett program läser synkroniseringsstatistiken, t.ex. historiken över synkroniseringar som har inträffat." + "läsa flöden som du prenumererar på" + "Tillåter att ett program får information om aktuella synkroniserade flöden." + "skriva flöden som du prenumererar på" + "Tillåter att ett program ändrar dina aktuella synkroniserade flöden. Det kan innebära att ett skadligt program kan ändra dina synkroniserade flöden." + "läsa användardefinierad ordlista" + "Tillåt att ett program läser alla privata ord, namn och fraser som användaren lagrar i sin ordlista." + "skriva till användardefinierad ordlista" + "Tillåter att ett program skriver in nya ord i användarordlistan." + + + + + + "Hem" + "Mobil" + "Arbete" + "Fax, arbete" + "Hemfax" + "Personsökare" + "Övrigt" + "Anpassad" + + + "Hem" + "Arbete" + "Övrigt" + "Anpassad" + + "Mobil" + + "Hem" + "Arbete" + "Övrigt" + "Anpassad" + + + "Hem" + "Arbete" + "Övrigt" + "Anpassad" + + + "Arbete" + "Övrigt" + "Anpassad" + + + "AIM" + "Windows Live" + "Yahoo" + "Skype" + "QQ" + "Google Talk" + "ICQ" + "Jabber" + + "Ange PIN-kod" + "Fel PIN-kod!" + "Tryck på Meny och sedan på 0 om du vill låsa upp." + "Nödsamtalsnummer" + "(Ingen tjänst)" + "Skärmen har låsts." + "Tryck på Meny om du vill låsa upp eller ringa nödsamtal." + "Tryck på Meny om du vill låsa upp." + "Rita grafiskt lösenord för att låsa upp" + "Nödsamtal" + "Korrekt!" + "Försök igen" + "Laddar (%d%%)" + + + "Anslut din laddare." + "Inget SIM-kort." + "Inget SIM-kort i telefonen." + "Sätt i ett SIM-kort." + "Nätverk låst" + "SIM-kortet är PUK-låst." + "Se användarhandboken eller kontakta Kundtjänst." + "SIM-kortet är låst." + "Låser upp SIM-kort…" + "Du har ritat ditt grafiska lösenord fel %d gånger. "\n\n"Försök igen om %d sekunder." + "Du har ritat ditt grafiska lösenord fel %d gånger. Efter %d försök till kommer du att uppmanas att låsa upp telefonen med din Google-inloggning."\n\n" Försök igen om %d sekunder." + "Försök igen om %d sekunder." + "Glömt ditt grafiska lösenord?" + "För många försök med grafiskt lösenord!" + "Logga in med ditt Google-konto om du vill låsa upp" + "Användarnamn (e-post)" + "Lösenord" + "Logga in" + "Ogiltigt användarnamn eller lösenord." + "%-l%P" + "%-l%p" + + + "Inga aviseringar" + "Pågående" + "Meddelanden" + "%d%%" + "Laddar…" + "Anslut laddaren" + "Batteriet håller på att ta slut:" + "Mindre än %d%% återstår." + + + "Det gick fel vid fabrikstestet" + "Åtgärden FACTORY_TEST stöds endast för paket som har installerats i /system/app." + "Vi hittade inget paket som erbjuder åtgärden FACTORY_TEST." + "Starta om" + "På sidan på %s står det:" + "JavaScript" + "Vill du lämna den här den här sidan?"\n\n"%s"\n\n"Tryck på OK om du vill fortsätta eller på Avbryt om du vill vara kvar på den aktuella sidan." + "Bekräfta" + + + + + + + + + "Vill du att webbläsaren ska komma ihåg lösenordet?" + "Inte nu" + "Kom ihåg" + "Aldrig" + "Du har inte behörighet att öppna den här sidan." + "Text har kopierats till urklipp." + "Mer" + "Meny+" + "utrymme" + "retur" + "ta bort" + "Sök" + "för 1 månad sedan" + "För mer än en månad sedan" + + "för 1 sekund sedan" + "för %d sekunder sedan" + + + "för 1 minut sedan" + "för %d minuter sedan" + + + "för 1 timme sedan" + "för %d timmar sedan" + + + "igår" + "för %d dagar sedan" + + + "om 1 sekund" + "om %d sekunder" + + + "om 1 minut" + "om %d minuter" + + + "om 1 timme" + "om %d timmar" + + + "imorgon" + "om %d dagar" + + + "för 1 sek sedan" + "för %d sekunder sedan" + + + "för 1 minut sedan" + "för %d minuter sedan" + + + "för 1 timme sedan" + "för %d timmar sedan" + + + "igår" + "%d dagar sedan" + + + "om 1 sekund" + "om %d sek" + + + "om 1 minut" + "om %d minuter" + + + "om 1 timme" + "om %d timmar" + + + "imorgon" + "om %d dagar" + + "den %s" + "vid %s" + "%s" + "dag" + "dagar" + "timme" + "timmar" + "minut" + "minuter" + "sekunder" + "sekunder" + "vecka" + "veckor" + "år" + "år" + "Alla vardagar (mån–fre)" + "Varje dag" + "Varje vecka på %s" + "Varje månad" + "Varje år" + "Det går inte att spela upp videon" + "Videon kan tyvärr inte spelas upp i den här enheten." + "Det går tyvärr inte att spela upp den här videon." + "OK" + "%1$s, %2$s" + "eftermiddag" + "Mitt på dagen" + "midnatt" + "Midnatt" + "%1$02d:%2$02d" + "%1$d:%2$02d:%3$02d" + "Välj alla" + "Markera text" + "Sluta välja text" + "Klipp ut" + "Klipp ut alla" + "Kopiera" + "Kopiera alla" + "Klistra in" + "Kopiera webbadress" + "Indatametod" + "Lägg till %s i ordlistan" + "Redigera text" + "Dåligt med utrymme" + "Telefonens lagringsutrymme håller på att ta slut." + "OK" + "Avbryt" + "OK" + "Avbryt" + "Obs!" + "PÅ" + "AV" + "Slutför åtgärd genom att använda" + "Använd som standard för denna åtgärd." + "Rensa standardinställning i Startinställningar > Program > Hantera program." + "Välj en åtgärd" + "Inga program kan utföra den här åtgärden." + "Tyvärr!" + "Processen %2$s för programmet %1$s stoppades oväntat. Försök igen." + "Processen %1$s avslutades oväntat. Försök igen." + "Tyvärr!" + "Aktiviteten %1$s (i programmet %2$s) svarar inte." + "Aktiviteten %1$s (i processen %2$s) svarar inte." + "Programmet %1$s (i processen %2$s) svarar inte." + "Processen %1$s svarar inte." + "Tvinga fram en stängning" + + + "Vänta" + "Felsökning" + "Välj en åtgärd för text" + "Ringvolym" + "Mediavolym" + "Spelar upp genom Bluetooth" + "Samtalsvolym" + "Samtalsvolym för Bluetooth" + "Larmvolym" + "Aviseringsvolym" + "Volym" + "Standardringsignal" + "Standardringsignal (%1$s)" + "Tyst" + "Ringsignaler" + "Okänd ringsignal" + + "Wi-Fi-nätverk är tillgängliga" + "Wi-Fi-nätverk är tillgängliga" + + + "Öppna Wi-Fi-nätverk är tillgängliga" + "Öppna Wi-Fi-nätverk är tillgängliga" + + "Infoga tecken" + "Okänt program" + "Skickar SMS" + "Flera SMS-meddelanden skickas. Tryck på OK om du vill fortsätta eller på Avbryt om du vill avsluta sändningen." + "OK" + "Avbryt" + "Ställ in" + "Standardinställning" + "Inga behörigheter krävs" + "Dölj" + "Visa alla" + "Läser in…" + "USB-ansluten" + "Du har anslutit telefonen till datorn via USB. Välj Montera om du vill kopiera filer mellan datorn och telefonens SD-kort." + "Montera" + "Montera inte" + "Det gick inte att använda ditt SD-kort för USB-lagring." + "USB-ansluten" + "Välj om du vill kopiera filer till/från din dator." + "Inaktivera USB-lagring" + "Välj om USB-lagring ska inaktiveras." + "Inaktivera USB-lagring" + "Innan du inaktiverar USB-lagring måste du kontrollera att du har demonterat USB-värden. Välj Inaktivera om du vill inaktivera USB-lagring." + "Inaktivera" + "Avbryt" + "Ett problem uppstod när vi skulle inaktivera USB-lagringsplatsen. Kontrollera att USB-värden har demonterats och försök igen." + "Formatera SD-kort" + "Vill du formatera SD-kortet? Alla data på ditt kort kommer att gå förlorade." + "Format" + + + + + "Välj indatametod" + " ABCDEFGHIJKLMNOPQRSTUVWXYZ" + " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "kandidater" + "Förbereder SD-kort" + + + "Tomt SD-kort" + + + "Skadat SD-kort" + + + "SD-kort togs oväntat bort" + "Demontera SD-kort innan borttagning för att undvika dataförlust." + "Säkert att ta bort SD-kort" + + + "Borttaget SD-kort" + + + "Inga matchande aktiviteter hittades" + "uppdatera statistik över användning av komponenter" + "Tillåter att samlad komponentstatistik ändras. Används inte av vanliga program." + "Peka två gånger för zoomkontroll" + "Fel när widgeten expanderades" + "Kör" + "Sök" + "Skicka" + "Nästa" + "Färdig" + "Utför" + "Slå nummer "\n"med %s" + "Skapa kontakt"\n"med %s" + + + + + diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml new file mode 100644 index 0000000000000..ccaa08bf0db71 --- /dev/null +++ b/core/res/res/values-tr/strings.xml @@ -0,0 +1,765 @@ + + + + "B" + "KB" + "MB" + "GB" + "TB" + "PB" + + + "<başlıksız>" + "…" + "(Telefon numarası yok)" + "(Bilinmiyor)" + "Sesli Mesaj" + "MSISDN1" + "Bağlantı sorunu veya geçersiz MMI kodu." + "Hizmet etkindi." + "Hizmet şunun için etkinleştirildi:" + "Hizmet devre dışı bırakıldı." + "Kayıt işlemi başarılı oldu." + "Silme işlemi başarılı." + "Yanlış şifre." + "MMI tamamlandı." + "Yazdığınız eski PIN doğru değil." + "Yazdığınız PUK doğru değil." + "Girdiğiniz PIN kodları eşleşmiyor." + "4 ila 8 rakamdan oluşan bir PIN girin." + "SIM kartınızın PUK kilidi devrede. Kilidi açmak için PUK kodunu yazın." + "Engellenen SIM kartı açmak için PUK2 kodunu yazın." + "Gelen Çağrı Kimliği" + "Giden Çağrı Kimliği" + "Çağrı yönlendirme" + "Çağrı bekletme" + "Çağrı engelleme" + "Şifre değişikliği" + "PIN kodu değişikliği" + + + + + + + + + + + + + "Arayan kimliği varsayılanları kısıtlanmıştır. Sonraki çağrı: Kısıtlanmış" + "Arayan kimliği varsayılanları kısıtlanmıştır. Sonraki çağrı: Kısıtlanmamış" + "Arayan kimliği varsayılanları kısıtlanmamıştır. Sonraki çağrı: Kısıtlanmış" + "Arayan kimliği varsayılanları kısıtlanmamıştır. Sonraki çağrı: Kısıtlanmamış" + "Hizmet sağlanamadı." + "Arayan kimliği ayarı değiştirilemez." + "Kısıtlanmış erişim değiştirildi" + "Veri hizmeti engellendi." + "Acil durum hizmeti engellendi." + "Ses/SMS hizmeti engellendi." + "Tüm ses/SMS hizmetleri engellendi." + "Ses" + "Veri" + "FAKS" + "SMS" + "Asenk." + "Senk." + "Paket" + "PAD" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "{0}: Yönlendirilmedi" + "{0}: {1}" + "{0}: {2} saniye sonra {1}" + "{0}: Yönlendirilmedi" + "{0}: Yönlendirilmedi" + + + + + "Tamam" + "Web sayfası hata içeriyor." + "URL bulunamadı." + "Site kimlik doğrulaması şeması desteklenmiyor." + "Kimlik doğrulanamadı." + "Proxy sunucusu üzerinden kimlik doğrulanamadı." + "Sunucu ile bağlantı kurulamadı." + "Sunucu iletişim kuramadı. Daha sonra yeniden deneyin." + "Sunucuya bağlanma işlemi zaman aşımına uğradı." + "Sayfada çok fazla sunucu yeniden yönlendirmesi bulunuyor." + "Protokol desteklenmiyor." + "Güvenli bir bağlantı kurulamadı." + "URL geçersiz olduğundan sayfa açılamadı." + "Dosyaya erişilemedi." + "İstenen dosya bulunamadı." + "Çok fazla sayıda istek işleniyor. Daha sonra yeniden deneyin." + + + "Senk." + "Senk." + "Çok fazla %s silme var." + "Telefonun depolama alanı doldu! Yer açmak için bazı dosyaları silin." + "Ben" + "Telefon seçenekleri" + "Sessiz mod" + "Kablosuzu aç" + "Kablosuzu kapat" + "Ekran kilidi" + "Kapat" + "Kapanıyor…" + "Telefonunuz kapanacak." + "Hiçbir yeni uygulama yok." + "Telefon seçenekleri" + "Ekran kilidi" + "Kapat" + "Sessiz mod" + "Ses KAPALI" + "Ses AÇIK" + "Uçak modu" + "Uçak modu AÇIK" + "Uçak modu KAPALI" + "Güvenli mod" + "Android Sistemi" + "Size maliyet getiren hizmetler" + "Uygulamaların size maliyet getirebilecek işlemler yapmasına izin verir." + "Mesajlarınız" + "SMS mesajlarınızı, e-postanızı ve diğer mesajlarınızı okuyup yazın." + "Kişisel bilgileriniz" + "Telefonunuzda depolanan kişilere ve takvime doğrudan erişim." + "Konumunuz" + "Fiziksel konumunuzu izleyin" + "Ağ iletişimi" + "Uygulamaların çeşitli ağ özelliklerine erişmesine izin verir." + "Google hesaplarınız" + "Kullanılabilir Google hesaplarına erişin." + "Donanım denetimleri" + "Telefon donanımına doğrudan erişim." + "Telefon çağrıları" + "Telefon görüşmelerini izleyin, kaydedin ve işleyin." + "Sistem araçları" + "Sisteme alt düzey erişim ve denetimi." + "Geliştirme araçları" + "Yalnızca uygulama geliştiriciler için gerekli özellikler." + + + + + "durum çubuğunu devre dışı bırak veya değiştir" + "Uygulamanın durum çubuğunu devre dışı bırakmasına veya sistem simgeleri ekleyip kaldırmasına izin verir." + "durum çubuğunu genişlet/daralt" + "Uygulamanın, durum çubuğunu genişletip daraltmasına izin verir." + "giden aramalarda araya gir" + "Uygulamanın, giden çağrıları işlemesine ve aranacak numarayı değiştirmesine izin verir. Kötü amaçlı uygulamalar giden çağrıları izleyebilir, yönlendirebilir veya engelleyebilir." + "SMS al" + "Uygulamanın SMS mesajları alıp işlemesine izin verir. Kötü amaçlı uygulamalar mesajlarınızı izleyebilir veya bunları size göstermeden silebilir." + "MMS al" + "Uygulamanın MMS mesajları almasına ve işlemesine izin verir. Kötü amaçlı uygulamalar mesajlarınızı izleyebilir veya size göstermeden silebilir." + "SMS mesajları gönder" + "Uygulamaların SMS mesajları göndermesine izin verir. Kötü amaçlı uygulamalar, onayınızı almadan mesaj göndererek size maliyet çıkarabilir." + "SMS veya MMS oku" + "Uygulamaların, telefonunuzda veya SIM kartta depolanan SMS mesajlarını okumasına izin verir. Kötü amaçlı uygulamalar gizli mesajlarınızı okuyabilir." + "SMS veya MMS düzenle" + "Uygulamanın telefonunuzda veya SIM kartta depolanan SMS mesajlarına yazmasına izin verir. Kötü amaçlı uygulamalar mesajlarınızı silebilir." + "WAP al" + "Uygulamanın WAP mesajları alıp işlemesine izin verir. Kötü amaçlı uygulamalar mesajlarınızı izleyebilir veya bunları size göstermeden silebilir." + "çalışan uygulamaları al" + "Uygulamaların şu anda ve yakın geçmişte çalışmakta olan işlemler hakkında bilgi almasına izin verir. Kötü amaçlı uygulamaların diğer uygulamalar ile ilgili gizli bilgileri keşfetmesine izin verebilir." + "çalışan uygulamaları yeniden sırala" + "Uygulamaların görevleri ön plana ve arka plana taşımasına izin verir. Kötü amaçlı uygulamalar kendilerini sizin denetiminiz dışında zorla ön plana çıkarabilir." + "uygulama hata ayıklamayı etkinleştir" + "Bir uygulamanın başka bir uygulama için hata ayıklamayı çalıştırmasına izin verir. Kötü amaçlı uygulamalar bu işlevi başka uygulamaları kapatmak için kullanabilir." + "kullanıcı arayüzü ayarlarınızı değiştirin" + "Uygulamaların güncel yapılandırmayı; örneğin yerel ayarı veya genel yazı tipi boyutunu değiştirmesine izin verir." + "diğer uygulamaları yeniden başlat" + "Uygulamaların başka uygulamaları zorla yeniden başlatmasına izin verir." + "uygulamayı kapanmaya zorla" + "Uygulamaların, ön plandaki herhangi bir etkinliği kapanmaya ve arka plana geçmeye zorlamasına izin verir. Normal uygulamalarda hiçbir zaman gerekmemelidir." + "sistemin dahili durumunu al" + "Uygulamanın dahili sistem durumunu almasına izin verir. Kötü amaçlı uygulamalar, normalde gerekli olmaması gereken çok çeşitli özel ve koruma altındaki bilgiyi alabilir." + + + + + + + + + "tüm uygulama başlatma işlemlerini izle ve denetle" + "Uygulamaların, sistemin etkinlikleri nasıl başlattığını izlemesine ve denetlemesine izin verir. Kötü amaçlı uygulamalar sistemin güvenliğini tamamen tehlikeye atabilir. Bu izin yalnızca program geliştirme amacıyla gereklidir, normal telefon kullanımı için gerekli değildir." + "paket ile kaldırılan yayını gönder" + "Uygulamaların bir uygulama paketinin kaldırıldığında dair bir bildirim yayınlamasına izin verir. Kötü amaçlı uygulamalar bunu çalışan diğer herhangi bir uygulamayı kapatmak için kullanabilir." + "SMS ile alınan yayın gönder" + "Uygulamaların bir SMS mesajı alındığında dair bir bildirim yayınlamasına izin verir. Kötü amaçlı uygulamalar bu işlevi telefona sahte SMS mesajları göndermek için kullanabilir." + "WAP-PUSH ile alınan yayın gönder" + "Uygulamaların, WAP PUSH mesajının alındığına dair bildirim yayınlamasına izin verir. Kötü amaçlı uygulamalar bu işlevi, sahte MMS alındıları göndermek veya bir web sayfasını sessizce kötü amaçla tasarlanmış başkaları ile değiştirmek için kullanabilir." + "çalışan işlem sayısını sınırla" + "Uygulamaların, çalışacak maksimum işlem sayısını denetlemesine izin verir. Normal uygulamalar için hiçbir zaman gerekmez." + "tüm arka plan uygulamaları kapat" + "Uygulamaların, etkinliklerin arka planda daima tamamlanıp tamamlanmadığını denetlemesine izin verir. Normal uygulamalar için hiçbir zaman gerekli değildir." + "pil istatistiklerini değiştir" + "Toplanan pil istatistiklerinin değiştirilmesine izin verir. Normal uygulamalarda kullanılmamalıdır." + + + + + "yetkisiz pencereleri görüntüle" + "Dahili sistem kullanıcı arayüzü tarafından kullanılmak üzere tasarlanmış pencerelerin oluşturulmasına izin verir. Normal uygulamalarda kullanılmaz." + "sistem düzeyi uyarıları görüntüle" + "Uygulamaların sistem uyarı pencereleri göstermesine izin verir. Kötü amaçlı uygulamalar telefonun tüm ekranını işgal edebilir." + "genel animasyon hızını değiştir" + "Uygulamaların, istedikleri zaman genel animasyon hızını değiştirmesine (animasyonları hızlandırmasına veya yavaşlatmasına) izin verir." + "uygulama simgelerini yönet" + "Uygulamaların, kendi normal Z sıralamalarını atlayarak kendi simgelerini oluşturup yönetmelerine izin verir. Normal uygulamalar için hiçbir zaman gerekli olmamalıdır." + "tuşlara bas ve düğmeleri denetle" + "Uygulamaların kendi giriş işlemlerini (tuşa basma vb.) başka uygulamalara göndermesine izin verir. Kötü amaçlı uygulamalar bunu telefonun denetimini ele geçirmek için kullanabilir." + "yazdıklarınızı ve yaptığınız işlemleri kaydedin" + "Uygulamaların, başka bir uygulama ile etkileşim halindeyken (örneğin bir şifre girerken) bile bastığınız tuşları izlemesine izin verir. Normal uygulamalarda hiçbir zaman gerek duyulmamalıdır." + "bir giriş yöntemine bağla" + "Tutucunun bir giriş yönteminin en üst düzey arayüzüne bağlanmasına izin verir. Normal uygulamalarda hiçbir zaman gerek duyulmamalıdır." + "ekran yönünü değiştir" + "Uygulamaların ekran yönünü istedikleri zaman değiştirmesine izin verir. Normal uygulamalarda hiçbir zaman gerekmemelidir." + "uygulamalara Linux sinyalleri gönder" + "Uygulamaların, sağlanan sinyalin tüm kalıcı işlemlere gönderilmesini istemesine izin verir." + "uygulamayı her zaman çalıştır" + "Uygulamaların, sistemin başka uygulamalarda kullanamaması için kendi parçalarını kalıcı kılmasına izin verir." + "uygulamaları sil" + "Uygulamaların Android paketlerini silmesine izin verir. Kötü amaçlı uygulamalar bu işlevi önemli uygulamaları silmek için kullanabilir." + "diğer uygulamaların verilerini sil" + "Uygulamaların kullanıcı verilerini temizlemesine izin verir." + "diğer uygulamaların önbelleklerini sil" + "Uygulamaların önbellek dosyalarını silmesine izin verir." + "uygulama depolama alanını ölç" + "Uygulamanın kodunu, verilerini ve önbellek boyutunu almasına izin verir" + "doğrudan uygulama yükle" + "Uygulamaların yeni veya güncellenmiş Android paketleri yüklemesine izin verir. Kötü amaçlı uygulamalar bunu, kendilerine verilen izin derecesi keyfi olarak değişen yeni uygulamalar eklemek için kullanabilir." + "tüm uygulama önbelleği verilerini sil" + "Uygulamaların uygulama önbelleği dizinindeki dosyaları silerek telefonda yer açmasına izin verir. Erişim genellikle sistem işlemlerine ve yüksek düzeyde kısıtlı olarak verilir." + "sistem günlük dosyalarını oku" + "Uygulamaların sistemin çeşitli günlük dosyalarından okumalarına izin verir. Bu, uygulamaların telefon ile neler yaptığınız ile ilgili genel bilgi bulmasına izin verir, ancak bunlar kişisel veya özel bir bilgi içermemelidir." + "sahibi tanılama olan kaynakları oku/bunlara yaz" + "Uygulamanın tanılama grubundaki bir kaynağa ait herhangi bir kaynağı; örneğin /dev içindeki dosyaları okumasına ve bunlara yazmasına izin verir. Bu işlevin sistem kararlılığını ve güvenliğini olumsuz etkileme olasılığı vardır. Üretici veya operatör tarafından YALNIZCA donanıma özgü tanılama için kullanılmalıdır." + "uygulama bileşenlerini etkinleştir veya devre dışı bırak" + "Uygulamaların başka bir uygulamanın bir bileşenini etkinleştirme ayarını değiştirmesine izin verir. Kötü amaçlı uygulamalar bu ayarı telefonun önemli yeteneklerini devre dışı bırakmak için kullanabilir. Bu iznin verilmesi uygulama bileşenlerini kullanılamaz, tutarsız veya kararsız bir duruma sokabileceği için izin verilirken dikkatli olunmalıdır." + "tercih edilen uygulamaları ayarla" + "Uygulamanın tercih ettiğiniz uygulamaları değiştirmesine izin verir. Bu işlem, kötü amaçlı uygulamaların, çalışmakta olan uygulamaları sessizce değiştirerek mevcut uygulamalarınızı aldatıp kişisel bilgilerinizi almasına izin verebilir." + "genel sistem ayarlarını değiştir" + "Uygulamaların sistem ayar verilerini değiştirmesine izin verir. Kötü amaçlı uygulamalar sisteminizin yapılandırmasını bozabilir." + "güvenli sistem ayarlarını değiştir" + "Uygulamaların sistemin güvenlik ayarları verilerini değiştirmesine izin verir. Normal uygulamalarda kullanılmaz." + "Google hizmetler haritasını değiştir" + "Uygulamanın, Google hizmetleri haritasını değiştirmesine izin verir. Normal uygulamalarda kullanılmaz." + "açılışta otomatik başlat" + "Uygulamaların, sistem açıldıktan hemen sonra kendini başlatmasına izin verir. Bu işlev, telefonu başlatma süresini uzatabilir ve uygulama, sürekli çalışması nedeniyle telefonun çalışmasını genel olarak yavaşlatabilir." + "sabit yayın gönder" + "Uygulamaların yayın bittikten sonra da kalan sabit yayınlar göndermesine izin verir. Kötü amaçlı uygulamalar telefonun aşırı miktarda bellek kullanmasına neden olarak telefonu yavaşlatabilir veya telefonun kararsız hale gelmesine neden olabilir." + "kişi verilerini oku" + "Uygulamaların telefonunuzda depolanan tüm kişi (adres) verilerini okumasına izin verir. Kötü amaçlı uygulamalar bu işlevi verilerinizi başkalarına göndermek için kullanabilir." + "kişi verileri yaz" + "Uygulamaların telefonunuzda depolanan kişi (adres) verilerini değiştirmesine izin verir. Kötü amaçlı uygulamalar bu işlevi kişi verilerinizi silmek veya değiştirmek için kullanabilir." + "sahip verilerini yaz" + "Uygulamaların telefonunuzda depolanan telefon sahibi verilerini değiştirmesine izin verir. Kötü amaçlı uygulamalar bu işlevi kullanıcı verilerini silmek veya değiştirmek için kullanabilir." + "sahip verilerini oku" + "Uygulamaların telefonunuzda depolanan telefon sahibi verilerini okumasına izin verir. Kötü amaçlı uygulamalar bunu telefon sahibi verilerini okumak için kullanabilir." + "takvim verilerini oku" + "Uygulamaların telefonunuzda depolanan takvim etkinliklerinin tümünü okumasına izin verir. Kötü amaçlı uygulamalar bunu, takvim etkinliklerinizi başkalarına göndermek için kullanabilir." + "takvim verilerini yaz" + "Uygulamaların telefonunuzda depolanan takvim etkinliklerini değiştirmesine izin verir. Kötü amaçlı uygulamaları bunu takvim verilerinizi silmek veya değiştirmek için kullanabilir." + "test için sahte konum kaynakları" + "Test amacıyla sahte konum kaynakları oluşturur. Kötü amaçlı uygulamalar bu işlevi GPS veya Ağ Hizmeti sağlayıcılar gibi gerçek kaynaklardan gelen konum ve/veya durum bilgilerini geçersiz kılmak için kullanabilir." + "ek konum sağlayıcı komutlarına eriş" + "Ek konum sağlayıcı komutlarına erişin. Kötü amaçlı uygulamalar bu işlevi GPS veya diğer konum kaynaklarının işleyişine müdahale etmek için kullanabilir." + + + + + "iyi (GPS) konum" + "Bulunduğu yerlerde telefondan Küresel Konumlandırma Sistemi gibi hassas konum bulma kaynaklarına erişin. Kötü amaçlı uygulamalar bu işlevi bulunduğunuz yeri belirlemek için kullanabilir ve ek pil gücü tüketebilir." + "kesinliksiz (ağ tabanlı) konum" + "Telefonun yaklaşık yerini belirlemek için bulunduğu yerlerde hücresel ağ veritabanı gibi tahmini konum kaynaklarına erişir. Kötü amaçlı uygulamalar, bu işlevi bulunduğunuz yeri yaklaşık olarak belirlemek için kullanabilir." + "SurfaceFlinger\'a eriş" + "Uygulamanın SurfaceFlinger alt düzey özelliklerini kullanmasına izin verir." + "çerçeve arabelleğini oku" + "Kullanılacak uygulamanın çerçeve arabelleğinin içeriğini okumasına izin verir." + "ses ayarlarınızı değiştirin" + "Uygulamaların, ses düzeyi ve yönlendirme gibi genel ses ayarlarını değiştirmesine izin verir." + "ses kaydet" + "Uygulamanın, ses kayıt yoluna erişmesine izin verir." + "resim çek" + "Uygulamaların kamera ile resim çekmesine izin verir. Bu işlev herhangi bir zamanda kameranın görmekte olduğu görüntüyü uygulamaların toplamasına izin verir." + "telefonu tamamen devre dışı bırak" + "Uygulamaların tüm telefonu kalıcı olarak devre dışı bırakmasına izin verir. Bu çok tehlikelidir." + "telefonu yeniden başlamaya zorla" + "Uygulamanın telefonu yeniden açılmaya zorlamasına izin verir." + "dosya sistemlerini bağlama ve bağlantısını kesme" + "Uygulamaların çıkarılabilir depolama birimleri için dosya sistemleri ile bağlantı kurmasına ve bağlantıyı kesmesine izin verir." + "harici depolama birimini biçimlendir" + "Uygulamanın çıkarılabilir depolama birimini biçimlendirmesine izin verir." + "titreşimi denetle" + "Uygulamanın titreşimi denetlemesine izin verir." + "flaşı denetle" + "Uygulamaların flaş ışığını denetlemesine izin verir." + "donanımı test et" + "Uygulamanın donanım testi için çeşitli çevre birimlerini denetlemesine izin verir." + "telefon numaralarını doğrudan ara" + "Uygulamanın müdahaleniz olmadan telefon numaralarını aramasına izin verir. Kötü amaçlı uygulamalar, telefon faturanızda beklenmedik görüşmeler çıkmasına neden olabilir. Bu işlev, uygulamanın acil numara aramasına izin vermez." + "herhangi bir telefon numarasını doğrudan ara" + "Uygulamanın, siz müdahale etmeden acil numaralar dahil herhangi bir numarayı aramasına izin verir. Kötü amaçlı uygulamalar acil servisleri gereksiz yere ve yasal olmayan şekilde arayabilir." + "konum güncelleme bildirimlerini denetle" + "Radyo ile alınan konum güncelleme bildirimlerini etkinleştirmeye/devreden çıkarmaya izin verir. Normal uygulamalarda kullanılmamalıdır." + "erişim giriş özellikleri" + "Kayıt hizmeti tarafından karşıya yüklenen özelliklere okuma/yazma erişimi verir. Normal uygulamalarda kullanılmamalıdır." + "widget seç" + "Uygulamaların sisteme hangi uygulamalar tarafından hangi widget\'ların kullanılabileceğini söylemesine izin verir. Bu izin sayesinde uygulamalar, başka uygulamalara kişisel verilere erişim verebilir. Normal uygulamalarda kullanılmaz." + "telefon durumunu değiştir" + "Uygulamaların cihazın telefon özelliklerini kullanmasına izin verir. Bu izne sahip bir uygulama, size bildirmeden ağ değiştirebilir ve telefon radyosunu kapatıp açabilir." + "telefon durumunu oku" + "Uygulamaların cihazın telefon özelliklerine erişmesine izin verir. Bu izne sahip bir uygulama telefonun telefon numarasını, o anda bir çağrı sürmekte olup olmadığını, çağrının bağlanmış olduğu numarayı ve benzerini belirleyebilir." + "telefonunun uykuya geçmesini önle" + "Uygulamaların telefonun uykuya geçmesini önlemesine izin verir." + "telefonu aç veya kapat" + "Uygulamaların telefonunuzu açmasına veya kapatmasına izin verir." + "fabrika test modunda çalıştır" + "Telefon donanımına tam erişim veren alt düzey bir üretici testi olarak çalıştırılır. Yalnızca telefon üretici test modunda çalışırken kullanılabilir." + "duvar kağıdını ayarla" + "Uygulamanın sistem duvar kağıdını ayarlamasına izin verir." + "duvar kağıdı boyutu ipuçlarını ayarla" + "Uygulamanın sistem duvar kağıdı boyutu ipuçlarını ayarlamasına izin verir." + "sistemi fabrika değerlerine sıfırla" + "Uygulamanın, sistemi tamamen fabrika ayarlarına sıfırlamasına; verileri, yapılandırmayı ve yüklü uygulamaları silmesine izin verir." + "saat dilimini ayarla" + "Uygulamaların telefonun saat dilimini değiştirmesine izin verir." + "bilinen hesapları keşfet" + "Uygulamaların telefonda bilinen hesapların listesini almasına izin verir." + "ağ durumunu görüntüle" + "Uygulamaların, tüm ağların durumunu görmesine izin verir." + "tam İnternet erişimi" + "Uygulamaların ağ yuvaları oluşturmasına izin verir." + "Erişim Noktası Adı ayarlarını yaz" + "Uygulamaların herhangi bir APN\'nin Proxy ve Bağlantı Noktası gibi APN ayarlarını değiştirmesine izin verir." + "ağ bağlantısını değiştir" + "Uygulamaların ağ bağlantı durumunu değiştirmesine izin verir." + "arka plan veri kullanımı ayarını değiştir" + "Uygulamaların arka plan veri kullanımı ayarını değiştirmesine izin verir." + "Kablosuz durumunu görüntüle" + "Uygulamaların, kablosuz bağlantının durumu ile ilgili bilgileri görüntülemesine izin verir." + "Kablosuz durumunu değiştir" + "Uygulamaların kablosuz erişim noktalarına bağlanıp bunlarla bağlantısını kesmesine ve yapılandırılmış kablosuz ağlarda değişiklikler yapmasına izin verir." + + + + + "bluetooth yönetimi" + "Uygulamaların yerel Bluetooth telefonunu yapılandırmasına ve uzak cihazları keşfedip bunlar ile eşleşmesine izin verir." + "Bluetooth bağlantıları oluştur" + "Uygulamaların yerel Bluetooth telefonunun yapılandırmasını görüntülemesine ve eşleşilmiş cihazlar ile bağlantı kurup kabul etmesine izin verir." + "tuş kilidini devre dışı bırak" + "Uygulamaların tuş kilidini ve ilgili şifreli güvenlik önlemini devre dışı bırakmasına izin verir. Bunun geçerli bir örneği gelen bir çağrı alındığında tuş kilidinin devre dışı bırakılması, sonra çağrı bittiğinde kilidin yeniden devreye sokulmasıdır." + "senk. ayarlarını oku" + "Uygulamanın, senkronizasyon işlevinin Kişiler için devrede olup olmadığı gibi senkronizasyon ayarlarını okumasına izin verir." + "senk. ayarlarını yaz" + "Uygulamanın, senkronizasyon işlevinin Kişiler için devrede olup olmadığı gibi senkronizasyon ayarlarını değiştirmesine izin verir." + "senk. istatistiklerini oku" + "Uygulamaların senk. istatistiklerini; örn. geçmişte yapılmış senkronizasyonları okumasına izin verir." + "abone olunan yayınları oku" + "Uygulamaların, o anda senkronize olan yayınlar ile ilgili bilgi almasına izin verir." + "abone olunan yayınları yaz" + "Uygulamaların senkronize edilmiş yayınlarınızı değiştirmesine izin verir. Bu ayar, kötü amaçlı bir uygulamanın senkronize edilmiş yayınlarınızı değiştirmesine izin verebilir." + "kullanıcı tanımlı sözlüğü oku" + "Kullanıcının kullanıcı sözlüğünde depolamış olabileceği kişisel kelimeleri, adları ve kelime öbeklerini uygulamaların okumasına izin verir." + "kullanıcı tanımlı sözlüğe yaz" + "Uygulamaların kullanıcı sözlüğüne yeni kelimeler yazmasına izin verir." + + + + + + "Ev" + "Mobil" + "İş" + "İş Faks" + "Ev Faks" + "Çağrı cihazı" + "Diğer" + "Özel" + + + "Ev" + "İş" + "Diğer" + "Özel" + + "Mobil" + + "Ev" + "İş" + "Diğer" + "Özel" + + + "Ev" + "İş" + "Diğer" + "Özel" + + + "İş" + "Diğer" + "Özel" + + + "AIM" + "Windows Live" + "Yahoo" + "Skype" + "QQ" + "Google Talk" + "ICQ" + "Jabber" + + "PIN kodunu gir" + "Yanlış PIN kodu!" + "Kilidi açmak için önce Menü\'ye, sonra 0\'a basın." + "Acil durum numarası" + "(Hizmet yok)" + "Ekran kilitli." + "Kilidi açmak veya acil çağrı yapmak için Menü\'ye basın." + "Kilidi açmak için Menü\'ye basın." + "Kilit açmak için deseni çizin" + "Acil durum çağrısı" + "Doğru!" + "Üzgünüz, lütfen yeniden deneyin" + "Şarj oluyor (%%%d)" + + + "Şarj cihazınızı bağlayın." + "SIM kart yok." + "Telefonda SIM kart yok." + "Lütfen SIM kart takın." + "Ağ kilitli" + "SIM kart PUK kilidi devrede." + "Lütfen Kullanıcı Rehberi\'ne bakın veya Müşteri Hizmetleri\'ne başvurun." + "SIM kart kilitli." + "SIM kart kilidi açılıyor…" + "Kilit açma deseninizi %d kez yanlış çizdiniz. "\n\n"Lütfen %d saniye içinde yeniden deneyin." + "Kilit açma deseninizi %d kez yanlış çizdiniz. %d başarısız denemeden sonra telefonunuzu Google oturum açma bilgilerinizi kullanarak açmanız istenir."\n\n" Lütfen %d saniye içinde yeniden deneyin." + "%d saniye içinde yeniden deneyin." + "Deseni unuttunuz mu?" + "Çok fazla sayıda desen denemesi yapıldı!" + "Kilidi açmak için Google hesabınızla oturum açın" + "Kullanıcı adı (e-posta)" + "Şifre" + "Oturum aç" + "Geçersiz kullanıcı adı veya şifre." + "%-l %P" + "%-l %p" + + + "Bildirim yok" + "Sürüyor" + "Bildirimler" + "%d %%" + "Şarj oluyor…" + "Lütfen şarj cihazını takın" + "Pil tükeniyor:" + "%d%% adetten daha az kaldı." + + + "Fabrika testi yapılamadı" + "FACTORY_TEST işlemi yalnızca /system/app dizinine yüklenmiş paketler için desteklenir." + "FACTORY_TEST işlemini sağlayan hiçbir paket bulunamadı." + "Yeniden başlat" + "\"%s\" adresindeki sayfada şunlar belirtiliyor:" + "JavaScript" + "Bu sayfadan ayrılıyor musunuz?"\n\n"%s"\n\n"Devam etmek için Tamam\'ı, sayfada kalmak için İptal\'i tıklatın." + "Onayla" + + + + + + + + + "Tarayıcının bu şifreyi anımsamasını istiyor musunuz?" + "Şimdi değil" + "Anımsa" + "Hiçbir zaman" + "Bu sayfayı açma izniniz yok." + "Metin panoya kopyalandı." + "Diğer" + "Menü+" + "boşluk" + "gir" + "sil" + "Ara" + "1 ay önce" + "1 ay önce" + + "1 saniye önce" + "%d saniye önce" + + + "1 dakika önce" + "%d dakika önce" + + + "1 saat önce" + "%d saat önce" + + + "dün" + "%d gün önce" + + + "1 saniye içinde" + "%d saniye içinde" + + + "1 dakika içinde" + "%d dakika içinde" + + + "1 saat içinde" + "%d saat içinde" + + + "yarın" + "%d gün içinde" + + + "1 saniye önce" + "%d saniye önce" + + + "1 dak. önce" + "%d dakika önce" + + + "1 saat önce" + "%d saat önce" + + + "dün" + "%d gün önce" + + + "1 san. içinde" + "%d saniye içinde" + + + "1 dak. içinde" + "%d dakika içinde" + + + "1 saat içinde" + "%d saat içinde" + + + "yarın" + "%d gün içinde" + + "%s üzerinde" + "saat: %s" + "%s içinde" + "gün" + "gün" + "saat" + "saat" + "dak" + "dakika" + "san." + "saniye" + "hafta" + "hafta" + "yıl" + "yıl" + "Hafta içi her gün (Pzt-Cum)" + "Günlük" + "Her hafta %s günü" + "Aylık" + "Yılda bir" + "Video oynatılamıyor" + "Maalesef, bu video cihaza akışla göndermek için uygun değil." + "Maalesef bu video oynatılamıyor." + "Tamam" + "%1$s, %2$s" + "öğle" + "Öğle" + "geceyarısı" + "Gece Yarısı" + "%1$02d:%2$02d" + "%1$d:%2$02d:%3$02d" + "Tümünü seç" + "Metni seç" + "Metin seçmeyi durdur" + "Kes" + "Tümünü kes" + "Kopyala" + "Tümünü kopyala" + "Yapıştır" + "URL\'yi kopyala" + "Giriş Yöntemi" + "\"%s\" kelimesini sözlüğe ekle" + "Metin düzenle" + "Yer az" + "Telefonun depolama alanı azalıyor." + "Tamam" + "İptal" + "Tamam" + "İptal" + "Dikkat" + "AÇIK" + "KAPALI" + "İşlemi şunu kullanarak tamamla" + "Varsayılan olarak bu işlem için kullan." + "Giriş Ayarları > Uygulamalar > Uygulamaları yönet\'te varsayılanı temizleyin." + "İşlem seç" + "Hiçbir uygulama bu işlemi yapamaz." + "Üzgünüz!" + "%1$s uygulaması (%2$s işlemi) beklenmedik biçimde durdu. Lütfen yeniden deneyin." + "%1$s işlemi beklenmedik biçimde durdu. Lütfen yeniden deneyin." + "Üzgünüz!" + "%1$s etkinliği (%2$s uygulamasında) yanıt vermiyor." + "%1$s etkinliği (%2$s işleminde) yanıt vermiyor." + "%1$s uygulaması (%2$s işleminde) yanıt vermiyor." + "%1$s işlemi yanıt vermiyor." + "Kapanmaya zorla" + + + "Bekle" + "Hata ayıkla" + "Metin için bir işlem seçin" + "Zil sesi düzeyi" + "Medya ses düzeyi" + "Bluetooth üzerinden çalıyor" + "Gelen çağrı ses düzeyi" + "Bluetooth gelen çağrı ses düzeyi" + "Alarm ses düzeyi" + "Bildirim ses düzeyi" + "Ses" + "Varsayılan zil sesi" + "Varsayılan zil sesi (%1$s)" + "Sessiz" + "Zil sesleri" + "Bilinmeyen zil sesi" + + "Kablosuz ağ var" + "Kablosuz ağlar var" + + + "Kullanılabilir kablosuz ağı aç" + "Kullanılabilir kablosuz ağları aç" + + "Karakter ekle" + "Bilinmeyen uygulama" + "SMS mesajları gönderme" + "Çok sayıda SMS mesajı gönderiliyor. Devam etmek için \"Tamam\"ı, göndermeyi durdurmak için \"İptal\"i seçin." + "Tamam" + "İptal" + "Ayarla" + "Varsayılan" + "İzin gerektirmez" + "Gizle" + "Tümünü göster" + "Yükleniyor…" + "USB bağlandı" + "Telefonunuzu bilgisayarınıza USB ile bağladınız. Bilgisayarınız ve telefonunuzun SD kartı arasında dosya kopyalamak istiyorsanız, \"Bağla\"\'yı seçin." + "Bağla" + "Bağlama" + "SD kartınızı USB depolama birimi için kullanmada bir sorun var." + "USB bağlandı" + "Bilgisayarınıza/bilgisayarınızdan dosya kopyalamak için seçin." + "USB depolama birimini kapat" + "USB depolama birimini kapatmak için seçin." + "USB depolama birimini kapat" + "USB depolama birimini kapatmadan önce USB ana makinesinde bağlantıyı kestiğinizden emin olun. USB depolama birimini kapatmak için \"Kapat\"ı seçin." + "Kapat" + "İptal" + "USB depolama birimini kapatırken bir sorunla karşılaştık. USB ana makinesinde bağlantıyı kestiğinizden emin olun, sonra yeniden deneyin." + "SD kartı biçimlendir" + "SD kartı biçimlendirmek istediğinizden emin misiniz? Kartınızdaki tüm veriler yok olacak." + "Biçimlendir" + + + + + "Giriş Yöntemini Seç" + " ABCDEFGHIJKLMNOPQRSTUVWXYZ" + " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "adaylar" + "SD kart hazırlanıyor" + + + "Boş SD kart" + + + "Hasarlı SD kart" + + + "SD kart beklenmedik biçimde çıkarıldı" + "Veri kaybından kaçınmak için SD kartı çıkarmadan önce bağlantısını kesin." + "SD kart güvenle çıkarılabilir" + + + "SD kart çıkarılmış" + + + "Eşleşen hiçbir etkinlik bulunamadı" + "bileşen kullanım istatistiklerini güncelle" + "Toplanmış bileşen istatistiklerinin değiştirilmesine izin verir. Normal uygulamalarda kullanılmamalıdır." + "Zum denetimi için iki kez dokun" + "Widget\'ı genişletirken hata oluştu" + "Git" + "Ara" + "Gönder" + "İleri" + "Bitti" + "Çalıştır" + "Numarayı çevir:"\n"%s" + "%s"\n" ile kişi oluştur" + + + + + diff --git a/core/res/res/values-vi-rVN/donottranslate-cldr.xml b/core/res/res/values-vi-rVN/donottranslate-cldr.xml index 72ff8b68999c3..6f2d3422e9fb4 100644 --- a/core/res/res/values-vi-rVN/donottranslate-cldr.xml +++ b/core/res/res/values-vi-rVN/donottranslate-cldr.xml @@ -133,8 +133,8 @@ %3$s %2$s %5$s - %8$s %7$s %10$s %1$s %3$s %2$s %5$s - %6$s %8$s %7$s %10$s %1$s %3$s %2$s %5$s - %6$s %8$s %7$s %10$s - Ngày %3$s tháng %2$s năm %4$s %5$s - 'Ngày %8$s tháng %7$s năm %9$s %10$s - Ngày %3$s tháng %2$s năm %4$s %5$s - 'Ngày %8$s tháng %7$s năm %9$s %10$s + Ngày %3$s tháng %2$s năm %4$s %5$s - \'Ngày %8$s tháng %7$s năm %9$s %10$s + Ngày %3$s tháng %2$s năm %4$s %5$s - \'Ngày %8$s tháng %7$s năm %9$s %10$s %1$s, %3$s %2$s %4$s %5$s - %6$s, %8$s %7$s %9$s %10$s %1$s, %3$s %2$s %4$s %5$s - %6$s, %8$s %7$s %9$s %10$s %1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 3be8aa09a5fe6..48c4d38744566 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -21,6 +21,8 @@ "GB" "TB" "PB" + + "<无标题>" "..." "(无电话号码)" @@ -30,69 +32,110 @@ "出现连接问题或 MMI 码无效。" "服务已启用。" "已针对以下内容启用了服务:" - "服务已被禁用。" + "服务已被停用。" "注册成功。" - "清除已成功。" + "清除成功。" "密码不正确。" - "MMI 码已完成。" - "您键入的旧 PIN 码不正确。" - "您键入的 PUK 码不正确。" - "您输入的 PIN 码不匹配。" - "键入一个 4 到 8 位数的 PIN 码。" - "已对 SIM 卡进行 PUK 码锁定。键入 PUK 码将其解锁。" - "键入 PUK2 码以解锁 SIM 卡。" - "来电者 ID" - "去电者 ID" - "呼叫转移" + "MMI 完成。" + "您输入的旧 PIN 不正确。" + "您输入的 PUK 不正确。" + "您输入的 PIN 码不一致。" + "输入一个 4 至 8 位数的 PIN。" + "您的 SIM 卡被 PUK 锁定。请输入 PUK 码进行解锁。" + "输入 PUK2 以解锁 SIM 卡。" + "收到来电显示" + "外拨电话显示" + "呼叫转接" "呼叫等待" "呼叫限制" "密码更改" "PIN 码更改" - "呼叫者 ID 默认情况下受限制。下一个呼叫:受限制" - "呼叫者 ID 默认情况下受限制。下一个呼叫:不受限制" - "呼叫者 ID 默认情况下不受限制。下一个呼叫:受限制" - "呼叫者 ID 默认情况下不受限制。下一个呼叫:不受限制" + + + + + + + + + + + + + "来电显示默认设置为受限制。下一个呼叫:受限制" + "来电显示默认设置为受限制。下一个呼叫:不受限制" + "来电显示默认设置为不受限制。下一个呼叫:受限制" + "来电显示默认设置为不受限制。下一个呼叫:不受限制" "未提供服务。" - "不能更改呼叫者 ID 设置。" - - - - - - - - - - + "无法更改来电显示设置。" + "访问受限情况已发生变化" + "数据服务已禁用。" + "紧急服务已禁用。" + "语音/短信服务已禁用。" + "所有语音/短信服务均已禁用。" "语音" "数据" "传真" "短信" "异步" "同步" - "包" + "封包" "PAD" - "{0}:未转移呼叫" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "{0}:无法转接" "{0}{1}" - "{0}{2} 秒后转移呼叫 {1}" - "{0}:未转移呼叫" - "{0}:未转移呼叫" + "{0}{2} 秒后拨打 {1}" + "{0}:没有转接" + "{0}:没有转接" + + + + "确定" - "此网页包含错误。" - "找不到该网址。" - "不支持此站点验证方案。" - "验证失败。" - "通过代理服务器进行验证失败。" - "与服务器的连接失败。" - "服务器无法通讯。请稍后重试。" + "网页包含错误。" + "找不到网址。" + "不支持此网站身份验证方案。" + "身份验证失败。" + "通过代理服务器进行身份验证失败。" + "未能连接到服务器。" + "服务器无法通信,请稍后重试。" "与服务器的连接超时。" - "该页面包含太多服务器重定向。" + "网页包含过多服务器重定向。" "不支持该协议。" - "不能建立安全连接。" - "网址无效,此页面无法打开。" - "此文件无法访问。" + "无法建立安全连接。" + "网址无效,此网页无法打开。" + "无法访问该文件。" "找不到请求的文件。" - "正在处理的请求太多。请稍后重试。" + "正在处理的请求太多,请稍后重试。" + + "同步" "同步" "太多%s删除项。" @@ -105,171 +148,191 @@ "屏幕锁定" "关机" "正在关机..." - "您的手机会关机。" - "没有最近的应用程序。" + "您的手机会关闭。" + "无最近的应用程序。" "手机选项" "屏幕锁定" "关机" "静音模式" - "声音已关闭" - "声音已开启" + "声音已“关闭”" + "声音已“开启”" "飞行模式" "飞行模式已开启" "飞行模式已关闭" "安全模式" "Android 系统" - "需要您支付费用的服务" - "允许应用程序执行可能需要您支付费用的操作。" - "您的信息" - "阅读并编写您的短信、电子邮件和其他消息。" + "需要您付费的服务" + "允许应用程序执行可能需要您付费的操作。" + "您的消息" + "读/写短信、电子邮件和其他消息。" "您的个人信息" - "直接访问手机中存储的联系人和日历。" - "您所处的位置" + "直接访问手机上存储的联系人和日历。" + "您的位置" "监视您的物理位置" - "网络通讯" + "网络通信" "允许应用程序访问各种网络功能。" "您的 Google 帐户" "访问可用的 Google 帐户。" - "硬件控件" - "直接在手机上访问硬件。" + "硬件控制" + "直接访问手机上的硬件。" "手机通话" - "监视、记录和处理手机呼叫。" + "监视、记录和处理电话。" "系统工具" - "对系统进行低级访问和控制。" + "对系统的低级别访问和控制。" "开发工具" - "只有应用程序开发人员才需要的功能。" - "禁用或修改状态栏" - "允许应用程序禁用状态栏或者添加和删除系统图标。" - "展开/收拢状态栏" - "允许应用程序展开或收拢状态栏。" - "拦截去电" - "允许应用程序处理去电和更改要拨打的号码。恶意应用程序可能会借此监视、重定向或阻止去电。" + "只有应用程序开发人员需要这些功能。" + + + + + "停用或修改状态栏" + "允许应用程序停用状态栏,或者添加和删除系统图标。" + "展开/折叠状态栏" + "允许应用程序展开或折叠状态栏。" + "拦截对外呼叫" + "允许应用程序处理对外呼叫和更改要拨打的号码。恶意应用程序可借此监视、重定向或阻止对外呼叫。" "接收短信" - "允许应用程序接收和处理短信。恶意应用程序可能会借此监视您的信息,或将信息删除,而不向您显示。" + "允许应用程序接收和处理短信。恶意应用程序可借此监视您的信息,或者将信息删除而不向您显示。" "接收彩信" - "允许应用程序接收和处理彩信。恶意应用程序可能会借此监视您的信息,或在您尚未看到的情况下就将其删除。" + "允许应用程序接收和处理彩信。恶意应用程序可借此监视您的信息,或者将信息删除而不向您显示。" "发送短信" - "允许应用程序发送短信。恶意应用程序可能会借此在未经您确认的情况下发送信息从而让您支付费用。" + "允许应用程序发送短信。恶意应用程序可借此不经您的确认发送信息来让您付费。" "读取短信或彩信" - "允许应用程序读取您的手机或 SIM 卡中存储的短信。恶意应用程序可能会借此读取您的机密信息。" + "允许应用程序读取您的手机或 SIM 卡中存储的短信。恶意应用程序可借此读取您的机密信息。" "编辑短信或彩信" - "允许应用程序写入手机或 SIM 卡中存储的短信。恶意应用程序可能会借此删除您的信息。" + "允许应用程序写入手机或 SIM 卡中存储的短信。恶意应用程序可借此删除您的信息。" "接收 WAP" - "允许应用程序接收和处理 WAP 信息。恶意应用程序可能会借此监视您的信息,或将信息删除,而不向您显示。" - "检索正在运行的应用程序" - "恶意应用程序可能会借此找到有关其他应用程序的私有信息。恶意应用程序可能会借此发现有关其他应用程序的私有信息。" + "允许应用程序接收和处理 WAP 消息。恶意应用程序可借此监视您的消息,或者将消息删除而不向您显示。" + "检索所运行的应用程序" + "允许应用程序检索有关当前和最近运行的任务的信息。恶意应用程序可借此发现有关其他应用程序的私有信息。" "对正在运行的应用程序重新排序" - "允许应用程序将任务移至前端和后台。恶意应用程序可能会借此强行进到前台,而不受您的控制。" + "允许应用程序将任务移至前台和后台。恶意应用程序可借此强行进到前台,而不受您的控制。" "启用应用程序调试" - "允许应用程序启动对其他应用程序的调试。恶意应用程序可能会借此终止其他应用程序。" - "更改您的 UI 设置" - "允许应用程序更改当前配置,例如语言设置或整体的字体大小。" + "允许应用程序启动对其他应用程序的调试。恶意应用程序可借此终止其他应用程序。" + "更改您的用户界面设置" + "允许应用程序更改当前配置,例如语言区域或整体字号。" "重新启动其他应用程序" - "允许应用程序强制重新启动其他应用程序。" - "强制应用程序关闭" - "允许应用程序强制前台的任何活动关闭和重新开始。普通应用程序从不需要使用此权限。" + "允许应用程序强行重新启动其他应用程序。" + "强行关闭应用程序" + "允许应用程序强行关闭前台中的任何活动并返回。普通应用程序从不需要使用此权限。" "检索系统内部状态" - "允许应用程序检索系统的内部状态。恶意应用程序可能会借此检索通常它们本不需要的各种私有和安全信息。" - "监视和控制所有应用程序启动" - "允许应用程序监视和控制系统启动活动的方式。恶意应用程序可能会借此彻底损坏系统。此权限仅在开发时才需要,普通的手机应用不需要。" - "发送包删除的广播" - "允许应用程序广播已删除某应用程序包的通知。恶意应用程序可能会借此来终止任何其他正在运行的应用程序。" - "发送短信收到的广播" - "允许应用程序广播已收到短信的通知。恶意应用程序可能会借此伪造收到的短信。" - "发送 WAP-PUSH 收到的广播" - "允许应用程序播报收到 WAP PUSH 消息的通知。恶意应用程序可能会借此乱发彩信或暗中用恶意内容替换任意网页中的内容。" - "限制正在运行的进程数" - "允许应用程序控制运行的进程数上限。普通应用程序从不需要使用此权限。" + "允许应用程序检索系统的内部状态。恶意应用程序可借此检索它们通常并不需要的各种私有信息和安全信息。" + + + + + + + + + "监控所有应用程序的启动" + "允许应用程序监控系统启动活动的方式。恶意应用程序可借此彻底损坏系统。这一权限只在开发过程中需要,普通的手机操作不需要。" + "发送已删除包的广播" + "允许应用程序广播已删除应用程序包的通知。恶意应用程序可借此终止任何正在运行的其他应用程序。" + "发送可通过短信接收的广播" + "允许应用程序广播已收到短信的通知。恶意应用程序可借此伪造收到的短信。" + "发送 WAP 一键接收广播" + "允许应用程序广播收到 WAP 一键信息的通知。恶意应用程序可借此乱发彩信或暗中用恶意内容替换任意网页中的内容。" + "限制所运行进程的数量" + "允许应用程序控制将运行的最大进程数。普通应用程序从不需要使用此权限。" "关闭所有后台应用程序" "允许应用程序控制活动是否始终是一转至后台就完成。普通应用程序从不需要使用此权限。" - "修改电池统计信息" - "允许修改收集的电池统计信息。普通应用程序不能使用此权限。" + "修改电池使用情况统计信息" + "允许修改收集的电池使用情况统计信息。普通应用程序不能使用此权限。" + + + + "显示未授权的窗口" - "允许创建专用于内部系统用户界面的窗口。普通应用程序不能使用此权限。" + "允许创建专供内部系统用户界面使用的窗口。普通应用程序不能使用此权限。" "显示系统级警报" - "允许应用程序显示系统警报窗口。恶意应用程序可能会借此掌控整个手机屏幕。" + "允许应用程序显示系统警报窗口。恶意应用程序可借此掌控整个手机屏幕。" "修改全局动画速度" - "允许应用程序随时更改全局动画速度(加快或减慢动画)。" + "允许应用程序随时更改全局动画速度(加快或放慢动画)。" "管理应用程序令牌" - "允许应用程序创建和管理自己的令牌,从而绕开其常规的 Z 方向。普通应用程序从不需要使用此权限。" + "允许应用程序创建和管理自己的令牌,从而绕开正常的 Z 排序方式。普通应用程序从不需要使用此权限。" "按键和控制按钮" - "允许应用程序将其自己的输入活动(按键等)提供给其他应用程序。恶意应用程序可能会借此掌控手机。" - "记录您键入的内容和执行的操作" - "即使在与其他应用程序交互时(例如输入密码),也允许应用程序查看您按的键。普通应用程序从不需要使用此权限。" - "绑定到输入方法" - "允许持有者绑定到输入方法的顶级接口。普通应用程序从不需要使用此权限。" - "更改屏幕方向" + "允许应用程序将其自己的输入活动(按键等)提供给其他应用程序。恶意应用程序可借此掌控手机。" + "记录您输入的内容和采取的操作" + "允许应用程序查看您按的键,即使在与其他应用程序交互(例如输入密码)时也不例外。普通应用程序从不需要使用此权限。" + "绑定至输入法" + "允许手机用户绑定至输入法的顶级界面。普通应用程序从不需要使用此权限。" + "更改屏幕浏览模式" "允许应用程序随时更改屏幕的旋转方向。普通应用程序从不需要使用此权限。" "向应用程序发送 Linux 信号" - "允许应用程序请求将提供的信号发送给所有持久进程。" + "允许应用程序请求将提供的信号发送给所有持续的进程。" "让应用程序始终运行" "允许应用程序部分持续运行,这样系统便不能将其用于其他应用程序。" "删除应用程序" - "允许应用程序删除 Android 包。恶意应用程序可能会借此删除重要的应用程序。" + "允许应用程序删除 Android 包。恶意应用程序可借此删除重要的应用程序。" "删除其他应用程序的数据" "允许应用程序清除用户数据。" - "删除其他应用程序的缓存" + "删除其他应用程序缓存" "允许应用程序删除缓存文件。" "计算应用程序存储空间" "允许应用程序检索其代码、数据和缓存大小" "直接安装应用程序" - "允许应用程序安装新的或更新的 Android 包。恶意应用程序可能会借此添加其具有任意权限的新应用程序。" + "允许应用程序安装新的或更新的 Android 包。恶意应用程序可借此添加具有极大权限的新应用程序。" "删除所有应用程序缓存数据" - "允许应用程序通过删除应用程序缓存目录中的文件释放手机存储空间。通常只限于访问系统进程。" + "允许应用程序通过删除应用程序缓存目录中的文件释放手机存储空间。对系统进程的访问通常受到严格限制。" "读取系统日志文件" - "允许应用程序从系统的各日志文件中进行读取。这样应用程序可以发现有关您正在通过手机执行的操作的常规信息,但这些信息不应包含任何个人或私有信息。" - "读取/写入诊断拥有的资源" - "允许应用程序读取和写入诊断组拥有的任何资源;例如 /dev 中的文件。这可能会潜在地影响系统稳定性和安全性。此权限只应用于由制造商或操作员执行的硬件特定的诊断。" - "启用或禁用应用程序组件" - "允许应用程序更改是否启用其他应用程序的组件。恶意应用程序可能会借此来禁用重要的手机功能。使用此权限时务必谨慎,因为这可能导致应用程序组件进入不可用、不一致或不稳定的状态。" - "设置首选的应用程序" - "允许应用程序修改首选的应用程序。恶意应用程序可能会借此暗中更改运行的应用程序,从而骗过您的现有应用程序来收集您的私有数据。" + "允许应用程序读取系统的各日志文件。这样应用程序可以发现有关您操作手机的一般信息,但这些信息不应包含任何个人信息或私有信息。" + "读取/写入诊断所拥有的资源" + "允许应用程序读取/写入诊断组所拥有的任何资源;例如,/dev 中的文件。这可能会影响系统稳定性和安全性。此权限只应由制造商或运营商用于硬件特定的诊断。" + "启用或停用应用程序组件" + "允许应用程序更改是否启用其他应用程序的组件。恶意应用程序可借此停用重要的手机功能。使用此权限时务必谨慎,因为这可能导致应用程序组件进入不可用、不一致或不稳定的状态。" + "设置首选应用程序" + "允许应用程序修改首选的应用程序。这样恶意应用程序可能会暗中更改运行的应用程序,从而骗过您的现有应用程序来收集您的私有数据。" "修改全局系统设置" - "允许应用程序修改系统的设置数据。恶意应用程序可能会借此破坏您的系统配置。" + "允许应用程序修改系统的设置数据。恶意应用程序可借此破坏您的系统配置。" "修改安全系统设置" "允许应用程序修改系统安全设置数据。普通应用程序不能使用此权限。" "修改 Google 服务地图" "允许应用程序修改 Google 服务地图。普通应用程序不能使用此权限。" - "引导时自动启动" - "允许应用程序在系统完成引导后即自行启动。这样会加长启动手机所需的时间,而且如果应用程序一直运行,会降低手机的整体速度。" + "开机时自动启动" + "允许应用程序在系统完成启动后即自行启动。这样会延长手机的启动时间,而且如果应用程序一直运行,会降低手机的整体速度。" "发送顽固广播" - "允许应用程序发送顽固广播,这些广播在结束后仍会保留。恶意应用程序可能会借此使手机使用太多内存,从而降低其速度和稳定性。" - "读取联系数据" - "允许应用程序读取您手机中存储的所有联系(地址)数据。恶意应用程序可能会借此将您的数据发送给其他人。" + "允许应用程序发送顽固广播,这些广播在结束后仍会保留。恶意应用程序可能会借此使手机耗用太多内存,从而降低其速度或稳定性。" + "读取联系人数据" + "允许应用程序读取您手机上存储的所有联系人(地址)数据。恶意应用程序可借此将您的数据发送给其他人。" "写入联系数据" - "允许应用程序修改您手机中存储的联系(地址)数据。恶意应用程序可能会借此清除或修改您的联系数据。" - "写入所有者数据" - "允许应用程序修改您手机中存储的手机所有者数据。恶意应用程序可能会借此清除或修改所有者数据。" - "读取所有者数据" - "允许应用程序读取您手机中存储的手机所有者数据。恶意应用程序可能会借此读取手机所有者数据。" + "允许应用程序修改您手机上存储的联系人(地址)数据。恶意应用程序可借此清除或修改您的联系人数据。" + "写入拥有者数据" + "允许应用程序修改您手机上存储的手机拥有者数据。恶意应用程序可借此清除或修改拥有者数据。" + "读取拥有者数据" + "允许应用程序读取您手机上存储的手机拥有者数据。恶意应用程序可借此读取手机拥有者数据。" "读取日历数据" - "允许应用程序读取您手机中存储的所有日历活动。恶意应用程序可能会借此将您的日历活动发送给其他人。" + "允许应用程序读取您手机上存储的所有日历活动。恶意应用程序可借此将您的日历活动发送给其他人。" "写入日历数据" - "允许应用程序修改您手机中存储的日历活动。恶意应用程序可能会借此清除或修改您的日历数据。" - "用于测试的模仿位置源" - "创建用于测试的模仿位置源。恶意应用程序可能会借此替代真正的位置源(例如 GPS 或网络提供商)返回的位置和/或状态。" - "访问额外的位置提供程序命令" - "访问额外的位置提供程序命令。恶意应用程序可能会借此干扰 GPS 或其他位置源的操作。" - "精准 (GPS) 位置" - "访问精准的位置源,例如手机上的全球定位系统(如果有)。恶意应用程序可能会借此确定您所处的位置,并可能消耗额外的电池电量。" - "粗略(基于网络的)位置" - "访问粗略的位置源(例如蜂窝网络数据库)以确定手机的大体位置(如果适用)。恶意应用程序可能会借此来确定您的大体位置。" + "允许应用程序修改您手机上存储的日历活动。恶意应用程序可借此清除或修改您的日历数据。" + "用于测试的模拟位置源" + "创建用于测试的模拟位置源。恶意应用程序可借此替代真正的位置源(如 GPS 或网络提供商)返回的位置和/或状态。" + "允许访问额外的位置提供命令" + "访问额外的位置提供程序命令。恶意应用程序可借此干扰 GPS 或其他位置源的运作。" + + + + + "精准位置 (GPS)" + "访问精准的位置源,例如手机上的全球定位系统(如果适用)。恶意应用程序可能借此确定您所处的位置,并消耗额外的电池电量。" + "粗略位置(所在网络)" + "访问粗略的位置源(例如蜂窝网络数据库)以确定手机的大体位置(如果适用)。恶意应用程序可借此确定您所处的大体位置。" "访问 SurfaceFlinger" - "允许应用程序使用 SurfaceFlinger 低级功能。" + "允许应用程序使用 SurfaceFlinger 低级别功能。" "读取帧缓冲区" - "允许应用程序使用(读取)帧缓冲区中的内容。" + "允许应用程序读取帧缓冲区的内容。" "更改您的音频设置" - "允许应用程序修改全局音频设置,例如音量和路由。" + "允许应用程序修改全局音频设置,如音量和路由。" "录音" "允许应用程序访问录音路径。" "拍照" - "允许应用程序通过相机拍照。这样应用程序可随时收集相机正在拍摄的图片。" - "永久禁用手机" - "允许应用程序永久禁用整个手机,这是很危险的。" - "强制手机重新引导" - "允许应用程序强制手机重新引导。" - "装载和卸载文件系统" - "允许应用程序装载和卸载文件系统以进行可移动存储。" + "允许应用程序使用相机拍照。此权限允许应用程序随时收集相机看到的图片。" + "永久停用手机" + "允许应用程序永久停用整个手机,这非常危险。" + "强行重新启动手机" + "允许应用程序强行重新启动手机。" + "安装和卸载文件系统" + "允许应用程序安装和卸载可移动存储器的文件系统。" "格式化外部存储设备" "允许应用程序格式化可移除的存储设备。" "控制振动器" @@ -277,103 +340,112 @@ "控制闪光灯" "允许应用程序控制闪光灯。" "测试硬件" - "允许应用程序控制各外围设备以进行硬件测试。" - "直接呼叫电话号码" - "允许应用程序在没有您干预的情况下呼叫电话号码。恶意应用程序可能会借此在您的电话帐单上产生意外呼叫。请注意,此权限不允许应用程序呼叫紧急电话号码。" + "允许应用程序控制各种用于硬件测试的外围设备。" + "直接拨打电话号码" + "允许应用程序在没有您干预的情况下呼叫电话号码。恶意应用程序可借此在您的话费单上产生意外通话费。请注意,此权限不允许应用程序呼叫紧急电话号码。" "直接呼叫任何电话号码" - "允许应用程序在没有您干预的情况下呼叫任何电话号码(包括紧急电话号码)。恶意应用程序可能会借此对紧急服务拨打骚扰电话和非法电话。" + "允许应用程序在没有您干预的情况下呼叫任何电话号码(包括紧急电话号码)。恶意应用程序可借此对紧急服务拨打骚扰电话和非法电话。" "控制位置更新通知" - "允许启用/禁用来自收音机的位置更新通知。普通应用程序不能使用此权限。" + "允许启用/停用收音机的位置更新通知。普通应用程序不能使用此权限。" "访问检入属性" "允许对检入服务上传的属性进行读/写访问。普通应用程序不能使用此权限。" "选择窗口小部件" "允许应用程序告诉系统哪个应用程序可以使用哪些窗口小部件。具有该权限的应用程序可以允许其他应用程序访问个人数据。普通应用程序不适合使用此权限。" "修改手机状态" - "允许应用程序控制设备的手机功能。具有此权限的应用程序可能会切换网络,打开和关闭手机收音机以及类似操作,而不会通知您。" + "允许应用程序控制设备的手机功能。具有此权限的应用程序可切换网络、打开和关闭手机收音机等,而不通知您。" "读取手机状态" - "允许应用程序访问设备的电话功能。具有此权限的应用程序可确定此电话的电话号码、是否在进行通话以及通话对方的号码等。" + "允许应用程序访问设备的手机功能。具有此权限的应用程序可确定此手机的号码、是否在通话以及通话对方的号码等。" "防止手机休眠" "允许应用程序防止手机进入休眠状态。" "开机或关机" "允许应用程序打开或关闭手机。" "在出厂测试模式下运行" - "作为一项低级制造商测试来运行,从而允许对手机硬件进行完全访问。此权限仅当手机在制造商测试模式下运行时才可用。" + "作为低级别制造商测试运行,以允许完全访问手机硬件。此权限只有当手机在制造商测试模式下运行时才可用。" "设置壁纸" "允许应用程序设置系统壁纸。" - "大体设置壁纸大小" - "允许应用程序大体设置系统壁纸大小。" - "将系统重设为出厂默认值" - "允许应用程序将系统完全重设为其出厂设置,即清除所有数据、配置和安装的应用程序。" + "设置壁纸大小提示" + "允许应用程序设置系统壁纸大小提示。" + "将系统重置为出厂时的默认设置" + "允许应用程序将系统完全重置为出厂设置,即清除所有数据、配置和安装的应用程序。" "设置时区" "允许应用程序更改手机的时区。" "发现已知帐户" "允许应用程序获取手机已知的帐户列表。" "查看网络状态" "允许应用程序查看所有网络的状态。" - "完全的互联网访问" + "不受限制的互联网访问权限" "允许应用程序创建网络套接字。" - "写入“接入点名称”设置" + "写入接入点名称设置" "允许应用程序修改 APN 设置,例如任何 APN 的代理和端口。" - "更改网络连接性" - "允许应用程序更改状态网络连接性。" + "更改网络连接" + "允许应用程序更改网络连接状态。" "更改背景数据使用设置" "允许应用程序更改背景数据使用设置。" "查看 Wi-Fi 状态" "允许应用程序查看有关 Wi-Fi 状态的信息。" "更改 Wi-Fi 状态" - "允许应用程序连接至 Wi-Fi 接入点以及与 Wi-Fi 接入点断开连接,并允许应用程序对配置的 Wi-Fi 网络进行更改。" + "允许应用程序连接到 Wi-Fi 接入点以及与 Wi-Fi 接入点断开连接,并对配置的 Wi-Fi 网络进行更改。" + + + + "蓝牙管理" - "允许应用程序配置本地蓝牙手机以及发现远程设备并与其配对。" + "允许应用程序配置本地蓝牙手机,以及查找远程设备并与之配对。" "创建蓝牙连接" - "允许应用程序查看本地蓝牙手机的配置以及建立和接受与配对设备的连接。" - "禁用键锁" - "允许应用程序禁用键锁和任何关联的密码安全措施。这种情况的一个恰当示例就是这样一个手机:当收到来电时禁用键锁,当通话结束后再重新启用键锁。" + "允许应用程序查看本地蓝牙手机的配置,以及建立和接受与配对设备的连接。" + "停用键锁" + "允许应用程序停用键锁和任何关联的密码安全设置。这种情况的一个恰当示例就是这样一个手机:在接听来电时停用键锁,在通话结束后重新启用键锁。" "读取同步设置" - "允许应用程序读取同步设置,例如是否为“联系人”启用同步。" + "允许应用程序读取同步设置,例如是否针对联系人启用同步。" "写入同步设置" - "允许应用程序修改同步设置,例如是否针对“联系人”启用同步。" + "允许应用程序修改同步设置,例如是否针对联系人启用同步。" "读取同步统计信息" - "允许应用程序读取同步统计信息;例如已发生的同步的历史记录。" + "允许应用程序读取同步统计信息;例如已发生的同步历史记录。" "读取订阅的供稿" - "允许应用程序获取有关当前同步的供稿的详情。" + "允许应用程序获取有关当前同步的供稿的详细信息。" "写入订阅的供稿" - "允许应用程序修改您当前同步的供稿。这样恶意程序可以更改您同步的供稿。" + "允许应用程序修改您当前同步的供稿。恶意应用程序可借此更改您同步的供稿。" "读取用户定义的词典" "允许应用程序读取用户在用户词典中存储的任意私有字词、名称和短语。" "写入用户定义的词典" "允许应用程序向用户词典中写入新词。" + + + + - "家庭" + "住宅电话" "手机" - "工作" - "工作传真" - "家庭传真" + "单位电话" + "单位传真" + "住宅传真" "寻呼机" - "其他" - "自定义" + "其他电话" + "自定义电话" - "家庭" - "工作" - "其他" - "自定义" + "住宅邮箱" + "单位邮箱" + "其他邮箱" + "自定义邮箱" + "手机" - "家庭" - "工作" - "其他" - "自定义" + "住宅地址" + "单位地址" + "其他地址" + "自定义地址" - "家庭" - "工作" - "其他" - "自定义" + "住宅聊天工具" + "单位聊天工具" + "其他聊天工具" + "自定义聊天工具" - "工作" - "其他" - "自定义" + "单位" + "其他组织" + "自定义组织" "AIM" @@ -387,32 +459,33 @@ "输入 PIN 码" "PIN 码不正确!" - "要解锁,请按“菜单”,然后按 0。" + "要解锁,请先按 MENU 再按 0。" "紧急电话号码" "(无服务)" "屏幕已锁定。" - "按“菜单”解锁或拨打紧急电话。" - "按“菜单”解锁。" + "按 MENU 解锁或拨打紧急电话。" + "按 MENU 解锁。" "绘制解锁图案" - "紧急电话" + "紧急呼叫" "正确!" "很抱歉,请重试" "正在充电 (%d%%)" + + "连接您的充电器。" "没有 SIM 卡。" "手机中无 SIM 卡。" "请插入 SIM 卡。" "网络已锁定" - "已对 SIM 卡进行 PUK 码锁定。" - - - "SIM 卡已被锁定。" + "SIM 卡被 PUK 锁定。" + "请参阅《用户指南》或联系客服人员。" + "SIM 卡被锁定。" "正在解锁 SIM 卡..." - "您 %d 次错误地绘制了您的解锁图案。"\n\n"请在 %d 秒后重试。" - "您已错误地绘制了您的解锁图案 %d 次。如果再尝试 %d 次后仍不成功,系统会要求您使用您的 Google 登录帐户解锁手机。"\n\n"请在 %d 秒后重试。" + "您已经 %d 次错误地绘制了解锁图案。"\n\n"请在 %d 秒后重试。" + "您已经 %d 次错误地绘制了解锁图案。如果再尝试 %d 次后仍不成功,系统会要求您使用自己的 Google 登录信息解锁手机。"\n\n"请在 %d 秒后重试。" "%d 秒后重试。" "忘记了图案?" - "图案尝试次数太多!" + "图案尝试次数过多!" "要解除锁定,请使用您的 Google 帐户登录" "用户名(电子邮件)" "密码" @@ -420,31 +493,42 @@ "用户名或密码无效。" "%P%-l点" "%p%-l点" - "清除通知" + + "无通知" - "正在进行的" + "正在进行" "通知" "%d%%" "正在充电..." "请连接充电器" "电量在减少:" "剩余电量不足 %d%%。" + + "出厂测试失败" - "只有在 /system/app 中安装的包支持 FACTORY_TEST 操作。" + "只有 /system/app 中安装的包支持 FACTORY_TEST 操作。" "未发现支持 FACTORY_TEST 操作的包。" - "重新引导" + "重新启动" "“%s”处的页面表明:" "JavaScript" "是否从该页面导航至它处?"\n\n"%s"\n\n"选择“确定”继续,或选择“取消”留在当前页面。" "确认" + + + + + + + + "是否希望浏览器记住此密码?" - "暂不保存" + "此时不保存密码" "记住" "从不" - "您无权打开此页面。" - "文本已复制到剪贴板。" + "您无权打开此网页。" + "文字已复制到剪贴板。" "更多" - "“菜单”+" + "MENU+" "空格" "Enter 键" "删除" @@ -516,8 +600,8 @@ "%d 天后" "在 %s" - "在 %s" - "%s 年内" + "在%s" + "%s 年" "天" "天" "小时" @@ -530,77 +614,75 @@ "周" "年" "年" - "每个工作日(周一到周五)" + "每个工作日(周一至周五)" "每天" "每周的%s" "每月" "每年" "无法播放视频" "抱歉,该视频不适合在此设备上播放。" - "很抱歉,此视频不能播放。" + "很抱歉,无法播放此视频。" "确定" - "%1$s%2$s" + "%1$s%2$s" "中午" "中午" "午夜" "午夜" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "全选" - "选择文本" - "停止选择文本" + "选择文字" + "停止选择文字" "剪切" "全部剪切" "复制" "全部复制" "粘贴" "复制网址" - "输入方法" + "输入法" "将“%s”添加到词典" - "编辑文本" - "存储空间不足" - "手机存储空间在减少。" - "正常" + "编辑文字" + "空间不足" + "手机存储空间正在减少。" + "确定" "取消" - "正常" + "确定" "取消" "注意事项" "开启" "关闭" "使用以下内容完成操作" "默认用于执行此操作。" - "通过“主页设置”>“应用程序”>“管理应用程序”清除默认值。" - "选择操作" + "清除“主屏幕设置”>“应用程序”>“管理应用程序”中的默认设置。" + "选择一项操作" "没有应用程序可执行此操作。" "很抱歉!" - "应用程序%1$s(在进程 %2$s 中)已意外停止。请重试。" - "进程 %1$s 已意外停止。请重试。" + "应用程序%1$s(进程 %2$s)意外停止,请重试。" + "进程 %1$s 已意外停止,请重试。" "很抱歉!" - "活动%1$s(在应用程序 %2$s 中)无响应。" - "活动%1$s(在进程 %2$s 中)无响应。" - "应用程序%1$s(在进程 %2$s 中)无响应。" - "进程 %1$s 无响应。" - "强制关闭" + "%1$s活动(在 %2$s应用程序中)无响应。" + "%1$s活动(在%2$s进程中)无响应。" + "%1$s应用程序(在%2$s进程中)无响应。" + "%1$s进程无响应。" + "强行关闭" + + "等待" "调试" - "选择一个文本操作" - "响铃音量" + "选择要对文字执行的操作" + "铃声音量" "媒体音量" - "正通过蓝牙播放" - "来电音量" + "通过蓝牙播放" + "通话音量" "使用蓝牙时的通话音量" - "警告音量" + "闹钟音量" "通知音量" "音量" - "默认的手机铃声" - "默认的手机铃声(%1$s)" + "默认铃声" + "默认铃声(%1$s)" "静音" "铃声" - "未知手机铃声" + "未知铃声" "有可用的 Wi-Fi 网络" "有可用的 Wi-Fi 网络" @@ -610,7 +692,7 @@ "打开可用的 Wi-Fi 网络" "插入字符" - "未知应用程序" + "未知的应用程序" "正在发送短信" "正在发送大量短信。选择“确定”继续,或选择“取消”停止发送。" "确定" @@ -622,12 +704,12 @@ "全部显示" "正在载入..." "USB 已连接" - "您已通过 USB 将手机连接至计算机。如果要在计算机和手机的 SD 卡之间复制文件,请选择“装载”。" - "装载" - "不装载" + "您已通过 USB 将手机连接至计算机。如果要在计算机和手机的 SD 卡之间复制文件,请选择“安装”。" + "安装" + "不安装" "使用 SD 卡进行 USB 存储时出现问题。" "USB 已连接" - "选择以将文件复制到计算机或从计算机复制文件。" + "选择以将文件复制到计算机/从计算机复制文件。" "关闭 USB 存储设备" "选中以关闭 USB 存储设备。" "关闭 USB 存储设备" @@ -638,22 +720,31 @@ "格式化 SD 卡" "您确定要格式化 SD 卡?卡上的所有数据都会丢失。" "格式化" - "选择输入方法" + + + + + "选择输入法" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "候选" "正在准备 SD 卡" - "检查是否有错误" + + "空 SD 卡" - "SD 卡为空或使用不支持的文件系统。" + + "SD 卡受损" - "SD 卡受损。您可能需要重新格式化您的卡。" + + "SD 卡被意外拔除" "先卸载 SD 卡再拔除,以避免数据丢失。" "SD 卡已安全移除" - "现在可以安全移除 SD 卡。" + + "已移除 SD 卡" - "SD 卡已移除。请插入新 SD 卡来增加您的设备存储空间。" + + "找不到匹配的活动" "更新组件使用情况统计" "允许修改收集的组件使用情况统计。普通应用程序不能使用此权限。" @@ -665,8 +756,10 @@ "下一步" "完成" "执行" - + "拨打电话"\n"%s" + "创建电话号码为"\n"%s 的联系人" + - + diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 8cace6638b438..0f9c42314d1a9 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -21,6 +21,7 @@ "GB" "TB" "PB" + "%1$s%2$s" "(未命名)" "..." "(沒有電話號碼)" @@ -48,6 +49,12 @@ "通話限制" "變更密碼" "PIN 已變更" + "顯示來電號碼" + "隱藏發話號碼" + "三方通話" + "拒接不想接聽的騷擾電話" + "顯示發話號碼" + "勿干擾" "預設不顯示本機號碼,下一通電話也不顯示。" "預設不顯示本機號碼,但下一通電話顯示。" "預設顯示本機號碼,但下一通電話不顯示。" @@ -67,11 +74,27 @@ "同步處理" "封包" "按鍵" + "漫遊指示開啟" + "漫遊指示關閉" + "漫遊指示閃爍" + "超出鄰近範圍" + "超出建築物範圍" + "漫遊 - 偏好系統" + "漫遊 - 可用系統" + "漫遊 - 聯盟合作夥伴" + "漫遊 - Google Premium 合作夥伴" + "漫遊 - 完整服務功能" + "漫遊 - 部份服務功能" + "漫遊橫幅開啟" + "漫遊橫幅關閉" + "正在搜尋服務" "{0}:未轉接" "{0}: {1}" "{0}{2} 秒後 {1}" "{0}:未轉接" "{0}:未轉接" + "功能碼輸入完成。" + "連線發生問題或功能碼無效。" "確定" "網頁內容錯誤。" "找不到網址。" @@ -88,6 +111,7 @@ "無法存取此檔案。" "找不到要求的檔案。" "太多執行要求。請稍後再試一次。" + "憑證已儲存在系統的金鑰存放區。" "同步處理" "同步處理" "同時刪除太多 %s。" @@ -133,6 +157,8 @@ "系統低階存取與控制。" "開發工具" "只有開發者需要此功能。" + "儲存" + "存取 SD 卡。" "停用或變更狀態列" "允許應用程式停用狀態列或新增、移除系統圖示。" "展開/收攏狀態列" @@ -165,6 +191,10 @@ "允許應用程式強制關閉在前端運作的活動並返回。一般應用程式不需要此功能。" "接收系統內部狀態" "允許應用程式取得系統內部狀態。請注意:惡意程式可能利用此功能,不當取得私人或安全性資料。" + "部分關機" + "讓活動管理員進入關機狀態,而不執行完整的關機程序。" + "防止切換應用程式" + "防止使用者切換到其他應用程式。" "監視控制所有應用程式啟動狀態。" "允許應用程式監控管理系統啟動活動。請注意:惡意程式可能因此癱瘓整個系統。此權限只在開發時需要,一般手機使用不需要此權限。" "傳送程式已移除廣播" @@ -179,6 +209,8 @@ "允許應用程式控制哪些活動在被移到背景執行時,儘速結束。一般應用程式不需要此功能。" "編輯電池狀態" "允許修改電池狀態。一般應用程式不會使用此功能。" + "控制系統備份與還原" + "允許應用程式控制系統備份與還原機制,但一般應用程式不會使用此功能。" "顯示未授權視窗" "允許內部系統使用介面建立視窗。一般應用程式不會使用此功能。" "顯示系統警示" @@ -245,6 +277,8 @@ "建立模擬位置來源以供測試。請注意:惡意程式可能利用此功能覆寫 GPS 或電信業者傳回的位置及/或狀態。" "接收額外的位置提供者指令" "存取額外位置提供者命令。請注意:惡意程式可能利用此功能干擾 GPS 或其他位置來源。" + "准許安裝位置提供者" + "建立虛構的位置來源以供測試。請注意:惡意應用程式可能利用此選項覆寫由真實位置來源 (例如 GPS 或網路供應商) 所傳回的位置及/或狀態,或者監控您的位置並將之提供給外部來源。" "精確定位 (GPS)" "接收精確的位置來源 (例如:手機 GPS)。請注意:惡意程式可能使用此功能得知您的位置,並可能消耗額外電源。" "約略位置 (以網路為基準)" @@ -317,6 +351,8 @@ "允許應用程式檢視 Wi-Fi 狀態資訊。" "變更 Wi-Fi 狀態" "允許應用程式與 Wi-Fi 存取點連線或中斷連線,並可變更 Wi-Fi 網路設定。" + "允許接收 Wi-Fi 多點傳播封包" + "允許應用程式接收並非指定傳送給您裝置的封包,這在您發現附近有服務可使用時很有用,但消耗的電力比非多點傳播模式還要多。" "藍牙管理" "允許應用程式設定本機藍牙電話,以及偵測與配對其他遠端裝置。" "建立藍牙連線" @@ -337,6 +373,8 @@ "允許應用程式讀取使用者儲存在使用者字典內的任何私人字詞、名稱和詞組。" "寫入使用者定義的字典" "允許應用程式將新字詞寫入使用者的字典。" + "修改/刪除 SD 卡的內容" + "允許應用程式寫入 SD 卡。" "住家電話" "行動電話" @@ -353,6 +391,7 @@ "其他信箱" "自訂" + "行動裝置" "住家" "公司" @@ -382,17 +421,19 @@ "輸入 PIN 碼" "PIN 碼錯誤!" - "如要解鎖,請按 [選單],然後按 [0]。" + "如要解鎖,請按 Menu 鍵,然後按 0。" "緊急電話號碼" "(沒有服務)" "螢幕已鎖定。" "按下 [選單] 解鎖或撥打緊急電話。" - "按下 [選單] 解鎖。" + "按下 Menu 鍵解鎖。" "畫出解鎖圖形" "緊急電話" "正確!" "很抱歉,請再試一次" "正在充電 (%d%%)" + + "請連接充電器。" "沒有 SIM 卡。" "手機未插入 SIM 卡。" @@ -414,7 +455,8 @@ "使用者名稱或密碼錯誤。" "%-l%P" "%-l%p" - "清除通知" + + "沒有通知" "進行中" "通知" @@ -423,6 +465,7 @@ "請連接充電器" "電池電量即將不足:" "電池電量不到 %d%%。" + "原因" "出廠測試失敗" "只有安裝在 /system/app 裡的程式才能支援 FACTORY_TEST 操作。" "找不到提供 FACTORY_TEST 的程式。" @@ -431,6 +474,10 @@ "JavaScript" "離開此頁?"\n\n"%s"\n\n" 選取 [確定] 離開此頁;或 [取消] 留在此頁。" "確認" + "讀取瀏覽器的記錄與書籤" + "允許應用程式讀取瀏覽器曾經造訪過的所有網址,以及瀏覽器的所有書籤。" + "寫入瀏覽器的記錄與書籤" + "允許應用程式修改儲存在電話上的瀏覽記錄或書籤。請注意:惡意應用程式可能會使用此選項來清除或修改您瀏覽器的資料。" "是否記憶此密碼?" "現在不要" "記住" @@ -538,10 +585,6 @@ "中午" "午夜" "午夜" - - - - "%1$02d:%2$02d" "%1$d:%2$02d:%3$02d" "全部選取" @@ -579,6 +622,7 @@ "應用程式 %1$s (程序:%2$s) 無回應。" "%1$s 程序無回應。" "強制關閉" + "回報" "等待" "偵錯" "訊息傳送方式" @@ -632,22 +676,26 @@ "將 SD 卡格式化" "確定要將 SD 卡格式化嗎?該 SD 卡中的所有資料將會遺失。" "格式化" + + + + "選取輸入法" " ABCDEFGHIJKLMNOPQRSTUVWXYZ" " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" "待選項目" "正在準備 SD 卡" - "正在檢查錯誤" + "正在檢查錯誤。" "SD 卡為空白" - "SD 卡為空白或使用不支援的檔案系統。" + "SD 卡內無檔案系統,或檔案系統不受支援。" "SD 卡已損壞" - "SD 卡已損壞。您可能需要將 SD 卡重新格式化。" + "SD 卡已毀損,您可能必須予以重新格式化。" "SD 卡未正常移除" "請先卸載 SD 卡,再將其移除,以免資料遺失。" "可安全移除 SD 卡" - "現在可以安全移除 SD 卡。" + "您現在可以安全地移除 SD 卡。" "已移除 SD 卡" - "已移除 SD 卡。請插入新的 SD 卡來增加裝置的儲存容量。" + "SD 卡已移除,請插入新的 SD 卡。" "找不到符合的活動" "更新元件使用統計資料" "允許修改收集到的元件使用統計資料。一般應用程式不會使用此功能。" @@ -661,4 +709,6 @@ "執行" "使用 %s"\n"撥號" "建立手機號碼為 %s"\n"的聯絡人" + "已勾選" + "未勾選" diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 6f2a5d3c6f8a3..fd78f83698aa4 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2888,6 +2888,14 @@ attribute. --> + + + + + - - + + + + + + + + + + + - #ffd57e - #ddb66a - #eeeeee - #c0c0c0 + #dd6826 + #dd6826 - #7fa87f + #7fa87f + @android:color/black + @android:color/black @android:color/lighter_gray diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 32c693757dcf1..919c3d6e5b07f 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1125,6 +1125,8 @@ + + diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 7d235ec8d4ef9..8eda12e1f1314 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -348,7 +348,8 @@ -
     MyApp/
         res/
    -        drawable-en-rUS-port-160dpi-finger-keysexposed-qwerty-dpad-480x320/
    +        drawable-en-rUS-large-long-port-mdpi-finger-keysexposed-qwerty-dpad-480x320/
     

    More typically, you will only specify a few specific configuration options. You may drop any of the values from the @@ -453,7 +453,7 @@ MyApp/ res/ drawable-en-rUS-finger/ drawable-port/ - drawable-port-160dpi/ + drawable-port-mdpi/ drawable-qwerty/

    Table 2 lists the valid folder-name qualifiers, in order of precedence. Qualifiers that are listed higher in the table take precedence over those listed lower, as described in How Android finds the best matching directory.

    @@ -465,37 +465,110 @@ MyApp/ MCC and MNC - The mobile country code and mobile network code from the SIM in the device. For example mcc310-mnc004 (U.S., Verizon brand); mcc208-mnc00 (France, Orange brand); mcc234-mnc00 (U.K., BT brand).
    -
    - If the device uses a radio connection (GSM phone), the MCC will come from the SIM, and the MNC will come from the network to which the device is attached. You might sometimes use the MCC alone, for example to include country-specific legal resources in your application. If your application specifies resources for a MCC/MNC combination, those resources can only be used if both the MCC and the MNC match. - + The mobile country code optionally followed by mobile network code + from the SIM in the device. For example + mcc310 (U.S. on any carrier); + mcc310-mnc004 (U.S., Verizon brand); + mcc208-mnc00 (France, Orange brand); + mcc234-mnc00 (U.K., BT brand). +

    + If the device uses a radio connection (GSM phone), the MCC will come + from the SIM, and the MNC will come from the network to which the + device is attached. You might sometimes use the MCC alone, for example + to include country-specific legal resources in your application. If + your application specifies resources for a MCC/MNC combination, those + resources can only be used if both the MCC and the MNC match. + Language and region The two letter ISO - 639-1 language code and two letter + 639-1 language code optionally followed by a two letter ISO 3166-1-alpha-2 region code (preceded by lowercase "r"). For example - en-rUS, fr-rFR, es-rES.
    -
    - The codes are case-sensitive: The language code is lowercase, and the country code is uppercase. You cannot specify a region alone, but you can specify a language alone, for example en, fr, es. - + fr, en-rUS, fr-rFR, es-rES. +

    + The codes are not case-sensitive; the r prefix is used to + distinguish the region portion. + You cannot specify a region alone, but you can specify a language alone, + for example en, fr, es. + + + Screen dimensions + small, normal, large +

    + Specify that the resource is for a particular class of screen. + The meanings of these are:

    +
      +
    • Normal screens are based on the traditional Android HVGA + medium density screen. A screen is considered to be normal if it is + at least this size (independent of density) and not large. Examples + of such screens a WQVGA low density, HVGA medium density, WVGA + high density. +
    • Small screens are based on the space available on a + QVGA low density screen. Considering a portrait HVGA display, this has + the same available width but less height -- it is 3:4 vs. HVGA's + 2:3 aspect ratio. Examples are QVGA low density and VGA high + density. +
    • Large screens are based on the space available on a + VGA medium density screen. Such a screen has significantly more + available space in both width and height than an HVGA display. + Examples are VGA and WVGA medium density screens. + + + + Wider/taller screens + long, notlong +

      + Specify that the resource is for a taller/wider than traditional + screen. This is based purely on the aspect ration of the screen: + QVGA, HVGA, and VGA are notlong; WQVGA, WVGA, FWVGA are long. Note + that long may mean either wide or tall, depending on the current + orientation. + + Screen orientation - port, land, square + port, land, square +

      + Specifies that the resource is for a screen that is tall (port) + or wide (land); square is not currently used. + Screen pixel density - 92dpi, 108dpi, etc. When Android selects which resource files to use, it handles screen density differently than the other qualifiers. In step 1 of How Android finds the best matching directory (below), screen density is always considered to be a match. In step 4, if the qualifier being considered is screen density, Android will select the best final match at that point, without any need to move on to step 5. - + ldpi, mdpi, hdpi, nodpi +

      + Specifies the screen density the resource is defined for. The medium + density of traditional HVGA screens (mdpi) is defined to be approximately + 160dpi; low density (ldpi) is 120, and high density (hdpi) is 240. There + is thus a 4:3 scaling factor between each density, so a 9x9 bitmap + in ldpi would be 12x12 is mdpi and 16x16 in hdpi. The special + nodpi density can be used with bitmap resources to prevent + them from being scaled at load time to match the device density. +

      + When Android selects which resource files to use, + it handles screen density differently than the other qualifiers. + In step 1 of How Android finds the best + matching directory (below), screen density is always considered to + be a match. In step 4, if the qualifier being considered is screen + density, Android will select the best final match at that point, + without any need to move on to step 5. +

      + You can also specify explicit densities like 92dpi + or 108dpi, but these are not fully supported by the + system so should not be used. + + Touchscreen type notouch, stylus, finger Whether the keyboard is available to the user - keysexposed, keyshidden, keyssoft
      + keysexposed, keyshidden, keyssoft +

      If your application has specific resources that should only be used with a soft keyboard, use the keyssoft value. If no keyssoft resources are available (only keysexposed and keyshidden) and the device shows a soft keyboard, the system will use keysexposed resources. - + Primary text input method nokeys, qwerty, 12key @@ -508,15 +581,17 @@ MyApp/ Screen dimensions 320x240, 640x480, etc. The larger dimension - must be specified first. + must be specified first. This configuration is deprecated and + should not be used; use instead screen dimension, wider/taller + screens, and screen orientation described above. SDK version The SDK version supported by the device, for example v3. The Android 1.0 SDK is v1, the 1.1 SDK is v2, and the 1.5 SDK is v3. - + (Minor version) - (You cannot currently specify minor version. It is always set to 0.) + (You cannot currently specify minor version. It is always set to 0.) @@ -536,8 +611,11 @@ resource qualifiers in the table above.

    • Incorrect: values-nokeys-mcc460/
    -
  • Values are case-sensitive. For example, a portrait-specific drawable directory must be named - drawable-port, not drawable-PORT or drawable-Port.
  • +
  • Values are case-insensitive. The resource compiler converts folder names + to lower case before processing to avoid problems in case-insensitive + file systems. On case-sensitive file systems, you should keep all names + lower-case or at least use a consistent case to protect your future + sanity when trying to find a resource file.
  • Only one value for each qualifier type is supported. For example, if you want to use exactly the same drawable files for Spain and France, you will need two resource directories, such as drawable-rES/ and drawable-rFR/, containing identical files. You cannot have a directory named drawable-rES-rFR/.
  • Qualified directories cannot be nested. For example, you cannot have res/drawable/drawable-en.
  • @@ -546,7 +624,7 @@ resource qualifiers in the table above.

    How resources are referenced in code

    All resources will be referenced in code or resource reference syntax by their simple, undecorated names. So if a resource were named this:
    -      MyApp/res/drawable-port-92dpi/myimage.png
    +      MyApp/res/drawable-port-mdpi/myimage.png
    It would be referenced as this:
          R.drawable.myimage (code)
          @drawable/myimage (XML)

    @@ -554,11 +632,12 @@ resource qualifiers in the table above.

    How Android finds the best matching directory

    Android will pick which of the various underlying resource files should be -used at runtime, depending on the current configuration of the device. The example used here assumes the following device configuration:

    +used at runtime, depending on the current configuration of the device. +The example used here assumes the following device configuration:

    Locale = en-GB
    Screen orientation = port
    - Screen pixel density = 108dpi
    + Screen pixel density = mdpi
    Touchscreen type = notouch
    Primary text input method = 12key

    @@ -573,9 +652,9 @@ MyApp/res/drawable-en/ MyApp/res/drawable-fr-rCA/ MyApp/res/drawable-en-port/ MyApp/res/drawable-en-notouch-12key/ -MyApp/res/drawable-port-92dpi/ +MyApp/res/drawable-port-ldpi/ MyApp/res/drawable-port-notouch-12key - Exception: Screen pixel density is the one qualifier that is not used to eliminate files. Even though the screen density of the device is 108 dpi, drawable-port-92dpi/ is not eliminated from the list, because every screen density is considered to be a + Exception: Screen pixel density is the one qualifier that is not used to eliminate files. Even though the screen density of the device is medium dpi, drawable-port-ldpi/ is not eliminated from the list, because every screen density is considered to be a match at this point.
  • From Table 2, pick the highest-precedence qualifier that remains in the list. (Start with MCC, then move down through the list.)
  • Do any of the available resource directories include this qualifier?
  • @@ -588,7 +667,7 @@ MyApp/res/drawable-port-notouch-12key MyApp/res/drawable-en/ MyApp/res/drawable-en-port/ MyApp/res/drawable-en-notouch-12key/ -MyApp/res/drawable-port-92dpi/ +MyApp/res/drawable-port-ldpi/ MyApp/res/drawable-port-notouch-12key Exception: If the qualifier in question is screen pixel density, Android will select the option that most closely matches the device, and the selection process will be complete. In general, Android will prefer scaling down a larger original image to scaling up a smaller original image.

    @@ -597,7 +676,11 @@ MyApp/res/drawable-en-notouch-12key/
    MyApp/res/drawable-en/
     MyApp/res/drawable-en-port/
     MyApp/res/drawable-en-notouch-12key/
    - Only one choice remains, so that's it. When drawables are called for in this example application, the Android system will load resources from the MyApp/res/drawable-en-port/ directory. + Only one choice remains, so that's it. When drawables are called for in this + example application, the Android system will load resources from the + MyApp/res/drawable-en-port/ directory. In addition, if the + resource being loaded is a bitmap, it will be scaled up so that its supplied + low density matches the device's medium density.

    Tip: The precedence of the qualifiers is more important than the number of qualifiers that exactly match the device. For example, in step 4 above, the last choice on the list includes three qualifiers that exactly match the device (orientation, touchscreen type, and input method), while drawable-en has only one parameter that matches (language). However, language has a higher precedence, so drawable-port-notouch-12key is out.

    This flowchart summarizes how Android selects resource directories to load.

    diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index e2e93eb87e678..df659ef224dee 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -18,6 +18,7 @@ package android.graphics; import android.os.Parcel; import android.os.Parcelable; +import android.util.DisplayMetrics; import java.io.OutputStream; import java.nio.Buffer; @@ -31,8 +32,6 @@ public final class Bitmap implements Parcelable { * * @see Bitmap#getDensityScale() * @see Bitmap#setDensityScale(float) - * - * @hide pending API council approval */ public static final float DENSITY_SCALE_UNKNOWN = -1.0f; @@ -84,11 +83,9 @@ public final class Bitmap implements Parcelable { * @see #setDensityScale(float) * @see #isAutoScalingEnabled() * @see #setAutoScalingEnabled(boolean) - * @see android.util.DisplayMetrics#DEFAULT_DENSITY + * @see android.util.DisplayMetrics#DENSITY_DEFAULT * @see android.util.DisplayMetrics#density * @see #DENSITY_SCALE_UNKNOWN - * - * @hide pending API council approval */ public float getDensityScale() { return mDensityScale; @@ -106,11 +103,9 @@ public final class Bitmap implements Parcelable { * @see #getDensityScale() * @see #isAutoScalingEnabled() * @see #setAutoScalingEnabled(boolean) - * @see android.util.DisplayMetrics#DEFAULT_DENSITY + * @see android.util.DisplayMetrics#DENSITY_DEFAULT * @see android.util.DisplayMetrics#density * @see #DENSITY_SCALE_UNKNOWN - * - * @hide pending API council approval */ public void setDensityScale(float densityScale) { mDensityScale = densityScale; @@ -132,8 +127,6 @@ public final class Bitmap implements Parcelable { * @see #setAutoScalingEnabled(boolean) * @see #getDensityScale() * @see #setDensityScale(float) - * - * @hide pending API council approval */ public boolean isAutoScalingEnabled() { return mAutoScaling; @@ -150,8 +143,6 @@ public final class Bitmap implements Parcelable { * the bitmap will never be automatically scaled at drawing time.

    * * @param autoScalingEnabled True to scale the bitmap at drawing time, false otherwise. - * - * @hide pending API council approval */ public void setAutoScalingEnabled(boolean autoScalingEnabled) { mAutoScaling = autoScalingEnabled; @@ -465,8 +456,8 @@ public final class Bitmap implements Parcelable { // The new bitmap was created from a known bitmap source so assume that // they use the same density scale - bitmap.setDensityScale(source.getDensityScale()); - bitmap.setAutoScalingEnabled(source.isAutoScalingEnabled()); + bitmap.mDensityScale = source.mDensityScale; + bitmap.mAutoScaling = source.mAutoScaling; return bitmap; } @@ -615,26 +606,60 @@ public final class Bitmap implements Parcelable { * Convenience method that returns the width of this bitmap divided * by the density scale factor. * + * @param canvas The Canvas the bitmap will be drawn to. * @return The scaled width of this bitmap, according to the density scale factor. - * - * @hide pending API council approval */ - public int getScaledWidth() { - final float scale = getDensityScale(); - return scale == DENSITY_SCALE_UNKNOWN ? getWidth() : (int) (getWidth() / scale); + public int getScaledWidth(Canvas canvas) { + final float scale = mDensityScale; + if (!mAutoScaling || scale < 0) { + return getWidth(); + } + return (int)(getWidth() * canvas.getDensityScale() / scale); } /** * Convenience method that returns the height of this bitmap divided * by the density scale factor. * + * @param canvas The Canvas the bitmap will be drawn to. * @return The scaled height of this bitmap, according to the density scale factor. - * - * @hide pending API council approval */ - public int getScaledHeight() { - final float scale = getDensityScale(); - return scale == DENSITY_SCALE_UNKNOWN ? getWidth() : (int) (getHeight() / scale); + public int getScaledHeight(Canvas canvas) { + final float scale = mDensityScale; + if (!mAutoScaling || scale < 0) { + return getHeight(); + } + return (int)(getHeight() * canvas.getDensityScale() / scale); + } + + /** + * Convenience method that returns the width of this bitmap divided + * by the density scale factor. + * + * @param metrics The target display metrics. + * @return The scaled width of this bitmap, according to the density scale factor. + */ + public int getScaledWidth(DisplayMetrics metrics) { + final float scale = mDensityScale; + if (!mAutoScaling || scale < 0) { + return getWidth(); + } + return (int)(getWidth() * metrics.density / scale); + } + + /** + * Convenience method that returns the height of this bitmap divided + * by the density scale factor. + * + * @param metrics The target display metrics. + * @return The scaled height of this bitmap, according to the density scale factor. + */ + public int getScaledHeight(DisplayMetrics metrics) { + final float scale = mDensityScale; + if (!mAutoScaling || scale < 0) { + return getHeight(); + } + return (int)(getHeight() * metrics.density / scale); } /** diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index e5a9aab7ad63b..76abaa23b9a09 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -81,10 +81,8 @@ public class BitmapFactory { /** * The desired pixel density of the bitmap. * - * @see android.util.DisplayMetrics#DEFAULT_DENSITY + * @see android.util.DisplayMetrics#DENSITY_DEFAULT * @see android.util.DisplayMetrics#density - * - * @hide pending API council approval */ public int inDensity; @@ -97,8 +95,6 @@ public class BitmapFactory { * a non-scaled version of the bitmap. In this case, * {@link android.graphics.Bitmap#setAutoScalingEnabled(boolean)} can be used * to properly scale the bitmap at drawing time.

    - * - * @hide pending API council approval */ public boolean inScaled; @@ -128,6 +124,19 @@ public class BitmapFactory { */ public boolean inInputShareable; + /** + * Normally bitmap allocations count against the dalvik heap, which + * means they help trigger GCs when a lot have been allocated. However, + * in rare cases, the caller may want to allocate the bitmap outside of + * that heap. To request that, set inNativeAlloc to true. In these + * rare instances, it is solely up to the caller to ensure that OOM is + * managed explicitly by calling bitmap.recycle() as soon as such a + * bitmap is no longer needed. + * + * @hide pending API council approval + */ + public boolean inNativeAlloc; + /** * The resulting width of the bitmap, set independent of the state of * inJustDecodeBounds. However, if there is an error trying to decode, @@ -225,8 +234,6 @@ public class BitmapFactory { /** * Decode a new Bitmap from an InputStream. This InputStream was obtained from * resources, which we pass to be able to scale the bitmap accordingly. - * - * @hide */ public static Bitmap decodeStream(Resources res, TypedValue value, InputStream is, Rect pad, Options opts) { @@ -238,15 +245,19 @@ public class BitmapFactory { Bitmap bm = decodeStream(is, pad, opts); if (bm != null && res != null && value != null) { + final int density = value.density; + if (density == TypedValue.DENSITY_NONE) { + return bm; + } + byte[] np = bm.getNinePatchChunk(); final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np); - final int density = value.density; if (opts.inDensity == 0) { opts.inDensity = density == TypedValue.DENSITY_DEFAULT ? - DisplayMetrics.DEFAULT_DENSITY : density; + DisplayMetrics.DENSITY_DEFAULT : density; } - float scale = opts.inDensity / (float) DisplayMetrics.DEFAULT_DENSITY; + float scale = opts.inDensity / (float) DisplayMetrics.DENSITY_DEFAULT; if (opts.inScaled || isNinePatch) { bm.setDensityScale(1.0f); diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 4498e1a2e117e..da7359772ee38 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -184,8 +184,6 @@ public class Canvas { * * @see #setDensityScale(float) * @see Bitmap#getDensityScale() - * - * @hide pending API council approval */ public float getDensityScale() { if (mBitmap != null) { @@ -205,8 +203,6 @@ public class Canvas { * * @see #getDensityScale() * @see Bitmap#setDensityScale(float) - * - * @hide pending API council approval */ public void setDensityScale(float densityScale) { if (mBitmap != null) { diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index 50ab566bb26cc..42a14ce8417d0 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -552,10 +552,10 @@ public final class Rect implements Parcelable { */ public void scale(float scale) { if (scale != 1.0f) { - left *= scale; - top *= scale; - right *= scale; - bottom*= scale; + left = (int) (left * scale + 0.5f); + top = (int) (top * scale + 0.5f); + right = (int) (right * scale + 0.5f); + bottom = (int) (bottom * scale + 0.5f); } } } diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index d24194f545f12..6677a3560de38 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -278,10 +278,15 @@ public class ShapeDrawable extends Drawable { if (name.equals("padding")) { TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.ShapeDrawablePadding); - setPadding(a.getInt(com.android.internal.R.styleable.ShapeDrawablePadding_left, 0), - a.getInt(com.android.internal.R.styleable.ShapeDrawablePadding_top, 0), - a.getInt(com.android.internal.R.styleable.ShapeDrawablePadding_right, 0), - a.getInt(com.android.internal.R.styleable.ShapeDrawablePadding_bottom, 0)); + setPadding( + a.getDimensionPixelOffset( + com.android.internal.R.styleable.ShapeDrawablePadding_left, 0), + a.getDimensionPixelOffset( + com.android.internal.R.styleable.ShapeDrawablePadding_top, 0), + a.getDimensionPixelOffset( + com.android.internal.R.styleable.ShapeDrawablePadding_right, 0), + a.getDimensionPixelOffset( + com.android.internal.R.styleable.ShapeDrawablePadding_bottom, 0)); a.recycle(); return true; } diff --git a/include/ui/Camera.h b/include/ui/Camera.h index e3544ab0f1557..afb07b5cf0d9d 100644 --- a/include/ui/Camera.h +++ b/include/ui/Camera.h @@ -18,6 +18,7 @@ #ifndef ANDROID_HARDWARE_CAMERA_H #define ANDROID_HARDWARE_CAMERA_H +#include #include namespace android { @@ -94,6 +95,7 @@ class CameraListener: virtual public RefBase public: virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void postData(int32_t msgType, const sp& dataPtr) = 0; + virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr) = 0; }; class Camera : public BnCameraClient, public IBinder::DeathRecipient @@ -155,6 +157,7 @@ public: // ICameraClient interface virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2); virtual void dataCallback(int32_t msgType, const sp& dataPtr); + virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr); sp remote(); diff --git a/include/ui/CameraHardwareInterface.h b/include/ui/CameraHardwareInterface.h index 73036f0fa7837..822b4a8f5d3b9 100644 --- a/include/ui/CameraHardwareInterface.h +++ b/include/ui/CameraHardwareInterface.h @@ -28,7 +28,7 @@ namespace android { typedef void (*preview_callback)(const sp& mem, void* user); /** Callback for startRecord() */ -typedef void (*recording_callback)(const sp& mem, void* user); +typedef void (*recording_callback)(nsecs_t timestamp, const sp& mem, void* user); /** Callback for takePicture() */ typedef void (*shutter_callback)(void* user); diff --git a/include/ui/ICameraClient.h b/include/ui/ICameraClient.h index c4bdd07585757..1001c718905e9 100644 --- a/include/ui/ICameraClient.h +++ b/include/ui/ICameraClient.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace android { @@ -31,7 +32,7 @@ public: virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void dataCallback(int32_t msgType, const sp& data) = 0; - + virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp& data) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h index 93bca4aefc08a..edd0cae637261 100644 --- a/include/utils/ResourceTypes.h +++ b/include/utils/ResourceTypes.h @@ -825,7 +825,11 @@ struct ResTable_config }; enum { - DENSITY_ANY = 0 + DENSITY_DEFAULT = 0, + DENSITY_LOW = 120, + DENSITY_MEDIUM = 160, + DENSITY_HIGH = 240, + DENSITY_NONE = 0xffff }; union { @@ -854,7 +858,6 @@ struct ResTable_config enum { MASK_KEYSHIDDEN = 0x0003, - SHIFT_KEYSHIDDEN = 0, KEYSHIDDEN_ANY = 0x0000, KEYSHIDDEN_NO = 0x0001, KEYSHIDDEN_YES = 0x0002, @@ -906,10 +909,18 @@ struct ResTable_config }; enum { - SCREENLAYOUT_ANY = 0x0000, - SCREENLAYOUT_SMALL = 0x0001, - SCREENLAYOUT_NORMAL = 0x0002, - SCREENLAYOUT_LARGE = 0x0003, + // screenLayout bits for screen size class. + MASK_SCREENSIZE = 0x0f, + SCREENSIZE_ANY = 0x00, + SCREENSIZE_SMALL = 0x01, + SCREENSIZE_NORMAL = 0x02, + SCREENSIZE_LARGE = 0x03, + + // screenLayout bits for wide/long screen variation. + MASK_SCREENLONG = 0x30, + SCREENLONG_ANY = 0x00, + SCREENLONG_NO = 0x10, + SCREENLONG_YES = 0x20, }; union { @@ -1039,6 +1050,17 @@ struct ResTable_config } } + if (screenConfig || o.screenConfig) { + if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0) { + if (!(screenLayout & MASK_SCREENSIZE)) return false; + if (!(o.screenLayout & MASK_SCREENSIZE)) return true; + } + if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0) { + if (!(screenLayout & MASK_SCREENLONG)) return false; + if (!(o.screenLayout & MASK_SCREENLONG)) return true; + } + } + if (screenType || o.screenType) { if (orientation != o.orientation) { if (!orientation) return false; @@ -1055,7 +1077,7 @@ struct ResTable_config } if (input || o.input) { - if (inputFlags != o.inputFlags) { + if (((inputFlags^o.inputFlags) & MASK_KEYSHIDDEN) != 0) { if (!(inputFlags & MASK_KEYSHIDDEN)) return false; if (!(o.inputFlags & MASK_KEYSHIDDEN)) return true; } @@ -1083,13 +1105,6 @@ struct ResTable_config } } - if (screenConfig || o.screenConfig) { - if (screenLayout != o.screenLayout) { - if (!screenLayout) return false; - if (!o.screenLayout) return true; - } - } - if (version || o.version) { if (sdkVersion != o.sdkVersion) { if (!sdkVersion) return false; @@ -1138,6 +1153,17 @@ struct ResTable_config } } + if (screenConfig || o.screenConfig) { + if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0 + && (requested->screenLayout & MASK_SCREENSIZE)) { + return (screenLayout & MASK_SCREENSIZE); + } + if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0 + && (requested->screenLayout & MASK_SCREENLONG)) { + return (screenLayout & MASK_SCREENLONG); + } + } + if (screenType || o.screenType) { if ((orientation != o.orientation) && requested->orientation) { return (orientation); @@ -1219,12 +1245,6 @@ struct ResTable_config } } - if (screenConfig || o.screenConfig) { - if ((screenLayout != o.screenLayout) && requested->screenLayout) { - return (screenLayout); - } - } - if (version || o.version) { if ((sdkVersion != o.sdkVersion) && requested->sdkVersion) { return (sdkVersion); @@ -1272,6 +1292,21 @@ struct ResTable_config return false; } } + if (screenConfig != 0) { + const int screenSize = screenLayout&MASK_SCREENSIZE; + const int setScreenSize = settings.screenLayout&MASK_SCREENSIZE; + if (setScreenSize != 0 && screenSize != 0 + && screenSize != setScreenSize) { + return false; + } + + const int screenLong = screenLayout&MASK_SCREENLONG; + const int setScreenLong = settings.screenLayout&MASK_SCREENLONG; + if (setScreenLong != 0 && screenLong != 0 + && screenLong != setScreenLong) { + return false; + } + } if (screenType != 0) { if (settings.orientation != 0 && orientation != 0 && orientation != settings.orientation) { @@ -1316,12 +1351,6 @@ struct ResTable_config return false; } } - if (screenConfig != 0) { - if (settings.screenLayout != 0 && screenLayout != 0 - && screenLayout != settings.screenLayout) { - return false; - } - } if (version != 0) { if (settings.sdkVersion != 0 && sdkVersion != 0 && sdkVersion != settings.sdkVersion) { @@ -1351,12 +1380,14 @@ struct ResTable_config String8 toString() const { char buf[200]; sprintf(buf, "imsi=%d/%d lang=%c%c reg=%c%c orient=%d touch=%d dens=%d " - "kbd=%d nav=%d input=%d scrnW=%d scrnH=%d layout=%d vers=%d.%d", + "kbd=%d nav=%d input=%d scrnW=%d scrnH=%d sz=%d long=%d vers=%d.%d", mcc, mnc, language[0] ? language[0] : '-', language[1] ? language[1] : '-', country[0] ? country[0] : '-', country[1] ? country[1] : '-', orientation, touchscreen, density, keyboard, navigation, inputFlags, - screenWidth, screenHeight, screenLayout, sdkVersion, minorVersion); + screenWidth, screenHeight, + screenLayout&MASK_SCREENSIZE, screenLayout&MASK_SCREENLONG, + sdkVersion, minorVersion); return String8(buf); } }; diff --git a/include/utils/String8.h b/include/utils/String8.h index c49faf6fe0628..ecc57743796de 100644 --- a/include/utils/String8.h +++ b/include/utils/String8.h @@ -29,11 +29,107 @@ // --------------------------------------------------------------------------- +extern "C" { + +typedef uint32_t char32_t; + +size_t strlen32(const char32_t *); +size_t strnlen32(const char32_t *, size_t); + +/* + * Returns the length of "src" when "src" is valid UTF-8 string. + * Returns 0 if src is NULL, 0-length string or non UTF-8 string. + * This function should be used to determine whether "src" is valid UTF-8 + * characters with valid unicode codepoints. "src" must be null-terminated. + * + * If you are going to use other GetUtf... functions defined in this header + * with string which may not be valid UTF-8 with valid codepoint (form 0 to + * 0x10FFFF), you should use this function before calling others, since the + * other functions do not check whether the string is valid UTF-8 or not. + * + * If you do not care whether "src" is valid UTF-8 or not, you should use + * strlen() as usual, which should be much faster. + */ +size_t utf8_length(const char *src); + +/* + * Returns the UTF-32 length of "src". + */ +size_t utf32_length(const char *src, size_t src_len); + +/* + * Returns the UTF-8 length of "src". + */ +size_t utf8_length_from_utf32(const char32_t *src, size_t src_len); + +/* + * Returns the unicode value at "index". + * Returns -1 when the index is invalid (equals to or more than "src_len"). + * If returned value is positive, it is able to be converted to char32_t, which + * is unsigned. Then, if "next_index" is not NULL, the next index to be used is + * stored in "next_index". "next_index" can be NULL. + */ +int32_t utf32_at(const char *src, size_t src_len, + size_t index, size_t *next_index); + +/* + * Stores a UTF-32 string converted from "src" in "dst", if "dst_length" is not + * large enough to store the string, the part of the "src" string is stored + * into "dst". + * Returns the size actually used for storing the string. + * "dst" is not null-terminated when dst_len is fully used (like strncpy). + */ +size_t utf8_to_utf32(const char* src, size_t src_len, + char32_t* dst, size_t dst_len); + +/* + * Stores a UTF-8 string converted from "src" in "dst", if "dst_length" is not + * large enough to store the string, the part of the "src" string is stored + * into "dst" as much as possible. See the examples for more detail. + * Returns the size actually used for storing the string. + * dst" is not null-terminated when dst_len is fully used (like strncpy). + * + * Example 1 + * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84) + * "src_len" == 2 + * "dst_len" >= 7 + * -> + * Returned value == 6 + * "dst" becomes \xE3\x81\x82\xE3\x81\x84\0 + * (note that "dst" is null-terminated) + * + * Example 2 + * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84) + * "src_len" == 2 + * "dst_len" == 5 + * -> + * Returned value == 3 + * "dst" becomes \xE3\x81\x82\0 + * (note that "dst" is null-terminated, but \u3044 is not stored in "dst" + * since "dst" does not have enough size to store the character) + * + * Example 3 + * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84) + * "src_len" == 2 + * "dst_len" == 6 + * -> + * Returned value == 6 + * "dst" becomes \xE3\x81\x82\xE3\x81\x84 + * (note that "dst" is NOT null-terminated, like strncpy) + */ +size_t utf32_to_utf8(const char32_t* src, size_t src_len, + char* dst, size_t dst_len); + +} + +// --------------------------------------------------------------------------- + namespace android { class TextOutput; -//! This is a string holding UTF-8 characters. +//! This is a string holding UTF-8 characters. Does not allow the value more +// than 0x10FFFF, which is not valid unicode codepoint. class String8 { public: @@ -45,7 +141,8 @@ public: explicit String8(const String16& o); explicit String8(const char16_t* o); explicit String8(const char16_t* o, size_t numChars); - + explicit String8(const char32_t* o); + explicit String8(const char32_t* o, size_t numChars); ~String8(); inline const char* string() const; @@ -59,11 +156,20 @@ public: status_t setTo(const char* other); status_t setTo(const char* other, size_t numChars); status_t setTo(const char16_t* other, size_t numChars); - + status_t setTo(const char32_t* other, + size_t length); + status_t append(const String8& other); status_t append(const char* other); status_t append(const char* other, size_t numChars); + // Note that this function takes O(N) time to calculate the value. + // No cache value is stored. + size_t getUtf32Length() const; + int32_t getUtf32At(size_t index, + size_t *next_index) const; + size_t getUtf32(char32_t* dst, size_t dst_len) const; + inline String8& operator=(const String8& other); inline String8& operator=(const char* other); @@ -103,7 +209,7 @@ public: void toLower(size_t start, size_t numChars); void toUpper(); void toUpper(size_t start, size_t numChars); - + /* * These methods operate on the string as if it were a path name. */ @@ -346,7 +452,7 @@ inline String8::operator const char*() const return mString; } -}; // namespace android +} // namespace android // --------------------------------------------------------------------------- diff --git a/keystore/java/android/security/CertTool.java b/keystore/java/android/security/CertTool.java index 26d22aec57fbd..79418bd489958 100644 --- a/keystore/java/android/security/CertTool.java +++ b/keystore/java/android/security/CertTool.java @@ -16,11 +16,19 @@ package android.security; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; + import android.content.Context; import android.content.Intent; import android.security.Keystore; import android.text.TextUtils; - +import android.util.Log; /** * The CertTool class provides the functions to list the certs/keys, @@ -41,12 +49,13 @@ public class CertTool { public static final String KEY_NAMESPACE = "namespace"; public static final String KEY_DESCRIPTION = "description"; - private static final String TAG = "CertTool"; + public static final String TITLE_CA_CERT = "CA Certificate"; + public static final String TITLE_USER_CERT = "User Certificate"; + public static final String TITLE_PKCS12_KEYSTORE = "PKCS12 Keystore"; + public static final String TITLE_PRIVATE_KEY = "Private Key"; + public static final int INCORRECT_PKCS12_PASSPHRASE = -100; - private static final String TITLE_CA_CERT = "CA Certificate"; - private static final String TITLE_USER_CERT = "User Certificate"; - private static final String TITLE_PKCS12_KEYSTORE = "PKCS12 Keystore"; - private static final String TITLE_PRIVATE_KEY = "Private Key"; + private static final String TAG = "CertTool"; private static final String UNKNOWN = "Unknown"; private static final String ISSUER_NAME = "Issuer Name:"; private static final String DISTINCT_NAME = "Distinct Name:"; @@ -58,6 +67,11 @@ public class CertTool { private static final String KEYNAME_DELIMITER = "_"; private static final Keystore sKeystore = Keystore.getInstance(); + private native int getPkcs12Handle(byte[] data, String password); + private native String getPkcs12Certificate(int handle); + private native String getPkcs12PrivateKey(int handle); + private native String popPkcs12CertificateStack(int handle); + private native void freePkcs12Handle(int handle); private native String generateCertificateRequest(int bits, String subject); private native boolean isPkcs12Keystore(byte[] data); private native int generateX509Certificate(byte[] data); @@ -130,10 +144,52 @@ public class CertTool { intent.putExtra(KEY_NAMESPACE + "1", namespace); } + private int extractAndStoreKeysFromPkcs12(int handle, String keyname) { + int ret, i = 0; + String pemData; + + if ((pemData = getPkcs12Certificate(handle)) != null) { + if ((ret = sKeystore.put(USER_CERTIFICATE, keyname, pemData)) != 0) { + return ret; + } + } + if ((pemData = getPkcs12PrivateKey(handle)) != null) { + if ((ret = sKeystore.put(USER_KEY, keyname, pemData)) != 0) { + return ret; + } + } + while ((pemData = this.popPkcs12CertificateStack(handle)) != null) { + if (i++ > 0) { + if ((ret = sKeystore.put(CA_CERTIFICATE, keyname + i, pemData)) != 0) { + return ret; + } + } else { + if ((ret = sKeystore.put(CA_CERTIFICATE, keyname, pemData)) != 0) { + return ret; + } + } + } + return 0; + } + + public int addPkcs12Keystore(byte[] p12Data, String password, + String keyname) { + int handle, ret; + Log.i("CertTool", "addPkcs12Keystore()"); + + if ((handle = getPkcs12Handle(p12Data, password)) == 0) { + return INCORRECT_PKCS12_PASSPHRASE; + } + ret = extractAndStoreKeysFromPkcs12(handle, keyname); + freePkcs12Handle(handle); + return ret; + } + public synchronized void addCertificate(byte[] data, Context context) { int handle; Intent intent = null; + Log.i("CertTool", "addCertificate()"); if (isPkcs12Keystore(data)) { intent = prepareIntent(TITLE_PKCS12_KEYSTORE, data, USER_KEY, UNKNOWN, UNKNOWN); diff --git a/keystore/java/android/security/Keystore.java b/keystore/java/android/security/Keystore.java index 1f14da78c2c3b..a6cfbcac7c0c0 100644 --- a/keystore/java/android/security/Keystore.java +++ b/keystore/java/android/security/Keystore.java @@ -48,49 +48,6 @@ public abstract class Keystore { public abstract int remove(String namespace, String keyname); public abstract int reset(); - // TODO: for migrating to the mini-keystore, clean up from here - /** - */ - public abstract String getCaCertificate(String key); - - /** - */ - public abstract String getUserCertificate(String key); - - /** - */ - public abstract String getUserPrivateKey(String key); - - /** - * Returns the array of the certificate keynames in keystore if successful. - * Or return an empty array if error. - * - * @return array of the certificate keynames - */ - public abstract String[] getAllUserCertificateKeys(); - - /** - */ - public abstract String[] getAllCaCertificateKeys(); - - /** - */ - public abstract String[] getSupportedKeyStrenghs(); - - /** - * Generates a key pair and returns the certificate request. - * @param keyStrengthIndex index to the array of supported key strengths - * @param challenge the challenge message in the keygen tag - * @param organizations the organization string, e.g., - * "/C=US/ST={state}/L={city}/O={company}/OU={app}/CN={hostname}" - * @return the certificate request - */ - public abstract String generateKeyPair( - int keyStrengthIndex, String challenge, String organizations); - - public abstract void addCertificate(byte[] cert); - // to here - private static class FileKeystore extends Keystore { private static final String SERVICE_NAME = "keystore"; private static final String CA_CERTIFICATE = "CaCertificate"; @@ -100,69 +57,6 @@ public abstract class Keystore { private static final ServiceCommand mServiceCommand = new ServiceCommand(SERVICE_NAME); - // TODO: for migrating to the mini-keystore, start from here - @Override - public String getUserPrivateKey(String key) { - return ""; - } - - @Override - public String getUserCertificate(String key) { - return ""; - } - - @Override - public String getCaCertificate(String key) { - return ""; - } - - @Override - public String[] getAllUserCertificateKeys() { - return new String[0]; - } - - @Override - public String[] getAllCaCertificateKeys() { - return new String[0]; - } - - @Override - public String[] getSupportedKeyStrenghs() { - // TODO: real implementation - return new String[] {"High Grade", "Medium Grade"}; - } - - @Override - public String generateKeyPair(int keyStrengthIndex, String challenge, - String organizations) { - // TODO: real implementation - return "-----BEGIN CERTIFICATE REQUEST-----" - + "\nMIICzjCCAbYCAQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh" - + "\nMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRYw" - + "\nFAYDVQQLEw1SZW1vdGUgQWNjZXNzMRAwDgYDVQQLEwdHbGFwdG9wMQ0wCwYDVQQD" - + "\nEwR0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAznwy7a16O35u" - + "\nODLQOw6yHAxozrrX1J+c0reiIh8GYohwKrBedFnQ/FnTls6bxY4fNHD+SZvFFgvU" - + "\nECBFOfRmRm7AFo51qT0t2a8qgvDLM6L1qGkmy94W28Q3OlcpF2QianHYdjyGT+Ac" - + "\nYDek1Zi/E/mdPzuVM/K8tkB7n8ktC0PTm1ZtdMRauE5R0WrEhWuF6In/2gy1Q/Zh" - + "\noy7/zQqpbPl2ouulvkx1Y3OXHM6XPNFLoHS1gH0HyAuBUokO0QmetRn6ngJSvz7e" - + "\nVD7QYRppGp+g4BxqaV9XSxhaaKrMs4PAld9enV51X9qjvjCRBve2QxtuJgMfGJdU" - + "\njGr/JweZoQIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBADtxOtEseoLOVYh6sh4b" - + "\nWCdngK87uHn2bdGipFwKdNTxQDdxNQLAKdoGYIfbVsC1cDgFiufeNwVukxxymdnm" - + "\nk0GGK+0O0tZKENv8ysgfbgEsHpJH9FoR5Y5XEq1etejkcgCp59dyhrSk0DLyVm0D" - + "\nIfTC/nsK95H7AAGOkbbDFo2otyLNNrthYncQ9diAG0UzzLacA+86JXZmD3HyC48u" - + "\nI9hsivVnTTfl9afcfVAhfxbQ6HgkhZZjbjFjfABSd4v8wKlAAqK58VxCajNVOVcV" - + "\ncCzOWf6NpE7xEHCf32i8bWDP6hi0WgQcdpQwnZNKhhTLGNb23Uty6HYlJhbxexC7" - + "\nUoM=" - + "\n-----END CERTIFICATE REQUEST-----"; - } - - @Override - public void addCertificate(byte[] cert) { - // TODO: real implementation - } - - // to here - @Override public int lock() { Reply result = mServiceCommand.execute(ServiceCommand.LOCK, null); diff --git a/keystore/jni/cert.c b/keystore/jni/cert.c index cc36b84e99a38..0db28fd0e8227 100644 --- a/keystore/jni/cert.c +++ b/keystore/jni/cert.c @@ -136,30 +136,126 @@ err: return ret_code; } -int is_pkcs12(const char *buf, int bufLen) +PKCS12 *get_p12_handle(const char *buf, int bufLen) { - int ret = 0; BIO *bp = NULL; PKCS12 *p12 = NULL; - if (!buf || bufLen < 1) goto err; + if (!buf || (bufLen < 1) || (buf[0] != 48)) goto err; bp = BIO_new(BIO_s_mem()); if (!bp) goto err; - if (buf[0] != 48) goto err; // it is not DER. - if (!BIO_write(bp, buf, bufLen)) goto err; - if ((p12 = d2i_PKCS12_bio(bp, NULL)) != NULL) { - PKCS12_free(p12); - ret = 1; - } + p12 = d2i_PKCS12_bio(bp, NULL); + err: if (bp) BIO_free(bp); + return p12; +} + +PKCS12_KEYSTORE *get_pkcs12_keystore_handle(const char *buf, int bufLen, + const char *passwd) +{ + PKCS12_KEYSTORE *p12store = NULL; + EVP_PKEY *pkey = NULL; + X509 *cert = NULL; + STACK_OF(X509) *certs = NULL; + PKCS12 *p12 = get_p12_handle(buf, bufLen); + + if (p12 == NULL) return NULL; + if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) { + LOGE("Can not parse PKCS12 content"); + PKCS12_free(p12); + return NULL; + } + if ((p12store = malloc(sizeof(PKCS12_KEYSTORE))) == NULL) { + if (cert) X509_free(cert); + if (pkey) EVP_PKEY_free(pkey); + if (certs) sk_X509_free(certs); + } + p12store->p12 = p12; + p12store->pkey = pkey; + p12store->cert = cert; + p12store->certs = certs; + return p12store; +} + +void free_pkcs12_keystore(PKCS12_KEYSTORE *p12store) +{ + if (p12store != NULL) { + if (p12store->cert) X509_free(p12store->cert); + if (p12store->pkey) EVP_PKEY_free(p12store->pkey); + if (p12store->certs) sk_X509_free(p12store->certs); + free(p12store); + } +} + +int is_pkcs12(const char *buf, int bufLen) +{ + int ret = 0; + PKCS12 *p12 = get_p12_handle(buf, bufLen); + if (p12 != NULL) ret = 1; + PKCS12_free(p12); return ret; } +static int convert_to_pem(void *data, int is_cert, char *buf, int size) +{ + int len = 0; + BIO *bio = NULL; + + if (data == NULL) return -1; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) goto err; + if (is_cert) { + if ((len = PEM_write_bio_X509(bio, (X509*)data)) == 0) { + goto err; + } + } else { + if ((len = PEM_write_bio_PrivateKey(bio, (EVP_PKEY *)data, NULL, + NULL, 0, NULL, NULL)) == 0) { + goto err; + } + } + if (len < size && (len = BIO_read(bio, buf, size - 1)) > 0) { + buf[len] = 0; + } +err: + if (bio) BIO_free(bio); + return (len == 0) ? -1 : 0; +} + +int get_pkcs12_certificate(PKCS12_KEYSTORE *p12store, char *buf, int size) +{ + if ((p12store != NULL) && (p12store->cert != NULL)) { + return convert_to_pem((void*)p12store->cert, 1, buf, size); + } + return -1; +} + +int get_pkcs12_private_key(PKCS12_KEYSTORE *p12store, char *buf, int size) +{ + if ((p12store != NULL) && (p12store->pkey != NULL)) { + return convert_to_pem((void*)p12store->pkey, 0, buf, size); + } + return -1; +} + +int pop_pkcs12_certs_stack(PKCS12_KEYSTORE *p12store, char *buf, int size) +{ + X509 *cert = NULL; + + if ((p12store != NULL) && (p12store->certs != NULL) && + ((cert = sk_X509_pop(p12store->certs)) != NULL)) { + int ret = convert_to_pem((void*)cert, 1, buf, size); + X509_free(cert); + return ret; + } + return -1; +} + X509* parse_cert(const char *buf, int bufLen) { X509 *cert = NULL; diff --git a/keystore/jni/cert.h b/keystore/jni/cert.h index a9807b1b20f0e..aaa7602d81262 100644 --- a/keystore/jni/cert.h +++ b/keystore/jni/cert.h @@ -41,6 +41,13 @@ typedef struct { int key_len; } PKEY_STORE; +typedef struct { + PKCS12 *p12; + EVP_PKEY *pkey; + X509 *cert; + STACK_OF(X509) *certs; +} PKCS12_KEYSTORE; + #define PKEY_STORE_free(x) { \ if(x.pkey) EVP_PKEY_free(x.pkey); \ if(x.public_key) free(x.public_key); \ @@ -49,8 +56,14 @@ typedef struct { #define nelem(x) (sizeof (x) / sizeof *(x)) int gen_csr(int bits, const char *organizations, char reply[REPLY_MAX]); +PKCS12_KEYSTORE *get_pkcs12_keystore_handle(const char *buf, int bufLen, + const char *passwd); +int get_pkcs12_certificate(PKCS12_KEYSTORE *p12store, char *buf, int size); +int get_pkcs12_private_key(PKCS12_KEYSTORE *p12store, char *buf, int size); +int pop_pkcs12_certs_stack(PKCS12_KEYSTORE *p12store, char *buf, int size); +void free_pkcs12_keystore(PKCS12_KEYSTORE *p12store); int is_pkcs12(const char *buf, int bufLen); -X509* parse_cert(const char *buf, int bufLen); +X509 *parse_cert(const char *buf, int bufLen); int get_cert_name(X509 *cert, char *buf, int size); int get_issuer_name(X509 *cert, char *buf, int size); int is_ca_cert(X509 *cert); diff --git a/keystore/jni/certtool.c b/keystore/jni/certtool.c index fabf5cdf3fb7f..1ae8dab4281f5 100644 --- a/keystore/jni/certtool.c +++ b/keystore/jni/certtool.c @@ -19,10 +19,13 @@ #include #include #include +#include #include #include "cert.h" +typedef int PKCS12_KEYSTORE_FUNC(PKCS12_KEYSTORE *store, char *buf, int size); + jstring android_security_CertTool_generateCertificateRequest(JNIEnv* env, jobject thiz, @@ -42,12 +45,88 @@ android_security_CertTool_isPkcs12Keystore(JNIEnv* env, jobject thiz, jbyteArray data) { - char buf[REPLY_MAX]; int len = (*env)->GetArrayLength(env, data); - if (len > REPLY_MAX) return 0; - (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf); - return (jboolean) is_pkcs12(buf, len); + if (len > 0) { + PKCS12 *handle = NULL; + char buf[len]; + + (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf); + return (jboolean)is_pkcs12(buf, len); + } else { + return 0; + } +} + +jint +android_security_CertTool_getPkcs12Handle(JNIEnv* env, + jobject thiz, + jbyteArray data, + jstring jPassword) +{ + jboolean bIsCopy; + int len = (*env)->GetArrayLength(env, data); + const char* passwd = (*env)->GetStringUTFChars(env, jPassword , &bIsCopy); + + if (len > 0) { + PKCS12_KEYSTORE *handle = NULL; + char buf[len]; + + (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf); + handle = get_pkcs12_keystore_handle(buf, len, passwd); + (*env)->ReleaseStringUTFChars(env, jPassword, passwd); + return (jint)handle; + } else { + return 0; + } +} + +jstring call_pkcs12_ks_func(PKCS12_KEYSTORE_FUNC *func, + JNIEnv* env, + jobject thiz, + jint phandle) +{ + char buf[REPLY_MAX]; + + if (phandle == 0) return NULL; + if (func((PKCS12_KEYSTORE*)phandle, buf, sizeof(buf)) == 0) { + return (*env)->NewStringUTF(env, buf); + } + return NULL; +} + +jstring +android_security_CertTool_getPkcs12Certificate(JNIEnv* env, + jobject thiz, + jint phandle) +{ + return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)get_pkcs12_certificate, + env, thiz, phandle); +} + +jstring +android_security_CertTool_getPkcs12PrivateKey(JNIEnv* env, + jobject thiz, + jint phandle) +{ + return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)get_pkcs12_private_key, + env, thiz, phandle); +} + +jstring +android_security_CertTool_popPkcs12CertificateStack(JNIEnv* env, + jobject thiz, + jint phandle) +{ + return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)pop_pkcs12_certs_stack, + env, thiz, phandle); +} + +void android_security_CertTool_freePkcs12Handle(JNIEnv* env, + jobject thiz, + jint handle) +{ + if (handle != 0) free_pkcs12_keystore((PKCS12_KEYSTORE*)handle); } jint @@ -117,6 +196,16 @@ static JNINativeMethod gCertToolMethods[] = { (void*)android_security_CertTool_generateCertificateRequest}, {"isPkcs12Keystore", "([B)Z", (void*)android_security_CertTool_isPkcs12Keystore}, + {"getPkcs12Handle", "([BLjava/lang/String;)I", + (void*)android_security_CertTool_getPkcs12Handle}, + {"getPkcs12Certificate", "(I)Ljava/lang/String;", + (void*)android_security_CertTool_getPkcs12Certificate}, + {"getPkcs12PrivateKey", "(I)Ljava/lang/String;", + (void*)android_security_CertTool_getPkcs12PrivateKey}, + {"popPkcs12CertificateStack", "(I)Ljava/lang/String;", + (void*)android_security_CertTool_popPkcs12CertificateStack}, + {"freePkcs12Handle", "(I)V", + (void*)android_security_CertTool_freePkcs12Handle}, {"generateX509Certificate", "([B)I", (void*)android_security_CertTool_generateX509Certificate}, {"isCaCertificate", "(I)Z", diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index 8a19fbd559e12..f5bdedaa1340c 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -738,12 +738,13 @@ bool AudioFlinger::streamMute(int stream) const bool AudioFlinger::isMusicActive() const { + Mutex::Autolock _l(mLock); #ifdef WITH_A2DP if (isA2dpEnabled()) { - return mA2dpMixerThread->isMusicActive(); + return mA2dpMixerThread->isMusicActive_l(); } #endif - return mHardwareMixerThread->isMusicActive(); + return mHardwareMixerThread->isMusicActive_l(); } status_t AudioFlinger::setParameter(const char* key, const char* value) @@ -1444,7 +1445,8 @@ bool AudioFlinger::MixerThread::streamMute(int stream) const return mStreamTypes[stream].mute; } -bool AudioFlinger::MixerThread::isMusicActive() const +// isMusicActive_l() must be called with AudioFlinger::mLock held +bool AudioFlinger::MixerThread::isMusicActive_l() const { size_t count = mActiveTracks.size(); for (size_t i = 0 ; i < count ; ++i) { @@ -2030,7 +2032,10 @@ void AudioFlinger::MixerThread::OutputTrack::write(int16_t* data, uint32_t frame inBuffer.i16 = data; if (mCblk->user == 0) { - if (mOutputMixerThread->isMusicActive()) { + mOutputMixerThread->mAudioFlinger->mLock.lock(); + bool isMusicActive = mOutputMixerThread->isMusicActive_l(); + mOutputMixerThread->mAudioFlinger->mLock.unlock(); + if (isMusicActive) { mCblk->forceReady = 1; LOGV("OutputTrack::start() force ready"); } else if (mCblk->frameCount > frames){ diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index 8e47b29be68a8..634934eb6e500 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -463,7 +463,7 @@ private: virtual float streamVolume(int stream) const; virtual bool streamMute(int stream) const; - bool isMusicActive() const; + bool isMusicActive_l() const; sp createTrack_l( diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index 9272983636dbd..ec5aa3f689a06 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -15,7 +15,6 @@ LOCAL_SRC_FILES:= \ LayerBitmap.cpp \ LayerDim.cpp \ LayerOrientationAnim.cpp \ - LayerOrientationAnimRotate.cpp \ OrientationAnimation.cpp \ SurfaceFlinger.cpp \ Tokenizer.cpp \ diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp index 3e4035e9fc192..79e53285c1fe5 100644 --- a/libs/surfaceflinger/LayerOrientationAnim.cpp +++ b/libs/surfaceflinger/LayerOrientationAnim.cpp @@ -46,10 +46,7 @@ const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim"; // Animation... const float DURATION = ms2ns(200); const float BOUNCES_PER_SECOND = 0.5f; -//const float BOUNCES_AMPLITUDE = 1.0f/16.0f; -const float BOUNCES_AMPLITUDE = 0; const float DIM_TARGET = 0.40f; -//#define INTERPOLATED_TIME(_t) ((_t)*(_t)) #define INTERPOLATED_TIME(_t) (_t) // --------------------------------------------------------------------------- @@ -64,14 +61,8 @@ LayerOrientationAnim::LayerOrientationAnim( mTextureName(-1), mTextureNameIn(-1) { // blur that texture. - mStartTime = systemTime(); - mFinishTime = 0; mOrientationCompleted = false; - mFirstRedraw = false; - mLastNormalizedTime = 0; mNeedsBlending = false; - mAlphaInLerp.set(1.0f, DIM_TARGET); - mAlphaOutLerp.set(0.5f, 1.0f); } LayerOrientationAnim::~LayerOrientationAnim() @@ -117,108 +108,37 @@ void LayerOrientationAnim::validateVisibility(const Transform&) void LayerOrientationAnim::onOrientationCompleted() { - mFinishTime = systemTime(); - mOrientationCompleted = true; - mFirstRedraw = true; - mNeedsBlending = true; - mFlinger->invalidateLayerVisibility(this); + mAnim->onAnimationFinished(); } void LayerOrientationAnim::onDraw(const Region& clip) const { - const nsecs_t now = systemTime(); - float alphaIn, alphaOut; + float alphaIn = DIM_TARGET; - if (mOrientationCompleted) { - if (mFirstRedraw) { - mFirstRedraw = false; - - // make a copy of what's on screen - copybit_image_t image; - mBitmapOut.getBitmapSurface(&image); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - hw.copyBackToImage(image); - - // and erase the screen for this round - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glDisable(GL_SCISSOR_TEST); - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT); - - // FIXME: code below is gross - mNeedsBlending = false; - LayerOrientationAnim* self(const_cast(this)); - mFlinger->invalidateLayerVisibility(self); - } - - // make sure pick-up where we left off - const float duration = DURATION * mLastNormalizedTime; - const float normalizedTime = (float(now - mFinishTime) / duration); - if (normalizedTime <= 1.0f) { - const float interpolatedTime = INTERPOLATED_TIME(normalizedTime); - alphaIn = mAlphaInLerp.getOut(); - alphaOut = mAlphaOutLerp(interpolatedTime); - } else { - mAnim->onAnimationFinished(); - alphaIn = mAlphaInLerp.getOut(); - alphaOut = mAlphaOutLerp.getOut(); - } - } else { - const float normalizedTime = float(now - mStartTime) / DURATION; - if (normalizedTime <= 1.0f) { - mLastNormalizedTime = normalizedTime; - const float interpolatedTime = INTERPOLATED_TIME(normalizedTime); - alphaIn = mAlphaInLerp(interpolatedTime); - alphaOut = 0.0f; - } else { - mLastNormalizedTime = 1.0f; - const float to_seconds = DURATION / seconds(1); - alphaIn = mAlphaInLerp.getOut(); - if (BOUNCES_AMPLITUDE > 0.0f) { - const float phi = BOUNCES_PER_SECOND * - (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); - if (alphaIn > 1.0f) alphaIn = 1.0f; - else if (alphaIn < 0.0f) alphaIn = 0.0f; - alphaIn += BOUNCES_AMPLITUDE * (1.0f - cosf(phi)); - } - alphaOut = 0.0f; - } - mAlphaOutLerp.setIn(alphaIn); + // clear screen + // TODO: with update on demand, we may be able + // to not erase the screen at all during the animation + if (!mOrientationCompleted) { + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); } - drawScaled(1.0f, alphaIn, alphaOut); -} - -void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut) const -{ + copybit_image_t dst; const GraphicPlane& plane(graphicPlane(0)); const DisplayHardware& hw(plane.displayHardware()); hw.getDisplaySurface(&dst); - // clear screen - // TODO: with update on demand, we may be able - // to not erase the screen at all during the animation - if (!mOrientationCompleted) { - if (scale==1.0f && (alphaIn>=1.0f || alphaOut>=1.0f)) { - // we don't need to erase the screen in that case - } else { - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glDisable(GL_SCISSOR_TEST); - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT); - } - } - copybit_image_t src; mBitmapIn.getBitmapSurface(&src); copybit_image_t srcOut; mBitmapOut.getBitmapSurface(&srcOut); - const int w = dst.w*scale; - const int h = dst.h*scale; + const int w = dst.w; + const int h = dst.h; const int xc = uint32_t(dst.w-w)/2; const int yc = uint32_t(dst.h-h)/2; const copybit_rect_t drect = { xc, yc, xc+w, yc+h }; @@ -237,13 +157,7 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_ENABLE); copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaIn*255)); err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } - - if (!err && alphaOut > 0.0f) { - region_iterator it(reg); copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_DISABLE); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaOut*255)); - err = copybit->stretch(copybit, &dst, &srcOut, &drect, &srect, &it); } LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err)); } @@ -258,7 +172,6 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); Transform tr; - tr.set(scale,0,0,scale); tr.set(xc, yc); // FIXME: we should not access mVertices and mDrawingState like that, @@ -285,18 +198,6 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut self.mDrawingState.alpha = int(alphaIn*255); drawWithOpenGL(reg, mTextureNameIn, t); } - - if (alphaOut > 0.0f) { - t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset); - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureName, t, w, h); - } - self.mDrawingState.alpha = int(alphaOut*255); - drawWithOpenGL(reg, mTextureName, t); - } } } diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/LayerOrientationAnim.h index 365c6aeed4d75..12b6f1ceb8e0e 100644 --- a/libs/surfaceflinger/LayerOrientationAnim.h +++ b/libs/surfaceflinger/LayerOrientationAnim.h @@ -64,45 +64,13 @@ public: virtual bool needsBlending() const; virtual bool isSecure() const { return false; } private: - void drawScaled(float scale, float alphaIn, float alphaOut) const; - - class Lerp { - float in; - float outMinusIn; - public: - Lerp() : in(0), outMinusIn(0) { } - Lerp(float in, float out) : in(in), outMinusIn(out-in) { } - float getIn() const { return in; }; - float getOut() const { return in + outMinusIn; } - void set(float in, float out) { - this->in = in; - this->outMinusIn = out-in; - } - void setIn(float in) { - this->in = in; - } - void setOut(float out) { - this->outMinusIn = out - this->in; - } - float operator()(float t) const { - return outMinusIn*t + in; - } - }; - OrientationAnimation* mAnim; LayerBitmap mBitmapIn; LayerBitmap mBitmapOut; - nsecs_t mStartTime; - nsecs_t mFinishTime; bool mOrientationCompleted; - mutable bool mFirstRedraw; - mutable float mLastNormalizedTime; mutable GLuint mTextureName; mutable GLuint mTextureNameIn; mutable bool mNeedsBlending; - - mutable Lerp mAlphaInLerp; - mutable Lerp mAlphaOutLerp; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp b/libs/surfaceflinger/LayerOrientationAnimRotate.cpp deleted file mode 100644 index 89ffb19ffb00c..0000000000000 --- a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include -#include -#include - -#include -#include - -#include - -#include - -#include "LayerBase.h" -#include "LayerOrientationAnim.h" -#include "LayerOrientationAnimRotate.h" -#include "SurfaceFlinger.h" -#include "DisplayHardware/DisplayHardware.h" -#include "OrientationAnimation.h" - -namespace android { -// --------------------------------------------------------------------------- - -const uint32_t LayerOrientationAnimRotate::typeInfo = LayerBase::typeInfo | 0x100; -const char* const LayerOrientationAnimRotate::typeID = "LayerOrientationAnimRotate"; - -// --------------------------------------------------------------------------- - -const float ROTATION = M_PI * 0.5f; -const float ROTATION_FACTOR = 1.0f; // 1.0 or 2.0 -const float DURATION = ms2ns(200); -const float BOUNCES_PER_SECOND = 0.8; -const float BOUNCES_AMPLITUDE = (5.0f/180.f) * M_PI; - -LayerOrientationAnimRotate::LayerOrientationAnimRotate( - SurfaceFlinger* flinger, DisplayID display, - OrientationAnimation* anim, - const LayerBitmap& bitmap, - const LayerBitmap& bitmapIn) - : LayerOrientationAnimBase(flinger, display), mAnim(anim), - mBitmap(bitmap), mBitmapIn(bitmapIn), - mTextureName(-1), mTextureNameIn(-1) -{ - mStartTime = systemTime(); - mFinishTime = 0; - mOrientationCompleted = false; - mFirstRedraw = false; - mLastNormalizedTime = 0; - mLastAngle = 0; - mLastScale = 0; - mNeedsBlending = false; - const GraphicPlane& plane(graphicPlane(0)); - mOriginalTargetOrientation = plane.getOrientation(); -} - -LayerOrientationAnimRotate::~LayerOrientationAnimRotate() -{ - if (mTextureName != -1U) { - LayerBase::deletedTextures.add(mTextureName); - } - if (mTextureNameIn != -1U) { - LayerBase::deletedTextures.add(mTextureNameIn); - } -} - -bool LayerOrientationAnimRotate::needsBlending() const -{ - return mNeedsBlending; -} - -Point LayerOrientationAnimRotate::getPhysicalSize() const -{ - const GraphicPlane& plane(graphicPlane(0)); - const DisplayHardware& hw(plane.displayHardware()); - return Point(hw.getWidth(), hw.getHeight()); -} - -void LayerOrientationAnimRotate::validateVisibility(const Transform&) -{ - const Layer::State& s(drawingState()); - const Transform tr(s.transform); - const Point size(getPhysicalSize()); - uint32_t w = size.x; - uint32_t h = size.y; - mTransformedBounds = tr.makeBounds(w, h); - mLeft = tr.tx(); - mTop = tr.ty(); - transparentRegionScreen.clear(); - mTransformed = true; - mCanUseCopyBit = false; -} - -void LayerOrientationAnimRotate::onOrientationCompleted() -{ - mFinishTime = systemTime(); - mOrientationCompleted = true; - mFirstRedraw = true; - mNeedsBlending = true; - mFlinger->invalidateLayerVisibility(this); -} - -void LayerOrientationAnimRotate::onDraw(const Region& clip) const -{ - // Animation... - - const nsecs_t now = systemTime(); - float angle, scale, alpha; - - if (mOrientationCompleted) { - if (mFirstRedraw) { - // make a copy of what's on screen - copybit_image_t image; - mBitmapIn.getBitmapSurface(&image); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - hw.copyBackToImage(image); - - // FIXME: code below is gross - mFirstRedraw = false; - mNeedsBlending = false; - LayerOrientationAnimRotate* self(const_cast(this)); - mFlinger->invalidateLayerVisibility(self); - } - - // make sure pick-up where we left off - const float duration = DURATION * mLastNormalizedTime; - const float normalizedTime = (float(now - mFinishTime) / duration); - if (normalizedTime <= 1.0f) { - const float squaredTime = normalizedTime*normalizedTime; - angle = (ROTATION*ROTATION_FACTOR - mLastAngle)*squaredTime + mLastAngle; - scale = (1.0f - mLastScale)*squaredTime + mLastScale; - alpha = normalizedTime; - } else { - mAnim->onAnimationFinished(); - angle = ROTATION; - alpha = 1.0f; - scale = 1.0f; - } - } else { - // FIXME: works only for portrait framebuffers - const Point size(getPhysicalSize()); - const float TARGET_SCALE = size.x * (1.0f / size.y); - const float normalizedTime = float(now - mStartTime) / DURATION; - if (normalizedTime <= 1.0f) { - mLastNormalizedTime = normalizedTime; - const float squaredTime = normalizedTime*normalizedTime; - angle = ROTATION * squaredTime; - scale = (TARGET_SCALE - 1.0f)*squaredTime + 1.0f; - alpha = 0; - } else { - mLastNormalizedTime = 1.0f; - angle = ROTATION; - if (BOUNCES_AMPLITUDE) { - const float to_seconds = DURATION / seconds(1); - const float phi = BOUNCES_PER_SECOND * - (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); - angle += BOUNCES_AMPLITUDE * sinf(phi); - } - scale = TARGET_SCALE; - alpha = 0; - } - mLastAngle = angle; - mLastScale = scale; - } - drawScaled(angle, scale, alpha); -} - -void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const -{ - copybit_image_t dst; - const GraphicPlane& plane(graphicPlane(0)); - const DisplayHardware& hw(plane.displayHardware()); - hw.getDisplaySurface(&dst); - - // clear screen - // TODO: with update on demand, we may be able - // to not erase the screen at all during the animation - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glDisable(GL_SCISSOR_TEST); - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT); - - const int w = dst.w; - const int h = dst.h; - - copybit_image_t src; - mBitmap.getBitmapSurface(&src); - const copybit_rect_t srect = { 0, 0, src.w, src.h }; - - - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.w; - t.height = src.h; - t.stride = src.w; - t.vstride= src.h; - t.format = src.format; - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - - if (!mOriginalTargetOrientation) { - f = -f; - } - - Transform tr; - tr.set(f, w*0.5f, h*0.5f); - tr.scale(s, w*0.5f, h*0.5f); - - // FIXME: we should not access mVertices and mDrawingState like that, - // but since we control the animation, we know it's going to work okay. - // eventually we'd need a more formal way of doing things like this. - LayerOrientationAnimRotate& self(const_cast(*this)); - tr.transform(self.mVertices[0], 0, 0); - tr.transform(self.mVertices[1], 0, src.h); - tr.transform(self.mVertices[2], src.w, src.h); - tr.transform(self.mVertices[3], src.w, 0); - - if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { - // Too slow to do this in software - self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; - } - - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureName, t, w, h); - } - self.mDrawingState.alpha = 255; //-int(alpha*255); - const Region clip(Rect( srect.l, srect.t, srect.r, srect.b )); - drawWithOpenGL(clip, mTextureName, t); - - if (alpha > 0) { - const float sign = (!mOriginalTargetOrientation) ? 1.0f : -1.0f; - tr.set(f + sign*(M_PI * 0.5f * ROTATION_FACTOR), w*0.5f, h*0.5f); - tr.scale(s, w*0.5f, h*0.5f); - tr.transform(self.mVertices[0], 0, 0); - tr.transform(self.mVertices[1], 0, src.h); - tr.transform(self.mVertices[2], src.w, src.h); - tr.transform(self.mVertices[3], src.w, 0); - - copybit_image_t src; - mBitmapIn.getBitmapSurface(&src); - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - if (UNLIKELY(mTextureNameIn == -1LU)) { - mTextureNameIn = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureNameIn, t, w, h); - } - self.mDrawingState.alpha = int(alpha*255); - const Region clip(Rect( srect.l, srect.t, srect.r, srect.b )); - drawWithOpenGL(clip, mTextureNameIn, t); - } -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.h b/libs/surfaceflinger/LayerOrientationAnimRotate.h deleted file mode 100644 index 5fbbd428d6716..0000000000000 --- a/libs/surfaceflinger/LayerOrientationAnimRotate.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H -#define ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H - -#include -#include -#include -#include - -#include "LayerBase.h" -#include "LayerBitmap.h" - -namespace android { - -// --------------------------------------------------------------------------- -class OrientationAnimation; - -class LayerOrientationAnimRotate : public LayerOrientationAnimBase -{ -public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - LayerOrientationAnimRotate(SurfaceFlinger* flinger, DisplayID display, - OrientationAnimation* anim, - const LayerBitmap& zoomOut, - const LayerBitmap& zoomIn); - virtual ~LayerOrientationAnimRotate(); - - void onOrientationCompleted(); - - virtual void onDraw(const Region& clip) const; - virtual Point getPhysicalSize() const; - virtual void validateVisibility(const Transform& globalTransform); - virtual bool needsBlending() const; - virtual bool isSecure() const { return false; } -private: - void drawScaled(float angle, float scale, float alpha) const; - - OrientationAnimation* mAnim; - LayerBitmap mBitmap; - LayerBitmap mBitmapIn; - nsecs_t mStartTime; - nsecs_t mFinishTime; - bool mOrientationCompleted; - int mOriginalTargetOrientation; - mutable bool mFirstRedraw; - mutable float mLastNormalizedTime; - mutable float mLastAngle; - mutable float mLastScale; - mutable GLuint mTextureName; - mutable GLuint mTextureNameIn; - mutable bool mNeedsBlending; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/OrientationAnimation.cpp index 70eec8d68e1fe..12c0eefe83bb8 100644 --- a/libs/surfaceflinger/OrientationAnimation.cpp +++ b/libs/surfaceflinger/OrientationAnimation.cpp @@ -21,7 +21,6 @@ #include #include "LayerOrientationAnim.h" -#include "LayerOrientationAnimRotate.h" #include "OrientationAnimation.h" #include "SurfaceFlinger.h" #include "VRamHeap.h" @@ -112,13 +111,8 @@ bool OrientationAnimation::prepare() LayerOrientationAnimBase* l; - if (mType & 0x80) { - l = new LayerOrientationAnimRotate( - mFlinger.get(), 0, this, bitmap, bitmapIn); - } else { - l = new LayerOrientationAnim( - mFlinger.get(), 0, this, bitmap, bitmapIn); - } + l = new LayerOrientationAnim( + mFlinger.get(), 0, this, bitmap, bitmapIn); l->initStates(w, h, 0); l->setLayer(INT_MAX-1); @@ -137,7 +131,7 @@ bool OrientationAnimation::phase1() return true; } - mLayerOrientationAnim->invalidate(); + //mLayerOrientationAnim->invalidate(); return false; } diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index ef4a8ea17a2ed..fb256638cd716 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -1236,6 +1236,13 @@ sp SurfaceFlinger::createSurface(ClientID clientId, int pid, { LayerBaseClient* layer = 0; sp surfaceHandle; + + if (int32_t(w|h) < 0) { + LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)", + int(w), int(h)); + return surfaceHandle; + } + Mutex::Autolock _l(mStateLock); Client* const c = mClientsMap.valueFor(clientId); if (UNLIKELY(!c)) { diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp index 975594f39e114..5015379d3142d 100644 --- a/libs/ui/Camera.cpp +++ b/libs/ui/Camera.cpp @@ -310,6 +310,19 @@ void Camera::dataCallback(int32_t msgType, const sp& dataPtr) } } +// callback from camera service when timestamped frame is ready +void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr) +{ + sp listener; + { + Mutex::Autolock _l(mLock); + listener = mListener; + } + if (listener != NULL) { + listener->postDataTimestamp(timestamp, msgType, dataPtr); + } +} + void Camera::binderDied(const wp& who) { LOGW("ICamera died"); notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0); diff --git a/libs/ui/ICameraClient.cpp b/libs/ui/ICameraClient.cpp index c6cf75c5e951d..59a6cf2b4ebf5 100644 --- a/libs/ui/ICameraClient.cpp +++ b/libs/ui/ICameraClient.cpp @@ -27,6 +27,7 @@ namespace android { enum { NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION, DATA_CALLBACK, + DATA_CALLBACK_TIMESTAMP, }; class BpCameraClient: public BpInterface @@ -60,6 +61,17 @@ public: remote()->transact(DATA_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } + // generic data callback from camera service to app with image data + void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp& imageData) + { + LOGV("dataCallback"); + Parcel data, reply; + data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); + data.writeInt64(timestamp); + data.writeInt32(msgType); + data.writeStrongBinder(imageData->asBinder()); + remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY); + } }; IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient"); @@ -86,13 +98,22 @@ status_t BnCameraClient::onTransact( return NO_ERROR; } break; case DATA_CALLBACK: { - LOGV("RAW_CALLBACK"); + LOGV("DATA_CALLBACK"); CHECK_INTERFACE(ICameraClient, data, reply); int32_t msgType = data.readInt32(); sp imageData = interface_cast(data.readStrongBinder()); dataCallback(msgType, imageData); return NO_ERROR; } break; + case DATA_CALLBACK_TIMESTAMP: { + LOGV("DATA_CALLBACK_TIMESTAMP"); + CHECK_INTERFACE(ICameraClient, data, reply); + nsecs_t timestamp = data.readInt64(); + int32_t msgType = data.readInt32(); + sp imageData = interface_cast(data.readStrongBinder()); + dataCallbackTimestamp(timestamp, msgType, imageData); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 109f28d305ee9..4dca8bd81608d 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -1573,7 +1573,6 @@ status_t ResTable::add(Asset* asset, void* cookie, bool copyData) status_t ResTable::add(ResTable* src) { mError = src->mError; - mParams = src->mParams; for (size_t i=0; imHeaders.size(); i++) { mHeaders.add(src->mHeaders[i]); @@ -4008,7 +4007,16 @@ void ResTable::print(bool inclValues) const printf(" NON-INTEGER ResTable_type ADDRESS: %p\n", type); continue; } - printf(" config %d lang=%c%c cnt=%c%c orien=%d touch=%d density=%d key=%d infl=%d nav=%d w=%d h=%d lyt=%d\n", + char density[16]; + uint16_t dval = dtohs(type->config.density); + if (dval == ResTable_config::DENSITY_DEFAULT) { + strcpy(density, "def"); + } else if (dval == ResTable_config::DENSITY_NONE) { + strcpy(density, "no"); + } else { + sprintf(density, "%d", (int)dval); + } + printf(" config %d lang=%c%c cnt=%c%c orien=%d touch=%d density=%s key=%d infl=%d nav=%d w=%d h=%d sz=%d lng=%d\n", (int)configIndex, type->config.language[0] ? type->config.language[0] : '-', type->config.language[1] ? type->config.language[1] : '-', @@ -4016,13 +4024,14 @@ void ResTable::print(bool inclValues) const type->config.country[1] ? type->config.country[1] : '-', type->config.orientation, type->config.touchscreen, - dtohs(type->config.density), + density, type->config.keyboard, type->config.inputFlags, type->config.navigation, dtohs(type->config.screenWidth), dtohs(type->config.screenHeight), - type->config.screenLayout); + type->config.screenLayout&ResTable_config::MASK_SCREENSIZE, + type->config.screenLayout&ResTable_config::MASK_SCREENLONG); size_t entryCount = dtohl(type->entryCount); uint32_t entriesStart = dtohl(type->entriesStart); if ((entriesStart&0x3) != 0) { diff --git a/libs/utils/String8.cpp b/libs/utils/String8.cpp index c50d343a731b4..e908ec1e87efc 100644 --- a/libs/utils/String8.cpp +++ b/libs/utils/String8.cpp @@ -25,25 +25,39 @@ #include -namespace android { +/* + * Functions outside android is below the namespace android, since they use + * functions and constants in android namespace. + */ // --------------------------------------------------------------------------- -static const uint32_t kByteMask = 0x000000BF; -static const uint32_t kByteMark = 0x00000080; +namespace android { + +static const char32_t kByteMask = 0x000000BF; +static const char32_t kByteMark = 0x00000080; // Surrogates aren't valid for UTF-32 characters, so define some // constants that will let us screen them out. -static const uint32_t kUnicodeSurrogateHighStart = 0x0000D800; -static const uint32_t kUnicodeSurrogateHighEnd = 0x0000DBFF; -static const uint32_t kUnicodeSurrogateLowStart = 0x0000DC00; -static const uint32_t kUnicodeSurrogateLowEnd = 0x0000DFFF; -static const uint32_t kUnicodeSurrogateStart = kUnicodeSurrogateHighStart; -static const uint32_t kUnicodeSurrogateEnd = kUnicodeSurrogateLowEnd; +static const char32_t kUnicodeSurrogateHighStart = 0x0000D800; +static const char32_t kUnicodeSurrogateHighEnd = 0x0000DBFF; +static const char32_t kUnicodeSurrogateLowStart = 0x0000DC00; +static const char32_t kUnicodeSurrogateLowEnd = 0x0000DFFF; +static const char32_t kUnicodeSurrogateStart = kUnicodeSurrogateHighStart; +static const char32_t kUnicodeSurrogateEnd = kUnicodeSurrogateLowEnd; +static const char32_t kUnicodeMaxCodepoint = 0x0010FFFF; // Mask used to set appropriate bits in first byte of UTF-8 sequence, // indexed by number of bytes in the sequence. -static const uint32_t kFirstByteMark[] = { +// 0xxxxxxx +// -> (00-7f) 7bit. Bit mask for the first byte is 0x00000000 +// 110yyyyx 10xxxxxx +// -> (c0-df)(80-bf) 11bit. Bit mask is 0x000000C0 +// 1110yyyy 10yxxxxx 10xxxxxx +// -> (e0-ef)(80-bf)(80-bf) 16bit. Bit mask is 0x000000E0 +// 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx +// -> (f0-f7)(80-bf)(80-bf)(80-bf) 21bit. Bit mask is 0x000000F0 +static const char32_t kFirstByteMark[] = { 0x00000000, 0x00000000, 0x000000C0, 0x000000E0, 0x000000F0 }; @@ -52,7 +66,7 @@ static const uint32_t kFirstByteMark[] = { #define RES_PATH_SEPARATOR '/' // Return number of utf8 bytes required for the character. -static size_t utf32_to_utf8_bytes(uint32_t srcChar) +static size_t utf32_to_utf8_bytes(char32_t srcChar) { size_t bytesToWrite; @@ -79,7 +93,7 @@ static size_t utf32_to_utf8_bytes(uint32_t srcChar) } } // Max code point for Unicode is 0x0010FFFF. - else if (srcChar < 0x00110000) + else if (srcChar <= kUnicodeMaxCodepoint) { bytesToWrite = 4; } @@ -94,7 +108,7 @@ static size_t utf32_to_utf8_bytes(uint32_t srcChar) // Write out the source character to . -static void utf32_to_utf8(uint8_t* dstP, uint32_t srcChar, size_t bytes) +static void utf32_to_utf8(uint8_t* dstP, char32_t srcChar, size_t bytes) { dstP += bytes; switch (bytes) @@ -126,7 +140,7 @@ void initialize_string8() // Bite me, Darwin! gDarwinIsReallyAnnoying = gDarwinCantLoadAllObjects; #endif - + SharedBuffer* buf = SharedBuffer::alloc(1); char* str = (char*)buf->data(); *str = 0; @@ -160,20 +174,20 @@ static char* allocFromUTF8(const char* in, size_t len) return getEmptyString(); } -// Note: not dealing with expanding surrogate pairs. -static char* allocFromUTF16(const char16_t* in, size_t len) +template +static char* allocFromUTF16OrUTF32(const T* in, L len) { if (len == 0) return getEmptyString(); - + size_t bytes = 0; - const char16_t* end = in+len; - const char16_t* p = in; - + const T* end = in+len; + const T* p = in; + while (p < end) { bytes += utf32_to_utf8_bytes(*p); p++; } - + SharedBuffer* buf = SharedBuffer::alloc(bytes+1); LOG_ASSERT(buf, "Unable to allocate shared buffer"); if (buf) { @@ -181,19 +195,30 @@ static char* allocFromUTF16(const char16_t* in, size_t len) char* str = (char*)buf->data(); char* d = str; while (p < end) { - uint32_t c = *p++; + const T c = *p++; size_t len = utf32_to_utf8_bytes(c); utf32_to_utf8((uint8_t*)d, c, len); d += len; } *d = 0; - + return str; } - + return getEmptyString(); } +// Note: not dealing with expanding surrogate pairs. +static char* allocFromUTF16(const char16_t* in, size_t len) +{ + return allocFromUTF16OrUTF32(in, len); +} + +static char* allocFromUTF32(const char32_t* in, size_t len) +{ + return allocFromUTF16OrUTF32(in, len); +} + // --------------------------------------------------------------------------- String8::String8() @@ -238,6 +263,16 @@ String8::String8(const char16_t* o, size_t len) { } +String8::String8(const char32_t* o) + : mString(allocFromUTF32(o, strlen32(o))) +{ +} + +String8::String8(const char32_t* o, size_t len) + : mString(allocFromUTF32(o, len)) +{ +} + String8::~String8() { SharedBuffer::bufferFromData(mString)->release(); @@ -280,6 +315,16 @@ status_t String8::setTo(const char16_t* other, size_t len) return NO_MEMORY; } +status_t String8::setTo(const char32_t* other, size_t len) +{ + SharedBuffer::bufferFromData(mString)->release(); + mString = allocFromUTF32(other, len); + if (mString) return NO_ERROR; + + mString = getEmptyString(); + return NO_MEMORY; +} + status_t String8::append(const String8& other) { const size_t otherLen = other.bytes(); @@ -418,6 +463,21 @@ void String8::toUpper(size_t start, size_t length) unlockBuffer(len); } +size_t String8::getUtf32Length() const +{ + return utf32_length(mString, length()); +} + +int32_t String8::getUtf32At(size_t index, size_t *next_index) const +{ + return utf32_at(mString, length(), index, next_index); +} + +size_t String8::getUtf32(char32_t* dst, size_t dst_len) const +{ + return utf8_to_utf32(mString, length(), dst, dst_len); +} + TextOutput& operator<<(TextOutput& to, const String8& val) { to << val.string(); @@ -427,7 +487,6 @@ TextOutput& operator<<(TextOutput& to, const String8& val) // --------------------------------------------------------------------------- // Path functions - void String8::setPathName(const char* name) { setPathName(name, strlen(name)); @@ -600,5 +659,192 @@ String8& String8::convertToResPath() return *this; } - }; // namespace android + +// --------------------------------------------------------------------------- + +size_t strlen32(const char32_t *s) +{ + const char32_t *ss = s; + while ( *ss ) + ss++; + return ss-s; +} + +size_t strnlen32(const char32_t *s, size_t maxlen) +{ + const char32_t *ss = s; + while ((maxlen > 0) && *ss) { + ss++; + maxlen--; + } + return ss-s; +} + +size_t utf8_length(const char *src) +{ + const char *cur = src; + size_t ret = 0; + while (*cur != '\0') { + const char first_char = *cur++; + if ((first_char & 0x80) == 0) { // ASCII + ret += 1; + continue; + } + // (UTF-8's character must not be like 10xxxxxx, + // but 110xxxxx, 1110xxxx, ... or 1111110x) + if ((first_char & 0x40) == 0) { + return 0; + } + + int32_t mask, to_ignore_mask; + size_t num_to_read = 0; + char32_t utf32 = 0; + for (num_to_read = 1, mask = 0x40, to_ignore_mask = 0x80; + num_to_read < 5 && (first_char & mask); + num_to_read++, to_ignore_mask |= mask, mask >>= 1) { + if ((*cur & 0xC0) != 0x80) { // must be 10xxxxxx + return 0; + } + // 0x3F == 00111111 + utf32 = (utf32 << 6) + (*cur++ & 0x3F); + } + // "first_char" must be (110xxxxx - 11110xxx) + if (num_to_read == 5) { + return 0; + } + to_ignore_mask |= mask; + utf32 |= ((~to_ignore_mask) & first_char) << (6 * (num_to_read - 1)); + if (utf32 > android::kUnicodeMaxCodepoint) { + return 0; + } + + ret += num_to_read; + } + return ret; +} + +size_t utf32_length(const char *src, size_t src_len) +{ + if (src == NULL || src_len == 0) { + return 0; + } + size_t ret = 0; + const char* cur; + const char* end; + size_t num_to_skip; + for (cur = src, end = src + src_len, num_to_skip = 1; + cur < end; + cur += num_to_skip, ret++) { + const char first_char = *cur; + num_to_skip = 1; + if ((first_char & 0x80) == 0) { // ASCII + continue; + } + int32_t mask; + + for (mask = 0x40; (first_char & mask); num_to_skip++, mask >>= 1) { + } + } + return ret; +} + +size_t utf8_length_from_utf32(const char32_t *src, size_t src_len) +{ + if (src == NULL || src_len == 0) { + return 0; + } + size_t ret = 0; + const char32_t *end = src + src_len; + while (src < end) { + ret += android::utf32_to_utf8_bytes(*src++); + } + return ret; +} + +static int32_t utf32_at_internal(const char* cur, size_t *num_read) +{ + const char first_char = *cur; + if ((first_char & 0x80) == 0) { // ASCII + *num_read = 1; + return *cur; + } + cur++; + char32_t mask, to_ignore_mask; + size_t num_to_read = 0; + char32_t utf32 = first_char; + for (num_to_read = 1, mask = 0x40, to_ignore_mask = 0xFFFFFF80; + (first_char & mask); + num_to_read++, to_ignore_mask |= mask, mask >>= 1) { + // 0x3F == 00111111 + utf32 = (utf32 << 6) + (*cur++ & 0x3F); + } + to_ignore_mask |= mask; + utf32 &= ~(to_ignore_mask << (6 * (num_to_read - 1))); + + *num_read = num_to_read; + return static_cast(utf32); +} + +int32_t utf32_at(const char *src, size_t src_len, + size_t index, size_t *next_index) +{ + if (index >= src_len) { + return -1; + } + size_t dummy_index; + if (next_index == NULL) { + next_index = &dummy_index; + } + size_t num_read; + int32_t ret = utf32_at_internal(src + index, &num_read); + if (ret >= 0) { + *next_index = index + num_read; + } + + return ret; +} + +size_t utf8_to_utf32(const char* src, size_t src_len, + char32_t* dst, size_t dst_len) +{ + if (src == NULL || src_len == 0 || dst == NULL || dst_len == 0) { + return 0; + } + + const char* cur = src; + const char* end = src + src_len; + char32_t* cur_utf32 = dst; + const char32_t* end_utf32 = dst + dst_len; + while (cur_utf32 < end_utf32 && cur < end) { + size_t num_read; + *cur_utf32++ = + static_cast(utf32_at_internal(cur, &num_read)); + cur += num_read; + } + if (cur_utf32 < end_utf32) { + *cur_utf32 = 0; + } + return static_cast(cur_utf32 - dst); +} + +size_t utf32_to_utf8(const char32_t* src, size_t src_len, + char* dst, size_t dst_len) +{ + if (src == NULL || src_len == 0 || dst == NULL || dst_len == 0) { + return 0; + } + const char32_t *cur_utf32 = src; + const char32_t *end_utf32 = src + src_len; + char *cur = dst; + const char *end = dst + dst_len; + while (cur_utf32 < end_utf32 && cur < end) { + size_t len = android::utf32_to_utf8_bytes(*cur_utf32); + android::utf32_to_utf8((uint8_t *)cur, *cur_utf32++, len); + cur += len; + } + if (cur < end) { + *cur = '\0'; + } + return cur - dst; +} diff --git a/libs/utils/ZipUtils.cpp b/libs/utils/ZipUtils.cpp index 5df94cbbd9a00..9138878ff776b 100644 --- a/libs/utils/ZipUtils.cpp +++ b/libs/utils/ZipUtils.cpp @@ -210,7 +210,7 @@ bail: LOGV("+++ reading %ld bytes (%ld left)\n", getSize, compRemaining); - int cc = fread(readBuf, getSize, 1, fp); + int cc = fread(readBuf, 1, getSize, fp); if (cc != (int) getSize) { LOGD("inflate read failed (%d vs %ld)\n", cc, getSize); @@ -341,4 +341,3 @@ bail: return true; } - diff --git a/location/java/android/location/Address.java b/location/java/android/location/Address.java index 3551363883278..ac275c677c76f 100644 --- a/location/java/android/location/Address.java +++ b/location/java/android/location/Address.java @@ -41,7 +41,10 @@ public class Address implements Parcelable { private String mAdminArea; private String mSubAdminArea; private String mLocality; + private String mSubLocality; private String mThoroughfare; + private String mSubThoroughfare; + private String mPremises; private String mPostalCode; private String mCountryCode; private String mCountryName; @@ -174,6 +177,21 @@ public class Address implements Parcelable { mLocality = locality; } + /** + * Returns the sub-locality of the address, or null if it is unknown. + * For example, this may correspond to the neighborhood of the locality. + */ + public String getSubLocality() { + return mSubLocality; + } + + /** + * Sets the sub-locality of the address to the given String, which may be null. + */ + public void setSubLocality(String sublocality) { + mSubLocality = sublocality; + } + /** * Returns the thoroughfare name of the address, for example, "1600 Ampitheater Parkway", * which may be null @@ -189,6 +207,35 @@ public class Address implements Parcelable { this.mThoroughfare = thoroughfare; } + /** + * Returns the sub-thoroughfare name of the address, which may be null. + * This may correspond to the street number of the address. + */ + public String getSubThoroughfare() { + return mSubThoroughfare; + } + + /** + * Sets the sub-thoroughfare name of the address, which may be null. + */ + public void setSubThoroughfare(String subthoroughfare) { + this.mSubThoroughfare = subthoroughfare; + } + + /** + * Returns the premises of the address, or null if it is unknown. + */ + public String getPremises() { + return mPremises; + } + + /** + * Sets the premises of the address to the given String, which may be null. + */ + public void setPremises(String premises) { + mPremises = premises; + } + /** * Returns the postal code of the address, for example "94110", * or null if it is unknown. diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index cfdf5e3de116a..a65a4172fb9c3 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1063,6 +1063,21 @@ public class AudioManager { } } + /** + * @hide + * Reload audio settings. This method is called by Settings backup + * agent when audio settings are restored and causes the AudioService + * to read and apply restored settings. + */ + public void reloadAudioSettings() { + IAudioService service = getService(); + try { + service.reloadAudioSettings(); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in reloadAudioSettings"+e); + } + } + /** * {@hide} */ diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 937baad5be945..58c04f3a1f74c 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -508,14 +508,14 @@ public class AudioService extends IAudioService.Stub { /** @see AudioManager#setRingerMode(int) */ public void setRingerMode(int ringerMode) { if (ringerMode != mRingerMode) { - setRingerModeInt(ringerMode); + setRingerModeInt(ringerMode, true); // Send sticky broadcast broadcastRingerMode(); } } - private void setRingerModeInt(int ringerMode) { + private void setRingerModeInt(int ringerMode, boolean persist) { mRingerMode = ringerMode; // Adjust volumes via posting message @@ -543,8 +543,10 @@ public class AudioService extends IAudioService.Stub { } // Post a persist ringer mode msg - sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, SHARED_MSG, - SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); + if (persist) { + sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, SHARED_MSG, + SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); + } } /** @see AudioManager#shouldVibrate(int) */ @@ -914,6 +916,46 @@ public class AudioService extends IAudioService.Stub { } } + /** @see AudioManager#reloadAudioSettings() */ + public void reloadAudioSettings() { + // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings + readPersistedSettings(); + + // restore volume settings + int numStreamTypes = AudioSystem.getNumStreamTypes(); + for (int streamType = 0; streamType < numStreamTypes; streamType++) { + VolumeStreamState streamState = mStreamStates[streamType]; + + // there is no volume setting for STREAM_BLUETOOTH_SCO + if (streamType != AudioSystem.STREAM_BLUETOOTH_SCO) { + String settingName = System.VOLUME_SETTINGS[streamType]; + String lastAudibleSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE; + + streamState.mIndex = streamState.getValidIndex(Settings.System.getInt(mContentResolver, + settingName, + AudioManager.DEFAULT_STREAM_VOLUME[streamType])); + streamState.mLastAudibleIndex = streamState.getValidIndex(Settings.System.getInt(mContentResolver, + lastAudibleSettingName, + streamState.mIndex > 0 ? streamState.mIndex : AudioManager.DEFAULT_STREAM_VOLUME[streamType])); + } + // unmute stream that whas muted but is not affect by mute anymore + if (streamState.muteCount() != 0 && !isStreamAffectedByMute(streamType)) { + int size = streamState.mDeathHandlers.size(); + for (int i = 0; i < size; i++) { + streamState.mDeathHandlers.get(i).mMuteCount = 1; + streamState.mDeathHandlers.get(i).mute(false); + } + } + // apply stream volume + if (streamState.muteCount() == 0) { + AudioSystem.setVolume(streamType, streamState.mVolumes[streamState.mIndex]); + } + } + + // apply new ringer mode + setRingerModeInt(getRingerMode(), false); + } + /////////////////////////////////////////////////////////////////////////// // Internal methods /////////////////////////////////////////////////////////////////////////// @@ -1285,10 +1327,12 @@ public class AudioService extends IAudioService.Stub { } private void persistVolume(VolumeStreamState streamState) { - System.putInt(mContentResolver, streamState.mVolumeIndexSettingName, - streamState.mIndex); - System.putInt(mContentResolver, streamState.mLastAudibleVolumeIndexSettingName, - streamState.mLastAudibleIndex); + if (streamState.mStreamType != AudioManager.STREAM_BLUETOOTH_SCO) { + System.putInt(mContentResolver, streamState.mVolumeIndexSettingName, + streamState.mIndex); + System.putInt(mContentResolver, streamState.mLastAudibleVolumeIndexSettingName, + streamState.mLastAudibleIndex); + } } private void persistRingerMode() { @@ -1426,7 +1470,7 @@ public class AudioService extends IAudioService.Stub { * Ensure all stream types that should be affected by ringer mode * are in the proper state. */ - setRingerModeInt(getRingerMode()); + setRingerModeInt(getRingerMode(), false); } } diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java new file mode 100644 index 0000000000000..645f3f63a6ef9 --- /dev/null +++ b/media/java/android/media/ExifInterface.java @@ -0,0 +1,398 @@ +/* + * 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.media; + +import android.util.Log; + +import java.util.HashMap; +import java.util.Map; + +/** + * Wrapper for native Exif library + * {@hide} + */ +public class ExifInterface { + private static final String TAG = "ExifInterface"; + private String mFilename; + + // Constants used for the Orientation Exif tag. + public static final int ORIENTATION_UNDEFINED = 0; + public static final int ORIENTATION_NORMAL = 1; + + // Constants used for white balance + public static final int WHITEBALANCE_AUTO = 0; + public static final int WHITEBALANCE_MANUAL = 1; + + // left right reversed mirror + public static final int ORIENTATION_FLIP_HORIZONTAL = 2; + public static final int ORIENTATION_ROTATE_180 = 3; + + // upside down mirror + public static final int ORIENTATION_FLIP_VERTICAL = 4; + + // flipped about top-left <--> bottom-right axis + public static final int ORIENTATION_TRANSPOSE = 5; + + // rotate 90 cw to right it + public static final int ORIENTATION_ROTATE_90 = 6; + + // flipped about top-right <--> bottom-left axis + public static final int ORIENTATION_TRANSVERSE = 7; + + // rotate 270 to right it + public static final int ORIENTATION_ROTATE_270 = 8; + + // The Exif tag names + public static final String TAG_ORIENTATION = "Orientation"; + + public static final String TAG_DATE_TIME_ORIGINAL = "DateTimeOriginal"; + public static final String TAG_MAKE = "Make"; + public static final String TAG_MODEL = "Model"; + public static final String TAG_FLASH = "Flash"; + public static final String TAG_IMAGE_WIDTH = "ImageWidth"; + public static final String TAG_IMAGE_LENGTH = "ImageLength"; + + public static final String TAG_GPS_LATITUDE = "GPSLatitude"; + 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_WHITE_BALANCE = "WhiteBalance"; + + private boolean mSavedAttributes = false; + private boolean mHasThumbnail = false; + private HashMap mCachedAttributes = null; + + static { + System.loadLibrary("exif"); + } + + private static ExifInterface sExifObj = null; + /** + * Since the underlying jhead native code is not thread-safe, + * ExifInterface should use singleton interface instead of public + * constructor. + */ + private static synchronized ExifInterface instance() { + if (sExifObj == null) { + sExifObj = new ExifInterface(); + } + + return sExifObj; + } + + /** + * The following 3 static methods are handy routines for atomic operation + * of underlying jhead library. It retrieves EXIF data and then release + * ExifInterface immediately. + */ + public static synchronized HashMap loadExifData(String filename) { + ExifInterface exif = instance(); + HashMap exifData = null; + if (exif != null) { + exif.setFilename(filename); + exifData = exif.getAttributes(); + } + return exifData; + } + + public static synchronized void saveExifData(String filename, HashMap exifData) { + ExifInterface exif = instance(); + if (exif != null) { + exif.setFilename(filename); + exif.saveAttributes(exifData); + } + } + + public static synchronized byte[] getExifThumbnail(String filename) { + ExifInterface exif = instance(); + if (exif != null) { + exif.setFilename(filename); + return exif.getThumbnail(); + } + return null; + } + + public void setFilename(String filename) { + mFilename = filename; + } + + /** + * Given a HashMap of Exif tags and associated values, an Exif section in + * the JPG file is created and loaded with the tag data. saveAttributes() + * is expensive because it involves copying all the JPG data from one file + * to another and deleting the old file and renaming the other. It's best + * to collect all the attributes to write and make a single call rather + * than multiple calls for each attribute. You must call "commitChanges()" + * at some point to commit the changes. + */ + public void saveAttributes(HashMap attributes) { + // format of string passed to native C code: + // "attrCnt attr1=valueLen value1attr2=value2Len value2..." + // example: + // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO" + StringBuilder sb = new StringBuilder(); + int size = attributes.size(); + if (attributes.containsKey("hasThumbnail")) { + --size; + } + sb.append(size + " "); + for (Map.Entry iter : attributes.entrySet()) { + String key = iter.getKey(); + if (key.equals("hasThumbnail")) { + // this is a fake attribute not saved as an exif tag + continue; + } + String val = iter.getValue(); + sb.append(key + "="); + sb.append(val.length() + " "); + sb.append(val); + } + String s = sb.toString(); + saveAttributesNative(mFilename, s); + commitChangesNative(mFilename); + mSavedAttributes = true; + } + + /** + * Returns a HashMap loaded with the Exif attributes of the file. The key + * is the standard tag name and the value is the tag's value: e.g. + * Model -> Nikon. Numeric values are returned as strings. + */ + public HashMap getAttributes() { + if (mCachedAttributes != null) { + return mCachedAttributes; + } + // format of string passed from native C code: + // "attrCnt attr1=valueLen value1attr2=value2Len value2..." + // example: + // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO" + mCachedAttributes = new HashMap(); + + String attrStr = getAttributesNative(mFilename); + + // get count + int ptr = attrStr.indexOf(' '); + int count = Integer.parseInt(attrStr.substring(0, ptr)); + // skip past the space between item count and the rest of the attributes + ++ptr; + + for (int i = 0; i < count; i++) { + // extract the attribute name + int equalPos = attrStr.indexOf('=', ptr); + String attrName = attrStr.substring(ptr, equalPos); + ptr = equalPos + 1; // skip past = + + // extract the attribute value length + int lenPos = attrStr.indexOf(' ', ptr); + int attrLen = Integer.parseInt(attrStr.substring(ptr, lenPos)); + ptr = lenPos + 1; // skip pas the space + + // extract the attribute value + String attrValue = attrStr.substring(ptr, ptr + attrLen); + ptr += attrLen; + + if (attrName.equals("hasThumbnail")) { + mHasThumbnail = attrValue.equalsIgnoreCase("true"); + } else { + mCachedAttributes.put(attrName, attrValue); + } + } + return mCachedAttributes; + } + + /** + * Given a numerical white balance value, return a + * human-readable string describing it. + */ + public static String whiteBalanceToString(int whitebalance) { + switch (whitebalance) { + case WHITEBALANCE_AUTO: + return "Auto"; + case WHITEBALANCE_MANUAL: + return "Manual"; + default: + return ""; + } + } + + /** + * Given a numerical orientation, return a human-readable string describing + * the orientation. + */ + public static String orientationToString(int orientation) { + // TODO: this function needs to be localized and use string resource ids + // rather than strings + String orientationString; + switch (orientation) { + case ORIENTATION_NORMAL: + orientationString = "Normal"; + break; + case ORIENTATION_FLIP_HORIZONTAL: + orientationString = "Flipped horizontal"; + break; + case ORIENTATION_ROTATE_180: + orientationString = "Rotated 180 degrees"; + break; + case ORIENTATION_FLIP_VERTICAL: + orientationString = "Upside down mirror"; + break; + case ORIENTATION_TRANSPOSE: + orientationString = "Transposed"; + break; + case ORIENTATION_ROTATE_90: + orientationString = "Rotated 90 degrees"; + break; + case ORIENTATION_TRANSVERSE: + orientationString = "Transversed"; + break; + case ORIENTATION_ROTATE_270: + orientationString = "Rotated 270 degrees"; + break; + default: + orientationString = "Undefined"; + break; + } + return orientationString; + } + + /** + * Copies the thumbnail data out of the filename and puts it in the Exif + * data associated with the file used to create this object. You must call + * "commitChanges()" at some point to commit the changes. + */ + public boolean appendThumbnail(String thumbnailFileName) { + if (!mSavedAttributes) { + throw new RuntimeException("Must call saveAttributes " + + "before calling appendThumbnail"); + } + mHasThumbnail = appendThumbnailNative(mFilename, thumbnailFileName); + return mHasThumbnail; + } + + public boolean hasThumbnail() { + if (!mSavedAttributes) { + getAttributes(); + } + return mHasThumbnail; + } + + public byte[] getThumbnail() { + return getThumbnailNative(mFilename); + } + + public static float[] getLatLng(HashMap exifData) { + if (exifData == null) { + return null; + } + + String latValue = exifData.get(ExifInterface.TAG_GPS_LATITUDE); + String latRef = exifData.get(ExifInterface.TAG_GPS_LATITUDE_REF); + String lngValue = exifData.get(ExifInterface.TAG_GPS_LONGITUDE); + String lngRef = exifData.get(ExifInterface.TAG_GPS_LONGITUDE_REF); + float[] latlng = null; + + if (latValue != null && latRef != null + && lngValue != null && lngRef != null) { + latlng = new float[2]; + latlng[0] = ExifInterface.convertRationalLatLonToFloat( + latValue, latRef); + latlng[1] = ExifInterface.convertRationalLatLonToFloat( + lngValue, lngRef); + } + + return latlng; + } + + public static float convertRationalLatLonToFloat( + String rationalString, String ref) { + try { + String [] parts = rationalString.split(","); + + String [] pair; + pair = parts[0].split("/"); + int degrees = (int) (Float.parseFloat(pair[0].trim()) + / Float.parseFloat(pair[1].trim())); + + pair = parts[1].split("/"); + int minutes = (int) ((Float.parseFloat(pair[0].trim()) + / Float.parseFloat(pair[1].trim()))); + + pair = parts[2].split("/"); + float seconds = Float.parseFloat(pair[0].trim()) + / Float.parseFloat(pair[1].trim()); + + float result = degrees + (minutes / 60F) + (seconds / (60F * 60F)); + if ((ref.equals("S") || ref.equals("W"))) { + return -result; + } + return result; + } catch (RuntimeException ex) { + // if for whatever reason we can't parse the lat long then return + // null + return 0f; + } + } + + public static String convertRationalLatLonToDecimalString( + String rationalString, String ref, boolean usePositiveNegative) { + float result = convertRationalLatLonToFloat(rationalString, ref); + + String preliminaryResult = String.valueOf(result); + if (usePositiveNegative) { + String neg = (ref.equals("S") || ref.equals("E")) ? "-" : ""; + return neg + preliminaryResult; + } else { + return preliminaryResult + String.valueOf((char) 186) + " " + + ref; + } + } + + public static String makeLatLongString(double d) { + d = Math.abs(d); + + int degrees = (int) d; + + double remainder = d - degrees; + int minutes = (int) (remainder * 60D); + // really seconds * 1000 + int seconds = (int) (((remainder * 60D) - minutes) * 60D * 1000D); + + String retVal = degrees + "/1," + minutes + "/1," + seconds + "/1000"; + return retVal; + } + + public static String makeLatStringRef(double lat) { + return lat >= 0D ? "N" : "S"; + } + + public static String makeLonStringRef(double lon) { + return lon >= 0D ? "W" : "E"; + } + + private native boolean appendThumbnailNative(String fileName, + String thumbnailFileName); + + private native void saveAttributesNative(String fileName, + String compressedAttributes); + + private native String getAttributesNative(String fileName); + + private native void commitChangesNative(String fileName); + + private native byte[] getThumbnailNative(String fileName); +} diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index f5e242d11d10c..9a8264f031fcc 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -71,4 +71,5 @@ interface IAudioService { oneway void unloadSoundEffects(); + oneway void reloadAudioSettings(); } diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index cccc0fcd53e9c..95f36809bdf1b 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -54,7 +54,7 @@ import java.util.Iterator; /** * Internal service helper that no-one should use directly. - * + * * The way the scan currently works is: * - The Java MediaScannerService creates a MediaScanner (this class), and calls * MediaScanner.scanDirectories on it. @@ -96,7 +96,7 @@ import java.util.Iterator; * {@hide} */ public class MediaScanner -{ +{ static { System.loadLibrary("media_jni"); } @@ -108,17 +108,17 @@ public class MediaScanner Audio.Media.DATA, // 1 Audio.Media.DATE_MODIFIED, // 2 }; - + private static final int ID_AUDIO_COLUMN_INDEX = 0; private static final int PATH_AUDIO_COLUMN_INDEX = 1; private static final int DATE_MODIFIED_AUDIO_COLUMN_INDEX = 2; - + private static final String[] VIDEO_PROJECTION = new String[] { Video.Media._ID, // 0 Video.Media.DATA, // 1 Video.Media.DATE_MODIFIED, // 2 }; - + private static final int ID_VIDEO_COLUMN_INDEX = 0; private static final int PATH_VIDEO_COLUMN_INDEX = 1; private static final int DATE_MODIFIED_VIDEO_COLUMN_INDEX = 2; @@ -128,11 +128,11 @@ public class MediaScanner Images.Media.DATA, // 1 Images.Media.DATE_MODIFIED, // 2 }; - + private static final int ID_IMAGES_COLUMN_INDEX = 0; private static final int PATH_IMAGES_COLUMN_INDEX = 1; private static final int DATE_MODIFIED_IMAGES_COLUMN_INDEX = 2; - + private static final String[] PLAYLISTS_PROJECTION = new String[] { Audio.Playlists._ID, // 0 Audio.Playlists.DATA, // 1 @@ -157,7 +157,7 @@ public class MediaScanner private static final String ALARMS_DIR = "/alarms/"; private static final String MUSIC_DIR = "/music/"; private static final String PODCAST_DIR = "/podcasts/"; - + private static final String[] ID3_GENRES = { // ID3v1 Genres "Blues", @@ -317,11 +317,11 @@ public class MediaScanner * to get the full system property. */ private static final String DEFAULT_RINGTONE_PROPERTY_PREFIX = "ro.config."; - + // set to true if file path comparisons should be case insensitive. // this should be set when scanning files on a case insensitive file system. private boolean mCaseInsensitivePaths; - + private BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); private static class FileCacheEntry { @@ -331,7 +331,7 @@ public class MediaScanner long mLastModified; boolean mSeenInFileSystem; boolean mLastModifiedChanged; - + FileCacheEntry(Uri tableUri, long rowId, String path, long lastModified) { mTableUri = tableUri; mRowId = rowId; @@ -346,10 +346,10 @@ public class MediaScanner return mPath; } } - - // hashes file path to FileCacheEntry. + + // hashes file path to FileCacheEntry. // path should be lower case if mCaseInsensitivePaths is true - private HashMap mFileCache; + private HashMap mFileCache; private ArrayList mPlayLists; private HashMap mGenreCache; @@ -360,7 +360,7 @@ public class MediaScanner mContext = c; mBitmapOptions.inSampleSize = 1; mBitmapOptions.inJustDecodeBounds = true; - + setDefaultRingtoneFileNames(); } @@ -370,11 +370,11 @@ public class MediaScanner mDefaultNotificationFilename = SystemProperties.get(DEFAULT_RINGTONE_PROPERTY_PREFIX + Settings.System.NOTIFICATION_SOUND); } - + private MyMediaScannerClient mClient = new MyMediaScannerClient(); - + private class MyMediaScannerClient implements MediaScannerClient { - + private String mArtist; private String mAlbumArtist; // use this if mArtist is missing private String mAlbum; @@ -389,11 +389,11 @@ public class MediaScanner private String mPath; private long mLastModified; private long mFileSize; - + public FileCacheEntry beginFile(String path, String mimeType, long lastModified, long fileSize) { - + // special case certain file names - // I use regionMatches() instead of substring() below + // I use regionMatches() instead of substring() below // to avoid memory allocation int lastSlash = path.lastIndexOf('/'); if (lastSlash >= 0 && lastSlash + 2 < path.length()) { @@ -401,7 +401,7 @@ public class MediaScanner if (path.regionMatches(lastSlash + 1, "._", 0, 2)) { return null; } - + // ignore album art files created by Windows Media Player: // Folder.jpg, AlbumArtSmall.jpg, AlbumArt_{...}_Large.jpg and AlbumArt_{...}_Small.jpg if (path.regionMatches(true, path.length() - 4, ".jpg", 0, 4)) { @@ -416,7 +416,7 @@ public class MediaScanner } } } - + mMimeType = null; // try mimeType first, if it is specified if (mimeType != null) { @@ -435,7 +435,7 @@ public class MediaScanner mMimeType = mediaFileType.mimeType; } } - + String key = path; if (mCaseInsensitivePaths) { key = path.toLowerCase(); @@ -446,20 +446,20 @@ public class MediaScanner mFileCache.put(key, entry); } entry.mSeenInFileSystem = true; - + // add some slack to avoid a rounding error long delta = lastModified - entry.mLastModified; if (delta > 1 || delta < -1) { entry.mLastModified = lastModified; entry.mLastModifiedChanged = true; } - + if (mProcessPlaylists && MediaFile.isPlayListFileType(mFileType)) { mPlayLists.add(entry); // we don't process playlists in the main scan, so return null return null; } - + // clear all the metadata mArtist = null; mAlbumArtist = null; @@ -472,10 +472,10 @@ public class MediaScanner mDuration = 0; mPath = path; mLastModified = lastModified; - + return entry; } - + public void scanFile(String path, long lastModified, long fileSize) { doScanFile(path, null, lastModified, fileSize, false); } @@ -513,7 +513,7 @@ public class MediaScanner } else if (MediaFile.isImageFileType(mFileType)) { // we used to compute the width and height but it's not worth it } - + result = endFile(entry, ringtones, notifications, alarms, music, podcasts); } } catch (RemoteException e) { @@ -531,17 +531,17 @@ public class MediaScanner char ch = s.charAt(start++); // return defaultValue if we have no integer at all if (ch < '0' || ch > '9') return defaultValue; - + int result = ch - '0'; while (start < length) { ch = s.charAt(start++); if (ch < '0' || ch > '9') return result; result = result * 10 + (ch - '0'); } - + return result; - } - + } + public void handleStringTag(String name, String value) { if (name.equalsIgnoreCase("title") || name.startsWith("title;")) { // Don't trim() here, to preserve the special \001 character @@ -577,7 +577,7 @@ public class MediaScanner // track number might be of the form "2/12" // we just read the number before the slash int num = parseSubstring(value, 0, 0); - mTrack = (mTrack / 1000) * 1000 + num; + mTrack = (mTrack / 1000) * 1000 + num; } else if (name.equalsIgnoreCase("discnumber") || name.equals("set") || name.startsWith("set;")) { // set number might be of the form "1/3" @@ -588,16 +588,16 @@ public class MediaScanner mDuration = parseSubstring(value, 0, 0); } } - + public void setMimeType(String mimeType) { mMimeType = mimeType; mFileType = MediaFile.getFileTypeForMimeType(mimeType); } - + /** * Formats the data into a values array suitable for use with the Media * Content Provider. - * + * * @return a map of values */ private ContentValues toValues() { @@ -608,7 +608,7 @@ public class MediaScanner map.put(MediaStore.MediaColumns.DATE_MODIFIED, mLastModified); map.put(MediaStore.MediaColumns.SIZE, mFileSize); map.put(MediaStore.MediaColumns.MIME_TYPE, mMimeType); - + if (MediaFile.isVideoFileType(mFileType)) { map.put(Video.Media.ARTIST, (mArtist != null && mArtist.length() > 0 ? mArtist : MediaFile.UNKNOWN_STRING)); map.put(Video.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0 ? mAlbum : MediaFile.UNKNOWN_STRING)); @@ -629,9 +629,9 @@ public class MediaScanner } return map; } - + private Uri endFile(FileCacheEntry entry, boolean ringtones, boolean notifications, - boolean alarms, boolean music, boolean podcasts) + boolean alarms, boolean music, boolean podcasts) throws RemoteException { // update database Uri tableUri; @@ -649,7 +649,7 @@ public class MediaScanner return null; } entry.mTableUri = tableUri; - + // use album artist if artist is missing if (mArtist == null || mArtist.length() == 0) { mArtist = mAlbumArtist; @@ -657,7 +657,7 @@ public class MediaScanner ContentValues values = toValues(); String title = values.getAsString(MediaStore.MediaColumns.TITLE); - if (TextUtils.isEmpty(title)) { + if (title == null || TextUtils.isEmpty(title.trim())) { title = values.getAsString(MediaStore.MediaColumns.DATA); // extract file name after last slash int lastSlash = title.lastIndexOf('/'); @@ -680,10 +680,18 @@ public class MediaScanner values.put(Audio.Media.IS_ALARM, alarms); values.put(Audio.Media.IS_MUSIC, music); values.put(Audio.Media.IS_PODCAST, podcasts); - } else if (isImage) { - // nothing right now + } else if (mFileType == MediaFile.FILE_TYPE_JPEG) { + HashMap exifData = + ExifInterface.loadExifData(entry.mPath); + if (exifData != null) { + float[] latlng = ExifInterface.getLatLng(exifData); + if (latlng != null) { + values.put(Images.Media.LATITUDE, latlng[0]); + values.put(Images.Media.LONGITUDE, latlng[1]); + } + } } - + Uri result = null; long rowId = entry.mRowId; if (rowId == 0) { @@ -730,15 +738,15 @@ public class MediaScanner } } } - + if (uri != null) { - // add entry to audio_genre_map + // add entry to audio_genre_map values.clear(); values.put(MediaStore.Audio.Genres.Members.AUDIO_ID, Long.valueOf(rowId)); mMediaProvider.insert(uri, values); } } - + if (notifications && !mDefaultNotificationSet) { if (TextUtils.isEmpty(mDefaultNotificationFilename) || doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) { @@ -752,36 +760,36 @@ public class MediaScanner mDefaultRingtoneSet = true; } } - + return result; } - + private boolean doesPathHaveFilename(String path, String filename) { int pathFilenameStart = path.lastIndexOf(File.separatorChar) + 1; int filenameLength = filename.length(); return path.regionMatches(pathFilenameStart, filename, 0, filenameLength) && pathFilenameStart + filenameLength == path.length(); } - + private void setSettingIfNotSet(String settingName, Uri uri, long rowId) { - + String existingSettingValue = Settings.System.getString(mContext.getContentResolver(), settingName); - + if (TextUtils.isEmpty(existingSettingValue)) { // Set the setting to the given URI Settings.System.putString(mContext.getContentResolver(), settingName, ContentUris.withAppendedId(uri, rowId).toString()); } } - + }; // end of anonymous MediaScannerClient instance - + private void prescan(String filePath) throws RemoteException { Cursor c = null; String where = null; String[] selectionArgs = null; - + if (mFileCache == null) { mFileCache = new HashMap(); } else { @@ -792,7 +800,7 @@ public class MediaScanner } else { mPlayLists.clear(); } - + // Build the list of files from the content provider try { // Read existing files from the audio table @@ -801,14 +809,14 @@ public class MediaScanner selectionArgs = new String[] { filePath }; } c = mMediaProvider.query(mAudioUri, AUDIO_PROJECTION, where, selectionArgs, null); - + if (c != null) { try { while (c.moveToNext()) { long rowId = c.getLong(ID_AUDIO_COLUMN_INDEX); String path = c.getString(PATH_AUDIO_COLUMN_INDEX); long lastModified = c.getLong(DATE_MODIFIED_AUDIO_COLUMN_INDEX); - + String key = path; if (mCaseInsensitivePaths) { key = path.toLowerCase(); @@ -829,14 +837,14 @@ public class MediaScanner where = null; } c = mMediaProvider.query(mVideoUri, VIDEO_PROJECTION, where, selectionArgs, null); - + if (c != null) { try { while (c.moveToNext()) { long rowId = c.getLong(ID_VIDEO_COLUMN_INDEX); String path = c.getString(PATH_VIDEO_COLUMN_INDEX); long lastModified = c.getLong(DATE_MODIFIED_VIDEO_COLUMN_INDEX); - + String key = path; if (mCaseInsensitivePaths) { key = path.toLowerCase(); @@ -858,7 +866,7 @@ public class MediaScanner } mOriginalCount = 0; c = mMediaProvider.query(mImagesUri, IMAGES_PROJECTION, where, selectionArgs, null); - + if (c != null) { try { mOriginalCount = c.getCount(); @@ -866,7 +874,7 @@ public class MediaScanner long rowId = c.getLong(ID_IMAGES_COLUMN_INDEX); String path = c.getString(PATH_IMAGES_COLUMN_INDEX); long lastModified = c.getLong(DATE_MODIFIED_IMAGES_COLUMN_INDEX); - + String key = path; if (mCaseInsensitivePaths) { key = path.toLowerCase(); @@ -879,7 +887,7 @@ public class MediaScanner c = null; } } - + if (mProcessPlaylists) { // Read existing files from the playlists table if (filePath != null) { @@ -888,16 +896,16 @@ public class MediaScanner where = null; } c = mMediaProvider.query(mPlaylistsUri, PLAYLISTS_PROJECTION, where, selectionArgs, null); - + if (c != null) { try { while (c.moveToNext()) { String path = c.getString(PATH_IMAGES_COLUMN_INDEX); - + if (path != null && path.length() > 0) { long rowId = c.getLong(ID_PLAYLISTS_COLUMN_INDEX); long lastModified = c.getLong(DATE_MODIFIED_PLAYLISTS_COLUMN_INDEX); - + String key = path; if (mCaseInsensitivePaths) { key = path.toLowerCase(); @@ -919,7 +927,7 @@ public class MediaScanner } } } - + private boolean inScanDirectory(String path, String[] directories) { for (int i = 0; i < directories.length; i++) { if (path.startsWith(directories[i])) { @@ -928,25 +936,25 @@ public class MediaScanner } return false; } - + private void pruneDeadThumbnailFiles() { HashSet existingFiles = new HashSet(); String directory = "/sdcard/DCIM/.thumbnails"; String [] files = (new File(directory)).list(); if (files == null) files = new String[0]; - + for (int i = 0; i < files.length; i++) { String fullPathString = directory + "/" + files[i]; existingFiles.add(fullPathString); } - + try { Cursor c = mMediaProvider.query( - mThumbsUri, - new String [] { "_data" }, - null, - null, + mThumbsUri, + new String [] { "_data" }, + null, + null, null); Log.v(TAG, "pruneDeadThumbnailFiles... " + c); if (c != null && c.moveToFirst()) { @@ -955,7 +963,7 @@ public class MediaScanner existingFiles.remove(fullPathString); } while (c.moveToNext()); } - + for (String fileToDelete : existingFiles) { if (Config.LOGV) Log.v(TAG, "fileToDelete is " + fileToDelete); @@ -964,7 +972,7 @@ public class MediaScanner } catch (SecurityException ex) { } } - + Log.v(TAG, "/pruneDeadThumbnailFiles... " + c); if (c != null) { c.close(); @@ -980,10 +988,10 @@ public class MediaScanner while (iterator.hasNext()) { FileCacheEntry entry = iterator.next(); String path = entry.mPath; - + // remove database entries for files that no longer exist. boolean fileMissing = false; - + if (!entry.mSeenInFileSystem) { if (inScanDirectory(path, directories)) { // we didn't see this file in the scan directory. @@ -997,7 +1005,7 @@ public class MediaScanner } } } - + if (fileMissing) { // do not delete missing playlists, since they may have been modified by the user. // the user can delete them in the media player instead. @@ -1016,25 +1024,25 @@ public class MediaScanner } } } - + // handle playlists last, after we know what media files are on the storage. if (mProcessPlaylists) { processPlayLists(); } - + if (mOriginalCount == 0 && mImagesUri.equals(Images.Media.getContentUri("external"))) pruneDeadThumbnailFiles(); - + // allow GC to clean up mGenreCache = null; mPlayLists = null; mFileCache = null; mMediaProvider = null; } - + private void initialize(String volumeName) { mMediaProvider = mContext.getContentResolver().acquireProvider("media"); - + mAudioUri = Audio.Media.getContentUri(volumeName); mVideoUri = Video.Media.getContentUri(volumeName); mImagesUri = Images.Media.getContentUri(volumeName); @@ -1051,23 +1059,23 @@ public class MediaScanner if ( Process.supportsProcesses()) { mCaseInsensitivePaths = true; } - } + } } public void scanDirectories(String[] directories, String volumeName) { try { long start = System.currentTimeMillis(); - initialize(volumeName); + initialize(volumeName); prescan(null); long prescan = System.currentTimeMillis(); - + for (int i = 0; i < directories.length; i++) { processDirectory(directories[i], MediaFile.sFileExtensions, mClient); } long scan = System.currentTimeMillis(); postscan(directories); long end = System.currentTimeMillis(); - + if (Config.LOGD) { Log.d(TAG, " prescan time: " + (prescan - start) + "ms\n"); Log.d(TAG, " scan time: " + (scan - prescan) + "ms\n"); @@ -1088,9 +1096,9 @@ public class MediaScanner // this function is used to scan a single file public Uri scanSingleFile(String path, String volumeName, String mimeType) { try { - initialize(volumeName); + initialize(volumeName); prescan(path); - + File file = new File(path); // always scan the file, so we can return the content://media Uri for existing files return mClient.doScanFile(path, mimeType, file.lastModified(), file.length(), true); @@ -1105,7 +1113,7 @@ public class MediaScanner int result = 0; int end1 = path1.length(); int end2 = path2.length(); - + while (end1 > 0 && end2 > 0) { int slash1 = path1.lastIndexOf('/', end1 - 1); int slash2 = path2.lastIndexOf('/', end2 - 1); @@ -1123,13 +1131,13 @@ public class MediaScanner end2 = start2 - 1; } else break; } - + return result; } - private boolean addPlayListEntry(String entry, String playListDirectory, + private boolean addPlayListEntry(String entry, String playListDirectory, Uri uri, ContentValues values, int index) { - + // watch for trailing whitespace int entryLength = entry.length(); while (entryLength > 0 && Character.isWhitespace(entry.charAt(entryLength - 1))) entryLength--; @@ -1146,36 +1154,36 @@ public class MediaScanner // if we have a relative path, combine entry with playListDirectory if (!fullPath) entry = playListDirectory + entry; - + //FIXME - should we look for "../" within the path? - + // best matching MediaFile for the play list entry FileCacheEntry bestMatch = null; - + // number of rightmost file/directory names for bestMatch - int bestMatchLength = 0; - + int bestMatchLength = 0; + Iterator iterator = mFileCache.values().iterator(); while (iterator.hasNext()) { FileCacheEntry cacheEntry = iterator.next(); String path = cacheEntry.mPath; - + if (path.equalsIgnoreCase(entry)) { bestMatch = cacheEntry; break; // don't bother continuing search } - + int matchLength = matchPaths(path, entry); if (matchLength > bestMatchLength) { bestMatch = cacheEntry; bestMatchLength = matchLength; } } - + if (bestMatch == null) { return false; } - + try { // OK, now we need to add this to the database values.clear(); @@ -1189,7 +1197,7 @@ public class MediaScanner return true; } - + private void processM3uPlayList(String path, String playListDirectory, Uri uri, ContentValues values) { BufferedReader reader = null; try { @@ -1266,7 +1274,7 @@ public class MediaScanner public WplHandler(String playListDirectory, Uri uri) { this.playListDirectory = playListDirectory; this.uri = uri; - + RootElement root = new RootElement("smil"); Element body = root.getChild("body"); Element seq = body.getChild("seq"); @@ -1316,12 +1324,12 @@ public class MediaScanner } } } - + private void processPlayLists() throws RemoteException { Iterator iterator = mPlayLists.iterator(); while (iterator.hasNext()) { FileCacheEntry entry = iterator.next(); - String path = entry.mPath; + String path = entry.mPath; // only process playlist files if they are new or have been modified since the last scan if (entry.mLastModifiedChanged) { @@ -1332,7 +1340,7 @@ public class MediaScanner long rowId = entry.mRowId; if (rowId == 0) { // Create a new playlist - + int lastDot = path.lastIndexOf('.'); String name = (lastDot < 0 ? path.substring(lastSlash + 1) : path.substring(lastSlash + 1, lastDot)); values.put(MediaStore.Audio.Playlists.NAME, name); @@ -1343,7 +1351,7 @@ public class MediaScanner membersUri = Uri.withAppendedPath(uri, Playlists.Members.CONTENT_DIRECTORY); } else { uri = ContentUris.withAppendedId(mPlaylistsUri, rowId); - + // update lastModified value of existing playlist values.put(MediaStore.Audio.Playlists.DATE_MODIFIED, entry.mLastModified); mMediaProvider.update(uri, values, null, null); @@ -1352,7 +1360,7 @@ public class MediaScanner membersUri = Uri.withAppendedPath(uri, Playlists.Members.CONTENT_DIRECTORY); mMediaProvider.delete(membersUri, null, null); } - + String playListDirectory = path.substring(0, lastSlash + 1); MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path); int fileType = (mediaFileType == null ? 0 : mediaFileType.fileType); @@ -1363,7 +1371,7 @@ public class MediaScanner processPlsPlayList(path, playListDirectory, membersUri, values); else if (fileType == MediaFile.FILE_TYPE_WPL) processWplPlayList(path, playListDirectory, membersUri); - + Cursor cursor = mMediaProvider.query(membersUri, PLAYLIST_MEMBERS_PROJECTION, null, null, null); try { @@ -1377,18 +1385,18 @@ public class MediaScanner } } } - + private native void processDirectory(String path, String extensions, MediaScannerClient client); private native void processFile(String path, String mimeType, MediaScannerClient client); public native void setLocale(String locale); - + public native byte[] extractAlbumArt(FileDescriptor fd); private native final void native_setup(); private native final void native_finalize(); @Override - protected void finalize() { + protected void finalize() { mContext.getContentResolver().releaseProvider(mMediaProvider); - native_finalize(); + native_finalize(); } } diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp index c22cd53d1d4af..5435da74825d1 100644 --- a/media/libmedia/ToneGenerator.cpp +++ b/media/libmedia/ToneGenerator.cpp @@ -1225,6 +1225,8 @@ audioCallback_EndLoop: LOGV("Cbk restarting track\n"); if (lpToneGen->prepareWave()) { lpToneGen->mState = TONE_STARTING; + // must reload lpToneDesc as prepareWave() may change mpToneDesc + lpToneDesc = lpToneGen->mpToneDesc; } else { LOGW("Cbk restarting prepareWave() failed\n"); lpToneGen->mState = TONE_IDLE; diff --git a/media/sdutils/sdutil.cpp b/media/sdutils/sdutil.cpp index a9aabf03624a8..06120f57431bc 100644 --- a/media/sdutils/sdutil.cpp +++ b/media/sdutils/sdutil.cpp @@ -88,7 +88,7 @@ static int mount(const char* path) { String16 string(path); gMountService->mountMedia(string); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 60; i++) { if (isMounted(path)) { return 0; } @@ -103,7 +103,7 @@ static int unmount(const char* path) { String16 string(path); gMountService->unmountMedia(string); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 20; i++) { if (!isMounted(path)) { return 0; } diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index c44478db83bec..44615679af6da 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -1103,7 +1103,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, // default value if (binarySearch( (config_pair_t const*)attrib_list, - 0, numAttributes, + 0, numAttributes-1, config_defaults[j].key) < 0) { for (int i=0 ; i - \ No newline at end of file + diff --git a/packages/SettingsProvider/res/values-cs/defaults.xml b/packages/SettingsProvider/res/values-cs/defaults.xml new file mode 100644 index 0000000000000..a7c01b39e143f --- /dev/null +++ b/packages/SettingsProvider/res/values-cs/defaults.xml @@ -0,0 +1,22 @@ + + + + "mobil,bluetooth,wifi" + "gps" + + + diff --git a/packages/SettingsProvider/res/values-cs/strings.xml b/packages/SettingsProvider/res/values-cs/strings.xml new file mode 100644 index 0000000000000..dc75a92d6cf4f --- /dev/null +++ b/packages/SettingsProvider/res/values-cs/strings.xml @@ -0,0 +1,19 @@ + + + + "Paměť pro nastavení" + diff --git a/packages/SettingsProvider/res/values-de/defaults.xml b/packages/SettingsProvider/res/values-de/defaults.xml new file mode 100644 index 0000000000000..f85d3f0ce8b7c --- /dev/null +++ b/packages/SettingsProvider/res/values-de/defaults.xml @@ -0,0 +1,22 @@ + + + + "Mobilfunk, Bluetooth, WLAN" + "GPS" + + + diff --git a/packages/SettingsProvider/res/values-de/strings.xml b/packages/SettingsProvider/res/values-de/strings.xml new file mode 100644 index 0000000000000..50c8a142357af --- /dev/null +++ b/packages/SettingsProvider/res/values-de/strings.xml @@ -0,0 +1,19 @@ + + + + "Einstellungsspeicher" + diff --git a/packages/SettingsProvider/res/values-es/defaults.xml b/packages/SettingsProvider/res/values-es/defaults.xml new file mode 100644 index 0000000000000..a64805aaa0ce8 --- /dev/null +++ b/packages/SettingsProvider/res/values-es/defaults.xml @@ -0,0 +1,22 @@ + + + + "móvil,bluetooth,wifi" + "gps" + + + diff --git a/packages/SettingsProvider/res/values-es/strings.xml b/packages/SettingsProvider/res/values-es/strings.xml new file mode 100644 index 0000000000000..d30d1953f47ef --- /dev/null +++ b/packages/SettingsProvider/res/values-es/strings.xml @@ -0,0 +1,19 @@ + + + + "Almacenamiento de configuración" + diff --git a/packages/SettingsProvider/res/values-fr/defaults.xml b/packages/SettingsProvider/res/values-fr/defaults.xml new file mode 100644 index 0000000000000..56334cc3fc402 --- /dev/null +++ b/packages/SettingsProvider/res/values-fr/defaults.xml @@ -0,0 +1,22 @@ + + + + "cellulaire, Bluetooth, Wi-Fi" + "gps" + + + diff --git a/packages/SettingsProvider/res/values-fr/strings.xml b/packages/SettingsProvider/res/values-fr/strings.xml new file mode 100644 index 0000000000000..686ec8b8f36d0 --- /dev/null +++ b/packages/SettingsProvider/res/values-fr/strings.xml @@ -0,0 +1,19 @@ + + + + "Stockage des paramètres" + diff --git a/packages/SettingsProvider/res/values-it/defaults.xml b/packages/SettingsProvider/res/values-it/defaults.xml new file mode 100644 index 0000000000000..19c0896553e6d --- /dev/null +++ b/packages/SettingsProvider/res/values-it/defaults.xml @@ -0,0 +1,22 @@ + + + + "cellulare,bluetooth,wifi" + "gps" + + + diff --git a/packages/SettingsProvider/res/values-it/strings.xml b/packages/SettingsProvider/res/values-it/strings.xml new file mode 100644 index 0000000000000..29e462fa4bbf7 --- /dev/null +++ b/packages/SettingsProvider/res/values-it/strings.xml @@ -0,0 +1,19 @@ + + + + "Archiviazione impostazioni" + diff --git a/packages/SettingsProvider/res/values-nl/defaults.xml b/packages/SettingsProvider/res/values-nl/defaults.xml new file mode 100644 index 0000000000000..625235ac7e2c0 --- /dev/null +++ b/packages/SettingsProvider/res/values-nl/defaults.xml @@ -0,0 +1,22 @@ + + + + "mobiel,bluetooth,wifi" + "gps" + + + diff --git a/packages/SettingsProvider/res/values-nl/strings.xml b/packages/SettingsProvider/res/values-nl/strings.xml new file mode 100644 index 0000000000000..b37b5357f82d2 --- /dev/null +++ b/packages/SettingsProvider/res/values-nl/strings.xml @@ -0,0 +1,19 @@ + + + + "Opslagruimte voor instellingen" + diff --git a/packages/SettingsProvider/res/values-pl/defaults.xml b/packages/SettingsProvider/res/values-pl/defaults.xml new file mode 100644 index 0000000000000..b60832ebbf3f8 --- /dev/null +++ b/packages/SettingsProvider/res/values-pl/defaults.xml @@ -0,0 +1,22 @@ + + + + "komórka,bluetooth,wifi" + "gps" + + + diff --git a/packages/SettingsProvider/res/values-pl/strings.xml b/packages/SettingsProvider/res/values-pl/strings.xml new file mode 100644 index 0000000000000..4ab1e915de992 --- /dev/null +++ b/packages/SettingsProvider/res/values-pl/strings.xml @@ -0,0 +1,19 @@ + + + + "Pamięć ustawień" + diff --git a/packages/SettingsProvider/res/values-zh-rTW/defaults.xml b/packages/SettingsProvider/res/values-zh-rTW/defaults.xml new file mode 100644 index 0000000000000..fdbba8827e843 --- /dev/null +++ b/packages/SettingsProvider/res/values-zh-rTW/defaults.xml @@ -0,0 +1,22 @@ + + + + "手機,藍牙,wifi" + "gps" + + + diff --git a/packages/SettingsProvider/res/values-zh-rTW/strings.xml b/packages/SettingsProvider/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000000..b24144a255a8a --- /dev/null +++ b/packages/SettingsProvider/res/values-zh-rTW/strings.xml @@ -0,0 +1,19 @@ + + + + "設定儲存空間" + diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index b6bc8a5964143..2b369043b6edf 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -16,12 +16,16 @@ package com.android.providers.settings; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.EOFException; import java.util.Arrays; import java.util.HashMap; +import java.util.zip.CRC32; import android.backup.BackupDataInput; import android.backup.BackupDataOutput; @@ -34,7 +38,9 @@ import android.database.Cursor; import android.media.AudioManager; import android.net.Uri; import android.net.wifi.WifiManager; +import android.os.FileUtils; import android.os.ParcelFileDescriptor; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; @@ -52,6 +58,13 @@ public class SettingsBackupAgent extends BackupHelperAgent { private static final String KEY_SYNC = "sync_providers"; private static final String KEY_LOCALE = "locale"; + private static final int STATE_SYSTEM = 0; + private static final int STATE_SECURE = 1; + private static final int STATE_SYNC = 2; + private static final int STATE_LOCALE = 3; + private static final int STATE_WIFI = 4; + private static final int STATE_SIZE = 5; // The number of state items + private static String[] sortedSystemKeys = null; private static String[] sortedSecureKeys = null; @@ -87,20 +100,22 @@ public class SettingsBackupAgent extends BackupHelperAgent { byte[] secureSettingsData = getSecureSettings(); byte[] syncProviders = mSettingsHelper.getSyncProviders(); byte[] locale = mSettingsHelper.getLocaleData(); - - data.writeEntityHeader(KEY_SYSTEM, systemSettingsData.length); - data.writeEntityData(systemSettingsData, systemSettingsData.length); + byte[] wifiData = getFileData(FILE_WIFI_SUPPLICANT); - data.writeEntityHeader(KEY_SECURE, secureSettingsData.length); - data.writeEntityData(secureSettingsData, secureSettingsData.length); + long[] stateChecksums = readOldChecksums(oldState); - data.writeEntityHeader(KEY_SYNC, syncProviders.length); - data.writeEntityData(syncProviders, syncProviders.length); + stateChecksums[STATE_SYSTEM] = + writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data); + stateChecksums[STATE_SECURE] = + writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data); + stateChecksums[STATE_SYNC] = + writeIfChanged(stateChecksums[STATE_SYNC], KEY_SYNC, syncProviders, data); + stateChecksums[STATE_LOCALE] = + writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data); + stateChecksums[STATE_WIFI] = + writeIfChanged(stateChecksums[STATE_WIFI], FILE_WIFI_SUPPLICANT, wifiData, data); - data.writeEntityHeader(KEY_LOCALE, locale.length); - data.writeEntityData(locale, locale.length); - - backupFile(FILE_WIFI_SUPPLICANT, data); + writeNewChecksums(stateChecksums, newState); } @Override @@ -115,11 +130,15 @@ public class SettingsBackupAgent extends BackupHelperAgent { final int size = data.getDataSize(); if (KEY_SYSTEM.equals(key)) { restoreSettings(data, Settings.System.CONTENT_URI); + mSettingsHelper.applyAudioSettings(); } else if (KEY_SECURE.equals(key)) { restoreSettings(data, Settings.Secure.CONTENT_URI); -// TODO: Re-enable WIFI restore when we figure out a solution for the permissions -// } else if (FILE_WIFI_SUPPLICANT.equals(key)) { -// restoreFile(FILE_WIFI_SUPPLICANT, data); + } else if (FILE_WIFI_SUPPLICANT.equals(key)) { + restoreFile(FILE_WIFI_SUPPLICANT, data); + FileUtils.setPermissions(FILE_WIFI_SUPPLICANT, + FileUtils.S_IRUSR | FileUtils.S_IWUSR | + FileUtils.S_IRGRP | FileUtils.S_IWGRP, + Process.myUid(), Process.WIFI_UID); } else if (KEY_SYNC.equals(key)) { mSettingsHelper.setSyncProviders(data); } else if (KEY_LOCALE.equals(key)) { @@ -132,6 +151,49 @@ public class SettingsBackupAgent extends BackupHelperAgent { } } + private long[] readOldChecksums(ParcelFileDescriptor oldState) throws IOException { + long[] stateChecksums = new long[STATE_SIZE]; + + DataInputStream dataInput = new DataInputStream( + new FileInputStream(oldState.getFileDescriptor())); + for (int i = 0; i < STATE_SIZE; i++) { + try { + stateChecksums[i] = dataInput.readLong(); + } catch (EOFException eof) { + break; + } + } + dataInput.close(); + return stateChecksums; + } + + private void writeNewChecksums(long[] checksums, ParcelFileDescriptor newState) + throws IOException { + DataOutputStream dataOutput = new DataOutputStream( + new FileOutputStream(newState.getFileDescriptor())); + for (int i = 0; i < STATE_SIZE; i++) { + dataOutput.writeLong(checksums[i]); + } + dataOutput.close(); + } + + private long writeIfChanged(long oldChecksum, String key, byte[] data, + BackupDataOutput output) { + CRC32 checkSummer = new CRC32(); + checkSummer.update(data); + long newChecksum = checkSummer.getValue(); + if (oldChecksum == newChecksum) { + return oldChecksum; + } + try { + output.writeEntityHeader(key, data.length); + output.writeEntityData(data, data.length); + } catch (IOException ioe) { + // Bail + } + return newChecksum; + } + private byte[] getSystemSettings() { Cursor sortedCursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION, null, null, Settings.NameValueTable.NAME); @@ -248,7 +310,7 @@ public class SettingsBackupAgent extends BackupHelperAgent { return result; } - private void backupFile(String filename, BackupDataOutput data) { + private byte[] getFileData(String filename) { try { File file = new File(filename); if (file.exists()) { @@ -260,14 +322,13 @@ public class SettingsBackupAgent extends BackupHelperAgent { got = fis.read(bytes, offset, bytes.length - offset); if (got > 0) offset += got; } while (offset < bytes.length && got > 0); - data.writeEntityHeader(filename, bytes.length); - data.writeEntityData(bytes, bytes.length); + return bytes; } else { - data.writeEntityHeader(filename, 0); - data.writeEntityData(EMPTY_DATA, 0); + return EMPTY_DATA; } } catch (IOException ioe) { Log.w(TAG, "Couldn't backup " + filename); + return EMPTY_DATA; } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java index 2c5775af683a6..ca739e6b15d93 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java @@ -167,6 +167,9 @@ public class SettingsHelper { // Check if locale was set by the user: Configuration conf = mContext.getResources().getConfiguration(); Locale loc = conf.locale; + // TODO: The following is not working as intended because the network is forcing a locale + // change after registering. Need to find some other way to detect if the user manually + // changed the locale if (conf.userSetLocale) return; // Don't change if user set it in the SetupWizard final String[] availableLocales = mContext.getAssets().getLocales(); @@ -193,6 +196,14 @@ public class SettingsHelper { } catch (RemoteException e) { // Intentionally left blank } + } + /** + * Informs the audio service of changes to the settings so that + * they can be re-read and applied. + */ + void applyAudioSettings() { + AudioManager am = new AudioManager(mContext); + am.reloadAudioSettings(); } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 2abf8b332aaa1..c0de9a5b00a09 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -126,11 +126,14 @@ public class SettingsProvider extends ContentProvider { // a notification and then using the contract class to get their data, // the system property will be updated and they'll get the new data. + boolean backedUpDataChanged = false; String property = null, table = uri.getPathSegments().get(0); if (table.equals("system")) { property = Settings.System.SYS_PROP_SETTING_VERSION; + backedUpDataChanged = true; } else if (table.equals("secure")) { property = Settings.Secure.SYS_PROP_SETTING_VERSION; + backedUpDataChanged = true; } else if (table.equals("gservices")) { property = Settings.Gservices.SYS_PROP_SETTING_VERSION; } @@ -142,7 +145,9 @@ public class SettingsProvider extends ContentProvider { } // Inform the backup manager about a data change - mBackupManager.dataChanged(); + if (backedUpDataChanged) { + mBackupManager.dataChanged(); + } // Now send the notification through the content framework. String notify = uri.getQueryParameter("notify"); diff --git a/packages/SubscribedFeedsProvider/res/values-cs/strings.xml b/packages/SubscribedFeedsProvider/res/values-cs/strings.xml new file mode 100644 index 0000000000000..9b782b0eb1d2e --- /dev/null +++ b/packages/SubscribedFeedsProvider/res/values-cs/strings.xml @@ -0,0 +1,19 @@ + + + + "Synchronizace zdrojů" + diff --git a/packages/SubscribedFeedsProvider/res/values-de/strings.xml b/packages/SubscribedFeedsProvider/res/values-de/strings.xml new file mode 100644 index 0000000000000..1ade5942b7261 --- /dev/null +++ b/packages/SubscribedFeedsProvider/res/values-de/strings.xml @@ -0,0 +1,19 @@ + + + + "Feedsynchronisierung" + diff --git a/packages/SubscribedFeedsProvider/res/values-es/strings.xml b/packages/SubscribedFeedsProvider/res/values-es/strings.xml new file mode 100644 index 0000000000000..86c6946911235 --- /dev/null +++ b/packages/SubscribedFeedsProvider/res/values-es/strings.xml @@ -0,0 +1,19 @@ + + + + "Sincronización de feeds" + diff --git a/packages/SubscribedFeedsProvider/res/values-fr/strings.xml b/packages/SubscribedFeedsProvider/res/values-fr/strings.xml new file mode 100644 index 0000000000000..924b960672229 --- /dev/null +++ b/packages/SubscribedFeedsProvider/res/values-fr/strings.xml @@ -0,0 +1,19 @@ + + + + "Synchronisation des flux" + diff --git a/packages/SubscribedFeedsProvider/res/values-it/strings.xml b/packages/SubscribedFeedsProvider/res/values-it/strings.xml new file mode 100644 index 0000000000000..eabb17e5d98c7 --- /dev/null +++ b/packages/SubscribedFeedsProvider/res/values-it/strings.xml @@ -0,0 +1,19 @@ + + + + "Sincronizzazione feed" + diff --git a/packages/SubscribedFeedsProvider/res/values-nl/strings.xml b/packages/SubscribedFeedsProvider/res/values-nl/strings.xml new file mode 100644 index 0000000000000..b9e82d1dcb0c7 --- /dev/null +++ b/packages/SubscribedFeedsProvider/res/values-nl/strings.xml @@ -0,0 +1,19 @@ + + + + "Feeds synchroniseren" + diff --git a/packages/SubscribedFeedsProvider/res/values-pl/strings.xml b/packages/SubscribedFeedsProvider/res/values-pl/strings.xml new file mode 100644 index 0000000000000..02da9f3c01942 --- /dev/null +++ b/packages/SubscribedFeedsProvider/res/values-pl/strings.xml @@ -0,0 +1,19 @@ + + + + "Synchronizowanie kanałów" + diff --git a/packages/SubscribedFeedsProvider/res/values-zh-rTW/strings.xml b/packages/SubscribedFeedsProvider/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000000..e6643cd610a3a --- /dev/null +++ b/packages/SubscribedFeedsProvider/res/values-zh-rTW/strings.xml @@ -0,0 +1,19 @@ + + + + "同步資訊提供" + diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp index 1958ba936946d..99d7723b98cdb 100644 --- a/packages/TtsService/jni/android_tts_SynthProxy.cpp +++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp @@ -33,6 +33,8 @@ #define DEFAULT_TTS_FORMAT AudioSystem::PCM_16_BIT #define DEFAULT_TTS_NB_CHANNELS 1 #define DEFAULT_TTS_BUFFERSIZE 1024 +// TODO use the TTS stream type when available +#define DEFAULT_TTS_STREAM_TYPE AudioSystem::MUSIC #define USAGEMODE_PLAY_IMMEDIATELY 0 #define USAGEMODE_WRITE_TO_FILE 1 @@ -46,22 +48,28 @@ struct fields_t { jmethodID synthProxyMethodPost; }; +// structure to hold the data that is used each time the TTS engine has synthesized more data struct afterSynthData_t { jint jniStorage; int usageMode; FILE* outputFile; + AudioSystem::stream_type streamType; }; // ---------------------------------------------------------------------------- static fields_t javaTTSFields; +// TODO move to synth member once we have multiple simultaneous engines running +static Mutex engineMutex; + // ---------------------------------------------------------------------------- class SynthProxyJniStorage { public : - //jclass tts_class; jobject tts_ref; TtsEngine* mNativeSynthInterface; + void* mEngineLibHandle; AudioTrack* mAudioOut; + AudioSystem::stream_type mStreamType; uint32_t mSampleRate; AudioSystem::audio_format mAudFormat; int mNbChannels; @@ -69,23 +77,31 @@ class SynthProxyJniStorage { size_t mBufferSize; SynthProxyJniStorage() { - //tts_class = NULL; tts_ref = NULL; mNativeSynthInterface = NULL; + mEngineLibHandle = NULL; mAudioOut = NULL; + mStreamType = DEFAULT_TTS_STREAM_TYPE; mSampleRate = DEFAULT_TTS_RATE; mAudFormat = DEFAULT_TTS_FORMAT; mNbChannels = DEFAULT_TTS_NB_CHANNELS; mBufferSize = DEFAULT_TTS_BUFFERSIZE; mBuffer = new int8_t[mBufferSize]; + memset(mBuffer, 0, mBufferSize); } ~SynthProxyJniStorage() { + //LOGV("entering ~SynthProxyJniStorage()"); killAudio(); if (mNativeSynthInterface) { mNativeSynthInterface->shutdown(); mNativeSynthInterface = NULL; } + if (mEngineLibHandle) { + //LOGE("~SynthProxyJniStorage(): before close library"); + int res = dlclose(mEngineLibHandle); + LOGE_IF( res != 0, "~SynthProxyJniStorage(): dlclose returned %d", res); + } delete mBuffer; } @@ -97,66 +113,66 @@ class SynthProxyJniStorage { } } - void createAudioOut(uint32_t rate, AudioSystem::audio_format format, - int channel) { + void createAudioOut(AudioSystem::stream_type streamType, uint32_t rate, + AudioSystem::audio_format format, int channel) { mSampleRate = rate; mAudFormat = format; mNbChannels = channel; - // TODO use the TTS stream type - int streamType = AudioSystem::MUSIC; + mStreamType = streamType; // retrieve system properties to ensure successful creation of the // AudioTrack object for playback int afSampleRate; - if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { + if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) { afSampleRate = 44100; } int afFrameCount; - if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { + if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) { afFrameCount = 2048; } uint32_t afLatency; - if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) { + if (AudioSystem::getOutputLatency(&afLatency, mStreamType) != NO_ERROR) { afLatency = 500; } uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); if (minBufCount < 2) minBufCount = 2; int minFrameCount = (afFrameCount * rate * minBufCount)/afSampleRate; - mAudioOut = new AudioTrack(streamType, rate, format, channel, + mAudioOut = new AudioTrack(mStreamType, rate, format, channel, minFrameCount > 4096 ? minFrameCount : 4096, 0, 0, 0, 0); // not using an AudioTrack callback if (mAudioOut->initCheck() != NO_ERROR) { - LOGI("AudioTrack error"); + LOGE("createAudioOut(): AudioTrack error"); delete mAudioOut; mAudioOut = NULL; } else { //LOGI("AudioTrack OK"); + mAudioOut->setVolume(2.0f, 2.0f); mAudioOut->start(); - LOGI("AudioTrack started"); + LOGV("AudioTrack started"); } } }; // ---------------------------------------------------------------------------- -void prepAudioTrack(SynthProxyJniStorage* pJniData, - uint32_t rate, AudioSystem::audio_format format, int channel) -{ +void prepAudioTrack(SynthProxyJniStorage* pJniData, AudioSystem::stream_type streamType, + uint32_t rate, AudioSystem::audio_format format, int channel) { // Don't bother creating a new audiotrack object if the current - // object is already set. + // object is already initialized with the same audio parameters. if ( pJniData->mAudioOut && (rate == pJniData->mSampleRate) && (format == pJniData->mAudFormat) && - (channel == pJniData->mNbChannels) ){ + (channel == pJniData->mNbChannels) && + (streamType == pJniData->mStreamType) ){ return; } if (pJniData->mAudioOut){ pJniData->killAudio(); } - pJniData->createAudioOut(rate, format, channel); + pJniData->createAudioOut(streamType, rate, format, channel); } @@ -186,9 +202,10 @@ static tts_callback_status ttsSynthDoneCB(void *& userdata, uint32_t rate, } if (bufferSize > 0) { - prepAudioTrack(pJniData, rate, format, channel); + prepAudioTrack(pJniData, pForAfter->streamType, rate, format, channel); if (pJniData->mAudioOut) { pJniData->mAudioOut->write(wav, bufferSize); + memset(wav, 0, bufferSize); //LOGV("AudioTrack wrote: %d bytes", bufferSize); } else { LOGE("Can't play, null audiotrack"); @@ -203,6 +220,7 @@ static tts_callback_status ttsSynthDoneCB(void *& userdata, uint32_t rate, } if (bufferSize > 0){ fwrite(wav, 1, bufferSize, pForAfter->outputFile); + memset(wav, 0, bufferSize); } } // Future update: @@ -241,23 +259,25 @@ android_tts_SynthProxy_native_setup(JNIEnv *env, jobject thiz, SynthProxyJniStorage* pJniStorage = new SynthProxyJniStorage(); prepAudioTrack(pJniStorage, - DEFAULT_TTS_RATE, DEFAULT_TTS_FORMAT, DEFAULT_TTS_NB_CHANNELS); + DEFAULT_TTS_STREAM_TYPE, DEFAULT_TTS_RATE, DEFAULT_TTS_FORMAT, DEFAULT_TTS_NB_CHANNELS); const char *nativeSoLibNativeString = env->GetStringUTFChars(nativeSoLib, 0); void *engine_lib_handle = dlopen(nativeSoLibNativeString, RTLD_NOW | RTLD_LOCAL); - if (engine_lib_handle==NULL) { - LOGI("engine_lib_handle==NULL"); + if (engine_lib_handle == NULL) { + LOGE("android_tts_SynthProxy_native_setup(): engine_lib_handle == NULL"); // TODO report error so the TTS can't be used } else { TtsEngine *(*get_TtsEngine)() = reinterpret_cast(dlsym(engine_lib_handle, "getTtsEngine")); pJniStorage->mNativeSynthInterface = (*get_TtsEngine)(); + pJniStorage->mEngineLibHandle = engine_lib_handle; if (pJniStorage->mNativeSynthInterface) { + Mutex::Autolock l(engineMutex); pJniStorage->mNativeSynthInterface->init(ttsSynthDoneCB); } } @@ -276,10 +296,29 @@ android_tts_SynthProxy_native_setup(JNIEnv *env, jobject thiz, static void android_tts_SynthProxy_native_finalize(JNIEnv *env, jobject thiz, jint jniData) { - if (jniData) { - SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData; - delete pSynthData; + //LOGV("entering android_tts_SynthProxy_finalize()"); + if (jniData == 0) { + //LOGE("android_tts_SynthProxy_native_finalize(): invalid JNI data"); + return; } + + Mutex::Autolock l(engineMutex); + + SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData; + env->DeleteGlobalRef(pSynthData->tts_ref); + delete pSynthData; + + env->SetIntField(thiz, javaTTSFields.synthProxyFieldJniData, 0); +} + + +static void +android_tts_SynthProxy_shutdown(JNIEnv *env, jobject thiz, jint jniData) +{ + //LOGV("entering android_tts_SynthProxy_shutdown()"); + + // do everything a call to finalize would + android_tts_SynthProxy_native_finalize(env, thiz, jniData); } @@ -321,6 +360,8 @@ android_tts_SynthProxy_setLanguage(JNIEnv *env, jobject thiz, jint jniData, return result; } + Mutex::Autolock l(engineMutex); + SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData; const char *langNativeString = env->GetStringUTFChars(language, 0); const char *countryNativeString = env->GetStringUTFChars(country, 0); @@ -380,6 +421,8 @@ android_tts_SynthProxy_setSpeechRate(JNIEnv *env, jobject thiz, jint jniData, char buffer [bufSize]; sprintf(buffer, "%d", speechRate); + Mutex::Autolock l(engineMutex); + SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData; LOGI("setting speech rate to %d", speechRate); @@ -402,6 +445,8 @@ android_tts_SynthProxy_setPitch(JNIEnv *env, jobject thiz, jint jniData, return result; } + Mutex::Autolock l(engineMutex); + int bufSize = 10; char buffer [bufSize]; sprintf(buffer, "%d", pitch); @@ -434,6 +479,8 @@ android_tts_SynthProxy_synthesizeToFile(JNIEnv *env, jobject thiz, jint jniData, return result; } + Mutex::Autolock l(engineMutex); + // Retrieve audio parameters before writing the file header AudioSystem::audio_format encoding = DEFAULT_TTS_FORMAT; uint32_t rate = DEFAULT_TTS_RATE; @@ -468,6 +515,7 @@ android_tts_SynthProxy_synthesizeToFile(JNIEnv *env, jobject thiz, jint jniData, unsigned int unique_identifier; + memset(pSynthData->mBuffer, 0, pSynthData->mBufferSize); result = pSynthData->mNativeSynthInterface->synthesizeText(textNativeString, pSynthData->mBuffer, pSynthData->mBufferSize, (void *)pForAfter); @@ -526,7 +574,7 @@ android_tts_SynthProxy_synthesizeToFile(JNIEnv *env, jobject thiz, jint jniData, static int android_tts_SynthProxy_speak(JNIEnv *env, jobject thiz, jint jniData, - jstring textJavaString) + jstring textJavaString, jint javaStreamType) { int result = TTS_FAILURE; @@ -535,19 +583,22 @@ android_tts_SynthProxy_speak(JNIEnv *env, jobject thiz, jint jniData, return result; } + Mutex::Autolock l(engineMutex); + SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData; if (pSynthData->mAudioOut) { - pSynthData->mAudioOut->stop(); pSynthData->mAudioOut->start(); } afterSynthData_t* pForAfter = new (afterSynthData_t); pForAfter->jniStorage = jniData; pForAfter->usageMode = USAGEMODE_PLAY_IMMEDIATELY; + pForAfter->streamType = (AudioSystem::stream_type) javaStreamType; if (pSynthData->mNativeSynthInterface) { const char *textNativeString = env->GetStringUTFChars(textJavaString, 0); + memset(pSynthData->mBuffer, 0, pSynthData->mBufferSize); result = pSynthData->mNativeSynthInterface->synthesizeText(textNativeString, pSynthData->mBuffer, pSynthData->mBufferSize, (void *)pForAfter); env->ReleaseStringUTFChars(textJavaString, textNativeString); @@ -569,51 +620,17 @@ android_tts_SynthProxy_stop(JNIEnv *env, jobject thiz, jint jniData) SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData; - if (pSynthData->mNativeSynthInterface) { - result = pSynthData->mNativeSynthInterface->stop(); - } if (pSynthData->mAudioOut) { pSynthData->mAudioOut->stop(); } + if (pSynthData->mNativeSynthInterface) { + result = pSynthData->mNativeSynthInterface->stop(); + } return result; } -static void -android_tts_SynthProxy_shutdown(JNIEnv *env, jobject thiz, jint jniData) -{ - if (jniData == 0) { - LOGE("android_tts_SynthProxy_shutdown(): invalid JNI data"); - return; - } - - SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData; - if (pSynthData->mNativeSynthInterface) { - pSynthData->mNativeSynthInterface->shutdown(); - pSynthData->mNativeSynthInterface = NULL; - } -} - - -// TODO add buffer format -static void -android_tts_SynthProxy_playAudioBuffer(JNIEnv *env, jobject thiz, jint jniData, - int bufferPointer, int bufferSize) -{ -LOGI("android_tts_SynthProxy_playAudioBuffer"); - if (jniData == 0) { - LOGE("android_tts_SynthProxy_playAudioBuffer(): invalid JNI data"); - return; - } - - SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData; - short* wav = (short*) bufferPointer; - pSynthData->mAudioOut->write(wav, bufferSize); - //LOGI("AudioTrack wrote: %d bytes", bufferSize); -} - - static jobjectArray android_tts_SynthProxy_getLanguage(JNIEnv *env, jobject thiz, jint jniData) { @@ -672,7 +689,7 @@ static JNINativeMethod gMethods[] = { (void*)android_tts_SynthProxy_stop }, { "native_speak", - "(ILjava/lang/String;)I", + "(ILjava/lang/String;I)I", (void*)android_tts_SynthProxy_speak }, { "native_synthesizeToFile", @@ -699,10 +716,6 @@ static JNINativeMethod gMethods[] = { "(II)I", (void*)android_tts_SynthProxy_setPitch }, - { "native_playAudioBuffer", - "(III)V", - (void*)android_tts_SynthProxy_playAudioBuffer - }, { "native_getLanguage", "(I)[Ljava/lang/String;", (void*)android_tts_SynthProxy_getLanguage diff --git a/packages/TtsService/src/android/tts/SynthProxy.java b/packages/TtsService/src/android/tts/SynthProxy.java index bb16b14dbcebe..a0814aa912a20 100755 --- a/packages/TtsService/src/android/tts/SynthProxy.java +++ b/packages/TtsService/src/android/tts/SynthProxy.java @@ -15,6 +15,8 @@ */ package android.tts; +import android.media.AudioManager; +import android.media.AudioSystem; import android.util.Log; import java.lang.ref.WeakReference; @@ -52,8 +54,13 @@ public class SynthProxy { /** * Synthesize speech and speak it directly using AudioTrack. */ - public int speak(String text) { - return native_speak(mJniData, text); + public int speak(String text, int streamType) { + if ((streamType > -1) && (streamType < AudioSystem.getNumStreamTypes())) { + return native_speak(mJniData, text, streamType); + } else { + Log.e("SynthProxy", "Trying to speak with invalid stream type " + streamType); + return native_speak(mJniData, text, AudioManager.STREAM_MUSIC); + } } /** @@ -101,13 +108,6 @@ public class SynthProxy { return native_setPitch(mJniData, pitch); } - /** - * Plays the given audio buffer. - */ - public void playAudioBuffer(int bufferPointer, int bufferSize) { - native_playAudioBuffer(mJniData, bufferPointer, bufferSize); - } - /** * Returns the currently set language, country and variant information. */ @@ -156,7 +156,7 @@ public class SynthProxy { private native final int native_stop(int jniData); - private native final int native_speak(int jniData, String text); + private native final int native_speak(int jniData, String text, int streamType); private native final int native_synthesizeToFile(int jniData, String text, String filename); @@ -173,9 +173,6 @@ public class SynthProxy { private native final int native_setPitch(int jniData, int speechRate); - // TODO add buffer format - private native final void native_playAudioBuffer(int jniData, int bufferPointer, int bufferSize); - private native final String[] native_getLanguage(int jniData); private native final int native_getRate(int jniData); diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java index a713edf0bd898..e52ba80eefa47 100755 --- a/packages/TtsService/src/android/tts/TtsService.java +++ b/packages/TtsService/src/android/tts/TtsService.java @@ -22,6 +22,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.net.Uri; @@ -38,6 +39,8 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Locale; import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.TimeUnit; + /** * @hide Synthesizes speech from text. This is implemented as a service so that @@ -57,23 +60,29 @@ public class TtsService extends Service implements OnCompletionListener { public int mType = TEXT; public long mDuration = 0; public String mFilename = null; + public String mCallingApp = ""; - public SpeechItem(String text, ArrayList params, int itemType) { + public SpeechItem(String source, String text, ArrayList params, int itemType) { mText = text; mParams = params; mType = itemType; + mCallingApp = source; } - public SpeechItem(long silenceTime) { + public SpeechItem(String source, long silenceTime, ArrayList params) { mDuration = silenceTime; + mParams = params; mType = SILENCE; + mCallingApp = source; } - public SpeechItem(String text, ArrayList params, int itemType, String filename) { + public SpeechItem(String source, String text, ArrayList params, + int itemType, String filename) { mText = text; mParams = params; mType = itemType; mFilename = filename; + mCallingApp = source; } } @@ -103,18 +112,26 @@ public class TtsService extends Service implements OnCompletionListener { private static final int MAX_SPEECH_ITEM_CHAR_LENGTH = 4000; private static final int MAX_FILENAME_LENGTH = 250; + // TODO use the TTS stream type when available + private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_MUSIC; private static final String ACTION = "android.intent.action.START_TTS_SERVICE"; private static final String CATEGORY = "android.intent.category.TTS"; private static final String PKGNAME = "android.tts"; - final RemoteCallbackList mCallbacks = new RemoteCallbackList(); + private final RemoteCallbackList mCallbacks + = new RemoteCallbackList(); + + private HashMap mCallbacksMap; private Boolean mIsSpeaking; private ArrayList mSpeechQueue; private HashMap mEarcons; private HashMap mUtterances; private MediaPlayer mPlayer; + private SpeechItem mCurrentSpeechItem; + private HashMap mKillList; // Used to ensure that in-flight synth calls + // are killed when stop is used. private TtsService mSelf; private ContentResolver mResolver; @@ -122,25 +139,30 @@ public class TtsService extends Service implements OnCompletionListener { private final ReentrantLock speechQueueLock = new ReentrantLock(); private final ReentrantLock synthesizerLock = new ReentrantLock(); - private SynthProxy nativeSynth; + private static SynthProxy sNativeSynth = null; @Override public void onCreate() { super.onCreate(); - //Log.i("TTS", "TTS starting"); + Log.i("TtsService", "TtsService.onCreate()"); mResolver = getContentResolver(); String soLibPath = "/system/lib/libttspico.so"; - nativeSynth = new SynthProxy(soLibPath); + if (sNativeSynth == null) { + sNativeSynth = new SynthProxy(soLibPath); + } mSelf = this; mIsSpeaking = false; mEarcons = new HashMap(); mUtterances = new HashMap(); + mCallbacksMap = new HashMap(); mSpeechQueue = new ArrayList(); mPlayer = null; + mCurrentSpeechItem = null; + mKillList = new HashMap(); setDefaultSettings(); } @@ -151,7 +173,8 @@ public class TtsService extends Service implements OnCompletionListener { // Don't hog the media player cleanUpPlayer(); - nativeSynth.shutdown(); + sNativeSynth.shutdown(); + sNativeSynth = null; // Unregister all callbacks. mCallbacks.kill(); @@ -159,10 +182,10 @@ public class TtsService extends Service implements OnCompletionListener { private void setDefaultSettings() { - setLanguage(this.getDefaultLanguage(), getDefaultCountry(), getDefaultLocVariant()); + setLanguage("", this.getDefaultLanguage(), getDefaultCountry(), getDefaultLocVariant()); // speech rate - setSpeechRate(getDefaultRate()); + setSpeechRate("", getDefaultRate()); } @@ -217,38 +240,38 @@ public class TtsService extends Service implements OnCompletionListener { } - private int setSpeechRate(int rate) { + private int setSpeechRate(String callingApp, int rate) { if (isDefaultEnforced()) { - return nativeSynth.setSpeechRate(getDefaultRate()); + return sNativeSynth.setSpeechRate(getDefaultRate()); } else { - return nativeSynth.setSpeechRate(rate); + return sNativeSynth.setSpeechRate(rate); } } - private int setPitch(int pitch) { - return nativeSynth.setPitch(pitch); + private int setPitch(String callingApp, int pitch) { + return sNativeSynth.setPitch(pitch); } private int isLanguageAvailable(String lang, String country, String variant) { - //Log.v("TTS", "TtsService.isLanguageAvailable(" + lang + ", " + country + ", " +variant+")"); - return nativeSynth.isLanguageAvailable(lang, country, variant); + //Log.v("TtsService", "TtsService.isLanguageAvailable(" + lang + ", " + country + ", " +variant+")"); + return sNativeSynth.isLanguageAvailable(lang, country, variant); } private String[] getLanguage() { - return nativeSynth.getLanguage(); + return sNativeSynth.getLanguage(); } - private int setLanguage(String lang, String country, String variant) { - //Log.v("TTS", "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")"); + private int setLanguage(String callingApp, String lang, String country, String variant) { + Log.v("TtsService", "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")"); if (isDefaultEnforced()) { - return nativeSynth.setLanguage(getDefaultLanguage(), getDefaultCountry(), + return sNativeSynth.setLanguage(getDefaultLanguage(), getDefaultCountry(), getDefaultLocVariant()); } else { - return nativeSynth.setLanguage(lang, country, variant); + return sNativeSynth.setLanguage(lang, country, variant); } } @@ -263,7 +286,7 @@ public class TtsService extends Service implements OnCompletionListener { * @param resId * The resource ID of the sound within its package */ - private void addSpeech(String text, String packageName, int resId) { + private void addSpeech(String callingApp, String text, String packageName, int resId) { mUtterances.put(text, new SoundResource(packageName, resId)); } @@ -276,7 +299,7 @@ public class TtsService extends Service implements OnCompletionListener { * The filename of the sound resource. This must be a complete * path like: (/sdcard/mysounds/mysoundbite.mp3). */ - private void addSpeech(String text, String filename) { + private void addSpeech(String callingApp, String text, String filename) { mUtterances.put(text, new SoundResource(filename)); } @@ -290,7 +313,7 @@ public class TtsService extends Service implements OnCompletionListener { * @param resId * The resource ID of the sound within its package */ - private void addEarcon(String earcon, String packageName, int resId) { + private void addEarcon(String callingApp, String earcon, String packageName, int resId) { mEarcons.put(earcon, new SoundResource(packageName, resId)); } @@ -303,7 +326,7 @@ public class TtsService extends Service implements OnCompletionListener { * The filename of the sound resource. This must be a complete * path like: (/sdcard/mysounds/mysoundbite.mp3). */ - private void addEarcon(String earcon, String filename) { + private void addEarcon(String callingApp, String earcon, String filename) { mEarcons.put(earcon, new SoundResource(filename)); } @@ -313,17 +336,20 @@ public class TtsService extends Service implements OnCompletionListener { * @param text * The text that should be spoken * @param queueMode - * 0 for no queue (interrupts all previous utterances), 1 for - * queued + * TextToSpeech.TTS_QUEUE_FLUSH for no queue (interrupts all previous utterances), + * TextToSpeech.TTS_QUEUE_ADD for queued * @param params * An ArrayList of parameters. This is not implemented for all * engines. */ - private int speak(String text, int queueMode, ArrayList params) { - if (queueMode == 0) { - stop(); + private int speak(String callingApp, String text, int queueMode, ArrayList params) { + Log.v("TtsService", "TTS service received " + text); + if (queueMode == TextToSpeech.TTS_QUEUE_FLUSH) { + stop(callingApp); + } else if (queueMode == 2) { + stopAll(callingApp); } - mSpeechQueue.add(new SpeechItem(text, params, SpeechItem.TEXT)); + mSpeechQueue.add(new SpeechItem(callingApp, text, params, SpeechItem.TEXT)); if (!mIsSpeaking) { processSpeechQueue(); } @@ -336,18 +362,20 @@ public class TtsService extends Service implements OnCompletionListener { * @param earcon * The earcon that should be played * @param queueMode - * 0 for no queue (interrupts all previous utterances), 1 for - * queued + * TextToSpeech.TTS_QUEUE_FLUSH for no queue (interrupts all previous utterances), + * TextToSpeech.TTS_QUEUE_ADD for queued * @param params * An ArrayList of parameters. This is not implemented for all * engines. */ - private int playEarcon(String earcon, int queueMode, + private int playEarcon(String callingApp, String earcon, int queueMode, ArrayList params) { - if (queueMode == 0) { - stop(); + if (queueMode == TextToSpeech.TTS_QUEUE_FLUSH) { + stop(callingApp); + } else if (queueMode == 2) { + stopAll(callingApp); } - mSpeechQueue.add(new SpeechItem(earcon, params, SpeechItem.EARCON)); + mSpeechQueue.add(new SpeechItem(callingApp, earcon, params, SpeechItem.EARCON)); if (!mIsSpeaking) { processSpeechQueue(); } @@ -355,49 +383,153 @@ public class TtsService extends Service implements OnCompletionListener { } /** - * Stops all speech output and removes any utterances still in the queue. + * Stops all speech output and removes any utterances still in the queue for the calling app. */ - private int stop() { - Log.i("TTS", "Stopping"); - mSpeechQueue.clear(); - - int result = nativeSynth.stop(); - mIsSpeaking = false; - if (mPlayer != null) { - try { - mPlayer.stop(); - } catch (IllegalStateException e) { - // Do nothing, the player is already stopped. + private int stop(String callingApp) { + int result = TextToSpeech.TTS_ERROR; + boolean speechQueueAvailable = false; + try{ + // If the queue is locked for more than 1 second, + // something has gone very wrong with processSpeechQueue. + speechQueueAvailable = speechQueueLock.tryLock(1000, TimeUnit.MILLISECONDS); + if (speechQueueAvailable) { + Log.i("TtsService", "Stopping"); + for (int i = mSpeechQueue.size() - 1; i > -1; i--){ + if (mSpeechQueue.get(i).mCallingApp.equals(callingApp)){ + mSpeechQueue.remove(i); + } + } + if ((mCurrentSpeechItem != null) && + mCurrentSpeechItem.mCallingApp.equals(callingApp)) { + result = sNativeSynth.stop(); + mKillList.put(mCurrentSpeechItem, true); + if (mPlayer != null) { + try { + mPlayer.stop(); + } catch (IllegalStateException e) { + // Do nothing, the player is already stopped. + } + } + mIsSpeaking = false; + mCurrentSpeechItem = null; + } else { + result = TextToSpeech.TTS_SUCCESS; + } + Log.i("TtsService", "Stopped"); } + } catch (InterruptedException e) { + Log.e("TtsService", "TTS stop: tryLock interrupted"); + e.printStackTrace(); + } finally { + // This check is needed because finally will always run; even if the + // method returns somewhere in the try block. + if (speechQueueAvailable) { + speechQueueLock.unlock(); + } + return result; + } + } + + + + /** + * Stops all speech output and removes any utterances still in the queue globally. + */ + private int stopAll(String callingApp) { + int result = TextToSpeech.TTS_ERROR; + boolean speechQueueAvailable = false; + try{ + // If the queue is locked for more than 1 second, + // something has gone very wrong with processSpeechQueue. + speechQueueAvailable = speechQueueLock.tryLock(1000, TimeUnit.MILLISECONDS); + if (speechQueueAvailable) { + for (int i = mSpeechQueue.size() - 1; i > -1; i--){ + if (mSpeechQueue.get(i).mType != SpeechItem.TEXT_TO_FILE){ + mSpeechQueue.remove(i); + } + } + if ((mCurrentSpeechItem != null) && + ((mCurrentSpeechItem.mType != SpeechItem.TEXT_TO_FILE) || + mCurrentSpeechItem.mCallingApp.equals(callingApp))) { + result = sNativeSynth.stop(); + mKillList.put(mCurrentSpeechItem, true); + if (mPlayer != null) { + try { + mPlayer.stop(); + } catch (IllegalStateException e) { + // Do nothing, the player is already stopped. + } + } + mIsSpeaking = false; + mCurrentSpeechItem = null; + } else { + result = TextToSpeech.TTS_SUCCESS; + } + Log.i("TtsService", "Stopped all"); + } + } catch (InterruptedException e) { + Log.e("TtsService", "TTS stopAll: tryLock interrupted"); + e.printStackTrace(); + } finally { + // This check is needed because finally will always run; even if the + // method returns somewhere in the try block. + if (speechQueueAvailable) { + speechQueueLock.unlock(); + } + return result; } - Log.i("TTS", "Stopped"); - return result; } public void onCompletion(MediaPlayer arg0) { + String callingApp = mCurrentSpeechItem.mCallingApp; + ArrayList params = mCurrentSpeechItem.mParams; + String utteranceId = ""; + if (params != null){ + for (int i = 0; i < params.size() - 1; i = i + 2){ + String param = params.get(i); + if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){ + utteranceId = params.get(i+1); + } + } + } + if (utteranceId.length() > 0){ + dispatchUtteranceCompletedCallback(utteranceId, callingApp); + } processSpeechQueue(); } - private int playSilence(long duration, int queueMode, + private int playSilence(String callingApp, long duration, int queueMode, ArrayList params) { - if (queueMode == 0) { - stop(); + if (queueMode == TextToSpeech.TTS_QUEUE_FLUSH) { + stop(callingApp); } - mSpeechQueue.add(new SpeechItem(duration)); + mSpeechQueue.add(new SpeechItem(callingApp, duration, params)); if (!mIsSpeaking) { processSpeechQueue(); } return TextToSpeech.TTS_SUCCESS; } - private void silence(final long duration) { + private void silence(final SpeechItem speechItem) { class SilenceThread implements Runnable { public void run() { + String utteranceId = ""; + if (speechItem.mParams != null){ + for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){ + String param = speechItem.mParams.get(i); + if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){ + utteranceId = speechItem.mParams.get(i+1); + } + } + } try { - Thread.sleep(duration); + Thread.sleep(speechItem.mDuration); } catch (InterruptedException e) { e.printStackTrace(); } finally { + if (utteranceId.length() > 0){ + dispatchUtteranceCompletedCallback(utteranceId, speechItem.mCallingApp); + } processSpeechQueue(); } } @@ -407,47 +539,70 @@ public class TtsService extends Service implements OnCompletionListener { slnc.start(); } - private void speakInternalOnly(final String text, - final ArrayList params) { + private void speakInternalOnly(final SpeechItem speechItem) { class SynthThread implements Runnable { public void run() { boolean synthAvailable = false; + String utteranceId = ""; try { synthAvailable = synthesizerLock.tryLock(); if (!synthAvailable) { Thread.sleep(100); Thread synth = (new Thread(new SynthThread())); - synth.setPriority(Thread.MIN_PRIORITY); + //synth.setPriority(Thread.MIN_PRIORITY); synth.start(); return; } - if (params != null){ - String language = ""; - String country = ""; - String variant = ""; - for (int i = 0; i < params.size() - 1; i = i + 2){ - String param = params.get(i); - if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_RATE)){ - setSpeechRate(Integer.parseInt(params.get(i+1))); - } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_LANGUAGE)){ - language = params.get(i+1); - } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_COUNTRY)){ - country = params.get(i+1); - } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_VARIANT)){ - variant = params.get(i+1); + int streamType = DEFAULT_STREAM_TYPE; + String language = ""; + String country = ""; + String variant = ""; + String speechRate = ""; + if (speechItem.mParams != null){ + for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){ + String param = speechItem.mParams.get(i); + if (param != null) { + if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_RATE)) { + speechRate = speechItem.mParams.get(i+1); + } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_LANGUAGE)){ + language = speechItem.mParams.get(i+1); + } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_COUNTRY)){ + country = speechItem.mParams.get(i+1); + } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_VARIANT)){ + variant = speechItem.mParams.get(i+1); + } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){ + utteranceId = speechItem.mParams.get(i+1); + } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_STREAM)) { + try { + streamType + = Integer.parseInt(speechItem.mParams.get(i + 1)); + } catch (NumberFormatException e) { + streamType = DEFAULT_STREAM_TYPE; + } + } } } - if (language.length() > 0){ - setLanguage(language, country, variant); - } } - nativeSynth.speak(text); + // Only do the synthesis if it has not been killed by a subsequent utterance. + if (mKillList.get(speechItem) == null) { + if (language.length() > 0){ + setLanguage("", language, country, variant); + } + if (speechRate.length() > 0){ + setSpeechRate("", Integer.parseInt(speechRate)); + } + sNativeSynth.speak(speechItem.mText, streamType); + } } catch (InterruptedException e) { + Log.e("TtsService", "TTS speakInternalOnly(): tryLock interrupted"); e.printStackTrace(); } finally { // This check is needed because finally will always run; // even if the // method returns somewhere in the try block. + if (utteranceId.length() > 0){ + dispatchUtteranceCompletedCallback(utteranceId, speechItem.mCallingApp); + } if (synthAvailable) { synthesizerLock.unlock(); } @@ -456,52 +611,67 @@ public class TtsService extends Service implements OnCompletionListener { } } Thread synth = (new Thread(new SynthThread())); - synth.setPriority(Thread.MIN_PRIORITY); + //synth.setPriority(Thread.MIN_PRIORITY); synth.start(); } - private void synthToFileInternalOnly(final String text, - final ArrayList params, final String filename) { + private void synthToFileInternalOnly(final SpeechItem speechItem) { class SynthThread implements Runnable { public void run() { - Log.i("TTS", "Synthesizing to " + filename); boolean synthAvailable = false; + String utteranceId = ""; + Log.i("TtsService", "Synthesizing to " + speechItem.mFilename); try { synthAvailable = synthesizerLock.tryLock(); if (!synthAvailable) { Thread.sleep(100); Thread synth = (new Thread(new SynthThread())); - synth.setPriority(Thread.MIN_PRIORITY); + //synth.setPriority(Thread.MIN_PRIORITY); synth.start(); return; } - if (params != null){ - String language = ""; - String country = ""; - String variant = ""; - for (int i = 0; i < params.size() - 1; i = i + 2){ - String param = params.get(i); - if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_RATE)){ - setSpeechRate(Integer.parseInt(params.get(i+1))); - } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_LANGUAGE)){ - language = params.get(i+1); - } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_COUNTRY)){ - country = params.get(i+1); - } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_VARIANT)){ - variant = params.get(i+1); + String language = ""; + String country = ""; + String variant = ""; + String speechRate = ""; + if (speechItem.mParams != null){ + for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){ + String param = speechItem.mParams.get(i); + if (param != null) { + if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_RATE)) { + speechRate = speechItem.mParams.get(i+1); + } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_LANGUAGE)){ + language = speechItem.mParams.get(i+1); + } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_COUNTRY)){ + country = speechItem.mParams.get(i+1); + } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_VARIANT)){ + variant = speechItem.mParams.get(i+1); + } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){ + utteranceId = speechItem.mParams.get(i+1); + } } } - if (language.length() > 0){ - setLanguage(language, country, variant); - } } - nativeSynth.synthesizeToFile(text, filename); + // Only do the synthesis if it has not been killed by a subsequent utterance. + if (mKillList.get(speechItem) == null){ + if (language.length() > 0){ + setLanguage("", language, country, variant); + } + if (speechRate.length() > 0){ + setSpeechRate("", Integer.parseInt(speechRate)); + } + sNativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename); + } } catch (InterruptedException e) { + Log.e("TtsService", "TTS synthToFileInternalOnly(): tryLock interrupted"); e.printStackTrace(); } finally { // This check is needed because finally will always run; // even if the // method returns somewhere in the try block. + if (utteranceId.length() > 0){ + dispatchUtteranceCompletedCallback(utteranceId, speechItem.mCallingApp); + } if (synthAvailable) { synthesizerLock.unlock(); } @@ -510,7 +680,7 @@ public class TtsService extends Service implements OnCompletionListener { } } Thread synth = (new Thread(new SynthThread())); - synth.setPriority(Thread.MIN_PRIORITY); + //synth.setPriority(Thread.MIN_PRIORITY); synth.start(); } @@ -532,26 +702,30 @@ public class TtsService extends Service implements OnCompletionListener { sendBroadcast(i); } - private void dispatchSpeechCompletedCallbacks(String mark) { - Log.i("TTS callback", "dispatch started"); + + private void dispatchUtteranceCompletedCallback(String utteranceId, String packageName) { + ITtsCallback cb = mCallbacksMap.get(packageName); + if (cb == null){ + return; + } + Log.i("TtsService", "TTS callback: dispatch started"); // Broadcast to all clients the new value. final int N = mCallbacks.beginBroadcast(); - for (int i = 0; i < N; i++) { - try { - mCallbacks.getBroadcastItem(i).markReached(mark); - } catch (RemoteException e) { - // The RemoteCallbackList will take care of removing - // the dead object for us. - } + try { + cb.utteranceCompleted(utteranceId); + } catch (RemoteException e) { + // The RemoteCallbackList will take care of removing + // the dead object for us. } mCallbacks.finishBroadcast(); - Log.i("TTS callback", "dispatch completed to " + N); + Log.i("TtsService", "TTS callback: dispatch completed to " + N); } private SpeechItem splitCurrentTextIfNeeded(SpeechItem currentSpeechItem){ if (currentSpeechItem.mText.length() < MAX_SPEECH_ITEM_CHAR_LENGTH){ return currentSpeechItem; } else { + String callingApp = currentSpeechItem.mCallingApp; ArrayList splitItems = new ArrayList(); int start = 0; int end = start + MAX_SPEECH_ITEM_CHAR_LENGTH - 1; @@ -559,13 +733,13 @@ public class TtsService extends Service implements OnCompletionListener { SpeechItem splitItem; while (end < currentSpeechItem.mText.length()){ splitText = currentSpeechItem.mText.substring(start, end); - splitItem = new SpeechItem(splitText, null, SpeechItem.TEXT); + splitItem = new SpeechItem(callingApp, splitText, null, SpeechItem.TEXT); splitItems.add(splitItem); start = end; end = start + MAX_SPEECH_ITEM_CHAR_LENGTH - 1; } splitText = currentSpeechItem.mText.substring(start); - splitItem = new SpeechItem(splitText, null, SpeechItem.TEXT); + splitItem = new SpeechItem(callingApp, splitText, null, SpeechItem.TEXT); splitItems.add(splitItem); mSpeechQueue.remove(0); for (int i = splitItems.size() - 1; i >= 0; i--){ @@ -588,23 +762,21 @@ public class TtsService extends Service implements OnCompletionListener { return; } - SpeechItem currentSpeechItem = mSpeechQueue.get(0); + mCurrentSpeechItem = mSpeechQueue.get(0); mIsSpeaking = true; - SoundResource sr = getSoundResource(currentSpeechItem); + SoundResource sr = getSoundResource(mCurrentSpeechItem); // Synth speech as needed - synthesizer should call // processSpeechQueue to continue running the queue - Log.i("TTS processing: ", currentSpeechItem.mText); + Log.i("TtsService", "TTS processing: " + mCurrentSpeechItem.mText); if (sr == null) { - if (currentSpeechItem.mType == SpeechItem.TEXT) { - currentSpeechItem = splitCurrentTextIfNeeded(currentSpeechItem); - speakInternalOnly(currentSpeechItem.mText, - currentSpeechItem.mParams); - } else if (currentSpeechItem.mType == SpeechItem.TEXT_TO_FILE) { - synthToFileInternalOnly(currentSpeechItem.mText, - currentSpeechItem.mParams, currentSpeechItem.mFilename); + if (mCurrentSpeechItem.mType == SpeechItem.TEXT) { + mCurrentSpeechItem = splitCurrentTextIfNeeded(mCurrentSpeechItem); + speakInternalOnly(mCurrentSpeechItem); + } else if (mCurrentSpeechItem.mType == SpeechItem.TEXT_TO_FILE) { + synthToFileInternalOnly(mCurrentSpeechItem); } else { // This is either silence or an earcon that was missing - silence(currentSpeechItem.mDuration); + silence(mCurrentSpeechItem); } } else { cleanUpPlayer(); @@ -615,8 +787,7 @@ public class TtsService extends Service implements OnCompletionListener { // Utterance is part of the app calling the library Context ctx; try { - ctx = this.createPackageContext(sr.mSourcePackageName, - 0); + ctx = this.createPackageContext(sr.mSourcePackageName, 0); } catch (NameNotFoundException e) { e.printStackTrace(); mSpeechQueue.remove(0); // Remove it from the queue and @@ -639,6 +810,7 @@ public class TtsService extends Service implements OnCompletionListener { } mPlayer.setOnCompletionListener(this); try { + mPlayer.setAudioStreamType(getStreamTypeFromParams(mCurrentSpeechItem.mParams)); mPlayer.start(); } catch (IllegalStateException e) { mSpeechQueue.clear(); @@ -659,6 +831,24 @@ public class TtsService extends Service implements OnCompletionListener { } } + private int getStreamTypeFromParams(ArrayList paramList) { + int streamType = DEFAULT_STREAM_TYPE; + if (paramList == null) { + return streamType; + } + for (int i = 0; i < paramList.size() - 1; i = i + 2) { + String param = paramList.get(i); + if ((param != null) && (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_STREAM))) { + try { + streamType = Integer.parseInt(paramList.get(i + 1)); + } catch (NumberFormatException e) { + streamType = DEFAULT_STREAM_TYPE; + } + } + } + return streamType; + } + private void cleanUpPlayer() { if (mPlayer != null) { mPlayer.release(); @@ -679,7 +869,7 @@ public class TtsService extends Service implements OnCompletionListener { * something like "/sdcard/myappsounds/mysound.wav". * @return A boolean that indicates if the synthesis succeeded */ - private boolean synthesizeToFile(String text, ArrayList params, + private boolean synthesizeToFile(String callingApp, String text, ArrayList params, String filename) { // Don't allow a filename that is too long if (filename.length() > MAX_FILENAME_LENGTH) { @@ -690,7 +880,7 @@ public class TtsService extends Service implements OnCompletionListener { if (text.length() >= MAX_SPEECH_ITEM_CHAR_LENGTH){ return false; } - mSpeechQueue.add(new SpeechItem(text, params, SpeechItem.TEXT_TO_FILE, filename)); + mSpeechQueue.add(new SpeechItem(callingApp, text, params, SpeechItem.TEXT_TO_FILE, filename)); if (!mIsSpeaking) { processSpeechQueue(); } @@ -711,14 +901,22 @@ public class TtsService extends Service implements OnCompletionListener { private final android.speech.tts.ITts.Stub mBinder = new Stub() { - public void registerCallback(ITtsCallback cb) { - if (cb != null) + public int registerCallback(String packageName, ITtsCallback cb) { + if (cb != null) { mCallbacks.register(cb); + mCallbacksMap.put(packageName, cb); + return TextToSpeech.TTS_SUCCESS; + } + return TextToSpeech.TTS_ERROR; } - public void unregisterCallback(ITtsCallback cb) { - if (cb != null) + public int unregisterCallback(String packageName, ITtsCallback cb) { + if (cb != null) { + mCallbacksMap.remove(packageName); mCallbacks.unregister(cb); + return TextToSpeech.TTS_SUCCESS; + } + return TextToSpeech.TTS_ERROR; } /** @@ -728,18 +926,18 @@ public class TtsService extends Service implements OnCompletionListener { * @param text * The text that should be spoken * @param queueMode - * 0 for no queue (interrupts all previous utterances), 1 for - * queued + * TextToSpeech.TTS_QUEUE_FLUSH for no queue (interrupts all previous utterances) + * TextToSpeech.TTS_QUEUE_ADD for queued * @param params * An ArrayList of parameters. The first element of this * array controls the type of voice to use. */ - public int speak(String text, int queueMode, String[] params) { + public int speak(String callingApp, String text, int queueMode, String[] params) { ArrayList speakingParams = new ArrayList(); if (params != null) { speakingParams = new ArrayList(Arrays.asList(params)); } - return mSelf.speak(text, queueMode, speakingParams); + return mSelf.speak(callingApp, text, queueMode, speakingParams); } /** @@ -748,17 +946,17 @@ public class TtsService extends Service implements OnCompletionListener { * @param earcon * The earcon that should be played * @param queueMode - * 0 for no queue (interrupts all previous utterances), 1 for - * queued + * TextToSpeech.TTS_QUEUE_FLUSH for no queue (interrupts all previous utterances) + * TextToSpeech.TTS_QUEUE_ADD for queued * @param params * An ArrayList of parameters. */ - public int playEarcon(String earcon, int queueMode, String[] params) { + public int playEarcon(String callingApp, String earcon, int queueMode, String[] params) { ArrayList speakingParams = new ArrayList(); if (params != null) { speakingParams = new ArrayList(Arrays.asList(params)); } - return mSelf.playEarcon(earcon, queueMode, speakingParams); + return mSelf.playEarcon(callingApp, earcon, queueMode, speakingParams); } /** @@ -767,25 +965,25 @@ public class TtsService extends Service implements OnCompletionListener { * @param duration * The duration of the silence that should be played * @param queueMode - * 0 for no queue (interrupts all previous utterances), 1 for - * queued + * TextToSpeech.TTS_QUEUE_FLUSH for no queue (interrupts all previous utterances) + * TextToSpeech.TTS_QUEUE_ADD for queued * @param params * An ArrayList of parameters. */ - public int playSilence(long duration, int queueMode, String[] params) { + public int playSilence(String callingApp, long duration, int queueMode, String[] params) { ArrayList speakingParams = new ArrayList(); if (params != null) { speakingParams = new ArrayList(Arrays.asList(params)); } - return mSelf.playSilence(duration, queueMode, speakingParams); + return mSelf.playSilence(callingApp, duration, queueMode, speakingParams); } /** * Stops all speech output and removes any utterances still in the * queue. */ - public int stop() { - return mSelf.stop(); + public int stop(String callingApp) { + return mSelf.stop(callingApp); } /** @@ -807,8 +1005,8 @@ public class TtsService extends Service implements OnCompletionListener { * @param resId * The resource ID of the sound within its package */ - public void addSpeech(String text, String packageName, int resId) { - mSelf.addSpeech(text, packageName, resId); + public void addSpeech(String callingApp, String text, String packageName, int resId) { + mSelf.addSpeech(callingApp, text, packageName, resId); } /** @@ -820,8 +1018,8 @@ public class TtsService extends Service implements OnCompletionListener { * The filename of the sound resource. This must be a * complete path like: (/sdcard/mysounds/mysoundbite.mp3). */ - public void addSpeechFile(String text, String filename) { - mSelf.addSpeech(text, filename); + public void addSpeechFile(String callingApp, String text, String filename) { + mSelf.addSpeech(callingApp, text, filename); } /** @@ -834,8 +1032,8 @@ public class TtsService extends Service implements OnCompletionListener { * @param resId * The resource ID of the sound within its package */ - public void addEarcon(String earcon, String packageName, int resId) { - mSelf.addEarcon(earcon, packageName, resId); + public void addEarcon(String callingApp, String earcon, String packageName, int resId) { + mSelf.addEarcon(callingApp, earcon, packageName, resId); } /** @@ -847,8 +1045,8 @@ public class TtsService extends Service implements OnCompletionListener { * The filename of the sound resource. This must be a * complete path like: (/sdcard/mysounds/mysoundbite.mp3). */ - public void addEarconFile(String earcon, String filename) { - mSelf.addEarcon(earcon, filename); + public void addEarconFile(String callingApp, String earcon, String filename) { + mSelf.addEarcon(callingApp, earcon, filename); } /** @@ -858,8 +1056,8 @@ public class TtsService extends Service implements OnCompletionListener { * @param speechRate * The speech rate that should be used */ - public int setSpeechRate(int speechRate) { - return mSelf.setSpeechRate(speechRate); + public int setSpeechRate(String callingApp, int speechRate) { + return mSelf.setSpeechRate(callingApp, speechRate); } /** @@ -869,8 +1067,8 @@ public class TtsService extends Service implements OnCompletionListener { * @param pitch * The pitch that should be used for the synthesized voice */ - public int setPitch(int pitch) { - return mSelf.setPitch(pitch); + public int setPitch(String callingApp, int pitch) { + return mSelf.setPitch(callingApp, pitch); } /** @@ -904,8 +1102,8 @@ public class TtsService extends Service implements OnCompletionListener { * @param country the three letter ISO country code. * @param variant the variant code associated with the country and language pair. */ - public int setLanguage(String lang, String country, String variant) { - return mSelf.setLanguage(lang, country, variant); + public int setLanguage(String callingApp, String lang, String country, String variant) { + return mSelf.setLanguage(callingApp, lang, country, variant); } /** @@ -922,13 +1120,13 @@ public class TtsService extends Service implements OnCompletionListener { * be something like "/sdcard/myappsounds/mysound.wav". * @return A boolean that indicates if the synthesis succeeded */ - public boolean synthesizeToFile(String text, String[] params, + public boolean synthesizeToFile(String callingApp, String text, String[] params, String filename) { ArrayList speakingParams = new ArrayList(); if (params != null) { speakingParams = new ArrayList(Arrays.asList(params)); } - return mSelf.synthesizeToFile(text, speakingParams, filename); + return mSelf.synthesizeToFile(callingApp, text, speakingParams, filename); } }; diff --git a/packages/VpnServices/res/values-cs/strings.xml b/packages/VpnServices/res/values-cs/strings.xml new file mode 100644 index 0000000000000..5f3522da9914f --- /dev/null +++ b/packages/VpnServices/res/values-cs/strings.xml @@ -0,0 +1,25 @@ + + + + "Služby VPN" + + + + + + + diff --git a/packages/VpnServices/res/values-de/strings.xml b/packages/VpnServices/res/values-de/strings.xml new file mode 100644 index 0000000000000..93fa474c05b8f --- /dev/null +++ b/packages/VpnServices/res/values-de/strings.xml @@ -0,0 +1,25 @@ + + + + "VPN-Dienste" + + + + + + + diff --git a/packages/VpnServices/res/values-es/strings.xml b/packages/VpnServices/res/values-es/strings.xml new file mode 100644 index 0000000000000..bb4f3483850fc --- /dev/null +++ b/packages/VpnServices/res/values-es/strings.xml @@ -0,0 +1,25 @@ + + + + "Servicios VPN" + + + + + + + diff --git a/packages/VpnServices/res/values-fr/strings.xml b/packages/VpnServices/res/values-fr/strings.xml new file mode 100644 index 0000000000000..4395d03d55bb4 --- /dev/null +++ b/packages/VpnServices/res/values-fr/strings.xml @@ -0,0 +1,25 @@ + + + + "Services VPN" + + + + + + + diff --git a/packages/VpnServices/res/values-it/strings.xml b/packages/VpnServices/res/values-it/strings.xml new file mode 100644 index 0000000000000..76e0214dc7587 --- /dev/null +++ b/packages/VpnServices/res/values-it/strings.xml @@ -0,0 +1,25 @@ + + + + "Servizi VPN" + + + + + + + diff --git a/packages/VpnServices/res/values-nl/strings.xml b/packages/VpnServices/res/values-nl/strings.xml new file mode 100644 index 0000000000000..9a50f3bb90992 --- /dev/null +++ b/packages/VpnServices/res/values-nl/strings.xml @@ -0,0 +1,25 @@ + + + + "VPN-services" + + + + + + + diff --git a/packages/VpnServices/res/values-pl/strings.xml b/packages/VpnServices/res/values-pl/strings.xml new file mode 100644 index 0000000000000..d2e8c609cf1da --- /dev/null +++ b/packages/VpnServices/res/values-pl/strings.xml @@ -0,0 +1,25 @@ + + + + "Usługi VPN" + + + + + + + diff --git a/packages/VpnServices/res/values-zh-rTW/strings.xml b/packages/VpnServices/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000000..021077bf7bbaf --- /dev/null +++ b/packages/VpnServices/res/values-zh-rTW/strings.xml @@ -0,0 +1,25 @@ + + + + "VPN 服務" + + + + + + + diff --git a/packages/VpnServices/src/com/android/server/vpn/AndroidServiceProxy.java b/packages/VpnServices/src/com/android/server/vpn/AndroidServiceProxy.java index 7dd9d9ea4744c..e4c070ff8b296 100644 --- a/packages/VpnServices/src/com/android/server/vpn/AndroidServiceProxy.java +++ b/packages/VpnServices/src/com/android/server/vpn/AndroidServiceProxy.java @@ -18,6 +18,7 @@ package com.android.server.vpn; import android.net.LocalSocket; import android.net.LocalSocketAddress; +import android.net.vpn.VpnManager; import android.os.SystemProperties; import android.util.Log; @@ -48,6 +49,9 @@ public class AndroidServiceProxy extends ProcessProxy { private static final int END_OF_ARGUMENTS = 255; + private static final int STOP_SERVICE = -1; + private static final int AUTH_ERROR_CODE = 51; + private String mServiceName; private String mSocketName; private LocalSocket mKeepaliveSocket; @@ -72,14 +76,22 @@ public class AndroidServiceProxy extends ProcessProxy { @Override public synchronized void stop() { - if (isRunning()) setResultAndCloseControlSocket(-1); + if (isRunning()) { + try { + setResultAndCloseControlSocket(STOP_SERVICE); + } catch (IOException e) { + // should not occur + throw new RuntimeException(e); + } + } + Log.d(mTag, "----- Stop: " + mServiceName); SystemProperties.set(SVC_STOP_CMD, mServiceName); } /** * Sends a command with arguments to the service through the control socket. */ - public void sendCommand(String ...args) throws IOException { + public synchronized void sendCommand(String ...args) throws IOException { OutputStream out = getControlSocketOutput(); for (String arg : args) outputString(out, arg); out.write(END_OF_ARGUMENTS); @@ -94,7 +106,14 @@ public class AndroidServiceProxy extends ProcessProxy { @Override protected void performTask() throws IOException { String svc = mServiceName; - Log.d(mTag, "+++++ Execute: " + svc); + Log.d(mTag, "----- Stop the daemon just in case: " + mServiceName); + SystemProperties.set(SVC_STOP_CMD, mServiceName); + if (!blockUntil(SVC_STATE_STOPPED, 5)) { + throw new IOException("cannot start service anew: " + svc + + ", it is still running"); + } + + Log.d(mTag, "+++++ Start: " + svc); SystemProperties.set(SVC_START_CMD, svc); boolean success = blockUntil(SVC_STATE_RUNNING, WAITING_TIME); @@ -114,30 +133,22 @@ public class AndroidServiceProxy extends ProcessProxy { InputStream in = s.getInputStream(); int data = in.read(); if (data >= 0) { - Log.d(mTag, "got data from keepalive socket: " + data); + Log.d(mTag, "got data from control socket: " + data); - if (data == 0) { - // re-establish the connection: - // synchronized here so that checkSocketResult() - // returns when new mKeepaliveSocket is available for - // next cmd - synchronized (this) { - setResultAndCloseControlSocket((byte) data); - s = mKeepaliveSocket = createServiceSocket(); - } - } else { - // keep the socket - setSocketResult(data); - } + setSocketResult(data); } else { // service is gone if (mControlSocketInUse) setSocketResult(-1); break; } } - Log.d(mTag, "keepalive connection closed"); + Log.d(mTag, "control connection closed"); } catch (IOException e) { - Log.d(mTag, "keepalive socket broken: " + e.getMessage()); + if (e instanceof VpnConnectingError) { + throw e; + } else { + Log.d(mTag, "control socket broken: " + e.getMessage()); + } } // Wait 5 seconds for the service to exit @@ -179,7 +190,7 @@ public class AndroidServiceProxy extends ProcessProxy { } } - private synchronized void checkSocketResult() throws IOException { + private void checkSocketResult() throws IOException { try { // will be notified when the result comes back from service if (mSocketResult == null) wait(); @@ -194,14 +205,21 @@ public class AndroidServiceProxy extends ProcessProxy { } } - private synchronized void setSocketResult(int result) { + private synchronized void setSocketResult(int result) + throws VpnConnectingError { if (mControlSocketInUse) { mSocketResult = result; notifyAll(); + } else if (result > 0) { + // error from daemon + throw new VpnConnectingError((result == AUTH_ERROR_CODE) + ? VpnManager.VPN_ERROR_AUTH + : VpnManager.VPN_ERROR_CONNECTION_FAILED); } } - private void setResultAndCloseControlSocket(int result) { + private void setResultAndCloseControlSocket(int result) + throws VpnConnectingError { setSocketResult(result); try { mKeepaliveSocket.shutdownInput(); diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java index 6abf81c60c6f6..7b3ddf85faece 100644 --- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java +++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java @@ -30,12 +30,11 @@ class L2tpIpsecPskService extends VpnService { @Override protected void connect(String serverIp, String username, String password) throws IOException { - String hostIp = getHostIp(); L2tpIpsecPskProfile p = getProfile(); // IPSEC AndroidServiceProxy ipsecService = startService(IPSEC_DAEMON); - ipsecService.sendCommand(hostIp, serverIp, L2tpService.L2TP_PORT, + ipsecService.sendCommand(serverIp, L2tpService.L2TP_PORT, p.getPresharedKey()); sleep(2000); // 2 seconds diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java index 825953c33ac94..e2d4ff49ea56a 100644 --- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java +++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java @@ -30,11 +30,9 @@ class L2tpIpsecService extends VpnService { @Override protected void connect(String serverIp, String username, String password) throws IOException { - String hostIp = getHostIp(); - // IPSEC AndroidServiceProxy ipsecService = startService(IPSEC_DAEMON); - ipsecService.sendCommand(hostIp, serverIp, L2tpService.L2TP_PORT, + ipsecService.sendCommand(serverIp, L2tpService.L2TP_PORT, getUserkeyPath(), getUserCertPath(), getCaCertPath()); sleep(2000); // 2 seconds diff --git a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java b/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java index 16d253a41b112..5fac799b288ac 100644 --- a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java +++ b/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java @@ -48,7 +48,6 @@ class MtpdHelper { "linkname", VPN_LINKNAME, "name", username, "password", password, - "ipparam", serverIp + "@" + vpnService.getGatewayIp(), "refuse-eap", "nodefaultroute", "usepeerdns", "idle", "1800", "mtu", "1400", diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnConnectingError.java b/packages/VpnServices/src/com/android/server/vpn/VpnConnectingError.java new file mode 100644 index 0000000000000..3c4ec7d8c41af --- /dev/null +++ b/packages/VpnServices/src/com/android/server/vpn/VpnConnectingError.java @@ -0,0 +1,35 @@ +/* + * 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.server.vpn; + +import java.io.IOException; + +/** + * Exception thrown when a connecting attempt fails. + */ +class VpnConnectingError extends IOException { + private int mErrorCode; + + VpnConnectingError(int errorCode) { + super("Connecting error: " + errorCode); + mErrorCode = errorCode; + } + + int getErrorCode() { + return mErrorCode; + } +} diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java index a60788aad24ff..87bd780ff8b48 100644 --- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java +++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java @@ -20,7 +20,6 @@ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; -import android.net.NetworkUtils; import android.net.vpn.VpnManager; import android.net.vpn.VpnProfile; import android.net.vpn.VpnState; @@ -30,10 +29,8 @@ import android.util.Log; import java.io.IOException; import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.Socket; +import java.net.UnknownHostException; import java.util.ArrayList; -import java.util.Enumeration; import java.util.List; /** @@ -46,9 +43,9 @@ abstract class VpnService { private static final String DNS2 = "net.dns2"; private static final String VPN_DNS1 = "vpn.dns1"; private static final String VPN_DNS2 = "vpn.dns2"; - private static final String VPN_UP = "vpn.up"; - private static final String VPN_IS_UP = "1"; - private static final String VPN_IS_DOWN = "0"; + private static final String VPN_STATUS = "vpn.status"; + private static final String VPN_IS_UP = "ok"; + private static final String VPN_IS_DOWN = "down"; private static final String REMOTE_IP = "net.ipremote"; private static final String DNS_DOMAIN_SUFFICES = "net.dns.search"; @@ -60,6 +57,7 @@ abstract class VpnService { private VpnState mState = VpnState.IDLE; private boolean mInError; + private VpnConnectingError mError; // connection settings private String mOriginalDns1; @@ -67,7 +65,6 @@ abstract class VpnService { private String mVpnDns1 = ""; private String mVpnDns2 = ""; private String mOriginalDomainSuffices; - private String mHostIp; private long mStartTime; // VPN connection start time @@ -105,14 +102,6 @@ abstract class VpnService { return mProfile; } - /** - * Returns the host IP for establishing the VPN connection. - */ - protected String getHostIp() throws IOException { - if (mHostIp == null) mHostIp = reallyGetHostIp(); - return mHostIp; - } - /** * Returns the IP address of the specified host name. */ @@ -120,21 +109,6 @@ abstract class VpnService { return InetAddress.getByName(hostName).getHostAddress(); } - /** - * Returns the IP address of the default gateway. - */ - protected String getGatewayIp() throws IOException { - Enumeration ifces = - NetworkInterface.getNetworkInterfaces(); - for (; ifces.hasMoreElements(); ) { - NetworkInterface ni = ifces.nextElement(); - int gateway = NetworkUtils.getDefaultRoute(ni.getName()); - if (gateway == 0) continue; - return toInetAddress(gateway).getHostAddress(); - } - throw new IOException("Default gateway is not available"); - } - /** * Sets the system property. The method is blocked until the value is * settled in. @@ -166,20 +140,28 @@ abstract class VpnService { return mState; } - synchronized void onConnect(String username, String password) - throws IOException { - mState = VpnState.CONNECTING; - broadcastConnectivity(VpnState.CONNECTING); + synchronized boolean onConnect(String username, String password) { + try { + mState = VpnState.CONNECTING; + broadcastConnectivity(VpnState.CONNECTING); - String serverIp = getIp(getProfile().getServerName()); + String serverIp = getIp(getProfile().getServerName()); - onBeforeConnect(); - connect(serverIp, username, password); - waitUntilConnectedOrTimedout(); + onBeforeConnect(); + connect(serverIp, username, password); + waitUntilConnectedOrTimedout(); + return true; + } catch (Throwable e) { + Log.e(TAG, "onConnect()", e); + mError = newConnectingError(e); + onError(); + return false; + } } synchronized void onDisconnect(boolean cleanUpServices) { try { + Log.d(TAG, " disconnecting VPN..."); mState = VpnState.DISCONNECTING; broadcastConnectivity(VpnState.DISCONNECTING); mNotification.showDisconnect(); @@ -189,7 +171,7 @@ abstract class VpnService { mServiceHelper.stop(); } catch (Throwable e) { - Log.e(TAG, "onError()", e); + Log.e(TAG, "onDisconnect()", e); onFinalCleanUp(); } } @@ -214,26 +196,35 @@ abstract class VpnService { SystemProperties.set(VPN_DNS1, "-"); SystemProperties.set(VPN_DNS2, "-"); - SystemProperties.set(VPN_UP, VPN_IS_DOWN); - Log.d(TAG, " VPN UP: " + SystemProperties.get(VPN_UP)); + SystemProperties.set(VPN_STATUS, VPN_IS_DOWN); + Log.d(TAG, " VPN UP: " + SystemProperties.get(VPN_STATUS)); } private void waitUntilConnectedOrTimedout() { - sleep(2000); // 2 seconds - for (int i = 0; i < 60; i++) { - if (VPN_IS_UP.equals(SystemProperties.get(VPN_UP))) { - onConnected(); - return; - } - sleep(500); // 0.5 second - } + // Run this in the background thread to not block UI + new Thread(new Runnable() { + public void run() { + sleep(2000); // 2 seconds + for (int i = 0; i < 60; i++) { + if (VPN_IS_UP.equals(SystemProperties.get(VPN_STATUS))) { + onConnected(); + return; + } else if (mState != VpnState.CONNECTING) { + break; + } + sleep(500); // 0.5 second + } - synchronized (this) { - if (mState == VpnState.CONNECTING) { - Log.d(TAG, " connecting timed out !!"); - onError(); + synchronized (VpnService.this) { + if (mState == VpnState.CONNECTING) { + Log.d(TAG, " connecting timed out !!"); + mError = newConnectingError( + new IOException("Connecting timed out")); + onError(); + } + } } - } + }).start(); } private synchronized void onConnected() { @@ -264,6 +255,13 @@ abstract class VpnService { mContext.stopSelf(); } + private VpnConnectingError newConnectingError(Throwable e) { + return new VpnConnectingError( + (e instanceof UnknownHostException) + ? VpnManager.VPN_ERROR_UNKNOWN_SERVER + : VpnManager.VPN_ERROR_CONNECTION_FAILED); + } + private synchronized void onOneServiceGone() { switch (mState) { case IDLE: @@ -304,12 +302,12 @@ abstract class VpnService { private void saveVpnDnsProperties() { mOriginalDns1 = mOriginalDns2 = ""; - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 5; i++) { mVpnDns1 = SystemProperties.get(VPN_DNS1); mVpnDns2 = SystemProperties.get(VPN_DNS2); if (mOriginalDns1.equals(mVpnDns1)) { Log.d(TAG, "wait for vpn dns to settle in..." + i); - sleep(500); + sleep(200); } else { mOriginalDns1 = SystemProperties.get(DNS1); mOriginalDns2 = SystemProperties.get(DNS2); @@ -322,7 +320,9 @@ abstract class VpnService { return; } } - Log.e(TAG, "saveVpnDnsProperties(): DNS not updated??"); + Log.d(TAG, "saveVpnDnsProperties(): DNS not updated??"); + mOriginalDns1 = mVpnDns1 = SystemProperties.get(DNS1); + mOriginalDns2 = mVpnDns2 = SystemProperties.get(DNS2); } private void saveAndSetDomainSuffices() { @@ -340,7 +340,13 @@ abstract class VpnService { } private void broadcastConnectivity(VpnState s) { - new VpnManager(mContext).broadcastConnectivity(mProfile.getName(), s); + VpnManager m = new VpnManager(mContext); + if ((s == VpnState.IDLE) && (mError != null)) { + m.broadcastConnectivity(mProfile.getName(), s, + mError.getErrorCode()); + } else { + m.broadcastConnectivity(mProfile.getName(), s); + } } private void startConnectivityMonitor() { @@ -373,26 +379,11 @@ abstract class VpnService { private void checkDnsProperties() { String dns1 = SystemProperties.get(DNS1); if (!mVpnDns1.equals(dns1)) { - Log.w(TAG, " @@ !!! dns being overridden"); + Log.w(TAG, " dns being overridden by: " + dns1); onError(); } } - private String reallyGetHostIp() throws IOException { - Enumeration ifces = - NetworkInterface.getNetworkInterfaces(); - for (; ifces.hasMoreElements(); ) { - NetworkInterface ni = ifces.nextElement(); - int gateway = NetworkUtils.getDefaultRoute(ni.getName()); - if (gateway == 0) continue; - Enumeration addrs = ni.getInetAddresses(); - for (; addrs.hasMoreElements(); ) { - return addrs.nextElement().getHostAddress(); - } - } - throw new IOException("Host IP is not available"); - } - protected void sleep(int ms) { try { Thread.currentThread().sleep(ms); @@ -440,6 +431,9 @@ abstract class VpnService { //@Override public void error(ProcessProxy p, Throwable e) { Log.e(TAG, "service error: " + p.getName(), e); + if (e instanceof VpnConnectingError) { + mError = (VpnConnectingError) e; + } commonCallback((AndroidServiceProxy) p); } diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java index 617875e64d2cf..32b8e51f278da 100644 --- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java +++ b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java @@ -27,7 +27,6 @@ import android.net.vpn.VpnManager; import android.net.vpn.VpnProfile; import android.net.vpn.VpnState; import android.os.IBinder; -import android.util.Log; import java.io.IOException; @@ -55,6 +54,12 @@ public class VpnServiceBinder extends Service { } }; + public void onStart (Intent intent, int startId) { + super.onStart(intent, startId); + setForeground(true); + android.util.Log.d("VpnServiceBinder", "becomes a foreground service"); + } + public IBinder onBind(Intent intent) { return mBinder; } @@ -62,21 +67,13 @@ public class VpnServiceBinder extends Service { private synchronized boolean connect( VpnProfile p, String username, String password) { if (mService != null) return false; - try { - mService = createService(p); - mService.onConnect(username, password); - return true; - } catch (Throwable e) { - Log.e(TAG, "connect()", e); - if (mService != null) mService.onError(); - return false; - } + mService = createService(p); + return mService.onConnect(username, password); } private synchronized void checkStatus(VpnProfile p) { - if (mService == null) broadcastConnectivity(p.getName(), VpnState.IDLE); - - if (!p.getName().equals(mService.mProfile.getName())) { + if ((mService == null) + || (!p.getName().equals(mService.mProfile.getName()))) { broadcastConnectivity(p.getName(), VpnState.IDLE); } else { broadcastConnectivity(p.getName(), mService.getState()); diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index 131e156748d01..78db6f93727ee 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -68,6 +68,7 @@ class AppWidgetService extends IAppWidgetService.Stub private static final String SETTINGS_FILENAME = "appwidgets.xml"; private static final String SETTINGS_TMP_FILENAME = SETTINGS_FILENAME + ".tmp"; + private static final int MIN_UPDATE_PERIOD = 30 * 60 * 1000; // 30 minutes /* * When identifying a Host or Provider based on the calling process, use the uid field. @@ -629,9 +630,12 @@ class AppWidgetService extends IAppWidgetService.Stub Binder.restoreCallingIdentity(token); } if (!alreadyRegistered) { + long period = p.info.updatePeriodMillis; + if (period < MIN_UPDATE_PERIOD) { + period = MIN_UPDATE_PERIOD; + } mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, - SystemClock.elapsedRealtime() + p.info.updatePeriodMillis, - p.info.updatePeriodMillis, p.broadcast); + SystemClock.elapsedRealtime() + period, period, p.broadcast); } } } diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 3b82284c0c4bc..6e285157d5e4d 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -810,17 +810,25 @@ class BackupManagerService extends IBackupManager.Stub { // Now propagate the newly-backed-up data to the transport if (success) { - if (DEBUG) Log.v(TAG, "doBackup() success; calling transport"); - backupData = - ParcelFileDescriptor.open(backupDataName, ParcelFileDescriptor.MODE_READ_ONLY); - if (!transport.performBackup(packInfo, backupData)) { - // STOPSHIP TODO: handle errors - Log.e(TAG, "Backup failure in performBackup()"); + if (DEBUG) Log.v(TAG, "doBackup() success"); + if (backupDataName.length() > 0) { + backupData = + ParcelFileDescriptor.open(backupDataName, + ParcelFileDescriptor.MODE_READ_ONLY); + if (!transport.performBackup(packInfo, backupData)) { + // STOPSHIP TODO: handle errors + Log.e(TAG, "Backup failure in performBackup()"); + } + } else { + if (DEBUG) { + Log.i(TAG, "no backup data written; not calling transport"); + } } - // !!! TODO: After successful transport, delete the now-stale data - // and juggle the files so that next time the new state is passed - //backupDataName.delete(); + // After successful transport, delete the now-stale data + // and juggle the files so that next time we supply the agent + // with the new state file it just created. + backupDataName.delete(); newStateName.renameTo(savedStateName); } } catch (Exception e) { diff --git a/services/java/com/android/server/MountListener.java b/services/java/com/android/server/MountListener.java index 2e430c849d973..3e535851b9e91 100644 --- a/services/java/com/android/server/MountListener.java +++ b/services/java/com/android/server/MountListener.java @@ -202,6 +202,7 @@ final class MountListener implements Runnable { byte[] buffer = new byte[100]; writeCommand(VOLD_CMD_SEND_UMS_STATUS); + mountMedia(Environment.getExternalStorageDirectory().getAbsolutePath()); while (true) { int count = inputStream.read(buffer); diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 854138c740854..38fb7c9cd9d85 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -49,6 +49,7 @@ import android.os.IBinder; import android.os.Message; import android.os.Power; import android.os.RemoteException; +import android.os.SystemProperties; import android.os.Vibrator; import android.provider.Settings; import android.text.TextUtils; @@ -88,7 +89,8 @@ class NotificationManagerService extends INotificationManager.Stub private NotificationRecord mSoundNotification; private AsyncPlayer mSound; - private int mDisabledNotifications; + private boolean mSystemReady; + private int mDisabledNotifications = StatusBarManager.DISABLE_NOTIFICATION_ALERTS; private NotificationRecord mVibrateNotification; private Vibrator mVibrator = new Vibrator(); @@ -377,6 +379,11 @@ class NotificationManagerService extends INotificationManager.Stub mSettingsObserver.observe(); } + void systemReady() { + // no beeping until we're basically done booting + mSystemReady = true; + } + // Toasts // ============================================================================ public void enqueueToast(String pkg, ITransientNotification callback, int duration) @@ -637,7 +644,7 @@ class NotificationManagerService extends INotificationManager.Stub } } - sendAccessibilityEventTypeNotificationChangedDoCheck(notification, pkg); + sendAccessibilityEvent(notification, pkg); } else { if (old != null && old.statusBarKey != null) { @@ -654,7 +661,8 @@ class NotificationManagerService extends INotificationManager.Stub // If we're not supposed to beep, vibrate, etc. then don't. if (((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0) && (!(old != null - && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))) { + && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 )) + && mSystemReady) { // sound final boolean useDefaultSound = (notification.defaults & Notification.DEFAULT_SOUND) != 0; @@ -721,8 +729,7 @@ class NotificationManagerService extends INotificationManager.Stub idOut[0] = id; } - private void sendAccessibilityEventTypeNotificationChangedDoCheck(Notification notification, - CharSequence packageName) { + private void sendAccessibilityEvent(Notification notification, CharSequence packageName) { AccessibilityManager manager = AccessibilityManager.getInstance(mContext); if (!manager.isEnabled()) { return; @@ -939,6 +946,9 @@ class NotificationManagerService extends INotificationManager.Stub // to accidentally lose. private void updateAdbNotification() { if (mAdbEnabled && mBatteryPlugged == BatteryManager.BATTERY_PLUGGED_USB) { + if ("0".equals(SystemProperties.get("persist.adb.notify"))) { + return; + } if (!mAdbNotificationShown) { NotificationManager notificationManager = (NotificationManager) mContext .getSystemService(Context.NOTIFICATION_SERVICE); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 06435c87ff19b..ee53274ec1c1e 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -56,12 +56,11 @@ import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.Signature; -import android.content.res.CompatibilityInfo; -import android.content.res.Configuration; 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.Parcel; import android.os.RemoteException; @@ -251,6 +250,9 @@ class PackageManagerService extends IPackageManager.Stub { final HashMap mPermissionGroups = new HashMap(); + // Broadcast actions that are only available to the system. + final HashSet mProtectedBroadcasts = new HashSet(); + boolean mSystemReady; boolean mSafeMode; boolean mHasSystemUidErrors; @@ -260,7 +262,6 @@ class PackageManagerService extends IPackageManager.Stub { final ResolveInfo mResolveInfo = new ResolveInfo(); ComponentName mResolveComponentName; PackageParser.Package mPlatformPackage; - private boolean mCompatibilityModeEnabled = true; public static final IPackageManager main(Context context, boolean factoryTest) { PackageManagerService m = new PackageManagerService(context, factoryTest); @@ -763,7 +764,7 @@ class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); if (Config.LOGV) Log.v( - TAG, "getApplicationInfo " + packageName + TAG, "getPackageInfo " + packageName + ": " + p); if (p != null) { return generatePackageInfo(p, flags); @@ -794,7 +795,7 @@ class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); if (Config.LOGV) Log.v( - TAG, "getApplicationInfo " + packageName + TAG, "getPackageGids" + packageName + ": " + p); if (p != null) { final PackageSetting ps = (PackageSetting)p.mExtras; @@ -892,11 +893,7 @@ class PackageManagerService extends IPackageManager.Stub { + ": " + p); if (p != null) { // Note: isEnabledLP() does not apply here - always return info - ApplicationInfo appInfo = PackageParser.generateApplicationInfo(p, flags); - if (!mCompatibilityModeEnabled) { - appInfo.disableCompatibilityMode(); - } - return appInfo; + return PackageParser.generateApplicationInfo(p, flags); } if ("android".equals(packageName)||"system".equals(packageName)) { return mAndroidApplication; @@ -1128,6 +1125,12 @@ class PackageManagerService extends IPackageManager.Stub { } } + public boolean isProtectedBroadcast(String actionName) { + synchronized (mPackages) { + return mProtectedBroadcasts.contains(actionName); + } + } + public int checkSignatures(String pkg1, String pkg2) { synchronized (mPackages) { PackageParser.Package p1 = mPackages.get(pkg1); @@ -2039,8 +2042,9 @@ class PackageManagerService extends IPackageManager.Stub { + suid.userId + "): packages=" + suid.packages); } } - - // Just create the setting, don't add it yet + + // Just create the setting, don't add it yet. For already existing packages + // the PkgSetting exists already and doesn't have to be created. pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile, destResourceFile, pkg.applicationInfo.flags, true, false); if (pkgSetting == null) { @@ -2265,7 +2269,7 @@ class PackageManagerService extends IPackageManager.Stub { // Add the new setting to mSettings mSettings.insertPackageSettingLP(pkgSetting, pkg.packageName, suid); // Add the new setting to mPackages - mPackages.put(pkg.applicationInfo.packageName, pkg); + mPackages.put(pkg.applicationInfo.packageName, pkg); int N = pkg.providers.size(); StringBuilder r = null; int i; @@ -2500,6 +2504,13 @@ class PackageManagerService extends IPackageManager.Stub { if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r); } + if (pkg.protectedBroadcasts != null) { + N = pkg.protectedBroadcasts.size(); + for (i=0; i=0; i--) { AppWindowToken wtoken = order.get(i); //Log.i(TAG, "Token " + wtoken + " with " + wtoken.windows.size() + " windows"); - if (tokenList1.contains(wtoken) || tokenList2.contains(wtoken)) { + if (openingTokenList1.contains(wtoken) || closingTokenList2.contains(wtoken)) { int j = wtoken.windows.size(); while (j > 0) { j--; @@ -7228,6 +7304,21 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo return animParams; } + private static LayoutParams findCompatibleWindowParams(ArrayList tokenList) { + for (int appCount = tokenList.size() - 1; appCount >= 0; appCount--) { + AppWindowToken wtoken = tokenList.get(appCount); + // Just checking one window is sufficient as all windows have the compatible flag + // if the application is in compatibility mode. + if (wtoken.windows.size() > 0) { + WindowManager.LayoutParams params = wtoken.windows.get(0).mAttrs; + if ((params.flags & FLAG_COMPATIBLE_WINDOW) != 0) { + return params; + } + } + } + return null; + } + // ------------------------------------------------------------- // DummyAnimation // ------------------------------------------------------------- @@ -8102,6 +8193,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo boolean dimming = false; boolean covered = false; boolean syswin = false; + boolean backgroundFillerShown = false; for (i=N-1; i>=0; i--) { WindowState w = (WindowState)mWindows.get(i); @@ -8371,11 +8463,39 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo syswin = true; } } - if (w.isFullscreenOpaque(dw, dh)) { + + boolean opaqueDrawn = w.isOpaqueDrawn(); + if (opaqueDrawn && w.isFullscreen(dw, dh)) { // This window completely covers everything behind it, // so we want to leave all of them as unblurred (for // performance reasons). obscured = true; + } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) { + if (SHOW_TRANSACTIONS) Log.d(TAG, "showing background filler"); + // This window is in compatibility mode, and needs background filler. + obscured = true; + if (mBackgroundFillerSurface == null) { + try { + mBackgroundFillerSurface = new Surface(mFxSession, 0, + 0, dw, dh, + PixelFormat.OPAQUE, + Surface.FX_SURFACE_NORMAL); + } catch (Exception e) { + Log.e(TAG, "Exception creating filler surface", e); + } + } + try { + mBackgroundFillerSurface.setPosition(0, 0); + mBackgroundFillerSurface.setSize(dw, dh); + // Using the same layer as Dim because they will never be shown at the + // same time. + mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1); + mBackgroundFillerSurface.show(); + } catch (RuntimeException e) { + Log.e(TAG, "Exception showing filler surface"); + } + backgroundFillerShown = true; + mBackgroundFillerShown = true; } else if (canBeSeen && !obscured && (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) { if (localLOGV) Log.v(TAG, "Win " + w @@ -8386,56 +8506,12 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if (!dimming) { //Log.i(TAG, "DIM BEHIND: " + w); dimming = true; - mDimShown = true; - if (mDimSurface == null) { - if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " - + mDimSurface + ": CREATE"); - try { - mDimSurface = new Surface(mFxSession, 0, - -1, 16, 16, - PixelFormat.OPAQUE, - Surface.FX_SURFACE_DIM); - } catch (Exception e) { - Log.e(TAG, "Exception creating Dim surface", e); - } - } - if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " - + mDimSurface + ": SHOW pos=(0,0) (" + - dw + "x" + dh + "), layer=" + (w.mAnimLayer-1)); - if (mDimSurface != null) { - try { - mDimSurface.setPosition(0, 0); - mDimSurface.setSize(dw, dh); - mDimSurface.show(); - } catch (RuntimeException e) { - Log.w(TAG, "Failure showing dim surface", e); - } + if (mDimAnimator == null) { + mDimAnimator = new DimAnimator(mFxSession); } + mDimAnimator.show(dw, dh); } - mDimSurface.setLayer(w.mAnimLayer-1); - final float target = w.mExiting ? 0 : attrs.dimAmount; - if (mDimTargetAlpha != target) { - // If the desired dim level has changed, then - // start an animation to it. - mLastDimAnimTime = currentTime; - long duration = (w.mAnimating && w.mAnimation != null) - ? w.mAnimation.computeDurationHint() - : DEFAULT_DIM_DURATION; - if (target > mDimTargetAlpha) { - // This is happening behind the activity UI, - // so we can make it run a little longer to - // give a stronger impression without disrupting - // the user. - duration *= DIM_DURATION_MULTIPLIER; - } - if (duration < 1) { - // Don't divide by zero - duration = 1; - } - mDimTargetAlpha = target; - mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) - / duration; - } + mDimAnimator.updateParameters(w, currentTime); } if ((attrFlags&FLAG_BLUR_BEHIND) != 0) { if (!blurring) { @@ -8472,59 +8548,19 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } } } - - if (!dimming && mDimShown) { - // Time to hide the dim surface... start fading. - if (mDimTargetAlpha != 0) { - mLastDimAnimTime = currentTime; - mDimTargetAlpha = 0; - mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION; + + if (backgroundFillerShown == false && mBackgroundFillerShown) { + mBackgroundFillerShown = false; + if (SHOW_TRANSACTIONS) Log.d(TAG, "hiding background filler"); + try { + mBackgroundFillerSurface.hide(); + } catch (RuntimeException e) { + Log.e(TAG, "Exception hiding filler surface", e); } } - if (mDimShown && mLastDimAnimTime != 0) { - mDimCurrentAlpha += mDimDeltaPerMs - * (currentTime-mLastDimAnimTime); - boolean more = true; - if (mDisplayFrozen) { - // If the display is frozen, there is no reason to animate. - more = false; - } else if (mDimDeltaPerMs > 0) { - if (mDimCurrentAlpha > mDimTargetAlpha) { - more = false; - } - } else if (mDimDeltaPerMs < 0) { - if (mDimCurrentAlpha < mDimTargetAlpha) { - more = false; - } - } else { - more = false; - } - - // Do we need to continue animating? - if (more) { - if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " - + mDimSurface + ": alpha=" + mDimCurrentAlpha); - mLastDimAnimTime = currentTime; - mDimSurface.setAlpha(mDimCurrentAlpha); - animating = true; - } else { - mDimCurrentAlpha = mDimTargetAlpha; - mLastDimAnimTime = 0; - if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " - + mDimSurface + ": final alpha=" + mDimCurrentAlpha); - mDimSurface.setAlpha(mDimCurrentAlpha); - if (!dimming) { - if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface - + ": HIDE"); - try { - mDimSurface.hide(); - } catch (RuntimeException e) { - Log.w(TAG, "Illegal argument exception hiding dim surface"); - } - mDimShown = false; - } - } + if (mDimAnimator != null && mDimAnimator.mDimShown) { + animating |= mDimAnimator.updateSurface(dimming, currentTime, mDisplayFrozen); } if (!blurring && mBlurShown) { @@ -9067,11 +9103,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded); pw.print(" mBlurShown="); pw.println(mBlurShown); - pw.print(" mDimShown="); pw.print(mDimShown); - pw.print(" current="); pw.print(mDimCurrentAlpha); - pw.print(" target="); pw.print(mDimTargetAlpha); - pw.print(" delta="); pw.print(mDimDeltaPerMs); - pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime); + if (mDimAnimator != null) { + mDimAnimator.printTo(pw); + } else { + pw.print( " no DimAnimator "); + } pw.print(" mInputMethodAnimLayerAdjustment="); pw.println(mInputMethodAnimLayerAdjustment); pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); @@ -9112,4 +9148,188 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo synchronized (mKeyguardDisabled) { } synchronized (mKeyWaiter) { } } + + /** + * DimAnimator class that controls the dim animation. This holds the surface and + * all state used for dim animation. + */ + private static class DimAnimator { + Surface mDimSurface; + boolean mDimShown = false; + float mDimCurrentAlpha; + float mDimTargetAlpha; + float mDimDeltaPerMs; + long mLastDimAnimTime; + + DimAnimator (SurfaceSession session) { + if (mDimSurface == null) { + if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + + mDimSurface + ": CREATE"); + try { + mDimSurface = new Surface(session, 0, -1, 16, 16, PixelFormat.OPAQUE, + Surface.FX_SURFACE_DIM); + } catch (Exception e) { + Log.e(TAG, "Exception creating Dim surface", e); + } + } + } + + /** + * Show the dim surface. + */ + void show(int dw, int dh) { + if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" + + dw + "x" + dh + ")"); + mDimShown = true; + try { + mDimSurface.setPosition(0, 0); + mDimSurface.setSize(dw, dh); + mDimSurface.show(); + } catch (RuntimeException e) { + Log.w(TAG, "Failure showing dim surface", e); + } + } + + /** + * Set's the dim surface's layer and update dim parameters that will be used in + * {@link updateSurface} after all windows are examined. + */ + void updateParameters(WindowState w, long currentTime) { + mDimSurface.setLayer(w.mAnimLayer-1); + + final float target = w.mExiting ? 0 : w.mAttrs.dimAmount; + if (SHOW_TRANSACTIONS) Log.i(TAG, "layer=" + (w.mAnimLayer-1) + ", target=" + target); + if (mDimTargetAlpha != target) { + // If the desired dim level has changed, then + // start an animation to it. + mLastDimAnimTime = currentTime; + long duration = (w.mAnimating && w.mAnimation != null) + ? w.mAnimation.computeDurationHint() + : DEFAULT_DIM_DURATION; + if (target > mDimTargetAlpha) { + // This is happening behind the activity UI, + // so we can make it run a little longer to + // give a stronger impression without disrupting + // the user. + duration *= DIM_DURATION_MULTIPLIER; + } + if (duration < 1) { + // Don't divide by zero + duration = 1; + } + mDimTargetAlpha = target; + mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration; + } + } + + /** + * Updating the surface's alpha. Returns true if the animation continues, or returns + * false when the animation is finished and the dim surface is hidden. + */ + boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) { + if (!dimming) { + if (mDimTargetAlpha != 0) { + mLastDimAnimTime = currentTime; + mDimTargetAlpha = 0; + mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION; + } + } + + boolean animating = false; + if (mLastDimAnimTime != 0) { + mDimCurrentAlpha += mDimDeltaPerMs + * (currentTime-mLastDimAnimTime); + boolean more = true; + if (displayFrozen) { + // If the display is frozen, there is no reason to animate. + more = false; + } else if (mDimDeltaPerMs > 0) { + if (mDimCurrentAlpha > mDimTargetAlpha) { + more = false; + } + } else if (mDimDeltaPerMs < 0) { + if (mDimCurrentAlpha < mDimTargetAlpha) { + more = false; + } + } else { + more = false; + } + + // Do we need to continue animating? + if (more) { + if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + + mDimSurface + ": alpha=" + mDimCurrentAlpha); + mLastDimAnimTime = currentTime; + mDimSurface.setAlpha(mDimCurrentAlpha); + animating = true; + } else { + mDimCurrentAlpha = mDimTargetAlpha; + mLastDimAnimTime = 0; + if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + + mDimSurface + ": final alpha=" + mDimCurrentAlpha); + mDimSurface.setAlpha(mDimCurrentAlpha); + if (!dimming) { + if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface + + ": HIDE"); + try { + mDimSurface.hide(); + } catch (RuntimeException e) { + Log.w(TAG, "Illegal argument exception hiding dim surface"); + } + mDimShown = false; + } + } + } + return animating; + } + + public void printTo(PrintWriter pw) { + pw.print(" mDimShown="); pw.print(mDimShown); + pw.print(" current="); pw.print(mDimCurrentAlpha); + pw.print(" target="); pw.print(mDimTargetAlpha); + pw.print(" delta="); pw.print(mDimDeltaPerMs); + pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime); + } + } + + /** + * Animation that fade in after 0.5 interpolate time, or fade out in reverse order. + * This is used for opening/closing transition for apps in compatible mode. + */ + private static class FadeInOutAnimation extends Animation { + int mWidth; + boolean mFadeIn; + + public FadeInOutAnimation(boolean fadeIn) { + setInterpolator(new AccelerateInterpolator()); + setDuration(DEFAULT_FADE_IN_OUT_DURATION); + mFadeIn = fadeIn; + } + + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + float x = interpolatedTime; + if (!mFadeIn) { + x = 1.0f - x; // reverse the interpolation for fade out + } + if (x < 0.5) { + // move the window out of the screen. + t.getMatrix().setTranslate(mWidth, 0); + } else { + t.getMatrix().setTranslate(0, 0);// show + t.setAlpha((x - 0.5f) * 2); + } + } + + @Override + public void initialize(int width, int height, int parentWidth, int parentHeight) { + // width is the screen width {@see AppWindowToken#stepAnimatinoLocked} + mWidth = width; + } + + @Override + public int getZAdjustment() { + return Animation.ZORDER_TOP; + } + } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 2fe4dd4c31092..d9c40ec602f6b 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -32,6 +32,7 @@ import android.app.ActivityThread; import android.app.AlertDialog; import android.app.ApplicationErrorReport; import android.app.Dialog; +import android.app.IActivityController; import android.app.IActivityWatcher; import android.app.IApplicationThread; import android.app.IInstrumentationWatcher; @@ -56,6 +57,7 @@ import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageManager; +import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; @@ -75,6 +77,7 @@ import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.Process; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -824,8 +827,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen String mOrigDebugApp = null; boolean mOrigWaitForDebugger = false; boolean mAlwaysFinishActivities = false; - IActivityWatcher mWatcher = null; + IActivityController mController = null; + final RemoteCallbackList mWatchers + = new RemoteCallbackList(); + /** * Callback of last caller to {@link #requestPss}. */ @@ -1622,7 +1628,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen /** * This is a simplified version of topRunningActivityLocked that provides a number of - * optional skip-over modes. It is intended for use with the ActivityWatcher hook only. + * optional skip-over modes. It is intended for use with the ActivityController hook only. * * @param token If non-null, any history records matching this token will be skipped. * @param taskId If non-zero, we'll attempt to skip over records with the same task ID. @@ -1727,10 +1733,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } ensurePackageDexOpt(r.intent.getComponent().getPackageName()); app.thread.scheduleLaunchActivity(new Intent(r.intent), r, + System.identityHashCode(r), r.info, r.icicle, results, newIntents, !andResume, isNextTransitionForward()); - // Update usage stats for launched activity - updateUsageStats(r, true); } catch (RemoteException e) { if (r.launchFailed) { // This is the second time we failed -- finish activity @@ -2183,6 +2188,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen mHandler.sendMessage(msg); } + reportResumedActivity(next); + next.thumbnail = null; setFocusedActivityLocked(next); next.resumeKeyDispatchingLocked(); @@ -2453,6 +2460,26 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } + private void reportResumedActivity(HistoryRecord r) { + //Log.i(TAG, "**** REPORT RESUME: " + r); + + final int identHash = System.identityHashCode(r); + updateUsageStats(r, true); + + int i = mWatchers.beginBroadcast(); + while (i > 0) { + i--; + IActivityWatcher w = mWatchers.getBroadcastItem(i); + if (w != null) { + try { + w.activityResuming(identHash); + } catch (RemoteException e) { + } + } + } + mWatchers.finishBroadcast(); + } + /** * Ensure that the top activity in the stack is resumed. * @@ -2641,10 +2668,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen EventLog.writeEvent(LOG_AM_RESUME_ACTIVITY, System.identityHashCode(next), next.task.taskId, next.shortComponentName); - updateUsageStats(next, true); next.app.thread.scheduleResumeActivity(next, isNextTransitionForward()); + pauseIfSleepingLocked(); } catch (Exception e) { @@ -3061,16 +3088,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen throw new SecurityException(msg); } - if (mWatcher != null) { + if (mController != null) { boolean abort = false; try { // The Intent we give to the watcher has the extra data // stripped off, since it can contain private information. Intent watchIntent = intent.cloneFilter(); - abort = !mWatcher.activityStarting(watchIntent, + abort = !mController.activityStarting(watchIntent, aInfo.applicationInfo.packageName); } catch (RemoteException e) { - mWatcher = null; + mController = null; } if (abort) { @@ -3495,8 +3522,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen intent = new Intent(intent); // Collect information about the target of the Intent. - // Must do this before locking, because resolving the intent - // may require launching a process to run its content provider. ActivityInfo aInfo; try { ResolveInfo rInfo = @@ -3630,17 +3655,24 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - final int startActivityInPackage(int uid, + public final int startActivityInPackage(int uid, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, boolean onlyIfNeeded) { + + // This is so super not safe, that only the system (or okay root) + // can do it. + final int callingUid = Binder.getCallingUid(); + if (callingUid != 0 && callingUid != Process.myUid()) { + throw new SecurityException( + "startActivityInPackage only available to the system"); + } + final boolean componentSpecified = intent.getComponent() != null; // Don't modify the client's object! intent = new Intent(intent); // Collect information about the target of the Intent. - // Must do this before locking, because resolving the intent - // may require launching a process to run its content provider. ActivityInfo aInfo; try { ResolveInfo rInfo = @@ -3967,16 +3999,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } synchronized(this) { - if (mWatcher != null) { + if (mController != null) { // Find the first activity that is not finishing. HistoryRecord next = topRunningActivityLocked(token, 0); if (next != null) { // ask watcher if this is allowed boolean resumeOK = true; try { - resumeOK = mWatcher.activityResuming(next.packageName); + resumeOK = mController.activityResuming(next.packageName); } catch (RemoteException e) { - mWatcher = null; + mController = null; } if (!resumeOK) { @@ -4468,9 +4500,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - if (mWatcher != null) { + if (mController != null) { try { - int res = mWatcher.appNotResponding(app.processName, + int res = mController.appNotResponding(app.processName, app.pid, info.toString()); if (res != 0) { if (res < 0) { @@ -4486,7 +4518,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } } catch (RemoteException e) { - mWatcher = null; + mController = null; } } @@ -6611,7 +6643,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } /** - * TODO: Add mWatcher hook + * TODO: Add mController hook */ public void moveTaskToFront(int task) { enforceCallingPermission(android.Manifest.permission.REORDER_TASKS, @@ -6756,7 +6788,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // If we have a watcher, preflight the move before committing to it. First check // for *other* available tasks, but if none are available, then try again allowing the // current task to be selected. - if (mWatcher != null) { + if (mController != null) { HistoryRecord next = topRunningActivityLocked(null, task); if (next == null) { next = topRunningActivityLocked(null, 0); @@ -6765,9 +6797,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // ask watcher if this is allowed boolean moveOK = true; try { - moveOK = mWatcher.activityResuming(next.packageName); + moveOK = mController.activityResuming(next.packageName); } catch (RemoteException e) { - mWatcher = null; + mController = null; } if (!moveOK) { return false; @@ -7072,6 +7104,27 @@ public final class ActivityManagerService extends ActivityManagerNative implemen == PackageManager.PERMISSION_GRANTED) { return null; } + + PathPermission[] pps = cpi.pathPermissions; + if (pps != null) { + int i = pps.length; + while (i > 0) { + i--; + PathPermission pp = pps[i]; + if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid, + cpi.exported ? -1 : cpi.applicationInfo.uid) + == PackageManager.PERMISSION_GRANTED + && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) { + return null; + } + if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid, + cpi.exported ? -1 : cpi.applicationInfo.uid) + == PackageManager.PERMISSION_GRANTED) { + return null; + } + } + } + String msg = "Permission Denial: opening provider " + cpi.name + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid + ", uid=" + callingUid + ") requires " @@ -7657,14 +7710,22 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - public void setActivityWatcher(IActivityWatcher watcher) { + public void setActivityController(IActivityController controller) { enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, - "setActivityWatcher()"); + "setActivityController()"); synchronized (this) { - mWatcher = watcher; + mController = controller; } } + public void registerActivityWatcher(IActivityWatcher watcher) { + mWatchers.register(watcher); + } + + public void unregisterActivityWatcher(IActivityWatcher watcher) { + mWatchers.unregister(watcher); + } + public final void enterSafeMode() { synchronized(this) { // It only makes sense to do this before the system is ready @@ -8225,11 +8286,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen //Process.sendSignal(MY_PID, Process.SIGNAL_QUIT); } - if (mWatcher != null) { + if (mController != null) { try { String name = r != null ? r.processName : null; int pid = r != null ? r.pid : Binder.getCallingPid(); - if (!mWatcher.appCrashed(name, pid, + if (!mController.appCrashed(name, pid, shortMsg, longMsg, crashData)) { Log.w(TAG, "Force-killing crashed app " + name + " at watcher's request"); @@ -8237,7 +8298,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen return 0; } } catch (RemoteException e) { - mWatcher = null; + mController = null; } } @@ -8663,7 +8724,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen + " mDebugTransient=" + mDebugTransient + " mOrigWaitForDebugger=" + mOrigWaitForDebugger); pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities - + " mWatcher=" + mWatcher); + + " mController=" + mController); } } @@ -10810,6 +10871,29 @@ public final class ActivityManagerService extends ActivityManagerNative implemen mHandler.sendEmptyMessage(UPDATE_TIME_ZONE); } + /* + * Prevent non-system code (defined here to be non-persistent + * processes) from sending protected broadcasts. + */ + if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID + || callingUid == Process.SHELL_UID || callingUid == 0) { + // Always okay. + } else if (callerApp == null || !callerApp.persistent) { + try { + if (ActivityThread.getPackageManager().isProtectedBroadcast( + intent.getAction())) { + String msg = "Permission Denial: not allowed to send broadcast " + + intent.getAction() + " from pid=" + + callingPid + ", uid=" + callingUid; + Log.w(TAG, msg); + throw new SecurityException(msg); + } + } catch (RemoteException e) { + Log.w(TAG, "Remote exception", e); + return BROADCAST_SUCCESS; + } + } + // Add to the sticky list if requested. if (sticky) { if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, @@ -11755,10 +11839,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen config.reqTouchScreen = mConfiguration.touchscreen; config.reqKeyboardType = mConfiguration.keyboard; config.reqNavigation = mConfiguration.navigation; - if (mConfiguration.navigation != Configuration.NAVIGATION_NONAV) { + if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD + || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) { config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV; } - if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED) { + if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED + && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) { config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD; } } diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index 39a1ee050226f..c834b34e35688 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -41,7 +41,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub { final BatteryStatsImpl mStats; Context mContext; - + BatteryStatsService(String filename) { mStats = new BatteryStatsImpl(filename); } diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java index 2d58659dfd3b3..d4589118d0d7f 100755 --- a/services/java/com/android/server/am/UsageStatsService.java +++ b/services/java/com/android/server/am/UsageStatsService.java @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -617,7 +618,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput, - boolean deleteAfterPrint) { + boolean deleteAfterPrint, HashSet packages) { List fileList = getUsageStatsFileListFLOCK(); if (fileList == null) { return; @@ -633,7 +634,8 @@ public final class UsageStatsService extends IUsageStats.Stub { String dateStr = file.substring(FILE_PREFIX.length()); try { Parcel in = getParcelForFile(dFile); - collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput); + collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput, + packages); if (deleteAfterPrint) { // Delete old file after collecting info only for checkin requests dFile.delete(); @@ -648,7 +650,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw, - String date, boolean isCompactOutput) { + String date, boolean isCompactOutput, HashSet packages) { StringBuilder sb = new StringBuilder(512); if (isCompactOutput) { sb.append("D:"); @@ -678,7 +680,10 @@ public final class UsageStatsService extends IUsageStats.Stub { } sb.setLength(0); PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in); - if (isCompactOutput) { + if (packages != null && !packages.contains(pkgName)) { + // This package has not been requested -- don't print + // anything for it. + } else if (isCompactOutput) { sb.append("P:"); sb.append(pkgName); sb.append(','); @@ -765,6 +770,25 @@ public final class UsageStatsService extends IUsageStats.Stub { return false; } + /** + * Searches array of arguments for the specified string's data + * @param args array of argument strings + * @param value value to search for + * @return the string of data after the arg, or null if there is none + */ + private static String scanArgsData(String[] args, String value) { + if (args != null) { + final int N = args.length; + for (int i=0; i packages = null; + if (rawPackages != null) { + if (!"*".equals(rawPackages)) { + // A * is a wildcard to show all packages. + String[] names = rawPackages.split(","); + for (String n : names) { + if (packages == null) { + packages = new HashSet(); + } + packages.add(n); + } + } + } else if (isCheckinRequest) { + // If checkin doesn't specify any packages, then we simply won't + // show anything. + Log.w(TAG, "Checkin without packages"); + return; + } + synchronized (mFileLock) { - collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint); + collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages); } } diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java index 7a8d4e5ed40bd..a4b47b523baa3 100644 --- a/services/java/com/android/server/status/StatusBarPolicy.java +++ b/services/java/com/android/server/status/StatusBarPolicy.java @@ -626,7 +626,9 @@ public class StatusBarPolicy { && mBatteryThreshold > BATTERY_THRESHOLD_WARNING))) { // Broadcast the low battery warning mSentLowBatteryBroadcast = true; - mContext.sendBroadcast(new Intent(Intent.ACTION_BATTERY_LOW)); + Intent batIntent = new Intent(Intent.ACTION_BATTERY_LOW); + batIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mContext.sendBroadcast(batIntent); if (SHOW_LOW_BATTERY_WARNING) { if (false) { @@ -644,7 +646,9 @@ public class StatusBarPolicy { } else if (mBatteryThreshold < BATTERY_THRESHOLD_WARNING) { if (mSentLowBatteryBroadcast == true) { mSentLowBatteryBroadcast = false; - mContext.sendBroadcast(new Intent(Intent.ACTION_BATTERY_OKAY)); + Intent batIntent = new Intent(Intent.ACTION_BATTERY_OKAY); + batIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mContext.sendBroadcast(batIntent); } if (SHOW_LOW_BATTERY_WARNING) { if (mLowBatteryDialog != null) { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index c9dcd8b0dd2af..ba5c6e73680ab 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -322,7 +322,9 @@ public class TelephonyManager { /** * Returns the alphabetic name of current registered operator. *

    - * Availability: Only when user is registered to a network + * Availability: Only when user is registered to a network. Result may be + * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if + * on a CDMA network). */ public String getNetworkOperatorName() { return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ALPHA); @@ -331,7 +333,9 @@ public class TelephonyManager { /** * Returns the numeric name (MCC+MNC) of current registered operator. *

    - * Availability: Only when user is registered to a network + * Availability: Only when user is registered to a network. Result may be + * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if + * on a CDMA network). */ public String getNetworkOperator() { return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC); @@ -341,7 +345,7 @@ public class TelephonyManager { * Returns true if the device is considered roaming on the current * network, for GSM purposes. *

    - * Availability: Only when user registered to a network + * Availability: Only when user registered to a network. */ public boolean isNetworkRoaming() { return "true".equals(SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING)); @@ -351,7 +355,9 @@ public class TelephonyManager { * Returns the ISO country code equivilent of the current registered * operator's MCC (Mobile Country Code). *

    - * Availability: Only when user is registered to a network + * Availability: Only when user is registered to a network. Result may be + * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if + * on a CDMA network). */ public String getNetworkCountryIso() { return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY); diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java index 189959b7dba51..b8778f8fee0fe 100644 --- a/telephony/java/android/telephony/cdma/CdmaCellLocation.java +++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java @@ -27,6 +27,8 @@ public class CdmaCellLocation extends CellLocation { private int mBaseStationId = -1; private int mBaseStationLatitude = -1; private int mBaseStationLongitude = -1; + private int mSystemId = -1; + private int mNetworkId = -1; /** * Empty constructor. Initializes the LAC and CID to -1. @@ -35,6 +37,8 @@ public class CdmaCellLocation extends CellLocation { this.mBaseStationId = -1; this.mBaseStationLatitude = -1; this.mBaseStationLongitude = -1; + this.mSystemId = -1; + this.mNetworkId = -1; } /** @@ -44,6 +48,8 @@ public class CdmaCellLocation extends CellLocation { this.mBaseStationId = bundleWithValues.getInt("baseStationId"); this.mBaseStationLatitude = bundleWithValues.getInt("baseStationLatitude"); this.mBaseStationLongitude = bundleWithValues.getInt("baseStationLongitude"); + this.mSystemId = bundleWithValues.getInt("systemId"); + this.mNetworkId = bundleWithValues.getInt("networkId"); } /** @@ -67,6 +73,20 @@ public class CdmaCellLocation extends CellLocation { return this.mBaseStationLongitude; } + /** + * @return cdma system identification number, -1 if unknown + */ + public int getSystemId() { + return this.mSystemId; + } + + /** + * @return cdma network identification number, -1 if unknown + */ + public int getNetworkId() { + return this.mNetworkId; + } + /** * Invalidate this object. The cell location data is set to -1. */ @@ -74,6 +94,8 @@ public class CdmaCellLocation extends CellLocation { this.mBaseStationId = -1; this.mBaseStationLatitude = -1; this.mBaseStationLongitude = -1; + this.mSystemId = -1; + this.mNetworkId = -1; } /** @@ -87,9 +109,23 @@ public class CdmaCellLocation extends CellLocation { this.mBaseStationLongitude = baseStationLongitude; //values[3]; } + /** + * Set the cell location data. + */ + public void setCellLocationData(int baseStationId, int baseStationLatitude, + int baseStationLongitude, int systemId, int networkId) { + // The following values have to be written in the correct sequence + this.mBaseStationId = baseStationId; + this.mBaseStationLatitude = baseStationLatitude; //values[2]; + this.mBaseStationLongitude = baseStationLongitude; //values[3]; + this.mSystemId = systemId; + this.mNetworkId = networkId; + } + @Override public int hashCode() { - return this.mBaseStationId ^ this.mBaseStationLatitude ^ this.mBaseStationLongitude; + return this.mBaseStationId ^ this.mBaseStationLatitude ^ this.mBaseStationLongitude + ^ this.mSystemId ^ this.mNetworkId; } @Override @@ -108,7 +144,9 @@ public class CdmaCellLocation extends CellLocation { return (equalsHandlesNulls(this.mBaseStationId, s.mBaseStationId) && equalsHandlesNulls(this.mBaseStationLatitude, s.mBaseStationLatitude) && - equalsHandlesNulls(this.mBaseStationLongitude, s.mBaseStationLongitude) + equalsHandlesNulls(this.mBaseStationLongitude, s.mBaseStationLongitude) && + equalsHandlesNulls(this.mSystemId, s.mSystemId) && + equalsHandlesNulls(this.mNetworkId, s.mNetworkId) ); } @@ -116,7 +154,9 @@ public class CdmaCellLocation extends CellLocation { public String toString() { return "[" + this.mBaseStationId + "," + this.mBaseStationLatitude + "," - + this.mBaseStationLongitude + "]"; + + this.mBaseStationLongitude + "," + + this.mSystemId + "," + + this.mNetworkId + "]"; } /** @@ -139,6 +179,8 @@ public class CdmaCellLocation extends CellLocation { bundleToFill.putInt("baseStationId", this.mBaseStationId); bundleToFill.putInt("baseStationLatitude", this.mBaseStationLatitude); bundleToFill.putInt("baseStationLongitude", this.mBaseStationLongitude); + bundleToFill.putInt("systemId", this.mSystemId); + bundleToFill.putInt("networkId", this.mNetworkId); } } diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java index 25c512e385f0e..e583110d87bee 100644 --- a/telephony/java/com/android/internal/telephony/CommandsInterface.java +++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java @@ -880,7 +880,7 @@ public interface CommandsInterface { * ar.userObject contains the orignal value of result.obj * ar.result is null on success and failure */ - void sendBurstDtmf(String dtmfString, Message result); + void sendBurstDtmf(String dtmfString, int on, int off, Message result); /** * smscPDU is smsc address in PDU form GSM BCD format prefixed diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java index c8d384d8d5f6e..7f2b8496f592d 100644 --- a/telephony/java/com/android/internal/telephony/Phone.java +++ b/telephony/java/com/android/internal/telephony/Phone.java @@ -760,10 +760,12 @@ public interface Phone { * back to caller. * * @param dtmfString is string representing the dialing digit(s) in the active call + * @param on the DTMF ON length in milliseconds, or 0 for default + * @param off the DTMF OFF length in milliseconds, or 0 for default * @param onCompelte is the callback message when the action is processed by BP * */ - void sendBurstDtmf(String dtmfString, Message onComplete); + void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete); /** * Sets the radio power on/off state (off is sometimes diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index a26e7296b2b69..bcb1ccc04c0f4 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -685,7 +685,7 @@ public abstract class PhoneBase implements Phone { return null; } - public void sendBurstDtmf(String dtmfString, Message onComplete) { + public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone. Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone."); } diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java index 5b3c8dd4c1629..da002683a8953 100644 --- a/telephony/java/com/android/internal/telephony/PhoneProxy.java +++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java @@ -713,8 +713,8 @@ public class PhoneProxy extends Handler implements Phone { return mActivePhone.getCdmaEriIconMode(); } - public void sendBurstDtmf(String dtmfString, Message onComplete){ - mActivePhone.sendBurstDtmf(dtmfString,onComplete); + public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete){ + mActivePhone.sendBurstDtmf(dtmfString, on, off, onComplete); } public void exitEmergencyCallbackMode(){ diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java index 4db3e5bfcf8b1..690b38a7fa384 100644 --- a/telephony/java/com/android/internal/telephony/RIL.java +++ b/telephony/java/com/android/internal/telephony/RIL.java @@ -1068,10 +1068,13 @@ public final class RIL extends BaseCommands implements CommandsInterface { } public void - sendBurstDtmf(String dtmfString, Message result) { + sendBurstDtmf(String dtmfString, int on, int off, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_BURST_DTMF, result); + rr.mp.writeInt(3); rr.mp.writeString(dtmfString); + rr.mp.writeString(Integer.toString(on)); + rr.mp.writeString(Integer.toString(off)); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " : " + dtmfString); diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index b2e16c74ec3ad..7834018246215 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -118,6 +118,12 @@ cat include/telephony/ril.h | \ */ int RIL_RESTRICTED_STATE_PS_ALL = 0x10; + /** Data profile for RIL_REQUEST_SETUP_DATA_CALL */ + static final int DATA_PROFILE_DEFAULT = 0; + static final int DATA_PROFILE_TETHERED = 1; + static final int DATA_PROFILE_OEM_BASE = 1000; + + int RIL_REQUEST_GET_SIM_STATUS = 1; int RIL_REQUEST_ENTER_SIM_PIN = 2; int RIL_REQUEST_ENTER_SIM_PUK = 3; diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java index 9152211849d6c..02e9800d830fe 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java +++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java @@ -32,6 +32,9 @@ public class TelephonyIntents { * *

    * Requires the READ_PHONE_STATE permission. + * + *

    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"; @@ -50,6 +53,9 @@ public class TelephonyIntents { * *

    * Requires no permission. + * + *

    This is a protected intent that can only be sent + * by the system. */ public static final String ACTION_RADIO_TECHNOLOGY_CHANGED = "android.intent.action.RADIO_TECHNOLOGY"; @@ -66,6 +72,9 @@ public class TelephonyIntents { * *

    * Requires no permission. + * + *

    This is a protected intent that can only be sent + * by the system. */ public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED"; @@ -89,6 +98,9 @@ public class TelephonyIntents { * *

    * Requires the READ_PHONE_STATE permission. + * + *

    This is a protected intent that can only be sent + * by the system. */ public static final String ACTION_SIGNAL_STRENGTH_CHANGED = "android.intent.action.SIG_STR"; @@ -110,6 +122,9 @@ public class TelephonyIntents { * *

    * Requires the READ_PHONE_STATE permission. + * + *

    This is a protected intent that can only be sent + * by the system. */ public static final String ACTION_ANY_DATA_CONNECTION_STATE_CHANGED = "android.intent.action.ANY_DATA_STATE"; @@ -127,6 +142,9 @@ public class TelephonyIntents { * *

    * Requires the READ_PHONE_STATE permission. + * + *

    This is a protected intent that can only be sent + * by the system. */ public static final String ACTION_DATA_CONNECTION_FAILED = "android.intent.action.DATA_CONNECTION_FAILED"; @@ -148,6 +166,9 @@ public class TelephonyIntents { * *

    * Requires the READ_PHONE_STATE permission. + * + *

    This is a protected intent that can only be sent + * by the system. */ public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED"; @@ -163,6 +184,9 @@ public class TelephonyIntents { * *

    * Requires the READ_PHONE_STATE permission. + * + *

    This is a protected intent that can only be sent + * by the system. */ public static final String ACTION_NETWORK_SET_TIME = "android.intent.action.NETWORK_SET_TIME"; @@ -178,6 +202,9 @@ public class TelephonyIntents { * *

    * Requires the READ_PHONE_STATE permission. + * + *

    This is a protected intent that can only be sent + * by the system. */ public static final String ACTION_NETWORK_SET_TIMEZONE = "android.intent.action.NETWORK_SET_TIMEZONE"; @@ -187,6 +214,9 @@ public class TelephonyIntents { *

    . * This is to pop up a notice to show user that the phone is in emergency callback mode * and atacalls and outgoing sms are blocked. + * + *

    This is a protected intent that can only be sent + * by the system. */ public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS = "android.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS"; @@ -197,6 +227,9 @@ public class TelephonyIntents { *

      *
    • mdn - An Integer of the updated MDN number.
    • *
    + * + *

    This is a protected intent that can only be sent + * by the system. * *

    */ diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 290e1fc24b71f..5ec4020d6fdc1 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -40,14 +40,16 @@ public interface TelephonyProperties //****** Current Network - /** Alpha name of current registered operator. - * Availability: when registered to a network + /** Alpha name of current registered operator.

    + * Availability: when registered to a network. Result may be unreliable on + * CDMA networks. */ static final String PROPERTY_OPERATOR_ALPHA = "gsm.operator.alpha"; //TODO: most of these proprieties are generic, substitute gsm. with phone. bug 1856959 - /** Numeric name (MCC+MNC) of current registered operator. - * Availability: when registered to a network + /** Numeric name (MCC+MNC) of current registered operator.

    + * Availability: when registered to a network. Result may be unreliable on + * CDMA networks. */ static final String PROPERTY_OPERATOR_NUMERIC = "gsm.operator.numeric"; @@ -64,8 +66,9 @@ public interface TelephonyProperties static final String PROPERTY_OPERATOR_ISROAMING = "gsm.operator.isroaming"; /** The ISO country code equivalent of the current registered operator's - * MCC (Mobile Country Code) - * Availability: when registered to a network + * MCC (Mobile Country Code)

    + * Availability: when registered to a network. Result may be unreliable on + * CDMA networks. */ static final String PROPERTY_OPERATOR_ISO_COUNTRY = "gsm.operator.iso-country"; diff --git a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java index 2984fa8a576cd..3bbe0e17a86e3 100644 --- a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java +++ b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java @@ -187,22 +187,30 @@ public class WspTypeDecoder { } /** - * Decode the "Extension-media" type for WSP pdu - * - * @param startIndex The starting position of the "Extension-media" in this pdu - * - * @return false when error(not a Extension-media) occur - * return value can be retrieved by getValueString() method - * length of data in pdu can be retrieved by getValue32() method - */ + * Decode the "Extension-media" type for WSP PDU. + * + * @param startIndex The starting position of the "Extension-media" in this PDU. + * + * @return false on error, such as if there is no Extension-media at startIndex. + * Side-effects: updates stringValue (available with getValueString()), which will be + * null on error. The length of the data in the PDU is available with getValue32(), 0 + * on error. + */ public boolean decodeExtensionMedia(int startIndex) { int index = startIndex; - while (wspData[index] != 0) { + dataLength = 0; + stringValue = null; + int length = wspData.length; + boolean rtrn = index < length; + + while (index < length && wspData[index] != 0) { index++; } + dataLength = index - startIndex + 1; stringValue = new String(wspData, startIndex, dataLength - 1); - return true; + + return rtrn; } /** diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index 3362de83e954d..23eedfeb191ea 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -18,17 +18,23 @@ package com.android.internal.telephony.cdma; import android.app.ActivityManagerNative; import android.content.Context; +import android.content.ContentValues; import android.content.Intent; +import android.content.res.Configuration; import android.content.SharedPreferences; +import android.database.SQLException; +import android.net.Uri; import android.os.AsyncResult; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.Registrant; import android.os.RegistrantList; +import android.os.RemoteException; import android.os.SystemProperties; import android.preference.PreferenceManager; import android.provider.Settings; +import android.provider.Telephony; import android.telephony.CellLocation; import android.telephony.PhoneNumberUtils; import android.telephony.ServiceState; @@ -41,6 +47,10 @@ import com.android.internal.telephony.CommandException; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.Connection; import com.android.internal.telephony.DataConnection; +// TODO(Moto): need to move MccTable from telephony.gsm to telephony +// since there is no difference between CDMA and GSM for MccTable and +// CDMA uses gsm's MccTable is not good. +import com.android.internal.telephony.gsm.MccTable; import com.android.internal.telephony.IccCard; import com.android.internal.telephony.IccException; import com.android.internal.telephony.IccFileHandler; @@ -56,6 +66,10 @@ import com.android.internal.telephony.RILConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyProperties; +import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; +import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC; +import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY; + import java.util.List; import java.util.Timer; import java.util.TimerTask; @@ -154,6 +168,23 @@ public class CDMAPhone extends PhoneBase { String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false"); mIsPhoneInECMState = inEcm.equals("true"); + // Sets operator alpha property by retrieving from build-time system property + String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha"); + setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, operatorAlpha); + + // Sets operator numeric property by retrieving from build-time system property + String operatorNumeric = SystemProperties.get("ro.cdma.home.operator.numeric"); + setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric); + + // Sets iso country property by retrieving from build-time system property + setIsoCountryProperty(operatorNumeric); + + // Sets current entry in the telephony carrier table + updateCurrentCarrierInProvider(operatorNumeric); + + // Updates MCC MNC device configuration information + updateMccMncConfiguration(operatorNumeric); + // Notify voicemails. notifier.notifyMessageWaitingChanged(this); } @@ -427,13 +458,7 @@ public class CDMAPhone extends PhoneBase { } public String getSubscriberId() { - // Subscriber ID is the combination of MCC+MNC+MIN as CDMA IMSI - // TODO(Moto): Replace with call to mRuimRecords.getIMSI_M() when implemented. - if ((getServiceState().getOperatorNumeric() != null) && (getCdmaMIN() != null)) { - return (getServiceState().getOperatorNumeric() + getCdmaMIN()); - } else { - return null; - } + return mSST.getImsi(); } public boolean canConference() { @@ -630,7 +655,7 @@ public class CDMAPhone extends PhoneBase { mCM.stopDtmf(null); } - public void sendBurstDtmf(String dtmfString, Message onComplete) { + public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { boolean check = true; for (int itr = 0;itr < dtmfString.length(); itr++) { if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) { @@ -641,7 +666,7 @@ public class CDMAPhone extends PhoneBase { } } if ((mCT.state == Phone.State.OFFHOOK)&&(check)) { - mCM.sendBurstDtmf(dtmfString, onComplete); + mCM.sendBurstDtmf(dtmfString, on, off, onComplete); } } @@ -1244,4 +1269,66 @@ public class CDMAPhone extends PhoneBase { editor.commit(); } + /** + * Sets PROPERTY_ICC_OPERATOR_ISO_COUNTRY property + * + */ + private void setIsoCountryProperty(String operatorNumeric) { + if (TextUtils.isEmpty(operatorNumeric)) { + setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, ""); + } else { + String iso = ""; + try { + iso = MccTable.countryCodeForMcc(Integer.parseInt( + operatorNumeric.substring(0,3))); + } catch (NumberFormatException ex) { + Log.w(LOG_TAG, "countryCodeForMcc error" + ex); + } catch (StringIndexOutOfBoundsException ex) { + Log.w(LOG_TAG, "countryCodeForMcc error" + ex); + } + + setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, iso); + } + } + + /** + * Sets the "current" field in the telephony provider according to the build-time + * operator numeric property + * + * @return true for success; false otherwise. + */ + // TODO(Moto): move this method into PhoneBase, since it looks identical to + // the one in GsmPhone + private boolean updateCurrentCarrierInProvider(String operatorNumeric) { + if (!TextUtils.isEmpty(operatorNumeric)) { + try { + Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"); + ContentValues map = new ContentValues(); + map.put(Telephony.Carriers.NUMERIC, operatorNumeric); + getContext().getContentResolver().insert(uri, map); + return true; + } catch (SQLException e) { + Log.e(LOG_TAG, "Can't store current operator", e); + } + } + return false; + } + + /** + * Updates MCC and MNC device configuration information for application retrieving + * correct version of resources + * + */ + private void updateMccMncConfiguration(String operatorNumeric) { + if (operatorNumeric.length() >= 5) { + Configuration config = new Configuration(); + config.mcc = Integer.parseInt(operatorNumeric.substring(0,3)); + config.mnc = Integer.parseInt(operatorNumeric.substring(3)); + try { + ActivityManagerNative.getDefault().updateConfiguration(config); + } catch (RemoteException e) { + Log.e(LOG_TAG, "Can't update configuration", e); + } + } + } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java index f2b07a8803565..fef6d3c633a7a 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java @@ -21,6 +21,7 @@ import android.util.EventLog; import android.util.Log; import com.android.internal.telephony.CommandException; +import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.DataLink; import com.android.internal.telephony.RILConstants; @@ -142,7 +143,8 @@ public class CdmaDataConnection extends DataConnection { lastFailTime = -1; lastFailCause = FailCause.NONE; receivedDisconnectReq = false; - phone.mCM.setupDataCall(Integer.toString(RILConstants.CDMA_PHONE), null, null, null, + phone.mCM.setupDataCall(Integer.toString(RILConstants.CDMA_PHONE), + Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), null, null, null, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE)); } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index e75a3331bb649..23a0520fbdf2d 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -19,11 +19,8 @@ package com.android.internal.telephony.cdma; import android.app.AlarmManager; import android.content.ContentResolver; import android.content.Context; -import android.content.ContentValues; import android.content.Intent; import android.database.ContentObserver; -import android.database.SQLException; -import android.net.Uri; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; @@ -35,7 +32,6 @@ import android.os.SystemProperties; import android.provider.Checkin; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; -import android.provider.Telephony; import android.provider.Telephony.Intents; import android.telephony.ServiceState; import android.telephony.SignalStrength; @@ -64,6 +60,7 @@ import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERAT import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; +import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC; import java.util.Arrays; import java.util.Date; @@ -571,7 +568,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { try { registrationState = Integer.parseInt(states[0]); radioTechnology = Integer.parseInt(states[3]); - baseStationId = Integer.parseInt(states[4], 16); + baseStationId = Integer.parseInt(states[4]); baseStationLatitude = Integer.parseInt(states[5], 16); baseStationLongitude = Integer.parseInt(states[6], 16); cssIndicator = Integer.parseInt(states[7]); @@ -608,7 +605,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { // values are -1 if not available newCellLoc.setCellLocationData(baseStationId, baseStationLatitude, - baseStationLongitude); + baseStationLongitude, systemId, networkId); if (reasonForDenial == 0) { mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN; @@ -634,27 +631,6 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { } else { newSS.setOperatorName(opNames[0], opNames[1], opNames[2]); } - - if (!(opNames[2].equals(currentCarrier))) { - // TODO(Moto): jsh asks, "This uses the MCC+MNC of the current registered - // network to set the "current" entry in the APN table. But the correct - // entry should be the MCC+MNC that matches the subscribed operator - // (eg, phone issuer). These can be different when roaming." - try { - // Set the current field of the telephony provider according to - // the CDMA's operator - Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"); - ContentValues map = new ContentValues(); - map.put(Telephony.Carriers.NUMERIC, opNames[2]); - cr.insert(uri, map); - // save current carrier for the next time check - currentCarrier = opNames[2]; - } catch (SQLException e) { - Log.e(LOG_TAG, "Can't store current operator", e); - } - } else { - Log.i(LOG_TAG, "current carrier is not changed"); - } } else { Log.w(LOG_TAG, "error parsing opNames"); } @@ -665,8 +641,15 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { if (cdmaSubscription != null && cdmaSubscription.length >= 4) { mMdn = cdmaSubscription[0]; - mHomeSystemId = Integer.parseInt(cdmaSubscription[1], 16); - mHomeNetworkId = Integer.parseInt(cdmaSubscription[2], 16); + // TODO: Only grabbing the first SID/NID for now. + if (cdmaSubscription[1] != null) { + String[] sid = cdmaSubscription[1].split(","); + mHomeSystemId = sid.length > 0 ? Integer.parseInt(sid[0]) : 0; + } + if (cdmaSubscription[2] != null) { + String[] nid = cdmaSubscription[2].split(","); + mHomeNetworkId = nid.length > 0 ? Integer.parseInt(nid[0]) : 0; + } mMin = cdmaSubscription[3]; } else { @@ -1437,4 +1420,19 @@ final class CdmaServiceStateTracker extends ServiceStateTracker { return mMin; } + /** + * Returns IMSI as MCC + MNC + MIN + */ + /*package*/ 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. + String operatorNumeric = SystemProperties.get(PROPERTY_ICC_OPERATOR_NUMERIC, ""); + + if (!TextUtils.isEmpty(operatorNumeric) && getCdmaMin() != null) { + return (operatorNumeric + getCdmaMin()); + } else { + return null; + } + } } diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java index c7e61da3f8d77..55f48b1fbfa7c 100644 --- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java +++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java @@ -55,8 +55,6 @@ public final class RuimRecords extends IccRecords { private String mImsi; private String mMyMobileNumber; - private String mSid; - private String mNid; private String mMin2Min1; private String mPrlVersion; @@ -125,21 +123,12 @@ public final class RuimRecords extends IccRecords { adnCache.reset(); - phone.setSystemProperty(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, null); - phone.setSystemProperty(TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, null); - // recordsRequested is set to false indicating that the SIM // read requests made so far are not valid. This is set to // true only when fresh set of read requests are made. recordsRequested = false; } - /** Returns null if RUIM is not yet ready */ - public String getIMSI_M() { - // TODO(Moto): mImsi is not initialized, fix. - return mImsi; - } - public String getMdnNumber() { return mMyMobileNumber; } @@ -242,8 +231,6 @@ public final class RuimRecords extends IccRecords { m_ota_commited = false; } mMyMobileNumber = localTemp[0]; - mSid = localTemp[1]; - mNid = localTemp[2]; mMin2Min1 = localTemp[3]; mPrlVersion = localTemp[4]; diff --git a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java index 55e5adc8ac66e..89de8673bb4e5 100644 --- a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java +++ b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java @@ -22,6 +22,7 @@ import android.util.EventLog; import android.util.Log; import com.android.internal.telephony.CommandException; +import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.DataConnection; import com.android.internal.telephony.DataLink; import com.android.internal.telephony.Phone; @@ -83,7 +84,8 @@ public class PdpConnection extends DataConnection { lastFailCause = FailCause.NONE; receivedDisconnectReq = false; - phone.mCM.setupDataCall(Integer.toString(RILConstants.GSM_PHONE), null, apn.apn, apn.user, + phone.mCM.setupDataCall(Integer.toString(RILConstants.GSM_PHONE), + Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), apn.apn, apn.user, apn.password, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE)); } diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java index 22adc19ef061d..f71ea4853e180 100644 --- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java +++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java @@ -937,7 +937,7 @@ public final class SimulatedCommands extends BaseCommands * ar.userObject contains the orignal value of result.obj * ar.result is null on success and failure */ - public void sendBurstDtmf(String dtmfString, Message result) { + public void sendBurstDtmf(String dtmfString, int on, int off, Message result) { resultSuccess(result, null); } diff --git a/tests/AndroidTests/AndroidManifest.xml b/tests/AndroidTests/AndroidManifest.xml index 55d4d64bf5473..845f547496412 100644 --- a/tests/AndroidTests/AndroidManifest.xml +++ b/tests/AndroidTests/AndroidManifest.xml @@ -48,6 +48,7 @@ + diff --git a/tests/AndroidTests/run_test.sh b/tests/AndroidTests/run_test.sh index 0cdf63f538acc..7ada698db81a1 100755 --- a/tests/AndroidTests/run_test.sh +++ b/tests/AndroidTests/run_test.sh @@ -1,4 +1,4 @@ framework=/system/framework bpath=$framework/core.jar:$framework/ext.jar:$framework/framework.jar:$framework/android.test.runner.jar -adb shell exec dalvikvm -Xbootclasspath:$bpath -cp system/app/AndroidTests.apk \ +adb shell exec dalvikvm -Xbootclasspath:$bpath -cp /system/app/AndroidTests.apk:/data/app/com.android.unit_tests.apk \ com.android.internal.util.WithFramework junit.textui.TestRunner $* diff --git a/tests/AndroidTests/src/com/android/unit_tests/HtmlTest.java b/tests/AndroidTests/src/com/android/unit_tests/HtmlTest.java index 27da4f1c72aef..027730fa3f43c 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/HtmlTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/HtmlTest.java @@ -16,11 +16,25 @@ package com.android.unit_tests; +import android.content.res.ColorStateList; +import android.content.res.Resources; import android.graphics.Typeface; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; -import android.text.*; -import android.text.style.*; +import android.text.Html; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.style.ForegroundColorSpan; +import android.text.style.QuoteSpan; +import android.text.style.StrikethroughSpan; +import android.text.style.StyleSpan; +import android.text.style.SubscriptSpan; +import android.text.style.SuperscriptSpan; +import android.text.style.TextAppearanceSpan; +import android.text.style.TypefaceSpan; +import android.text.style.URLSpan; +import android.text.style.UnderlineSpan; import junit.framework.TestCase; @@ -35,14 +49,54 @@ public class HtmlTest extends TestCase { s = Html.fromHtml("something"); colors = s.getSpans(0, s.length(), ForegroundColorSpan.class); - assertEquals(colors[0].getForegroundColor(), 0xFF00FF00); + assertEquals(1, colors.length); + assertEquals(0xFF00FF00, colors[0].getForegroundColor()); s = Html.fromHtml("something"); colors = s.getSpans(0, s.length(), ForegroundColorSpan.class); - assertEquals(colors[0].getForegroundColor(), 0xFF000080); + assertEquals(1, colors.length); + assertEquals(0xFF000080, colors[0].getForegroundColor()); s = Html.fromHtml("something"); colors = s.getSpans(0, s.length(), ForegroundColorSpan.class); + assertEquals(0, colors.length); + } + + @MediumTest + public void testResourceColor() throws Exception { + ColorStateList c = + Resources.getSystem().getColorStateList(android.R.color.primary_text_dark); + Spanned s; + TextAppearanceSpan[] colors; + + s = Html.fromHtml("something"); + colors = s.getSpans(0, s.length(), TextAppearanceSpan.class); + assertEquals(1, colors.length); + assertEquals(c.toString(), colors[0].getTextColor().toString()); + + s = Html.fromHtml("something"); + colors = s.getSpans(0, s.length(), TextAppearanceSpan.class); + assertEquals(1, colors.length); + assertEquals(c.toString(), colors[0].getTextColor().toString()); + + s = Html.fromHtml("something"); + colors = s.getSpans(0, s.length(), TextAppearanceSpan.class); + assertEquals(1, colors.length); + assertEquals(c.toString(), colors[0].getTextColor().toString()); + + s = Html.fromHtml("something"); + colors = s.getSpans(0, s.length(), TextAppearanceSpan.class); + assertEquals(1, colors.length); + assertEquals(c.toString(), colors[0].getTextColor().toString()); + + s = Html.fromHtml("something"); + colors = s.getSpans(0, s.length(), TextAppearanceSpan.class); + assertEquals(1, colors.length); + assertEquals(c.toString(), colors[0].getTextColor().toString()); + + s = Html.fromHtml("something"); + colors = s.getSpans(0, s.length(), TextAppearanceSpan.class); assertEquals(colors.length, 0); } diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java index c4f1ab6ad6b72..4c5fefc43b6f9 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java @@ -107,8 +107,6 @@ public class SearchManagerTest extends ActivityInstrumentationTestCase2 - + + + + + + + - diff --git a/tests/DpiTest/res/drawable-240dpi/logo240dpi.png b/tests/DpiTest/res/drawable-hdpi/logo240dpi.png similarity index 100% rename from tests/DpiTest/res/drawable-240dpi/logo240dpi.png rename to tests/DpiTest/res/drawable-hdpi/logo240dpi.png diff --git a/tests/DpiTest/res/drawable-120dpi/logo120dpi.png b/tests/DpiTest/res/drawable-ldpi/logo120dpi.png similarity index 100% rename from tests/DpiTest/res/drawable-120dpi/logo120dpi.png rename to tests/DpiTest/res/drawable-ldpi/logo120dpi.png diff --git a/tests/DpiTest/res/drawable-nodpi/logonodpi120.png b/tests/DpiTest/res/drawable-nodpi/logonodpi120.png new file mode 100644 index 0000000000000000000000000000000000000000..46bbd5bd3d485ba132f14fd5b04a7c6b69004d0c GIT binary patch literal 5178 zcmV-A6vgX_P)002t}0ssI2w=C_w0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU_+(|@1RCwCdTf3K5)fGSc&h1PX`pC>^ zI)O3i)M3rgl z?>plk5FX#-e&?R&e*E^{zYE`g|9$y?|3js~PyRSiZ_r$ z$!BI$=TWPa64p;>aup>j45bn*qaenq73AhfCUmt|Zb)Gd{67|Q*>-WJb^}^FUm+pt zjKba^QJ92Dx*biM(FnYue5G#`%aDko?yO1-%NKPqArJwPe6 z{Q$u%k!+(|CE{Hp*NtF%Om!&gN|11hsuIOsZA-mn$imp9Cz&)8o-S@wOc48pU_Et3 z7?w=i7*1*}(0{}ryj@}3Tn8cK0a;t3Ee%p>i^Mc39Oay3lL{ooRwD+<2}t*@(PBtd zUepq5zYsfALrJ0$!I-&8Qj=O#sBOkJFFhhL%5waWjA8F|EYb3~C8V?%nuvja6Nz&} z8IPZ`Q_Wr20S8469#ia#ZX`h2>Xf6gB{8h_U+wHLS%w^?7$um_jk1$3UC1Eq5ydH% z?QV5pQ>&17%_j<=(!%OPe)r@LqzxwUQAeUJyS>ebTNjz2OLReHyG6oQXhOc9Tdt>* zECG|zWJX&cP&&>2GEgzipdeloS5A~2yJ0*NwE(dwdSx+%lmG=^5!0kwuYKj)?9eHK z40DU7O?A2__-98opcCE*D zmySwidbm%qbL}q3Cjce-7XqMg4rZ47{*Bn?)@Gzm+wcVsLW4}k^ooXMV?dpA9kZ>Z4Fs)QQ4F9l!%?zD zX2BQ7tfB~J+kuCHhzz4(1IQhEZ@}o$2!_*%Cdlk!5Lm(YNjMZem}zGZ)S3)Ik6eAw zovgg{<8a@OjyJm^VKyYFJ#;up0$oWDwfF$0k?N>XZ2%9!V`5487)!)DXuFF1i(%g` zS0e@BVXk$8{B=uw5s>W}WkczZUqcL!3uzLT#F)VC8QBm?Fa(}LnZTHYNldVL6+@JB zv5vYwJ}XM0FK;R(N182N0QwVgkJm&W^-lC(12z+|D0UaiB>E}&CX+ksl|~y4(jjS3 zilWTjb|`|vBIuv(p&2&@P*@B}8LS4?3N`=`PP+>oFaje(8)4%?jhfz_%x*VF5Jd+x zis!=|MK{1qhE0UrnFlDZA&+j62290pv<40BR0NtTij?UzN5rTVJ@)9EL=osn$WIc} z%YlPOHkcz2CIPER$Op$5CU;>TAzNe6^c#P)If+V5DvfO8Z&;s7`6SIMghSDCeXRk$X}i%DFru1zbpzw78}R z*-1+1l(xmf0Rn+J z-xBid>O9-@2Ju$1^(e_Jppe2UL5w-ou7=8>iNV4m$#@NQ+SS1X2TUm-{MCRZC*Lh) z)Ei^)!;dR1A2EmF#u0+TkDxjwSqiC&e4D{0mfm~!Yn6?=_zkzLEZ8dPz*)ZiW^u-Q> zvQUjv$Fl9d!Ted*H?Q3Ekq7lu#EV3?G6LUP0fHli4*I}yErR`q0f=QH`ceg`l0=+??eA(PJU;91DxqBdk%(KtxagxU;eb#cKn2vFvoO5T3786&b1-3fV>(@V6efpWD zrAG!(sROus_wI=kC-*M@YH?xd;K3I@|LpT&n47EX8HRCywY9bS)578-wat(J{t?=; zSs=PNw|%IuBE@|x`i2Z5v_sn&7V{<#_wR4k5A{_oIgpuat>BOZ&LZQZ#ueCQtcxbH zD6)a*mZ{6y$rC3wHa?o4pBKH6tUjDQd-m?#e;qk;xX$9{#>Sz;N3MT(ZFOa({`Tst z$8X-;ID7VV?djsB%g2wOxVpYxm(a~#8)J}TA6U2b!r_RQDS*I$dzbB0-MUVUWC}V)dHV>u~t+;WKAWUAgkk`ua6b*&)60#+yrv z3r#X%IC}KRlTYotx_<4M)zvS*x?Pud;>7X#hgJRDxwk(1{MO3KN)hzLt7{8j3)v2H zR;8T!7WCogpu}9CXfk`Xb~;44&eu)@t=fp3FKxF-J&%GDB~PLC(e|x8wXm=-$z0dJ z4?p~iCf&2vdU3He*xcN#`*ZWgM*V#7`2(!6Pd~k{zTUd^SzS|=&9A@y`smS@ckNny z?6JL- zey#Fcmv{U2?L&u-?A$qj{=(av_wK*HzOJF6oad!WSC*IeR`K54ym#^9mHqpl|Kf{V zJ9g~QRuIE9#=VYI#Pf?Q@6i*6*x5r16h$lzcFbm|NnZh%#5LcZF&zYM!KKTWtD+t~ zdbs|+dGDTX1R6fB$6KfO=DD})hmSwrSXx}Hqa8eW;E5+z)YG-mYbPImcx`@uXPrs&aaiHNJRAvP9<<&*5t)0Jm_1fCnxqbUq*rl@4 z-oE`6&%8=zTg<{@y|pQ7D3B0g;z)$ztkqUvb4TZmOi8$N=Z@Noa^uF0($%=Ms?=4hP}j+uaO~KzJ$rW7^Q>2zWR_A- zxPINed-sFc?6ud9RjGUF(2=?$_cu4!uYRBe4sj#ZO1=2vk!pwUZQiSvwu-}{!!K1^ zAZm?$w+-`vaTf$alQSoJ1k4e2b9n^n3tMB<$_z_yQ&M$PvWZl_`|i8CJeI~Tkn-nu zzx~Y&%EiC@dF{f5%a@xo*uVd|*I)m`g9o$P$rDdJx&HoN*Un!!b?VH*!md-V|MA)f z*K5zso^@kd4|#d--fEEQ=Y9L0I(P2PhaURbZ1w}rNreU+Wfga+A|@P;Fcqp8Y-EHkVFG}bx1a|i70C>XOTS!QUAcPo zeU{<2vpt5ivYDuhf)itqIQb=5t#J!~%n#*B*8fzGGlxY{y$5KOKPS3$r) zJsfWVY75<|$L7dv8^mr+qp9Qg2RhJ|kd%=u*a~|*Bnhg*RlmMmEipEcoZ*b|7D*|Q z4TPi{WM@nv#dI_u2rg!$B~_s$k`@PS62-UU)8JH*0cs+lUU+~r=`&O(ASZq_JmhKC zB@GoegKcc{tI)v%{PQ1wuQ&YnKMzd4bO8;mL$PkKG16MtnFf7q;ay?foYV0mLevpgx0|B#M}xnuO!v`9FbAoQdUCpb*!&SL|PnVxryZ)RTof8 zBkg77#u-DI0BeONut!&6h#90Qi37F}T(Kz6$&%VYxxNaTDi%K%ii@5;_w0Tjzbf<$ zG@FN-x&zw6w-pUW&w$Htlxwt^*iq(~!TW{1;YjlN?Pfl&F-NS}|hbu>zEDig7crdkbwxTVP;u7jlfy6|Fc;w@V` zsFf*$)3_+6ye&lzW=kMM>y~jW2G;;oe85w?RB{=>cYM?X%o%IPGmWZBY=edgHsbz;=P^@wsbGm-)s0>iH&QuZyf*a!)jycc{6}rdz zrY?}E1Zs?1qA8yXavFcyTZ*Fz$~5gC7~g?-7>JP*YC=qwNBZGl98Js&tK#WZ&2Uo* zrk<20DisV2*^f-$(poBcI0jBdjYTx&F;Ur$LFz;l!)oX?&9E;{T2)&Lk(J}r1GdX( zl|MylPO47;PzdMSo z8Vd>{2|;)kLTMFJ1_e5S&J99+9jr3u)CRYP3eem^fkI0dDfdOSvs6Sic6(ZBagHQJn6G|^ZB4SsO60qg-H@@2Cz`0&4QrwLAv56s-3CfTjXbCg~V^=^a zS(pMI&}a?<=r`;DkpLN=(=j+JYzeYw%QT|nOjLlb;c+c>Gi2;=)9S%@!O>uTw#8Ah z&rPT*VEhq_VT)y8A|m$}$d9fnS;59ZCl>}tX*w_ps7m`??2$dr3fpQ}51cu|57U7& zT6L8kZ<)vfg>+|p zZmHY6YlEwNHpSCx0v`peb`# zk%r79!xV+czNzEYXOM@iyYWd9NcoU5B|T`7Kjcy&&Luor;Y#fZ7td>nu*dKxKu#wm om`jN4JqY9}2<%kf=Kl#W09eg7m%_(`=Kufz07*qoM6N<$f+I#q)|{_&6L|Gy+9{N=r-c*Oi&+OPV* z*v7t-|Gwdp8#c7_N%G(I2VJM{B5@qD@znbJy$8bQ8SYMx)KRscxW}zXxZothqbdgj zeS=8-ZT?m^>HuK3Bzobx|NI@|!)QD6l+-h}J4F9iPi{{Z^WUj|YvX87PV{d2-ASKV z_{7uq<%6MHhV;+TZnj@+F{ABcfe0PELh=V+E?@7apCU;=Ir?~^w^;8R?b+6y=b!yh zA<04ASSJ{Ds&o`>`s-y7MGAUH{mgA+A95dTKSvu;eU>I8m`~guTLN5o>Y;7Y(VybH zgXq>exONwO4D{ybF<|9l2;I!`D==~QtD2b5)AmOh7LU;F*$L-sxj@5(kw@C@Jg$2E z719S*Zx6EJihZ@AKU3*iDU1>NSZoqR?6K$rfX~EaqX-if6iFPc*rLxtZEVyaz6$xg z*%gvRbvPa^L3x<6$kKJ1j(bpJ!gs}=#fcZm{CD;tijO7R8kb4x`CQ#0sN^oZx(94{ zAk8B-e?kgESWlQ(NShaG)>Rq?)d+v1DRyvp%mX z)d*<%rR`nUTOF7_Tcoy7=lxVK>bE)_Fcn(QkeYh)b%(AF`(^qZnI%(2uM@Ho7WQNo z3h}(A19g;1$K8k9FYa{v#j3NGib)oVnmr`?BS)o^>B%J4W_fg?mcERHYl&)Q-f!VON&G0u(nLu- za&YMew=W#p?}p}N>a#7b*W&sX_u2e5B#~L-hvBjG7wipThm8F2PVo z4uj4frcd2NcBfKTUqZI2NeWmdOyX6ovUr#kS(&mHQ6-nm%>w*MpqqQxd?EV5qrjN@ zfF$s8=vRWR1JDC$huLJRy6k#Z=o#rw{zK2JTAG&(xl*}+Djjn`Dh4RR;DmKN)ld`?#gO(V{U>g$LdCiO1^$59uq`Su@BAeNwee0+yVr@ zUs`mPEM)S)#ja^b>e-sLPHNADP6=~sbb7(IS$%k@58t<}x(|qZ1ojKJT4Y$3CPK9E zHirF!Ruf_I1N+($0EkoNVjPOYj=!){=Ts`|3zReY+VpCnM}2^hhKuqO5R3 z*4W7`3!|A!U69Sd2O(nEV55)A@dQ{mOSqf**JPfaJEa4-*P~5|e&2|>#ZccD0iDVg zra?^>qmv`p12lw{-dxhK)Q2UDB%6>93`>^A5SU4_1SMW$)7)&!ELU1$9y!nWPQ1yk)fRDFZSn+8V5+oJ1 zK3{EE6B~-mu~Hr}D$!+P;+6HWb-r61wn62TV9F>7J3h zMoITET*)ND#KlhQs>W@L+8G5vI7qXrxi6v@W|X?G5k#Q3d|z=4Fc{B4jFTjZ!#4NC zC7T}5BCr|knc+TzVv7N8jG_qkiKpcq+>a#C(IcRR4`)#^1u%#!7#(#GS$LuB^Dx93 z950DWEc;xgG{hnS`ZZ5zfG!u{GtIfM0dOS|OjEEuncYWe+9SJ;AMqjy&z)5Tsgt@4 z{oc@IdkB_Q-8$AR$(D-mqKi!WKKM?Ivz_z+aHVH4Fxc#L8nJL<{< zXmL-6PzcxbQ}*2u2Fgf`DC$7MkbABV27h6GN^qN}t1c&pfGFN#Zvo(SC2Y5Ry~IVq z7!reJj@$Z!SjHpc+Co$zIVN~`9BrssBKDf?A-1oT-^eUg4XRel+T3FG6u{0bVaUn6 z?QRiN<%<~$$Ph<6)aCoTgrMggRQW2v3-%=_@v9KK#lcVqoQ{Cwbe{M0w17BR0kR~9 z<;}aSNSOxTaS=s}EHbv(5XA~1i6KQYh!7}3TR7e>7NnA8Kt@Hzv>6tGG6T7Y(3ddu zMiMUz{J~cEM7j0&i7d<`#T`<8Az^@fxOLXr?rsZZ%-nll8cO!42#tzENt6@<`C{P)wCt3_SKX6AKzk|KK7gYb4fE(dx(tHMen|JY zp~vWXf`H4AWmt+yeor0>8kO_X93d;AmYqQ}5uD^IGUmB`9{6NgzedO)X@=|njY3`A*)gr;wP+@EDVg1nF+Hv z5*l*h9n3>KlX6fxm`8+)zYOLz_ZVq_+_Nt@(sl?r76xElIfqZ-46u1{^U}&G!_mX2 zRBf(TLqgW5X>8J1$_<-so}FqFckG%cnH5F$91H@8YU`6tF*NPM2nc0jK-ScaTMk*A z?($|$OBuNh3XIHxqr(<+UrhyqI5mAeb``x6hhsggM@)%fpqr*N_^n`EbqS+IG2BGx z5(4u)F%!uF;VJ{`gdrDf;Drw36xRBQI8a0G7J)|5i6Q1^rmW)5u3L^dnk13A=`N=b zPph8LnXXllZJ?St$d(H1A=K}PIDp9V~|eT63>e! zBE3-{Ke~Cu-7}V!^X(R#M2ih$+zncMu8}*ltH?kDGvNF`qp8lCGAlK#P0s{^X-vm~ z$eZr)PjGpP4D}w*`h4~5RVLd`Fkj*%0vH6=XkU`$zMM6dMVJdBj4v5dY8g6C9i$QJ zb>|H-wZ(uQ1mvy}CgNtIuNT0HI%NlAhd2H+wk9}Gk=qSB@k`y#&L^9H)=Q_HdvaqE zR%UQBR|hts0-RGDYmT%6Y&qjn63^iUGJDYM>CTIEvC5P%Q8UcTv-mP@==FRfQzI`8W!h#8@>xF)dJ1y#ol&$B^ zo%`aKzI6Ti2S^~h6tnrkeHN#1b~0Py^u1!26y-={YBhbZCF#<|ORtTiMcgrFxyX1A#Xl3%slvT-_|G9p*3wD*DDSvcZF*W6jsx-=TEyK8a^~&MHhj^-V zuHf1}Tlix1o2s+Oy>lE>|;5r8#tvqw{Jgp>Qwpk-~a8(_JISpKf3j|fA{sXXJ08I_UTXm z&8(QpGm)(}Ut3$#L_*iaY}Qz_!P#n(xD{$)CdCljl)m!gv)A5w`{}2iaMdO`QT&Y| z#cea$Nln#*_b@iMiG+I`O}%Ez9YZw(c2Dho>QfKcgNDJhb&-|(xO(MEnW+N@4*bhM zU)nyfopWBVv)QAv&yQa@S044V&pur~EgSdj*?aQji5FiyeevRj)2Cl5axqoo+$_m7 zuUXY;dc|2umMNO2r2}38^_rm;uOrqYYV-KhHh^qC*L{PK^>ZaX_iiUlY$UjBdKyU#!Kou``k+~{UupNSBq>bmdZ zp{L`yVjknFO-H6;5U?<&WJO&e4y#dmStgkXJsKR(C%AU)THF5RuY9%KSW!%6#hpKY zacAe!uYPs0Y`=N)!?r`2l-#Wl_Izwl+xXG#+hs<|Y_^$t_0@}I1yz|%-+c6VnX<&* zX8ro*FE5lcm*>$&dg1(~=XOsOJ@DXX4nMqe#BK+HZex)mI-?3^&3Z|ofy)`{F*B>! zDLvx&mVT0j(!(BCF*I5)(4^+I*Is|&h422)e_#Lo@8AFR)i(|t*e*}IEYDf-0AbZj zAm2@OiJd=xq5OXGZ4&f8>t?|aXm=teLfI(+B{ zKR8`B&QpMx&8Y0BW!>$YZ_Y~Xkz>c^XEJ+_^EBMQe}4d&^{ecb>kfH6|0sJOd*oQz z{_eZ)x#wk(43d^rN+vpUlkhC6vlG)Vy9aNWQ4Ke876a`UWg?W_SP(!-)j~GcylmgQXU}}MeTSPyg9osw{L$%cXmE5Do~F@1^O?gj2Wkro znXzq&M0poC*fdUo;3G1kQr&-$K+>oD7}q!Ez6|EMICA8nvgP&H-{^{=p7F-b8%=ih z@4tVY<=C;KX?AX}HJ853LvwV?_I1@zZN@KOzTAEF8Vui5Nl}g2XJJ0J?$pA~GP##u zzcQQA!-wZ_nU={t<`Z3JRI?OOWTw3d2hxcnLss@S*D|cbHUb(%`>WjLtY5$N=%ZyR zoxgDL&1-L~dcp4Qcgt_jKfk-KlX3j`x5}Sq&z_qtV_k#g_p;^qV~?)yuGe?-V~;&n zb=<|vZ@kfho7=_dulBJQn~`jN|NEz}U%x(Ej{5(_3zy2(%l4o$3ab%x65=C)Bfa>PyG4r9QA$jllPrE_1u{=Km6L)juq#q7|OE4?(TD+yzlbYnJsZj0%pE+q{nf7?E1#A<%WiG)o;ma4{rBBh zW(qF;v+Cor6mu{g!J_m`BG_$Wj+)bVT~89LI2H!gMK_Dc{%W4OV6E#{`RJ~E{&S!E zumAjyB0jf1x^?;TmF?~QFTM2rU;NWQ-o1NwJ^%Z2k)0==c)ZMM`RMZHH_G?&d)ZQs zzk9cwdfw^r$LAf&6qlPXmf@Lap1N@U7qh?GZhP&b{nMYGD-mcB=W?p@=h35If92_^GRuYT&jfI6+vMLx-Cb+?=S-EpTc%-MLZ&quomSn9{v^vpo_$oOs{Q<6fBBy~;Q^-C@iH?gBnM~Nr>MxTutA@Lc z@R21{$Sa|GnzF|KWBxTlXVGblY};K zlW5GV(D{Ry>VAs3cljbpL5K9`0j)!hN7iZTjRwl<`|!gL|MaK-{lq8!S`}H(UAM~t zomHwyJ|`TaXVI+ckogkg6w~(Md+)v*$e-3pgP{K*PX=bWjBQ;a&BiFz2=RGfBQi?| zkvE7a-HdP4L_}4XY1*2azL#d_x>XJ|NM9jvmL&CoF-mMo5!O=r8TvA8v#(k{g)S@o ztUV{MhXR}v4zkMkCb5j$X%mS{Jwtpe-btZ4MT#jR#Om`7MSi9=D*9aA%k12pz|NNd z?D=TjIZ6q#sP8tkCOZ?#6}+bO5GrD5N@O4&BpH~O#QjN5br|TSo}X0?Zz7HmoDnsU zj>XH+?fK3#GuwuB+sU<}2~?Y>Y(+gr7zB+T+_NMFk5g|UH=V_ORk)47J)2fBpOI@< zLoc6^4K>i=JgLSQIB{J_LM0HxWm&ml^&@efdaDtxlQefa1)-C%7AjFWijWvAtf2y< zq0lCDe}d8bJw@rP9~iwKuCTn-h$D&INlUEd3q26mYB9+K%77A`KBK!miF+3*HQd|6 zct0m7Jso408W2uSx@{%om@&~gR5D7eVk8b1gcU*H-&!z%6xlG5eh%m6B5?g(+=Yv1 zAZg%L)a9nuS*YcZUM~w5I1sUm(|lIGOKoVV0$2Sku@W#Jd}J92kcimmrytiV2GHXLAi9^oBh^F30-PetV?q^Z8UXE zrY7IcxFNByOlzt|w2-93A;7@4A<~|oHW0U&3eydnf-8t^D!fU8<_nnwm?QH$3xWq^ zmEN8V^V;e*+*RlYVGO}OqbC{AKKhq5ykPV&;m0s*8@8X{EE&V7&E znW=lfiJg!fHSn3b;ZRrp{t5I?vc|)6J=y>ZB}K=IY}Vnv0LkL z1VCyd(D)Ns2~uA!%%KV(^dJD0FGThrf{&nO&ynL7i$?=!4=thdkS12_xU!TDjqD&y zXl8DhgqCJ$*#}P&)e*&e9oiRB7K55*U{MWbHA5tT!LN!1eZlELinL@f1&{DC> zP;5*jBFlVQvUakG!L$G!h0IdMK-&!@+H8$(td5OzcSe8;atbj?WO~e!#a#@L2Fht) zR@l_-#$?M$<`gkvs9J)vaE$rMZ11t`l2!qtdUPWI56m~7FtI03{_kLB+ z*9%;%KCra;}IY0+Iea4~$>mj5#rM5hz{%k@HW2{ex42^j(wED!@oJ;W$ymJ_ zD(%NkxUhc7+8bS{jus#wF~l_i7V(=mF{BhL)hMJ=h3j=9UY7-*DK6Icm1j+| zVp9}=GJ!h2RRAA-Y|)T}@xe*sAUn#KIh$Zmml4N;L0&du(*i8I>hMO1ty4r|yBd!T zEjj2KhD$mvC(ns0kxf{h8P{o?i_kEFJ3+|MW^!l^;31L>#b-kqkr^MgAIMEYz)OBwFT9U|t$ z6vZAq>#b=AFYrnG>w97=M0)2$P>N#iiNf-+4Nc-ilK^5b9-%BIz46DE{VMdj_g8!j zpr(QuqemgkM4}fZ!IQBL31^!6_86B`?WFH4_gc!$@BQ!=?a z4=Ob;-ajOsRT8H3Z1Oz@e=p!_@dXxYS0;OrK$1Xc?r5dR&}vwmA}PZoAbgN|K!_=F ze(zRtgY9X-QL*S-CPFh3(#K#;1AZx(RYwbi084(mfS)*djz+kL2qd=7o-z2qa2qQr zB57%n%>!5LAu+_|6@6eT7wAQE^$&QX9Zl;}#*<$)GW1fGn64Lp!NCw&3w6!#SGEb~ z(h_R|cW=Ub$f|;ufrpl250EtQfC5Y0TLq`kF)_F`p)K7I8ry5_JbSokZ0ndjLj@Rp zk1z&yFEF$K5iGlk#E=ez%#*>Gs9+KF5n;@>wHlM4wU)H}I}=DyCyGQ$CoM$K?ukGGt7_7U*vlGpnFOg- zvm#h)VO5uqpw;aN2u?cpzE7X`{O-NaKJWM4fYp=!)=lpHzVH1x@A=v1+0Xu?-~RTu z?*G63pT7|Pr^`8Yu&$K;27jO5@ZZp9Vy(7f-EUyDD!kE+VPC@j7U*@`!dvWg2-f=^ zMxPOS<5%0!Y0dwQ^?s|u9FM;(Yz+y{B z_{&h505s2pcw=(#pRxnv8~(wulRc7N5rm79=!H2HkJPty}Yjah0X ziQ%Ty8>F`ta?OLVAyO^YlbmvM;<&blg^5M{EfXEaRrO3I*0;1I9MJ8u@NO)BmVQQR zSolr)I`udBgYvsT->%Lm5;qVNr_Rp#h%^EuHZhdmO(Ov|ZiYO|@<0w2q)5x3mPKmx zV}9H$_o#LR#9~SFj<04kyIeU1>&<; zRI(Cj_wiQ)sL=veEI-017YA0|A1g5uG?+Bu*y?A60mO|9uWqt^LA~*@t4Yb17sOg~ z5y09{3>eBFjI9y&6)F8avK5*)WGZN~Y&l8tQuClhMSvH~N*ur>DO4e;Kve>$R!|8h z`Qisr_UBgRFHqqCIW0yLBu)D&d3c}bIWT9m7 zEx87aR!|fk7W3`I`SV*o(J&*@+%#i$77*27N~v*(ZHaB23eO6V$>y643TvxKg9|eD zFAD%xT#JkmNH!&nMsKZ<-nxv|HozGM76)19In@`|9jINM5+09C^?(+sOmQker(Thy zR$GBAsOe?4aKl0X3SJ}yc)^u5z00SwxGJcHVG%1u;Q}$l1~E5kpJ#C4s?x@elZqM= zo5H{*8RP&73=a)zxJ+X*iX5bpSH+x!zZsNPL250kG?~C4CI`adDVW>_)1;7;|GB%_ zs6+_`rg)&$OY78R;*K9Kp*D*4X6+eq`B9xlVv?Y{Yk@R^0-r4;(Szzla$HNy%tv?M zQqUd9?HFR__QOkweoUE$Ij-!-AG zUKXWIW5x|d_DR4&5~&oyLzeJQOP<)?1BjhmKux|Ukl=JAUS-S!hoYQ3st68{P$skQ z6pevYxFJ8j_P z+|t+Ra#L%+NU<`c0Vp&m?NGHO4;DI>!JPKdE-gF`snZRTQ^QMIxK-z_v|e@B4v@sJZ833Ti$0zKf_7V{3EkH9G5DUcm3mixh z2S=tfrVf3O;hsT~s^eRVPV~@dZfZ8ANv%DNfc33$#`lakK(o_eZ4RWnZDWzk0h5*n z?p)X}(*%JejfHC1T&R7o$uxEuXB)aD=^B3z4Kru;HVH|=IenNMl1-7eYY_%JDZ~V! z%c`MsE#${R=k}6usem5xx{y>PDhTyA+ban@@k9sF!fo*P8DKtt2I6Q-1 zxulp?ZTesb!hm?l6eJ~zp!~;d;c3qxTSm(LQXK0fM@CHPW@HFi)~oDGkk=6jo`C7@ z6|h(Gwi>1CAL32jWJqi7rIFH1r=AFna+m|`x{dCug z9;4s<<~Q$_p?Hr-op-5~NWzYGc-DI}e)yN|u_Q=QAqz=~MPe_l5`pV8jMP&0AP$j* z;z0_*75foL60O9QbE#z~6i!T>B@tdN11)0+D8mNW?xOhWY5)U&J}RmestcH)@moWa z;#E+To7ydW6Oj$q3U{?q6@fj{y0ffRy%tng!?%b!=1sv?SGPA?t?enp@;O(r5$qP| z>-dJEP2z@@Qy1FLxt+wCE?6|++14$7`Y5?}sZKJ7Bw|VlhqwA%)D;Y68g!OgLz;;! zb2B*@ay<#8w60=8VGc=3fvy^K>-$Fl^}rx!{TRomtooJcGCjH~xd?#zgg3-0MWrCB z0oXOZQe{H@`i)<^cV(nlEv#ur7K#-{5NVEBZX~$mu&ohhO%X%a4VR=|Ep{_DV5I#+iIjORbyZ{#()O%K1dDnk1yD#j^olJhdsO_2tHK|bZtdRrzfoAm?0G?*$+1FPf48=Aa~oKFu)$WL*Ki#(VJ*kdVU70^ zI=#`~yViT0MzIifTCym!u|xQSlt|W=ik7;jo|W64{H-j-s*zGN-*G@&dx{BJFwkl# zM2a^jV<^!0v_O-W(4Gl~iJ|C{d}mjNJ>yx$d$Na#xjzw@JR{}a4yi7Kf%C>tUAHBY z+Zv>ep6li!Du*1$(xk{xrzpit5J32=5+@u*L`oYxk@pH_;4j`{j1GVnj>U_$=s%nV z&{_(S2`0ek4X)wY-xnBscwxtleGS(%w3bK{_%|eY1MG&xR+8JKE@&i zVd}*#wdh#PD8HI&Go@XTw3_6cbhr`@yL$gYX~C2QpRz5rN_vViZB&v;bT_kqhhkZ~j}NilNH86M$`tLqnJ z*B)EXALUN3t>jb`um(Osk^OLuw^6lx=(rnnx=ekOfmIIdkpR2m4uGt^pd+fuNge<; zJhfvW4Y*liSx5y4DM8ct$}|z%Vxtlm7G*CqWN}`*Vwan;G-Q`iL_<1$GFEb{-atJE zwVN1Py&5uhmw?`$CgRzQ?ibUr0zj;>ad!45QaVBSbh5TYeLCxbNrwB@6DB3&%4=Yp zVHd{q=)pyYdnk7zQ#N!xwgj1|8-u{OfI6LuP82ccVX1uta@-TC^~PCHTgkO1kDjv( z%sUHM#N$+r?pBu_nd+1Ev=ofS!^MTgSE|yGznu{(RU-w9ErqSGq|#vtMQ3Mor{%9A zNu`cY#R%8ao(t@jEkGAbK|-~b%+VAoDg znlWg!5Ed>WId_;IbzB}hb-W?_>dmNfB!cDFVhUQ=qt!#u6K-9?MBPa00BGQsfd+bG zNA^)|9tWZJ42BVgbu<Jc>o}W`v})ldiD@!R;tb06NcX z*|&PJ^*agDZ`(QA7@0bKK}#k|*hjaSMeL9(v>1YH%)kv32HS6F&SY<9>sS^WhPAIx zp%s3xjRw?k&oZqB^`a#k!aWMo*67yiz)k|dR=$-0^y(d5C`3|3FmokXp=6y_S zhAC&sD1r#NMq|%I6LPAhoSE23>xzJu${hh%T;!9xIyo%M4l;7FpePmS@_&tLrGeK{ zsGMmCF&j0aTAr6Bgtet9$8XgrC_9} z47Tq2vA1V+8`kL-pgBRtL@(Hxdg7^#uR>#gM58cw8=GX ztES*KlI~v05TKfZqYS<(GBHNcbL2zL4wG#1v^dVfWuk;-o&!r}M@qH|LkcmKgp>%X zTOdgmQ_+m2;XKh@Nts}X-onj7`oG3Dl$<7}_=cvE(bz1UW$5C(a1IhsD4pc`3(QwC z^9_wH7E2j0VJf^(i9i?Tf0q{kjM%2;Xlmjeh&GHAfeI?(vzkztt<^x$Zint0A2ML%WZI1jof2r0>Yb6W8tZSQasH5n|W zw>yIuK@fLE~ScSP_Y9g1)Q|# zLk5&)5?YwUh4-wXjad_(YyUMNF}FBF`v4Pnh!fm_9;qoKWuCo^`$ zmrN`LHY9f>e78s&;ES>eZXwW4h!&in%MdJm2_RB*{T^QQ9v!yeQ%F0!*D`m>KgVLv z^u}d`N`bLL%ZJlCsBN!Mb^zs5BrH=}UNPeXdUiT2=_``IBbi4TrdaD?<&uN0Bh8ky zedF1s&0zt(S|6(ZDI3J-3@xw1py_!)EU=tS|kX75D^`U0y@3qC?K^R07i4lCWa~Ujg|*wotViLYFPr7cNFT z<))2Df!>W_=18Z;@F^n!(1<}|Dm*#!(jvt~{iN7+yM(Hh=e?E)X$7ZX=x3Vvqnr# zVUQ*ovds%FW=L)n$=ur1s^LU-)fJ>=#8e-v{i6{;LtMEQl)f|$LqJou(ueXCVXGZ7 z?kQ1!VftZmDkl}^+GvR5r&TeLSDw;V;SbKJ3a*5ufQiG_n_lKAo(IprHipDp~1=ix8Ph|147=00C~6OC^}*;R|bGs9E`^?J2vTlzlhdEgUt3cj5dg zO7zfU+pa1FfE7QR*vv3~!{(m7@rw%=UfbTDKb%sX7#UE7))A_Pvz0?BJVIWD{*hgL zxDIq{&~?=Qfjtpl<3eI5 zQyw6)!nIEnMr0Vm50P*5@#Duo_OXwDaQCMFx$fWHaOa(OKl|*nbC1vcGca>OmErTu zoi9S;I6V2}lbf4+uDNE<=H_01P83f_Jw7jSKN%@sCvV5)GDJ_c7 z(?n?TEE-IvZKPlR@|PVhy_XECpKT|s9=}vBzH{;Jd+t4R=Bzp6K6K-a&pvnZeec_~ zy*1syZC>=#K16v?z0FThbyj_*YO|z;buJjpa1#7*4EagOVjq&1eNL?MrAt| zf*(eIp2zbXI&$Q*u^$c}KJ@Uz4~OU7o+f3;=%7t!Wj7|M^!xPcFJCPzt~QUcz=-aWV8dh69!U**60yT5z+hd=yLJoqCYx%t$oXVQ?&|7N5! zBoR6b-+y(*_@{sRF@H+A{%?Nc`*hp?grS(_svp1O-~8rdkDUlN+I!!9_w2oP@9VF< z_S93)#1lXCp&MU#;raO{TVV)AF)Jzx$~=T#W{(?JTrqs$17!%`*t)bGTIkys#RKJV zvq2ir()KkW85YYB`qvw8ym9j6sjIHK>d>Lj`1us4Y%_wa5S%@POcP*RXR6Hj>Z`A6 z%O9znW7_#eEzwFMP~4x~OFw_fufk);9z1g7P?8?utC!E6`{XA-{pOo*`Q!im&yOGc z^uaia0r>^_>5mG%`NR`Xe*Np;xb|8JZ8$(4=hW`r0Vt(9rlqW7aDt zz_D6!m_JPHUOZ?Dn$rXlHk|o9-_D!%-E{i&UmrZ^M`-f>erYTGx4m`44cFgy-@WnZ z)2Gi;*w3QvisB&77-;y#E3f$R^T&Mgi}!NPE!*SMgn0b%@5Zmb^{wMqUitpHv$yAU zbLEx0zW@Cv;#ZG7{&)l?6pKm#|u)VdVgVTzfws2|i=TY3X z>&hti^3Svtwz1o8I~9oAahL!2PyXa1pZn~Q#$_a+&|$c6 z;f>R$&qQf?;K0rP+VMu0=9P-g&CO4I;#U8yU-3Ww@s9(hnbFWJ=R>ClkUS*38~+Gn zVD0Y|$2gxA$IJhpU~oag;}~(;kQFOe6vN~bNCrRP`u<)rQB)Vo4hzErrb=XIE6c$u zPm@`1iBM}E#UQ)3w-aWWf&iH&FYe-rQJiLTXxx!zgn8n`iPv90@4xu!S094m7ZWA6 z^8*t!C%-pdG5DXK{P&;SefK?n>RfZpUjK9W@DYE( zcYb$qj8h?s&oG+)tUY`F$p6F*(#!C)Cqt$nL+!c*R?*Sn0QJMFhz7)l;w}Uu6O1w_ zw^q9;p=ufNI`{eHG?-g)Qt+wX`1puGHB|KowxqmLf{*hfF=AJ*?VLAer&=G?|PfOaZwSxW6J z(4Tl-o#N*$3Rb1fIp&?QiZ^q_Vx@)ycWyAMjj)P@NE=w3)xM`n*QeP?VFU*+Lf^js zfd?aAz5AZKygVGJ#byCn(BL(#_;Z$n&2*cqpFhLD0ST z-o1Cvrhj|-%!^Mw_4Ma&|AO`&owsL{k?`~8lb@V{l1JJ{jvS7+ICt*cQ%{|I{q@)V zb?&(1uIHXRxqsijPzGFZ1yQ()ltg0K$ky1H?GPp8K-R1qWmJuFR#Cy96$dd_(>8BA zWSWV@k3?zaQB3^umRmkv_<*3x4-Y(e)Gr8+zmFe(#G|+Q?!MolMO&OcWgYn5y!3yz z;$-!!&tJ#O^9{HnvHg+r3J7!Mfd`Jp@%!v;N51*!@vv?Y8}qr(9{!J?JZS7RR9N)1 z^u6|S?C68@mg~o9paTc?-*)84!{2!12S0e)e|!J^55Dx$Sr;tv`W%SG*wt`1)RMeRMAw~ zd-PF1OSXgZKEq`XwXVPZ`Y+yhuevOeM)@8k`4&cP(Vul`)*Yw!?b`Lwv7`R7Q7k|6 z%*nVPYCbLUz*Fwni0b3MleuH*8qed#Ckl1}CUMet1BX2Q$jv2=k%L``K2I|-f(Q>a z{S1v?9Xob3?q3m%{_c10L=pOlPuwy?){Nzbx&U0ptkfp2hTxtJLwwXjewbzWefQn% z?>>*gR?z&i_IG&JVpn)E%;#>WSHau4(9H41Rj(`nWOh^vgQ+6e(ZtniFTnzfxfddBudYvLj4r^oEU%$v+*SCt^ zaQzLJwk`!7CQyCBu;ZIK4ciB9K2Y!xQOE6B%yIPW(rx4wR831}%p7=qoT4}cb5PV0 zCX`$eP@yX|wu3`s363SKt2jqgVgy ztK;GuI6=)!2SX}ZGDDuEGx+|>Tk?>zviUc!zkZ=WUp0h#_H6nmOE`AMuP)PXBF-a; zV;R&Ef$#hiRHrBwDSqzpFs^3P0q0-oq2u_ z!nPrh03fTo8NO>W>?@mmL5YBx`HNF0pL_V><8k~>oqBrLt}F8hrb$=SgEe3AyrMIB zOrN>g#Knd;bnfMI*)VcLTx1b$goS${Y|<4X4jgwjG7WlLEmp5`g?ZB3oaN+z1Ke&4cC&$j& zi1aDZnR>?qvl8#ftjduIQ?q!d%sZ*H3L^OD^z>l~8&}%P84j&rlxI9Gv zkH}(2X>YH@{PIuamBMM*n75z+XCmajc=7FM_L`e|V1G1j^dm7vCRyn`ZDn6KGX&(X z2Cy7FIXQ~RW^9(lD{7=nu$4U_#^J%E$JqEid-c^G{W_ zy-NkD&unLTmdLdRA~Z3gM~^-bzk2xLN4&-|WbXOmI~Tw7rKG+1W0K~uH68rS!8jrO z=z4e@y1x2?_<8W1?>w&Mbu*sd`Ob-FPM+Er1KpbV@r`#bUi6zq#M^!e?%TI7@xlTJ z>AklAL$g*PgnlTzF%)A;e!`kzZ!ojg%ej~xg{IBuer9UC~v;`mOuC7AOD!Yoqzaque{>Vjd%1@A(z=A!Vu0sR}7!M?azGw`VW8gtAC8z zbl9pXtexR^zkBD{u`kC_RIf08UyqV^M*s5=&MW4*=brnl%E9O|K1a)&z$-C z*B|k3UwiEzXP-Hb%tk*c>k$6cU%hbq?RRpPoVj}3aN@*wc7O1i=o=CVslC_!+xYEk zul>)h`4w%?Dgp0MhY&T34;HgBl*~SRvwNn(ZF%d*80d9{bN8+MGRm_W9>ui0iBc=14fU-;=yU--cf zo<4p0Y!naSj{XY!4<0-?1;!_+{94frlPURztD0EO%Eqcx8|v@T^vbz&WsuYWN)J&d zA}^Z+FvXa@k?h&g&RP>l2^XxOA#Z2jr$E$9wHY+eup#k`iJ^%Kb?DeB-_Fl-m#yfO zg+_Ws=4DF5p4io7e-DkT>4inM@cCcx?m#kP&Yn@@=H?&8=Kb&gbs@5&^CT-NV_bY9 zcE`X)1e`R}_{o4;ngf^^1tR*($;zfA%bL|>kfTH6dN0d{tqkXsQ35XRJsx%^KfaXj zI@zbdy*s9~sM@I)49J1Lp0c#3-Xm)UiwEffWUSG)2NS&cP~Yb`+JCQrl=L zMv^mBQ9k#MDmo)eU;%=ztiiZe4m&E#K^CQCN$hGO( zL4@xJ;HM2iO?qi6eMz>{u2BMOge=OS_$6A!^hV=`RyJEfftql~IhDf4vR_H8Yh?VD zONYgimbj8`RakSsFq{tJ_T^XHpcsbesl#0G9S@fwvlEQRrQ(gq5qghNZ^L<5GRr2R zKcwd{%ghZ@96f5}K?%&#c|T+sH(7Us&nPOQvX*cUdr1LsB?_u#bD2QkgqR5|A*lv^ktA!OD0@fAWqzZPFBrqY#W__OW);U8X&9|YPjhyE^P z{dava2B|G5Y|$pi>6D6dY6ztOW5}b;pQ-k%W{9cDVnVRxv(8?MHghTZd7_MTOfWbM zM|y`{(d$%`)Xge7ZIc(J+mx{BRFS8V{Ei8BjpC`F#I%*@3;9x=E)6~Jg^C&{@RYP< z%??@m+Nkza4m8TU3&wdAi9~P%s8cz`JZ1 zWg+t0mo!il72i*%1S89fW+oPIGi!*Pu4TGU3yAdcszSH^q^@r#F;Bd_d#&G8^o=&O zzyOAQCmS6=u1P<6S&z_)Tzhj_;|WJT^;CTgax1d7F1sq&8JZeysZG4sO~bG7qIE!< zLd_(KbUQhBa_kvz4! zDreYOQpu14j5QZW%437Z_UoGcg%|$QJL+I+-(pF>>x6e$l}jDkVRq#$$<*AjqQ(74 zA~GWTw7U=)x#|`QS7E&lf!#oYnaIRy{s{C`Yvr-nQ-w7bDe7;dmlz)n6{{tpTawG9 z(V5dp*`bL*D^Zk!`RHv6+=d68#?ExCPz^J$iIrj;ZM9OqoCQb9GKSO)%^in1o{Fw! zFOh=Xp0G~yH4vE)S*kHK$tF18NdgS>RN^u{Oj8a+frP5ZPm;^!`}*$C^yCDkg``j*i1+hdLCSucinD zAKJlcP4>m6DoX1I0sC~rEN5n+z^b0E_ktlv8|lzQt4S?gq=3?TyQ(`nldOxE7dtQVE`h76uVED0a~AvCs>?OtEIrrQ z@~|xXDB8q)45L~FvxTn!s%KoY4DywyB7d9gWDr7E{n7$3TLz=uwbe^0j~QHW3T0fhqV9ly zk%*)rR;+4q`STIdPE0m!;#BlKVSy;p#R-I=9s(VxnxV^Ci6PC#rjnzm9QjofYy`b8 z(h~Wk@2eetQ)eqdCPh)+hS&&V*T>q-@* z4bvu@3&=V{-M(4ubDpJL@{Sg33{i_k`8_ucH2ez4Nfx$EGXRttZx-2Ol^YhoSa`CL zTy;7dMP06A>p3dQWHd_FRP#N<6k@{V#$be5RwQeC1*j(DSKBETn02M?5HWuYQ3+O- z6w-Ddw)^W?6`0mR;gBHp{9MPbU~|YE0Ypyn{#j3;$tW~dGkl2^GKa+(!Vvx7EK|9H z6ks}E5uxY-f(W41jH*cZsUZOD%t*?ofQ;;(Rqg?c)D{zQ&PWuh6Mjl3FQ~j()J{Nv z47*LHDzSvHnQE^|ub{QSHL<_o478ozTzcf&aWXV#R5jma4 zYsm>ONbR={XH;fDb|-H_%Gtz=5*M;Y5_qL2wgZ5aOJ|)UB=WvGSL{v1H_Ap6C1Jay zCOE*732IJ`OPc-KR`O*!6st7YRr>8^8pk=mi_0?ZucC#qN{L+SkvrTn^>h+77Nbl# zk44ELjV)x^QzU3u!wmq2&nm3dufPJD!on-#f_il;O-&f~_hg>lr+lebcu(Uobm{h0 zb9-c-2xJx}=k^+Ebk^+G$oz>~8$U~q&E4*KDI4xcA^;s=_P0 zMkq5*%7c7!uz$s@L=ZpwNyM%?T8>RSt zo|&6dz39@brDjw6Ak=_nEX_G6q2EjdVG?SoS~Mz6XGY!e zHGZ;3C}yr3F({ErEAgDl0Ele$^wyQwixx zUA^jaSdwv4pY9Zqf(p(Nrt!*U@W6^Cvo3MN4UAeMYuKV%(zWXH8s>nJBY^G5W%C>u zu|WBE{T}LKr>111v^u~>xXf9qNJ5o%g&W&Ro42{EAi=qw2^?mW2dkzf1)*`USoqQ(8aOoc=`&Q?5cPi@2eg zt_+vd0aGPQOB;tBD$0E)@-=NUaD8K6!^?t8NvOystiqG6y@D*Mw48StkL} z8hx!yZOSapRjzSK$%V5_tU&8KrZ(PIV6v?g%P<~`BiwWG?{o0f*ZN_jVH;2>uMD)X z*xB4tQdX7Ro4mH{*rz6DNgbqevge>uJR;mmEH5mh{zb7>WPpt}AOFrox znG+pxqmv#JG^_TDbRW@QSx|T@lZ^-gYT#;q%+YkHZCseSaADSC((t=sw-t7reXUkxXJzmC2)Q=H+k!S-JE#wu$+m5ph;XrBDmV+-aU19*eQt8xTUMt9 zcP!n?5r(8MQh^#{gX?oTe0AIiQ8 z!!H-69!|YB>y&t;a#pe!MD&n=mAz@y!Sg&uUIIO-de-B$zE95Zb1!f+8@{EZzBK5E zHIE8Qo871ZnIgM%NBb1dCO8M=vf7zEAmyqltV+U>)EP0by$bg#1cvt;i6;TCxUTop zO8Anl+2nQ_!`{h_Lpujo{Tw2+Y)QxB#bM#&H6DlDQjk>F&aR9_v_m78c_f@o`zgI} zL4k&)af0j&BK;mFQ|(<~Qw)zMGc?}thIdWW6W~^*VzS&B4aX{A2gXcvRR^^F)(vWF z+pb%RQG1=jvObve5nyhr+P*3sFD2R8Sb2q^kLM{98m$rgpIw3D2POSlj{KR>hq z%U^M=&j_K0eywx>A!RKEy7VNloQz8O?zH%|1h93i=!zv-hUG>}tYaeI)cQqoFHvGL zmrU}O4D{=`lW*lnVS15?a6fMEup}&%jHfE(gPeArw!?=w&ri#i8U>jhv9xv4gA&x% z0)!Je1I^S(t+5uJY*np$gX7Ns9Vd!@A)xBLn->Pa!kvkP)>`a*qeTi(DUYYM6|`y? zbjmIPGD%nklyfc|3sFOw1$C<>wqU8+fyCNG&GcEilSITc$XNzI4NaipX_f7plO1*W zwMiO-?<+C+Q4%Yw92UqoB`c&%=yI|$Nnwn$Odqt>d@*+ic0ldXYQvRjkSEjRu{ttf zN70;EEiP#tN2$x=YTt`QFl-MQ7wtX^#3{Pl6ST3ov(YyP$jX^2A4b167FJj`?bOw+ zMRIY^?HWt_h3i(pb-O(VXDgVymd2Sa71=UEHNcTfMzNQU!Kihp8?MvoJ56{Kxsu~t zC&7@>{VKOARTC0aU~fZ{i=-haNqjBmKgxJdJ-!p68YJ=@vOLO5{+Bg(s|E(tFjXMU za=!cHsV2~&4$RXCLe~3fcU1qC^TK`Y{(7aEo5O0 zSG>Oz(MYZ#%ogP>YC%c9N7GvJUnU|7PdCEk8o5n_=O}GFN}#r0B|FLD>Y1lh1y7Ad zNu|_jN-zxI<`iUIuv@=f^>Sk=6tn%7Z_YwFs9}5hQgAlDugE4zw?FdP00&V zl3uSduX{tuGzqfWqzq`34$?s#IuSEhn?-O1iAROwF8WMZ5eJW?%w1Ji)=tjElbNcx zX6-)54S^uR!-53Hh3)Ijomg3>K`0khy^7jM6XB-MMsirhR@6^+WI-%mx1kHcXax~V zeb4rVD0_Z=qBZd1s#H#nYYtc&axe0-w3No$ZZoa!^--q!v9r}Jp)xFNi_m4G?BMPN zgQh_zN>5c<%~ZAldo_nUlL2l8u$7K! - DpiTest: Large Screen + DpiTest: Large Long diff --git a/tests/DpiTest/res/values-normalScreen/strings.xml b/tests/DpiTest/res/values-large-notlong/strings.xml similarity index 91% rename from tests/DpiTest/res/values-normalScreen/strings.xml rename to tests/DpiTest/res/values-large-notlong/strings.xml index 256d696df80ed..9681f4428908a 100644 --- a/tests/DpiTest/res/values-normalScreen/strings.xml +++ b/tests/DpiTest/res/values-large-notlong/strings.xml @@ -15,5 +15,5 @@ --> - DpiTest: Normal Screen + DpiTest: Large NotLong diff --git a/tests/DpiTest/res/values-smallScreen/strings.xml b/tests/DpiTest/res/values-large/strings.xml similarity index 92% rename from tests/DpiTest/res/values-smallScreen/strings.xml rename to tests/DpiTest/res/values-large/strings.xml index cdb4ac9f60bd8..faa95f2b8fd24 100644 --- a/tests/DpiTest/res/values-smallScreen/strings.xml +++ b/tests/DpiTest/res/values-large/strings.xml @@ -15,5 +15,5 @@ --> - DpiTest: Small Screen + DpiTest: Large diff --git a/tests/DpiTest/res/values-long/strings.xml b/tests/DpiTest/res/values-long/strings.xml new file mode 100644 index 0000000000000..d6e5d93394f6c --- /dev/null +++ b/tests/DpiTest/res/values-long/strings.xml @@ -0,0 +1,19 @@ + + + + + DpiTest: Long + diff --git a/tests/DpiTest/res/values-normal-long/strings.xml b/tests/DpiTest/res/values-normal-long/strings.xml new file mode 100644 index 0000000000000..640608396d758 --- /dev/null +++ b/tests/DpiTest/res/values-normal-long/strings.xml @@ -0,0 +1,19 @@ + + + + + DpiTest: Normal Long + diff --git a/tests/DpiTest/res/values-normal-notlong/strings.xml b/tests/DpiTest/res/values-normal-notlong/strings.xml new file mode 100644 index 0000000000000..3265e4c5ae024 --- /dev/null +++ b/tests/DpiTest/res/values-normal-notlong/strings.xml @@ -0,0 +1,19 @@ + + + + + DpiTest: Normal NotLong + diff --git a/tests/DpiTest/res/values-normal/strings.xml b/tests/DpiTest/res/values-normal/strings.xml new file mode 100644 index 0000000000000..1e27da4aa57cf --- /dev/null +++ b/tests/DpiTest/res/values-normal/strings.xml @@ -0,0 +1,19 @@ + + + + + DpiTest: Normal + diff --git a/tests/DpiTest/res/values-notlong/strings.xml b/tests/DpiTest/res/values-notlong/strings.xml new file mode 100644 index 0000000000000..4b9d5da319b91 --- /dev/null +++ b/tests/DpiTest/res/values-notlong/strings.xml @@ -0,0 +1,19 @@ + + + + + DpiTest: NotLong + diff --git a/tests/DpiTest/res/values-small-long/strings.xml b/tests/DpiTest/res/values-small-long/strings.xml new file mode 100644 index 0000000000000..2575b0d917b7b --- /dev/null +++ b/tests/DpiTest/res/values-small-long/strings.xml @@ -0,0 +1,19 @@ + + + + + DpiTest: Small Long + diff --git a/tests/DpiTest/res/values-small-notlong/strings.xml b/tests/DpiTest/res/values-small-notlong/strings.xml new file mode 100644 index 0000000000000..2df2b29a29543 --- /dev/null +++ b/tests/DpiTest/res/values-small-notlong/strings.xml @@ -0,0 +1,19 @@ + + + + + DpiTest: Small NotLong + diff --git a/tests/DpiTest/res/values-small/strings.xml b/tests/DpiTest/res/values-small/strings.xml new file mode 100644 index 0000000000000..9fd5e4014894c --- /dev/null +++ b/tests/DpiTest/res/values-small/strings.xml @@ -0,0 +1,19 @@ + + + + + DpiTest: Small + diff --git a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java index 5a9f3f548c7d8..49fff57ba0fe1 100644 --- a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java +++ b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java @@ -17,6 +17,8 @@ package com.google.android.test.dpi; import android.app.Activity; +import android.app.ActivityThread; +import android.app.Application; import android.os.Bundle; import android.graphics.BitmapFactory; import android.graphics.Bitmap; @@ -28,8 +30,43 @@ import android.widget.TextView; import android.widget.ScrollView; import android.view.View; import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.res.CompatibilityInfo; +import android.util.DisplayMetrics; public class DpiTestActivity extends Activity { + public DpiTestActivity() { + super(); + init(false); + } + + public DpiTestActivity(boolean noCompat) { + super(); + init(noCompat); + } + + public void init(boolean noCompat) { + try { + // This is all a dirty hack. Don't think a real application should + // be doing it. + Application app = ActivityThread.currentActivityThread().getApplication(); + ApplicationInfo ai = app.getPackageManager().getApplicationInfo( + "com.google.android.test.dpi", + PackageManager.GET_SUPPORTS_DENSITIES); + if (noCompat) { + ai.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS + | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS + | ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS + | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS; + ai.supportsDensities = new int[] { ApplicationInfo.ANY_DENSITY }; + app.getResources().setCompatibilityInfo(new CompatibilityInfo(ai)); + } + } catch (PackageManager.NameNotFoundException e) { + throw new RuntimeException("ouch", e); + } + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -73,6 +110,13 @@ public class DpiTestActivity extends Activity { addLabelToRoot(root, "Autoscaled bitmap"); addChildToRoot(root, layout); + layout = new LinearLayout(this); + addResourceDrawable(layout, R.drawable.logonodpi120); + addResourceDrawable(layout, R.drawable.logonodpi160); + addResourceDrawable(layout, R.drawable.logonodpi240); + addLabelToRoot(root, "No-dpi resource drawable"); + addChildToRoot(root, layout); + setContentView(scrollWrap(root)); } @@ -155,7 +199,10 @@ public class DpiTestActivity extends Activity { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - setMeasuredDimension(mBitmap.getScaledWidth(), mBitmap.getScaledHeight()); + final DisplayMetrics metrics = getResources().getDisplayMetrics(); + setMeasuredDimension( + mBitmap.getScaledWidth(metrics), + mBitmap.getScaledHeight(metrics)); } @Override diff --git a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestNoCompatActivity.java b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestNoCompatActivity.java new file mode 100644 index 0000000000000..4d25e083e039f --- /dev/null +++ b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestNoCompatActivity.java @@ -0,0 +1,23 @@ +/* + * 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 com.google.android.test.dpi; + +public class DpiTestNoCompatActivity extends DpiTestActivity { + public DpiTestNoCompatActivity() { + super(true); + } +} diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java index cbcac6caa9ea1..ba461973fbfb2 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java @@ -72,6 +72,11 @@ public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2 parts; - String8 mcc, mnc, loc, orient, den, touch, key, keysHidden, nav, size, layout, vers; + String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den; + String8 touch, key, keysHidden, nav, size, vers; const char *p = dir; const char *q; @@ -296,6 +304,30 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType) //printf("not region: %s\n", part.string()); } + if (getScreenLayoutSizeName(part.string())) { + layoutsize = part; + + index++; + if (index == N) { + goto success; + } + part = parts[index]; + } else { + //printf("not screen layout size: %s\n", part.string()); + } + + if (getScreenLayoutLongName(part.string())) { + layoutlong = part; + + index++; + if (index == N) { + goto success; + } + part = parts[index]; + } else { + //printf("not screen layout long: %s\n", part.string()); + } + // orientation if (getOrientationName(part.string())) { orient = part; @@ -385,18 +417,6 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType) //printf("not screen size: %s\n", part.string()); } - if (getScreenLayoutName(part.string())) { - layout = part; - - index++; - if (index == N) { - goto success; - } - part = parts[index]; - } else { - //printf("not screen layout: %s\n", part.string()); - } - if (getVersionName(part.string())) { vers = part; @@ -416,6 +436,8 @@ success: this->mcc = mcc; this->mnc = mnc; this->locale = loc; + this->screenLayoutSize = layoutsize; + this->screenLayoutLong = layoutlong; this->orientation = orient; this->density = den; this->touchscreen = touch; @@ -423,7 +445,6 @@ success: this->keyboard = key; this->navigation = nav; this->screenSize = size; - this->screenLayout = layout; this->version = vers; // what is this anyway? @@ -441,6 +462,10 @@ AaptGroupEntry::toString() const s += ","; s += this->locale; s += ","; + s += screenLayoutSize; + s += ","; + s += screenLayoutLong; + s += ","; s += this->orientation; s += ","; s += density; @@ -455,8 +480,6 @@ AaptGroupEntry::toString() const s += ","; s += screenSize; s += ","; - s += screenLayout; - s += ","; s += version; return s; } @@ -477,6 +500,14 @@ AaptGroupEntry::toDirName(const String8& resType) const s += "-"; s += locale; } + if (this->screenLayoutSize != "") { + s += "-"; + s += screenLayoutSize; + } + if (this->screenLayoutLong != "") { + s += "-"; + s += screenLayoutLong; + } if (this->orientation != "") { s += "-"; s += orientation; @@ -505,10 +536,6 @@ AaptGroupEntry::toDirName(const String8& resType) const s += "-"; s += screenSize; } - if (this->screenLayout != "") { - s += "-"; - s += screenLayout; - } if (this->version != "") { s += "-"; s += version; @@ -630,6 +657,57 @@ bool AaptGroupEntry::getLocaleName(const char* fileName, return false; } +bool AaptGroupEntry::getScreenLayoutSizeName(const char* name, + ResTable_config* out) +{ + if (strcmp(name, kWildcardName) == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) + | ResTable_config::SCREENSIZE_ANY; + return true; + } else if (strcmp(name, "small") == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) + | ResTable_config::SCREENSIZE_SMALL; + return true; + } else if (strcmp(name, "normal") == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) + | ResTable_config::SCREENSIZE_NORMAL; + return true; + } else if (strcmp(name, "large") == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) + | ResTable_config::SCREENSIZE_LARGE; + return true; + } + + return false; +} + +bool AaptGroupEntry::getScreenLayoutLongName(const char* name, + ResTable_config* out) +{ + if (strcmp(name, kWildcardName) == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_SCREENLONG) + | ResTable_config::SCREENLONG_ANY; + return true; + } else if (strcmp(name, "long") == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_SCREENLONG) + | ResTable_config::SCREENLONG_YES; + return true; + } else if (strcmp(name, "notlong") == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_SCREENLONG) + | ResTable_config::SCREENLONG_NO; + return true; + } + + return false; +} + bool AaptGroupEntry::getOrientationName(const char* name, ResTable_config* out) { @@ -654,9 +732,30 @@ bool AaptGroupEntry::getDensityName(const char* name, ResTable_config* out) { if (strcmp(name, kWildcardName) == 0) { - if (out) out->density = 0; + if (out) out->density = ResTable_config::DENSITY_DEFAULT; return true; } + + if (strcmp(name, "nodpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_NONE; + return true; + } + + if (strcmp(name, "ldpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_LOW; + return true; + } + + if (strcmp(name, "mdpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_MEDIUM; + return true; + } + + if (strcmp(name, "hdpi") == 0) { + if (out) out->density = ResTable_config::DENSITY_HIGH; + return true; + } + char* c = (char*)name; while (*c >= '0' && *c <= '9') { c++; @@ -812,26 +911,6 @@ bool AaptGroupEntry::getScreenSizeName(const char* name, return true; } -bool AaptGroupEntry::getScreenLayoutName(const char* name, - ResTable_config* out) -{ - if (strcmp(name, kWildcardName) == 0) { - if (out) out->screenLayout = out->SCREENLAYOUT_ANY; - return true; - } else if (strcmp(name, "smallscreen") == 0) { - if (out) out->screenLayout = out->SCREENLAYOUT_SMALL; - return true; - } else if (strcmp(name, "normalscreen") == 0) { - if (out) out->screenLayout = out->SCREENLAYOUT_NORMAL; - return true; - } else if (strcmp(name, "largescreen") == 0) { - if (out) out->screenLayout = out->SCREENLAYOUT_LARGE; - return true; - } - - return false; -} - bool AaptGroupEntry::getVersionName(const char* name, ResTable_config* out) { @@ -867,6 +946,8 @@ int AaptGroupEntry::compare(const AaptGroupEntry& o) const if (v == 0) v = mnc.compare(o.mnc); if (v == 0) v = locale.compare(o.locale); if (v == 0) v = vendor.compare(o.vendor); + if (v == 0) v = screenLayoutSize.compare(o.screenLayoutSize); + if (v == 0) v = screenLayoutLong.compare(o.screenLayoutLong); if (v == 0) v = orientation.compare(o.orientation); if (v == 0) v = density.compare(o.density); if (v == 0) v = touchscreen.compare(o.touchscreen); @@ -874,7 +955,6 @@ int AaptGroupEntry::compare(const AaptGroupEntry& o) const if (v == 0) v = keyboard.compare(o.keyboard); if (v == 0) v = navigation.compare(o.navigation); if (v == 0) v = screenSize.compare(o.screenSize); - if (v == 0) v = screenLayout.compare(o.screenLayout); if (v == 0) v = version.compare(o.version); return v; } @@ -886,6 +966,8 @@ ResTable_config AaptGroupEntry::toParams() const getMccName(mcc.string(), ¶ms); getMncName(mnc.string(), ¶ms); getLocaleName(locale.string(), ¶ms); + getScreenLayoutSizeName(screenLayoutSize.string(), ¶ms); + getScreenLayoutLongName(screenLayoutLong.string(), ¶ms); getOrientationName(orientation.string(), ¶ms); getDensityName(density.string(), ¶ms); getTouchscreenName(touchscreen.string(), ¶ms); @@ -893,7 +975,6 @@ ResTable_config AaptGroupEntry::toParams() const getKeyboardName(keyboard.string(), ¶ms); getNavigationName(navigation.string(), ¶ms); getScreenSizeName(screenSize.string(), ¶ms); - getScreenLayoutName(screenLayout.string(), ¶ms); getVersionName(version.string(), ¶ms); return params; } diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h index 3b96412c7c54a..63afe5ce174e6 100644 --- a/tools/aapt/AaptAssets.h +++ b/tools/aapt/AaptAssets.h @@ -30,6 +30,8 @@ enum { AXIS_MNC, AXIS_LANGUAGE, AXIS_REGION, + AXIS_SCREENLAYOUTSIZE, + AXIS_SCREENLAYOUTLONG, AXIS_ORIENTATION, AXIS_DENSITY, AXIS_TOUCHSCREEN, @@ -37,7 +39,6 @@ enum { AXIS_KEYBOARD, AXIS_NAVIGATION, AXIS_SCREENSIZE, - AXIS_SCREENLAYOUT, AXIS_VERSION }; @@ -56,6 +57,8 @@ public: String8 mnc; String8 locale; String8 vendor; + String8 screenLayoutSize; + String8 screenLayoutLong; String8 orientation; String8 density; String8 touchscreen; @@ -63,7 +66,6 @@ public: String8 keyboard; String8 navigation; String8 screenSize; - String8 screenLayout; String8 version; bool initFromDirName(const char* dir, String8* resType); @@ -73,6 +75,8 @@ public: static bool getMccName(const char* name, ResTable_config* out = NULL); static bool getMncName(const char* name, ResTable_config* out = NULL); static bool getLocaleName(const char* name, ResTable_config* out = NULL); + static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL); + static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL); static bool getOrientationName(const char* name, ResTable_config* out = NULL); static bool getDensityName(const char* name, ResTable_config* out = NULL); static bool getTouchscreenName(const char* name, ResTable_config* out = NULL); @@ -80,7 +84,6 @@ public: static bool getKeyboardName(const char* name, ResTable_config* out = NULL); static bool getNavigationName(const char* name, ResTable_config* out = NULL); static bool getScreenSizeName(const char* name, ResTable_config* out = NULL); - static bool getScreenLayoutName(const char* name, ResTable_config* out = NULL); static bool getVersionName(const char* name, ResTable_config* out = NULL); int compare(const AaptGroupEntry& o) const; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index d0a1c46bf6444..fd77d5143d9e9 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -286,8 +286,8 @@ public final class Bridge implements ILayoutBridge { } return computeLayout(layoutDescription, projectKey, - screenWidth, screenHeight, DisplayMetrics.DEFAULT_DENSITY, - DisplayMetrics.DEFAULT_DENSITY, DisplayMetrics.DEFAULT_DENSITY, + screenWidth, screenHeight, DisplayMetrics.DENSITY_DEFAULT, + DisplayMetrics.DENSITY_DEFAULT, DisplayMetrics.DENSITY_DEFAULT, themeName, isProjectTheme, projectResources, frameworkResources, customViewLoader, logger); } @@ -304,8 +304,8 @@ public final class Bridge implements ILayoutBridge { Map> frameworkResources, IProjectCallback customViewLoader, ILayoutLog logger) { return computeLayout(layoutDescription, projectKey, - screenWidth, screenHeight, DisplayMetrics.DEFAULT_DENSITY, - DisplayMetrics.DEFAULT_DENSITY, DisplayMetrics.DEFAULT_DENSITY, + screenWidth, screenHeight, DisplayMetrics.DENSITY_DEFAULT, + DisplayMetrics.DENSITY_DEFAULT, DisplayMetrics.DENSITY_DEFAULT, themeName, isProjectTheme, projectResources, frameworkResources, customViewLoader, logger); } @@ -340,7 +340,7 @@ public final class Bridge implements ILayoutBridge { try { // setup the display Metrics. DisplayMetrics metrics = new DisplayMetrics(); - metrics.density = density / (float) DisplayMetrics.DEFAULT_DENSITY; + metrics.density = density / (float) DisplayMetrics.DENSITY_DEFAULT; metrics.scaledDensity = metrics.density; metrics.widthPixels = screenWidth; metrics.heightPixels = screenHeight; diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java index dc70b264eacf1..0bf2346798353 100644 --- a/vpn/java/android/net/vpn/VpnManager.java +++ b/vpn/java/android/net/vpn/VpnManager.java @@ -42,6 +42,15 @@ public class VpnManager { public static final String BROADCAST_PROFILE_NAME = "profile_name"; /** Key to the connectivity state of a connectivity broadcast event. */ public static final String BROADCAST_CONNECTION_STATE = "connection_state"; + /** Key to the error code of a connectivity broadcast event. */ + public static final String BROADCAST_ERROR_CODE = "err"; + /** Error code to indicate an error from authentication. */ + public static final int VPN_ERROR_AUTH = 1; + /** Error code to indicate the connection attempt failed. */ + public static final int VPN_ERROR_CONNECTION_FAILED = 2; + /** Error code to indicate the server is not known. */ + public static final int VPN_ERROR_UNKNOWN_SERVER = 3; + private static final int VPN_ERROR_NO_ERROR = 0; public static final String PROFILES_PATH = "/data/misc/vpn/profiles"; @@ -52,7 +61,8 @@ public class VpnManager { private static final String ACTION_VPN_SERVICE = PACKAGE_PREFIX + "SERVICE"; // Action to start VPN settings - private static final String ACTION_VPN_SETTINGS = PACKAGE_PREFIX + "SETTINGS"; + private static final String ACTION_VPN_SETTINGS = + PACKAGE_PREFIX + "SETTINGS"; private static final String TAG = VpnManager.class.getSimpleName(); @@ -130,9 +140,18 @@ public class VpnManager { /** Broadcasts the connectivity state of the specified profile. */ public void broadcastConnectivity(String profileName, VpnState s) { + broadcastConnectivity(profileName, s, VPN_ERROR_NO_ERROR); + } + + /** Broadcasts the connectivity state with an error code. */ + public void broadcastConnectivity(String profileName, VpnState s, + int error) { Intent intent = new Intent(ACTION_VPN_CONNECTIVITY); intent.putExtra(BROADCAST_PROFILE_NAME, profileName); intent.putExtra(BROADCAST_CONNECTION_STATE, s); + if (error != VPN_ERROR_NO_ERROR) { + intent.putExtra(BROADCAST_ERROR_CODE, error); + } mContext.sendBroadcast(intent); } diff --git a/vpn/java/android/net/vpn/VpnState.java b/vpn/java/android/net/vpn/VpnState.java index ebd936454f889..6e61f9c0a7122 100644 --- a/vpn/java/android/net/vpn/VpnState.java +++ b/vpn/java/android/net/vpn/VpnState.java @@ -26,8 +26,13 @@ package android.net.vpn; * {@link DISCONNECTING} and then {@link IDLE}. * {@link CANCELLED} is a state when a VPN connection attempt is aborted, and * is in transition to {@link IDLE}. + * The {@link UNUSABLE} state indicates that the profile is not in a state for + * connecting due to possibly the integrity of the fields or another profile is + * connecting etc. + * The {@link UNKNOWN} state indicates that the profile state is to be + * determined. * {@hide} */ public enum VpnState { - CONNECTING, DISCONNECTING, CANCELLED, CONNECTED, IDLE + CONNECTING, DISCONNECTING, CANCELLED, CONNECTED, IDLE, UNUSABLE, UNKNOWN } diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 3d65d3c66f388..fa328e8d1c78c 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -40,7 +40,7 @@ interface IWifiManager boolean pingSupplicant(); - boolean startScan(); + boolean startScan(boolean forceActive); List getScanResults(); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 7a15f273d1409..1f73bec989845 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -476,9 +476,27 @@ public class WifiManager { * on completion of the scan. * @return {@code true} if the operation succeeded, i.e., the scan was initiated */ - public boolean startScan() { + public boolean startScan() { try { - return mService.startScan(); + return mService.startScan(false); + } catch (RemoteException e) { + return false; + } + } + + /** + * Request a scan for access points. Returns immediately. The availability + * of the results is made known later by means of an asynchronous event sent + * on completion of the scan. + * This is a variant of startScan that forces an active scan, even if passive + * scans are the current default + * @return {@code true} if the operation succeeded, i.e., the scan was initiated + * + * @hide + */ + public boolean startScanActive() { + try { + return mService.startScan(true); } catch (RemoteException e) { return false; } diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index 3851ac0b1ce80..0799f5f5ee044 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -51,7 +51,7 @@ public class WifiNative { public native static boolean pingCommand(); - public native static boolean scanCommand(); + public native static boolean scanCommand(boolean forceActive); public native static boolean setScanModeCommand(boolean setActive); diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java index 2fbc779503589..3aa31bfdecf99 100644 --- a/wifi/java/android/net/wifi/WifiStateTracker.java +++ b/wifi/java/android/net/wifi/WifiStateTracker.java @@ -239,6 +239,7 @@ public class WifiStateTracker extends NetworkStateTracker { private boolean mIsScanModeActive; private boolean mIsScanModeSetDueToAHiddenNetwork; + private boolean mEnableRssiPolling; // Wi-Fi run states: private static final int RUN_STATE_STARTING = 1; @@ -338,6 +339,7 @@ public class WifiStateTracker extends NetworkStateTracker { private void setSupplicantState(SupplicantState state) { mWifiInfo.setSupplicantState(state); updateNetworkInfo(); + checkPollTimer(); } public SupplicantState getSupplicantState() { @@ -352,6 +354,7 @@ public class WifiStateTracker extends NetworkStateTracker { private void setSupplicantState(String stateName) { mWifiInfo.setSupplicantState(stateName); updateNetworkInfo(); + checkPollTimer(); } /** @@ -540,8 +543,10 @@ public class WifiStateTracker extends NetworkStateTracker { * Set the interval timer for polling connection information * that is not delivered asynchronously. */ - private synchronized void setPollTimer () { - if (!hasMessages(EVENT_POLL_INTERVAL)) { + private synchronized void checkPollTimer() { + if (mEnableRssiPolling && + mWifiInfo.getSupplicantState() == SupplicantState.COMPLETED && + !hasMessages(EVENT_POLL_INTERVAL)) { sendEmptyMessageDelayed(EVENT_POLL_INTERVAL, POLL_STATUS_INTERVAL_MSECS); } } @@ -637,6 +642,13 @@ public class WifiStateTracker extends NetworkStateTracker { setBluetoothScanMode(isBluetoothPlaying); } + public void enableRssiPolling(boolean enable) { + if (mEnableRssiPolling != enable) { + mEnableRssiPolling = enable; + checkPollTimer(); + } + } + @Override public void releaseWakeLock() { if (mReleaseWakeLockCallback != null) { @@ -1022,9 +1034,7 @@ public class WifiStateTracker extends NetworkStateTracker { case EVENT_POLL_INTERVAL: if (mWifiInfo.getSupplicantState() != SupplicantState.UNINITIALIZED) { requestPolledInfo(mWifiInfo); - if (mWifiInfo.getSupplicantState() == SupplicantState.COMPLETED) { - setPollTimer(); - } + checkPollTimer(); } break; @@ -1121,7 +1131,7 @@ public class WifiStateTracker extends NetworkStateTracker { } else { // In some situations, supplicant needs to be kickstarted to // start the background scanning - WifiNative.scanCommand(); + WifiNative.scanCommand(true); } } } @@ -1163,7 +1173,7 @@ public class WifiStateTracker extends NetworkStateTracker { } private void configureInterface() { - setPollTimer(); + checkPollTimer(); mLastSignalLevel = -1; if (!mUseStaticIp) { if (!mHaveIpAddress && !mObtainingIpAddress) {